Polygons
Abstract polygons
In this package, any polygon regardless of its concrete representation in memory should be a subtype of Devices.AbstractPolygon
.
#
Devices.AbstractPolygon
— Type.
abstract type AbstractPolygon{T<:Coordinate} end
Anything you could call a polygon regardless of the underlying representation. Currently only Rectangle
or Polygon
are concrete subtypes, but one could imagine further subtypes to represent specific shapes that appear in highly optimized pattern formats. Examples include the OASIS format (which has 25 implementations of trapezoids) or e-beam lithography pattern files like the Raith GPF format.
Affine transformations
The mechanism for affine transformations is largely provided by the CoordinateTransformations.jl
package. For convenience, the documentation for Translation
and compose
is reproduced below from that package. We implement our own 2D rotations.
An example of how to use affine transformations with polygons:
julia> r = Rectangle(1,1) Rectangle{Int64}((0,0), (1,1)) julia> trans = Translation(10,10) Translation(10, 10) julia> trans = Rotation(90°) ∘ trans AffineMap([0.0 -1.0; 1.0 0.0], [-10.0, 10.0]) julia> trans(r) Polygon{Float64}(Point{Float64}[(-10.0,10.0), (-10.0,11.0), (-11.0,11.0), (-11.0,10.0)])
#
CoordinateTransformations.compose
— Function.
compose(trans1, trans2) trans1 ∘ trans2
Take two transformations and create a new transformation that is equivalent to successively applying trans2
to the coordinate, and then trans1
. By default will create a ComposedTransformation
, however this method can be overloaded for efficiency (e.g. two affine transformations naturally compose to a single affine transformation).
#
Devices.Points.Rotation
— Function.
Rotation(Θ)
Construct a rotation about the origin. Units accepted (no units ⇒ radians).
#
CoordinateTransformations.Translation
— Type.
Translation(v) <: AbstractAffineMap Translation(dx, dy) (2D) Translation(dx, dy, dz) (3D)
Construct the Translation
transformation for translating Cartesian points by an offset v = (dx, dy, ...)
#
Devices.Points.XReflection
— Function.
XReflection()
Construct a reflection about the x-axis (y-coordinate changes sign).
Example:
julia> trans = XReflection() LinearMap([1 0; 0 -1]) julia> trans(Point(1,1)) 2-element Point{Int64}: 1 -1
#
Devices.Points.YReflection
— Function.
YReflection()
Construct a reflection about the y-axis (x-coordinate changes sign).
Example:
julia> trans = YReflection() LinearMap([-1 0; 0 1]) julia> trans(Point(1,1)) 2-element Point{Int64}: -1 1
Clipping
#
Devices.Polygons.clip
— Function.
clip(op::Clipper.ClipType, s::AbstractPolygon{S}, c::AbstractPolygon{T}; pfs::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd, pfc::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd) where {S <: Coordinate,T <: Coordinate} clip(op::Clipper.ClipType, s::AbstractVector{A}, c::AbstractVector{B}; pfs::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd, pfc::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd) where {S, T, A <: AbstractPolygon{S}, B <: AbstractPolygon{T}} clip{S<:AbstractPolygon, T<:AbstractPolygon}(op::Clipper.ClipType, s::AbstractVector{S}, c::AbstractVector{T}; pfs::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd, pfc::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd)
Using the Clipper
library and the Clipper.jl
wrapper, perform polygon clipping. The first argument must be one of the following types :
Clipper.ClipTypeDifference
Clipper.ClipTypeIntersection
Clipper.ClipTypeUnion
Clipper.ClipTypeXor
Note that these are types; you should not follow them with ()
. The second and third arguments are AbstractPolygon
objects. Keyword arguments pfs
and pfc
specify polygon fill rules (see the Clipper
docs for further information). These arguments may include:
Clipper.PolyFillTypeNegative
Clipper.PolyFillTypePositive
Clipper.PolyFillTypeEvenOdd
Clipper.PolyFillTypeNonZero
Offsetting
#
Devices.Polygons.offset
— Function.
offset{S<:Coordinate}(s::AbstractPolygon{S}, delta::Coordinate; j::Clipper.JoinType=Clipper.JoinTypeMiter, e::Clipper.EndType=Clipper.EndTypeClosedPolygon) offset{S<:AbstractPolygon}(subject::AbstractVector{S}, delta::Coordinate; j::Clipper.JoinType=Clipper.JoinTypeMiter, e::Clipper.EndType=Clipper.EndTypeClosedPolygon) offset{S<:Polygon}(s::AbstractVector{S}, delta::Coordinate; j::Clipper.JoinType=Clipper.JoinTypeMiter, e::Clipper.EndType=Clipper.EndTypeClosedPolygon)
Using the Clipper
library and the Clipper.jl
wrapper, perform polygon offsetting.
The first argument should be an AbstractPolygon
. The second argument is how much to offset the polygon. Keyword arguments include a join type:
Clipper.JoinTypeMiter
Clipper.JoinTypeRound
Clipper.JoinTypeSquare
and also an end type:
Clipper.EndTypeClosedPolygon
Clipper.EndTypeClosedLine
Clipper.EndTypeOpenSquare
Clipper.EndTypeOpenRound
Clipper.EndTypeOpenButt
Rectangle API
#
Devices.Rectangles.Rectangle
— Type.
struct Rectangle{T} <: AbstractPolygon{T} ll::Point{T} ur::Point{T} function Rectangle(a,b) # Ensure ll is lower-left, ur is upper-right. ll = Point(a.<=b) .* a + Point(b.<=a) .* b ur = Point(a.<=b) .* b + Point(b.<=a) .* a new(ll,ur) end end
A rectangle, defined by opposing lower-left and upper-right corner coordinates. Lower-left and upper-right are guaranteed to be such by the inner constructor.
#
Devices.Rectangles.Rectangle
— Method.
Rectangle(ll::Point, ur::Point)
Convenience constructor for Rectangle
objects.
#
Devices.Rectangles.Rectangle
— Method.
Rectangle(width, height)
Constructs Rectangle
objects by specifying the width and height rather than the lower-left and upper-right corners.
The rectangle will sit with the lower-left corner at the origin. With centered rectangles we would need to divide width and height by 2 to properly position. If we wanted an object of Rectangle{Int}
type, this would not be possible if either width
or height
were odd numbers. This definition ensures type stability in the constructor.
#
Devices.bounds
— Method.
bounds(r::Rectangle)
No-op (just returns r
).
#
Devices.center
— Method.
center(r::Rectangle)
Returns a Point
corresponding to the center of the rectangle.
#
Devices.centered
— Method.
centered(r::Rectangle)
Centers a copy of r
, with promoted coordinates if necessary. This function will not throw an InexactError()
, even if r
had integer coordinates.
#
Devices.Rectangles.height
— Method.
height(r::Rectangle)
Return the height of a rectangle.
#
Devices.Rectangles.isproper
— Method.
isproper(r::Rectangle)
Returns true
if the rectangle has a non-zero area. Otherwise, returns false
. Note that the upper-right and lower-left corners are enforced to be the ur
and ll
fields of a Rectangle
by the inner constructor.
#
Devices.lowerleft
— Method.
lowerleft(r::Rectangle)
Returns the lower-left corner of a rectangle (Point object).
#
Devices.upperright
— Method.
upperright(r::Rectangle)
Returns the upper-right corner of a rectangle (Point object).
#
Devices.Polygons.points
— Method.
points{T}(x::Rectangle{T})
Returns the array of Point
objects defining the rectangle.
#
Devices.Rectangles.width
— Method.
width(r::Rectangle)
Return the width of a rectangle.
#
Base.:+
— Method.
+(r::Rectangle, p::Point)
Translate a rectangle by p
.
Polygon API
#
Devices.Polygons.Polygon
— Type.
struct Polygon{T} <: AbstractPolygon{T} p::Vector{Point{T}} Polygon(x) = new(x) Polygon(x::AbstractPolygon) = convert(Polygon{T}, x) end
Polygon defined by list of coordinates. The first point should not be repeated at the end (although this is true for the GDS format).
#
Devices.Polygons.Polygon
— Method.
Polygon{T}(parr::AbstractVector{Point{T}})
Convenience constructor for a Polygon{T}
object.
#
Devices.Polygons.Polygon
— Method.
Polygon(p0::Point, p1::Point, p2::Point, p3::Point...)
Convenience constructor for a Polygon{T}
object.
#
Devices.bounds
— Method.
bounds(p::Polygon)
Return a bounding Rectangle for polygon p
.
#
Devices.bounds
— Method.
bounds(parr::AbstractArray{<:AbstractPolygon})
Return a bounding Rectangle
for an array parr
of AbstractPolygon
objects. Rectangles having zero width and height should be excluded from the calculation.
#
Devices.bounds
— Method.
bounds(p0::AbstractPolygon, p::AbstractPolygon...)
Return a bounding Rectangle
for several AbstractPolygon
objects.
#
Devices.lowerleft
— Method.
lowerleft(x::Polygon)
Return the lower-left-most corner of a rectangle bounding polygon x
. Note that this point doesn't have to be in the polygon.
#
Devices.upperright
— Method.
upperright(x::Polygon)
Return the upper-right-most corner of a rectangle bounding polygon x
. Note that this point doesn't have to be in the polygon.
#
Devices.Polygons.points
— Method.
points(x::Polygon)
Returns the array of Point
objects defining the polygon.