Skip to content

Commit

Permalink
Merge 3da5f1b into 323efcf
Browse files Browse the repository at this point in the history
  • Loading branch information
ajkeller34 committed Dec 3, 2018
2 parents 323efcf + 3da5f1b commit abf8cc5
Show file tree
Hide file tree
Showing 26 changed files with 1,382 additions and 317 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
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
32 changes: 23 additions & 9 deletions src/paths/contstyles/compound.jl
@@ -1,17 +1,18 @@
"""
struct CompoundStyle <: ContinuousStyle
struct CompoundStyle{T<:FloatCoordinate} <: ContinuousStyle{false}
styles::Vector{Style}
grid::Vector{Float64}
grid::Vector{T}
end
Combines styles together, typically for use with a [`CompoundSegment`](@ref).
- `styles`: Array of styles making up the object. This is shallow-copied
by the outer constructor.
- `styles`: Array of styles making up the object. This is deep-copied by the outer
constructor.
- `grid`: An array of `t` values needed for rendering the parameteric path.
"""
struct CompoundStyle{T<:FloatCoordinate} <: ContinuousStyle{false}
styles::Vector{Style}
grid::Vector{T}
tag::Symbol
end
function (s::CompoundStyle)(t)
l0 = s.grid[1]
Expand All @@ -23,16 +24,16 @@ function (s::CompoundStyle)(t)
end
return s.styles[length(s.grid) - 1], t - l0
end
copy(s::CompoundStyle) = (typeof(s))(deepcopy(s.styles), copy(s.grid))
CompoundStyle(seg::AbstractVector, sty::AbstractVector) =
CompoundStyle(deepcopy(Vector{Style}(sty)), makegrid(seg, sty))
copy(s::CompoundStyle, tag=gensym()) = (typeof(s))(deepcopy(s.styles), copy(s.grid), tag)
CompoundStyle(seg::AbstractVector{Segment{T}}, sty::AbstractVector, tag=gensym()) where {T} =
CompoundStyle(deepcopy(Vector{Style}(sty)), makegrid(seg, sty), tag)

"""
makegrid{T<:Segment}(segments::AbstractVector{T}, styles)
makegrid(segments::AbstractVector{T}, styles) where {T<:Segment}
Returns a collection with the values of `t` to use for
rendering a `CompoundSegment` with a `CompoundStyle`.
"""
function makegrid(segments::AbstractVector{T}, styles) where T<:Segment
function makegrid(segments::AbstractVector{T}, styles) where {T<:Segment}
isempty(segments) && error("Cannot use makegrid with zero segments.")
length(segments) != length(styles) &&
error("Must have same number of segments and styles.")
Expand All @@ -52,3 +53,16 @@ for x in (:extent, :width)
end

summary(::CompoundStyle) = "Compound style"

function translate(s::CompoundStyle, x, tag=gensym())
s′ = copy(s, tag)
s′.grid .-= x
return s′
end

function pin(s::CompoundStyle; start=nothing, stop=nothing, tag=gensym())
if start !== nothing
return translate(s, start, tag)
end
return copy(s, tag)
end
2 changes: 2 additions & 0 deletions src/paths/contstyles/cpw.jl
Expand Up @@ -16,6 +16,7 @@ copy(x::GeneralCPW) = GeneralCPW(x.trace, x.gap)
extent(s::GeneralCPW, t) = s.trace(t)/2 + s.gap(t)
trace(s::GeneralCPW, t) = s.trace(t)
gap(s::GeneralCPW, t) = s.gap(t)
translate(s::GeneralCPW, t) = GeneralCPW(x->s.trace(x+t), x->s.gap(x+t))

"""
struct SimpleCPW{T<:Coordinate} <: CPW
Expand All @@ -32,6 +33,7 @@ copy(x::SimpleCPW) = SimpleCPW(x.trace, x.gap)
extent(s::SimpleCPW, t...) = s.trace/2 + s.gap
trace(s::SimpleCPW, t...) = s.trace
gap(s::SimpleCPW, t...) = s.gap
translate(s::SimpleCPW, t) = copy(s)

"""
CPW(trace::Coordinate, gap::Coordinate)
Expand Down
37 changes: 31 additions & 6 deletions src/paths/contstyles/decorated.jl
@@ -1,17 +1,17 @@
"""
mutable struct DecoratedStyle{T<:FloatCoordinate} <: ContinuousStyle{false}
s::Style
ts::Array{Float64,1}
dirs::Array{Int,1}
refs::Array{CellReference,1}
ts::Vector{Float64}
dirs::Vector{Int}
refs::Vector{CellReference}
end
Style with decorations, like structures periodically repeated along the path, etc.
"""
mutable struct DecoratedStyle{T<:FloatCoordinate} <: ContinuousStyle{false}
s::Style
ts::Array{T,1}
dirs::Array{Int,1}
refs::Array{CellReference,1}
ts::Vector{T}
dirs::Vector{Int}
refs::Vector{CellReference}
end
summary(s::DecoratedStyle) = string(summary(s.s), " with ", length(s.refs), " decorations")

Expand Down Expand Up @@ -85,3 +85,28 @@ function decorate(sty::DecoratedStyle, T, t, location, c)
push!(sty.refs, c)
sty
end

function pin(sty::DecoratedStyle{T}; start=nothing, stop=nothing) where T
x0 = ifelse(start === nothing, zero(sty.length), start)
x1 = ifelse(stop === nothing, sty.length, stop)
s = pin(undecorated(sty); start=start, stop=stop)
inds = findall(t->t in x0..x1, sty.ts)
ts = sty.ts[inds]
dirs = sty.dirs[inds]
refs = sty.refs[inds]
return DecoratedStyle{T}(s, ts, dirs, refs)
end

"""
undecorate!(sty, t)
Removes all attachments at position `t` from a style.
"""
function undecorate!(sty::DecoratedStyle, t)
inds = findall(x->x==t, sty.ts)
deleteat!(sty.ts, inds)
deleteat!(sty.dirs, inds)
deleteat!(sty.refs, inds)
return sty
end
undecorate!(sty::Style, t) = sty
# handling compound style is probably brittle if it has decorations inside
35 changes: 35 additions & 0 deletions src/paths/contstyles/interface.jl
@@ -0,0 +1,35 @@
"""
extent(s::Style, t)
For a style `s`, returns a distance tangential to the path specifying the lateral extent
of the polygons rendered. The extent is measured from the center of the path to the edge
of the polygon (half the total width along the path). The extent is evaluated at path length
`t` from the start of the associated segment.
"""
function extent end

"""
width(s::Style, t)
For a style `s` and parameteric argument `t`, returns the width of paths rendered.
"""
function width end

"""
translate(s::ContinuousStyle, x)
Creates a style `s′` such that all properties `f(s′, t) == f(s, t+x)`. Basically, advance
the style forward by path length `x`.
"""
function translate end

"""
pin(s::ContinuousStyle; start=nothing, stop=nothing)
Imagine having a styled segment of length `L` split into two, the first segment having
length `l` and the second having length `L-l`. In all but the simplest styles, the styles
need to be modified in order to maintain the rendered appearances. A style appropriate for
the segment of length `l` (`L-l`) is given by `pin(s; stop=l)` (`pin(s; start=l)`).
"""
function pin(s::ContinuousStyle{false}; start=nothing, stop=nothing)
if start !== nothing
return translate(s, start)
end
return s
end
4 changes: 4 additions & 0 deletions src/paths/contstyles/strands.jl
Expand Up @@ -26,11 +26,14 @@ struct GeneralStrands{S,T,U} <: Strands{false}
num::Int
end
copy(x::GeneralStrands) = GeneralStrands(x.offset, x.width, x.spacing, x.num)
GeneralStrands(o,w,s,n) = GeneralStrands{typeof(o), typeof(w), typeof(s)}(o,w,s,n)
extent(s::GeneralStrands, t) = s.offset(t) + (s.num)*(s.width(t)) + (s.num - 1)*(s.spacing(t))
offset(s::GeneralStrands, t) = s.offset(t)
width(s::GeneralStrands, t) = s.width(t)
spacing(s::GeneralStrands, t) = s.spacing(t)
num(s::GeneralStrands, t) = s.num
translate(s::GeneralStrands, t) =
GeneralStrands(x->s.offset(x+t), x->s.width(x+t), x->s.spacing(x+t), s.num)

"""
struct SimpleStrands{T<:Coordinate} <: Strands{false}
Expand Down Expand Up @@ -62,6 +65,7 @@ offset(s::SimpleStrands, t...) = s.offset
width(s::SimpleStrands, t...) = s.width
spacing(s::SimpleStrands, t...) = s.spacing
num(s::SimpleStrands, t...) = s.num
translate(s::SimpleStrands, t) = copy(s)

"""
Strands(offset::Coordinate, width::Coordinate, spacing::Coordinate, num::Int)
Expand Down
18 changes: 18 additions & 0 deletions src/paths/contstyles/tapers.jl
Expand Up @@ -16,6 +16,15 @@ end
copy(x::TaperTrace) = TaperTrace(x.width_start, x_width_end)
extent(s::TaperTrace, t) = 0.5 * width(s,t)
width(s::TaperTrace, t) = (1-t/s.length) * s.width_start + t/s.length * s.width_end
function pin(s::TaperTrace; start=nothing, stop=nothing)
!isdefined(s, :length) && error("cannot `pin`; length of $s not yet determined.")
x0 = ifelse(start === nothing, zero(s.length), start)
x1 = ifelse(stop === nothing, s.length, stop)
@assert x1 - x0 > zero(x1 - x0)
@assert zero(x0) <= x0 < s.length
@assert zero(x1) < x1 <= s.length
return typeof(s)(width(s, x0), width(s, x1), x1-x0)
end
function TaperTrace(width_start::Coordinate, width_end::Coordinate)
dimension(width_start) != dimension(width_end) && throw(DimensionError(trace,gap))
w_s,w_e = promote(float(width_start), float(width_end))
Expand Down Expand Up @@ -55,6 +64,15 @@ function TaperCPW(trace_start::Coordinate, gap_start::Coordinate, trace_end::Coo
t_s,g_s,t_e,g_e = promote(float(trace_start), float(gap_start), float(trace_end), float(gap_end))
return TaperCPW{typeof(t_s)}(t_s, g_s, t_e, g_e)
end
function pin(sty::TaperCPW; start=nothing, stop=nothing)
!isdefined(sty, :length) && error("cannot `pin`; length of $sty not yet determined.")
x0 = ifelse(start === nothing, zero(sty.length), start)
x1 = ifelse(stop === nothing, sty.length, stop)
@assert x1 - x0 > zero(x1 - x0)
@assert zero(x0) <= x0 < sty.length
@assert zero(x1) < x1 <= sty.length
return typeof(sty)(trace(sty, x0), gap(sty, x0), trace(sty, x1), gap(sty, x1), x1 - x0)
end

summary(s::TaperTrace) = string("Tapered trace with initial width ", s.width_start,
" and final width ", s.width_end)
Expand Down

0 comments on commit abf8cc5

Please sign in to comment.