Skip to content

Commit

Permalink
Merge 05bdebb into 323efcf
Browse files Browse the repository at this point in the history
  • Loading branch information
ajkeller34 committed Dec 3, 2018
2 parents 323efcf + 05bdebb commit ec8739a
Show file tree
Hide file tree
Showing 28 changed files with 1,477 additions and 329 deletions.
16 changes: 9 additions & 7 deletions LICENSE.md
Expand Up @@ -21,14 +21,13 @@ The Devices.jl package is licensed under the MIT "Expat" License:
> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
A modified version of `adaptive_grid` was originally from PlotUtils.jl,
an MIT "Expat" licensed Julia package by Tom Breloff and contributors (notably
Kristoffer Carlsson).
A modified version of `adaptive_grid` was originally from PlotUtils.jl, an MIT "Expat"
licensed Julia package by Tom Breloff and contributors (notably Kristoffer Carlsson).

Cadence Design Systems, Inc. holds the rights to the GDS-II format. The specification
has been described with permission in the SPIE Handbook of Microlithography, Micromachining
and Microfabrication, vol. 1 (accessible [here](http://www.cnf.cornell.edu/cnf_spie9.html)
as of April 17, 2017).
Cadence Design Systems, Inc. holds the rights to the GDS-II format. The specification has
been described with permission in the SPIE Handbook of Microlithography, Micromachining and
Microfabrication, vol. 1 (accessible [here](http://www.cnf.cornell.edu/cnf_spie9.html) as of
April 17, 2017).

This package uses the D3.js library for interactive visualization, under the 3-clause BSD
license:
Expand Down Expand Up @@ -58,3 +57,6 @@ license:
> ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The file `src/predicates.jl` contains a Julia adaptation of public domain C code written by
Jonathan Richard Shewchuk. Available at http://www.cs.cmu.edu/~quake/robust.html.
11 changes: 11 additions & 0 deletions NEWS.md
@@ -1,3 +1,14 @@
- v0.5.0
- Rewrite some line/ray/line-segment intersection code.
- `adjust!` has been renamed `reconcile!`
- For many array-like methods on paths, there is now a keyword argument that lets you
specify whether you want to reconcile the path immediately or defer. This is useful
when speed is a concern and you are chaining operations.
- Implement code to automatically handle path intersections: `Paths.intersect!`
- Path termination: `Paths.terminate!`
- Style translation: `Paths.pin` and `Paths.translate`.
- Node/segment/style splitting: `Paths.split`.
- Add some default colors: 21--29 is a red gradient, 31--39 is green, 41--49 is blue.
- v0.4.0
- Julia 1.0 compatibility.
- `Rectangles.isproper` has a slightly different definition. Rectangles are
Expand Down
2 changes: 2 additions & 0 deletions REQUIRE
Expand Up @@ -7,3 +7,5 @@ Clipper 0.5.0
Unitful 0.11.0
Cairo 0.5.4
WebIO 0.4 0.5-
IntervalSets 0.3.1
DataStructures 0.14
100 changes: 91 additions & 9 deletions docs/src/paths.md
Expand Up @@ -35,8 +35,9 @@ their respective constructors.

The following example illustrates the use of automatic tapering. First, we
construct a taper with two different traces surrounding it:
```@example 2
using Devices, Devices.PreferMicrons

```@example 1
using Devices, Devices.PreferMicrons, FileIO # hide
p = Path(μm)
straight!(p, 10μm, Paths.Trace(2.0μm))
Expand All @@ -50,15 +51,15 @@ even automatically taper between the current `Paths.Trace` and a hard-coded tape
(of concrete type [`Paths.TaperTrace`](@ref)), matching to the dimensions at the
beginning of the latter taper.

```@example 2
```@example 1
straight!(p, 10μm, Paths.Taper())
straight!(p, 10μm, Paths.TaperTrace(2.0μm, 1.0μm))
```

As a final example, `Paths.Taper` can also be used in [`turn!`](@ref) segments, and
as a way to automatically transition from a `Paths.Taper` to a `Paths.CPW`, or vice-versa:

```@example 2
```@example 1
turn!(p, -π/2, 10μm, Paths.Taper())
straight!(p, 10μm, Paths.Trace(2.0μm))
straight!(p, 10μm, Paths.Taper())
Expand All @@ -72,9 +73,16 @@ render!(c, p, GDSMeta(0))

Sharp turns in a path can be accomplished with [`Paths.corner!`](@ref). Sharp turns pose a
challenge to the path abstraction in that they have zero length, and when rendered
effectively take up some length of the neighboring segments. These details are
automatically accounted for by tweaking segment lengths and other captured segment variables
just before rendering a path.
effectively take up some length of the neighboring segments. Originally, the segment lengths
were tweaked at render time to achieve the intended output. As other code began taking
advantage of the path abstractions, the limitations of this approach became apparent.

Currently, corners are implemented such that the preceding [`Paths.Node`](@ref) is split
using [`Paths.split`](@ref) near the corner when `corner!` is used, and a short resulting
section near the corner has the style changed to [`Paths.SimpleNoRender`](@ref).
When this is followed by [`Paths.straight!`](@ref) to create the next segment, a similar
operation is done, to ensure the corner is not twice-rendered. This change was necessary
to be able to use [`Paths.intersect!`](@ref) on paths with corners.

## Attachments

Expand Down Expand Up @@ -133,13 +141,68 @@ if we want to refer to references inside that attachment: `aaa["bbb",2]["ccc"]`.
manner, it is easy to find the right `CellReference` to use with
[`Cells.transform(::Cell, ::Cells.CellRef)`](@ref).

## Intersections

How to do the right thing when paths intersect is often tedious. [`Paths.intersect!`](@ref)
provides a useful function to modify existing paths automatically to account for
intersections according to intersection styles ([`Paths.IntersectStyle`](@ref)). Since this
is done prior to rendering, further modification can be done easily. Both self-intersections
and pairwise intersections can be handled for any reasonable number of paths.

For now, one intersection style is implemented, but the heavy-lifting to add more has been
done already. Here's an example (consult API docs below for further information):

```@example 1
pa1 = Path(μm)
turn!(pa1, -360°, 100μm, Paths.CPW(10μm, 6μm))
pa2 = Path(Point(0,100)μm, α0=-90°)
straight!(pa2, 400μm, Paths.CPW(10μm, 6μm))
turn!(pa2, 270°, 200μm)
straight!(pa2, 400μm)
bridgemetas = GDSMeta.(20:30)
intersect!(Paths.Bridges(bridgemetas=bridgemetas, gap=2μm, footlength=2μm), pa1, pa2;
interactions=[true true; false true])
c = Cell("test", nm)
render!(c, pa1, GDSMeta(0))
render!(c, pa2, GDSMeta(1))
save("intersect_circle.svg", flatten(c); layercolors=merge(Devices.Graphics.layercolors, Dict(1=>(0,0,0,1)))); nothing # hide
```
<img src="../intersect_circle.svg" style="width:4in;"/>

Here's another example:

```@example 1
pa = Path(μm, α0=90°)
straight!(pa, 100μm, Paths.Trace(2μm))
corner!(pa, 90°, Paths.SimpleTraceCorner())
let L = 4μm
for i in 1:50
straight!(pa, L)
corner!(pa, 90°, Paths.SimpleTraceCorner())
L += 4μm
end
end
straight!(pa, 4μm)
c = Cell("test", nm)
bridgemetas = GDSMeta.(20:30)
intersect!(Paths.Bridges(bridgemetas=bridgemetas, gap=2μm, footlength=1μm), pa)
render!(c, pa, GDSMeta(1))
save("intersect_spiral.svg", flatten(c); layercolors=merge(Devices.Graphics.layercolors, Dict(1=>(0,0,0,1)))); nothing # hide
```
<img src="../intersect_spiral.svg" style="width:4in;"/>

## Path API

### Path construction

```@docs
Paths.Path
Paths.Path(::Point)
```
### Path interrogation

Expand All @@ -163,14 +226,23 @@ manner, it is easy to find the right `CellReference` to use with
append!(::Path, ::Path)
attach!
corner!
intersect!
meander!
reconcile!
simplify
simplify!
straight!
terminate!
turn!
```

### Path intersection styles

```@docs
Paths.IntersectStyle
Paths.Bridges
```

## Node API

### Node construction
Expand All @@ -185,6 +257,7 @@ manner, it is easy to find the right `CellReference` to use with
Paths.previous
Paths.next
Paths.segment
Paths.split(::Paths.Node, ::Devices.Coordinate)
Paths.style
Paths.setsegment!
Paths.setstyle!
Expand All @@ -209,13 +282,21 @@ manner, it is easy to find the right `CellReference` to use with

## Style API

### Constructors and methods
### Style construction

```@docs
Paths.Trace
Paths.CPW
Paths.Taper
Paths.Strands
Paths.NoRender
```

### Style manipulation

```@docs
Paths.pin
Paths.translate
Paths.undecorated
```

Expand All @@ -230,6 +311,7 @@ manner, it is easy to find the right `CellReference` to use with
### Concrete types

```@docs
Paths.SimpleNoRender
Paths.SimpleTrace
Paths.GeneralTrace
Paths.SimpleCPW
Expand Down
2 changes: 1 addition & 1 deletion docs/src/points.md
Expand Up @@ -19,7 +19,7 @@ julia> Point(1.0,1.0)
1.0
julia> Point(1.0u"μm", 1.0u"μm")
2-element Point{Unitful.Quantity{Float64,Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)},Unitful.FreeUnits{(Unitful.Unit{:Meter,Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}}(-6, 1//1),),Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}}}}:
2-element Point{Quantity{Float64,𝐋,Unitful.FreeUnits{(μm,),𝐋,nothing}}}:
1.0 μm
1.0 μm
```
Expand Down
47 changes: 43 additions & 4 deletions src/Devices.jl
@@ -1,5 +1,6 @@
module Devices
using Random
using LinearAlgebra
using ForwardDiff
using FileIO
using WebIO
Expand All @@ -10,8 +11,9 @@ import Clipper
import Clipper: cclipper
import FileIO: save, load

import Base: length, show, eltype
import Unitful: Length, DimensionlessQuantity, ustrip, unit, inch
import Base: length, show, eltype, intersect!
import Unitful: Length, LengthUnits, DimensionlessQuantity, NoUnits, DimensionError
import Unitful: ustrip, unit, inch
Unitful.@derived_dimension InverseLength inv(Unitful.𝐋)

export GDSMeta
Expand All @@ -21,6 +23,31 @@ const DEFAULT_LAYER = 0
const DEFAULT_DATATYPE = 0
const D3STR = read(joinpath(dirname(@__FILE__), "../deps/d3.min.js"), String)

# setup for robust 2d predicates
const splitter, epsilon =
let every_other = true, half = 0.5, epsilon = 1.0, splitter = 1.0, check = 1.0
lastcheck = check
epsilon *= half
every_other && (splitter *= 2.0)
every_other = !every_other
check = 1.0 + epsilon

while (check != 1.0) && (check != lastcheck)
lastcheck = check
epsilon *= half
every_other && (splitter *= 2.0)
every_other = !every_other
check = 1.0 + epsilon
end
splitter += 1.0
splitter, epsilon
end

const resulterrbound = (3.0 + 8.0 * epsilon) * epsilon
const ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon
const ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon
const ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon

function __init__()
# To ensure no crashes
global _clip = Ref(Clipper.Clip())
Expand Down Expand Up @@ -51,6 +78,12 @@ Type alias for numeric types suitable for coordinate systems.
"""
const Coordinate = Union{Real, Length}

"""
CoordinateUnits = Union{typeof(NoUnits), LengthUnits}
Type alias for units suitable for coordinate systems.
"""
const CoordinateUnits = Union{typeof(NoUnits), LengthUnits}

"""
PointTypes = Union{Real, DimensionlessQuantity, Length, InverseLength}
Allowed type variables for `Point{T}` types.
Expand Down Expand Up @@ -85,6 +118,8 @@ export Points, Point, Rotation, Translation, XReflection, YReflection,
gety,

include("predicates.jl")

abstract type Meta end
struct GDSMeta <: Meta
layer::Int
Expand Down Expand Up @@ -146,6 +181,10 @@ export Cells, Cell, CellArray, CellPolygon, CellReference,
uniquename

include("utils.jl")

function bridge! end # needed in Paths, but not defined in Microwave
export bridge!

include("paths/paths.jl")
import .Paths: Path,
α0,
Expand Down Expand Up @@ -174,6 +213,7 @@ import .Paths: Path,
style0,
style1,
setstyle!,
terminate!,
turn!,
undecorated

Expand All @@ -200,14 +240,14 @@ export Paths, Path, Segment, Style,
style1,
setstyle!,
straight!,
terminate!,
turn!,
undecorated

include("render/render.jl")

include("microwave.jl")
import .Microwave:
bridge!,
checkerboard!,
device_template!,
flux_bias!,
Expand All @@ -221,7 +261,6 @@ import .Microwave:
radialcut!,
radialstub!
export Microwave,
bridge!,
checkerboard!,
device_template!,
flux_bias!,
Expand Down
2 changes: 1 addition & 1 deletion src/microwave.jl
Expand Up @@ -9,7 +9,7 @@ using Devices.Rectangles
using Devices.Polygons
using Devices.Points
using Devices.Cells
import Devices: AbstractPolygon, Coordinate, GDSMeta, Meta
import Devices: AbstractPolygon, Coordinate, GDSMeta, Meta, bridge!
import Unitful: NoUnits, cm, μm, nm, ustrip, unit

export bridge!
Expand Down

0 comments on commit ec8739a

Please sign in to comment.