Geometry-Level Layout API Reference
Units
DeviceLayout.PreferredUnits — Module
module PreferredUnitsModule exporting fm, pm, nm, μm, mm, cm, dm, m.
Mixed unit operations with these imports will be converted based on the unit preference set by DeviceLayout.set_unit_preference! (default nm).
DeviceLayout.set_unit_preference! — Function
set_unit_preference!(pref::String; local_only=true)Set the unit preference. pref must be one of "NoUnits", "PreferMicrons", or "PreferNanometers".
If local_only is true, add the preference to LocalPreferences.toml. Otherwise, add it to Project.toml.
Because this preference is used at compile time, Julia must be restarted for a change to take effect.
DeviceLayout.Coordinate — Type
Coordinate = Union{Real, Length}Type alias for numeric types suitable for coordinate systems.
DeviceLayout.PreferNanometers.UPREFERRED — Constant
const PreferNanometers.UPREFERRED = nmConstant for DeviceLayout.jl compiled with units = "PreferNanometers" in LocalPreferences.toml.
Default value if no preference specified. Other options are PreferMicrons and NoUnits.
DeviceLayout.PreferMicrons.UPREFERRED — Constant
const PreferMicrons.UPREFERRED = μmConstant for DeviceLayout.jl compiled with units = "PreferMicrons" in LocalPreferences.toml.
Other options are PreferNanometers (the default) and NoUnits.
DeviceLayout.PreferNoUnits.UPREFERRED — Constant
const UPREFERRED = Unitful.NoUnitsConstant for DeviceLayout.jl compiled with units = "NoUnits" in LocalPreferences.toml.
Other options are PreferNanometers (the default) and PreferMicrons.
Points
DeviceLayout.PointTypes — Type
PointTypes = Union{Real, DimensionlessQuantity, Length, InverseLength}Allowed type variables for Point{T} types.
DeviceLayout.Points.Point — Type
struct Point{T<:PointTypes} <: StaticArrays.FieldVector{2,T}
x::T
y::T
end2D Cartesian coordinate in the plane.
DeviceLayout.Points.getx — Function
getx(p::Point)Get the x-coordinate of a point. You can also use p.x or p[1].
DeviceLayout.Points.gety — Function
gety(p::Point)Get the y-coordinate of a point. You can also use p.y or p[2].
DeviceLayout.Points.lowerleft — Method
lowerleft{T}(A::AbstractArray{Point{T}})Return the lower-left Point of the smallest bounding rectangle (with sides parallel to the x- and y-axes) that contains all points in A.
Example:
julia> lowerleft([Point(2, 0), Point(1, 1), Point(0, 2), Point(-1, 3)])
2-element Point{Int64} with indices SOneTo(2):
-1
0DeviceLayout.Points.upperright — Method
upperright{T}(A::AbstractArray{Point{T}})Return the upper-right Point of the smallest bounding rectangle (with sides parallel to the x- and y-axes) that contains all points in A.
Example:
julia> upperright([Point(2, 0), Point(1, 1), Point(0, 2), Point(-1, 3)])
2-element Point{Int64} with indices SOneTo(2):
2
3AbstractGeometry
DeviceLayout.AbstractGeometry — Type
AbstractGeometry{S <: Coordinate}Abstract supertype for things that have a geometric representation.
Abstract subtypes include GeometryStructure, GeometryEntity, and GeometryReference. Provides an interface for coordinate transformations and bounding boxes.
DeviceLayout.coordinatetype — Function
coordinatetype(::Type{S}) where {T, S <: AbstractGeometry{T}}
coordinatetype(S) where {T, S <: AbstractGeometry{T}}Return the coordinate type of the geometry.
DeviceLayout.bounds — Method
bounds(geo::AbstractGeometry)
bounds(geo0::AbstractGeometry, geo1::AbstractGeometry, geo::AbstractGeometry...)
bounds(geos)Return the minimum bounding Rectangle for geo or a collection/iterator geos.
If geo is empty or has no extent, a rectangle with zero width and height is returned.
For a collection or a structure that may contain multiple entities and references to other structures, geometries with bounds having zero width and height are excluded from the calculation.
DeviceLayout.center — Method
center(geo::AbstractGeometry)
center(geos)Return the center of the bounding rectangle bounds(geo) or bounds(geos). Note that this point doesn't have to be in ent.
Will not throw an InexactError even if geo has integer coordinates, but instead return floating point coordinates.
See also: lowerleft, upperright.
DeviceLayout.footprint — Function
footprint(geo::AbstractGeometry)
footprint(geos)Return the footprint of geo.
By default, this falls back to bounds(geo), but it may be any single GeometryEntity fully containing geo.
The footprint of a collection or iterator geos is bounds(geos).
DeviceLayout.Points.lowerleft — Method
lowerleft(ent::AbstractGeometry)
lowerleft(ents)Return the lower-left-most corner of a rectangle bounding ent or ents. Note that this point doesn't have to be in ent.
For iterable ents, entities with bounding rectangles of zero width and height will be excluded.
DeviceLayout.Points.upperright — Method
upperright(ent::AbstractGeometry)
upperright(ents)Return the upper-right-most corner of a rectangle bounding ent or ents. Note that this point doesn't have to be in ent.
For iterable ents, entities with bounding rectangles of zero width and height will be excluded.
DeviceLayout.transform — Function
transform(geom::AbstractGeometry, f::Transformation)
transform(
geom::AbstractGeometry{S};
origin=zero(Point{S}),
rot=0°,
xrefl=false,
mag=1
)Return a new AbstractGeometry obtained by applying f to geom.
For generic geom and transformation, attempts to decompose f into a scaled isometry: translate ∘ magnify ∘ rotate ∘ reflect_across_xaxis. In that case, if f does not preserve angles, a DomainError will be thrown.
A concrete subtype of AbstractGeometry must implement
transform(ent::MyEntity, f::Transformation)It is not, however, required that an arbitrary Transformation be valid on MyEntity. For example, one might write
transform(ent::MyEntity, f::Transformation) = transform(ent, ScaledIsometry(f))
function transform(ent::MyEntity, f::ScaledIsometry)
# ... create and return transformed entity
endwhich will throw a DomainError if !preserves_angles(f) (f is not a scaled isometry).
GeometryEntity
DeviceLayout.GeometryEntity — Type
GeometryEntity{T <: Coordinate}A geometric entity that can be placed in a coordinate system.
New concrete GeometryEntity subtypes must implement the following:
to_polygons(::MyEntity)
transform(ent::MyEntity, f)A subtype may also implement specialized transformations like transform(::MyEntity, ::ScaledIsometry), for example if special handling is possible for angle-preserving transformations, as well as specializations for
magnify
rotate
rotate90
reflect_across_xaxis
translatewhich otherwise construct the corresponding ScaledIsometry and call transform.
New subtypes may also implement
footprint
halo
lowerleft
upperrightif there are better ways to calculate these than with to_polygons (the default), which may be slow and expensive. The bounding rectangle returned by bounds is derived from lowerleft and upperright. By default, halo is derived from footprint and offset.
New subtypes may also implement any application functions required for valid styles. Not all styles need be valid for any given entity type.
DeviceLayout.to_polygons — Function
to_polygons(ent::GeometryEntity; kwargs...)Return a single polygon, an iterator, or Vector of Polygons equivalent to ent.
If ent is a StyledEntity, all styles will be applied before conversion to polygons.
DeviceLayout.halo — Method
halo(ent::GeometryEntity{T}, outer_delta, inner_delta=nothing)Return the "halo" of ent using an offset of outer_delta.
By default, the halo is a vector containing offset(footprint(ent), outer_delta), but it may contain any number of GeometryEntitys that together fully cover ent with a margin of outer_delta. It is not guaranteed to cover footprint(ent).
If inner_delta is provided, then the offset at inner_delta is subtracted from the result.
A GeometryEntity should implement a specialized halo if there is an efficient non-Polygon representation of the halo. If it does not, then by default offset will be used, which first resolves the entity into Polygons using to_polygons.
Entity Styles
DeviceLayout.GeometryEntityStyle — Type
abstract type GeometryEntityStyleA style that can be used with a GeometryEntity to create a modified entity.
May use (sty::MyStyle)(ent), styled(ent, sty), or MyStyle(ent, style_args...; style_kwargs...) to create a StyledEntity.
A GeometryEntityStyle should implement to_polygons(::MyEntity, ::MyStyle; kwargs...) for any entity type it can be applied to. As a fallback, it can implement to_polygons(::Polygon, ::MyStyle; kwargs...), in which case entities will be converted to polygons before applying the style.
Unless implemented by the style, lowerleft and upperright (and hence bounds) of a styled entity will use the underlying entity's bounds. Similarly, footprint and halo will fall back to using the underlying entity. Exceptions include the NoRender style, in which case the entity is treated as a zero-area Rectangle (ignored in collective bounds calculations), as well as OptionalStyle, in which case the default style is used (in case it has special behavior).
DeviceLayout.StyledEntity — Type
StyledEntity{T, U <: GeometryEntity{T}, S <: GeometryEntityStyle} <: GeometryEntityGeometryEntity composing another GeometryEntity with a GeometryEntityStyle.
The use of a StyledEntity allows the composition of operations like rounding on geometric entities without committing to a particular representation of those entities.
DeviceLayout.entity — Function
entity(styled_ent::StyledEntity)Return the GeometryEntity styled by styled_ent.
DeviceLayout.style — Method
style(styled_ent::StyledEntity)Return the GeometryEntityStyle of styled_ent.
DeviceLayout.styled — Function
styled(ent, sty)Return StyledEntity(ent, sty).
DeviceLayout.unstyled — Function
unstyled(styled_ent::StyledEntity)Return the unstyled entity referenced by styled_ent.
If styled_ent.ent is itself a StyledEntity, apply unstyled recursively until the original plain GeometyEntity is found.
DeviceLayout.unstyled_type — Function
unstyled_type(::GeometryEntity)
unstyled_type(::Type{GeometryEntity})Return the type of the unstyled entity beneath all styles.
DeviceLayout.Plain — Type
Plain <: GeometryEntityStylePlain style. Does not affect rendering of the styled entity.
DeviceLayout.MeshSized — Type
struct MeshSized{T, S} <: GeometryEntityStyle where {T, S <: Real}
h::T
α::S
endStyle that annotates a GeometryEntity with a mesh size to use in SolidModel rendering. The generated mesh will include a size field defined as:
$s = h * max(s_g, (d/h)^α)$
where $s$ is the mesh size, $d$ is the distance away from the styled entity, $s_g$ is the global mesh scale parameter specified in DeviceLayout.SolidModels.mesh_scale, and h and α are the parameters provided. A smaller value of h will give a finer mesh attached to the styled entity, and a larger value of α will give a more rapid increase in size away from the styled entity.
If α < 0, the resulting size field will use DeviceLayout.SolidModels.mesh_grading_default. It is generally recommended to use this global value in most scenarios, as it provides a helpful mechanism for global mesh modification.
Each MeshSized entity generates a corresponding set of DeviceLayout.SolidModels.mesh_control_points during the call to DeviceLayout.SolidModels.render! along the perimeter of the styled entity. Controlling the mesh only at the edges of entities, rather than within the interior, ensures that geometric entities are resolved whilst avoiding overrefinement in surface regions which can be reasonably achieved through adaptive mesh refinement. Increasing resolution of edges of entities can be achieved through reducing the value of h on the particular entity or $s_g$ to affect all entities globally.
For the set of all DeviceLayout.SolidModels.mesh_control_points computed, a corresponding mesh size will be computed, and the resulting mesh size is then the minimum over all of these values
$s(x) = \min_{x_p ∈ X_p} h_p \max(s_g, \frac{\| x - x_p \|_2}{h_p}^{α_p})$
where $s(x)$ explicitly expresses that the size is a function of position $x$, the $p$ subscript denotes parameters associated to a single control $x_p$ from the $X_p$ of all control points. Reducing $h_p$ will result in a finer mesh next to an entity which will then grow as a function of distance from the control point $x_p$. In the implementation a KDTree ordering per (h,α) pair is used to ensure the reduction over $X_p$ is highly efficient.
See also meshsized_entity.
Associated methods:
DeviceLayout.SolidModels.mesh_scalefor adjusting thes_gparameter.DeviceLayout.SolidModels.mesh_grading_defaultfor adjusting the value ofαthat aMeshSizedwithα < 0will map to.DeviceLayout.SolidModels.reset_mesh_control!for resetting thes_gandα_defaultvalues to the default values.DeviceLayout.SolidModels.add_mesh_size_pointfor adding a mesh sizing point (a point from which distancedwill be calculated), and used in calculating any size fields.DeviceLayout.SolidModels.mesh_control_pointsfor access to the global dictionary of control points for whichdand ultimately the mesh size will be calculated.
DeviceLayout.meshsized_entity — Function
meshsized_entity(ent::GeometryEntity, h::T, α::S=-1.0) where {T, S <: Real}Create a MeshSized entity, specifying a mesh size use in SolidModel rendering. The generated mesh will include a size field defined as:
mesh size = h * max(s_g, (d/h)^α)where d is the distance away from the styled entity, and s_g is the global mesh scale parameter specified in DeviceLayout.SolidModels.mesh_scale. A smaller value of h will give a finer mesh attached to the styled entity, and a larger value of α will give a more rapid increase in size away from the styled entity.
If α < 0, the size field will use DeviceLayout.SolidModels.mesh_grading_default used in rendering.
DeviceLayout.NoRender — Type
NoRender <: GeometryEntityStyleStyle that marks an entity to be skipped when rendering.
NoRender-styled entities have zero-area bounds and footprint and empty halo.
DeviceLayout.OptionalStyle — Type
struct OptionalStyle <: GeometryEntityStyle
true_style::GeometryEntityStyle
false_style::GeometryEntityStyle
flag::Symbol
default::Bool
end
OptionalStyle(true_style::GeometryEntityStyle, flag::Symbol;
false_style::GeometryEntityStyle=Plain(), default::Bool=true)Style that depends on a Boolean rendering option flag with default default.
lowerleft, upperright, bounds, footprint, and halo are forwarded to the underlying entity styled with the default style.
Examples
sty = OptionalStyle(Rounded(1μm), :rounding)
p = Rectangle(4μm, 4μm)
rounded_rect = to_polygons(sty(p))
plain_rect = to_polygons(sty(p), rounding=false)DeviceLayout.optional_entity — Function
optional_entity(ent::GeometryEntity, flag::Symbol;
true_style::GeometryEntityStyle=Plain(), default=true)Return an entity to be rendered or not based on the rendering option flag.
Example
julia> c = Cell();
julia> ent = optional_entity(Rectangle(2, 2), :optional_entities; default=false);
julia> render!(c, ent);
julia> length(elements(c))
0
julia> render!(c, ent; optional_entities=true);
julia> length(elements(c))
1DeviceLayout.ToTolerance — Type
struct ToTolerance{T<:Coordinate} <: GeometryEntityStyle
atol::T
endStyle for rendering an entity to absolute tolerance atol.
Equivalent to passing or overriding the keyword atol when rendering this entity.
GeometryStructure
DeviceLayout.GeometryStructure — Type
abstract type GeometryStructure{S} <: AbstractGeometry{S}Supertype for structures that may contain entities and references to other structures.
Subtypes include DeviceLayout.AbstractCoordinateSystem and Path.
DeviceLayout.elements — Method
elements(s::GeometryStructure)Return a vector of GeometryEntity in the structure.
For a Cell, these are Polygons. For a CoordinateSystem, these can be any GeometryEntity.
DeviceLayout.elementtype — Method
elementtype(cs::GeometryStructure)Return the type of elements in the structure.
DeviceLayout.element_metadata — Method
element_metadata(s::GeometryStructure)Return a vector of metadata associated one-to-one with elements(s) in the structure.
DeviceLayout.flatten — Method
flatten(c::GeometryStructure; depth::Integer=-1, name=uniquename("flatten_"*name(c)))Return a new coordinate system with name name with recursively flattened references and arrays up to a hierarchical depth.
Flattening a CoordinateSystem or Cell produces a coordinate system of the same type (meaning these can also be flattened in-place with flatten!), while flattening other structures generally produces a CoordinateSystem with the same coordinate type.
Flattening adds the elements of references to the top-level structure with appropriate transformations, then discards those references. Deeper references and arrays are brought upwards and are not discarded.
This function has no effect on references for depth == 0, and unlimited depth by default.
Base.getindex — Method
getindex(c::GeometryStructure, nom::AbstractString, index::Integer=1)If c references a structure with name nom, this method will return the corresponding GeometryReference. If there are several references to that coordinate system, then index specifies which one is returned (in the order they are found in refs(c)). e.g. to specify an index of 2: myCS["myreferencedCS",2].
DeviceLayout.map_metadata — Function
function map_metadata(geom::GeometryStructure, map_meta)Create a copy of geom and change original metadata m to map_meta(m) for all elements.
Recursive on the copies of referenced structures.
DeviceLayout.map_metadata! — Function
function map_metadata!(geom::GeometryStructure, map_meta, [visited])For every element in geom with original meta m, set its metadata to map_meta(m).
Operates on all unique structures in the reference hierarchy exactly once, so that multiply-referenced structures are not mapped multiple times.
The visited argument is used internally to track structures already processed.
function map_metadata(comp::AbstractComponent, map_meta)For every element in geometry(comp) with original meta m, set its metadata to map_meta(m).
Recursive on referenced structures.
DeviceLayout.name — Method
name(s::GeometryStructure)Return a name String for s.
DeviceLayout.refs — Method
refs(s::GeometryStructure)Return a vector of references to sub-structures.
DeviceLayout.reset_uniquename! — Function
reset_uniquename!(counter=GLOBAL_NAME_COUNTER)Reset uniquename counters for all strings.
counter is the Dict{String,Int} that counts how many times each name has been seen. The default is the same default global counter used by uniquename.
reset_uniquename!(str::String, counter=GLOBAL_NAME_COUNTER)Reset uniquename counter for str.
counter is the Dict{String,Int} that counts how many times each name has been seen. The default is the same default global counter used by uniquename.
DeviceLayout.uniquename — Function
uniquename(str, dlm="\$"; modify_first=false, counter=GLOBAL_NAME_COUNTER, case_sensitive=true)Given string input str for the nth time, return str * dlm * string(n).
If str is already formatted as str0 * dlm * n, where n is an integer, then str0 will be used with the larger of n and the number of times str0 has been counted plus one.
If modify_first is false, then str will be returned the first time uniquename(str, dlm; modify_first=false) is called.
Useful if programmatically making Cells and all of them will eventually be saved into a GDSII file.
The uniqueness is expected on a per-Julia session basis or until reset_uniquename! is called, so if you load an existing GDSII file and try to save unique cells on top of that you may get an unlucky clash. Calling uniquename on all loaded Cell names will effectively "register" them, making subsequent uniquename calls aware of them.
If case_sensitive is false, counter keys are lowercased so that e.g. "Main" and "main" are treated as duplicates. The original case of str is preserved in the output.
Example
julia> reset_uniquename!();
julia> uniquename("name"; modify_first=true)
"name\$1"
julia> uniquename("name\$4")
"name\$4"
julia> uniquename("name\$3")
"name\$5"
julia> uniquename("name")
"name\$6"counter is the Dict{String,Int} that counts how many times each name has been seen. The default is a global counter that persists until the end of the Julia session or until reset_uniquename! is called.
GeometryReference
DeviceLayout.GeometryReference — Type
GeometryReference{S<:Coordinate, T<:GeometryStructure} <: AbstractGeometry{S}Abstract supertype for references to geometry structures.
Subtypes are StructureReference and ArrayReference.
DeviceLayout.StructureReference — Type
mutable struct StructureReference{S, T} <: GeometryReference{S, T}
structure::T
origin::Point{S}
xrefl::Bool
mag::Float64
rot::Float64
endReference to a structure positioned at origin, with optional x-reflection xrefl, magnification factor mag, and rotation angle rot. If an angle is given without units it is assumed to be in radians.
That is, the transformation applied by the reference is the composition of the following transformations, ordered with reflection applied first:
- If
xrefl(f)istrue, a reflection across thex-axis - Rotation by
rotation(f) - Magnification by
mag(f) - Translation by
origin(f)
The type variable T is to avoid circular definitions.
DeviceLayout.ArrayReference — Type
mutable struct ArrayReference{S,T} <: GeometryReference{S,T}
structure::T
origin::Point{S}
deltacol::Point{S}
deltarow::Point{S}
col::Int
row::Int
xrefl::Bool
mag::Float64
rot::Float64
endArray of structure starting at origin with row rows and col columns, spanned by vectors deltacol and deltarow. Optional x-reflection xrefl, magnification factor mag, and rotation angle rot for the array as a whole. If an angle is given without units it is assumed to be in radians.
The type variable T is to avoid circular definitions.
Base.getindex — Method
getindex(c::GeometryReference, nom::AbstractString, index::Integer=1)If the structure referenced by c references a structure with name nom, this method will return the corresponding GeometryReference. If there are several references to that structure, then index specifies which one is returned (in the order they are found in refs(structure(c))).
This method is typically used so that we can type the first line instead of the second line in the following:
myCS["myreferencedCS"]["onedeeper"]
myCS["myreferencedCS"].structure["onedeeper"]DeviceLayout.aref — Function
aref(x::GeometryStructure{S}, origin::Point{T}=zero(Point{S}); kwargs...) where
{S <: Coordinate, T <: Coordinate}Construct a ArrayReference{float(T),typeof(x)} object.
Keyword arguments specify the column vector, row vector, number of columns, number of rows, x-reflection, magnification factor, and rotation.
Synonyms are accepted for these keywords:
- Column vector
dc::Point{T}::deltacol,:dcol,:dc,:vcol,:colv,:colvec,:colvector,:columnv,:columnvec,:columnvector - Row vector:
:deltarow,:drow,:dr,:vrow,:rv,:rowvec,:rowvector - Number of columns:
:nc,:numcols,:numcol,:ncols,:ncol - Number of rows:
:nr,:numrows,:numrow,:nrows,:nrow - X-reflection:
:xrefl,:xreflection,:refl,:reflect,:xreflect,:xmirror,:mirror - Magnification:
:mag,:magnification,:magnify,:zoom,:scale - Rotation:
:rot,:rotation,:rotate,:angle
aref(x, c::AbstractRange, r::AbstractRange; kwargs...)Construct an ArrayReference based on ranges (probably LinSpace or FloatRange). c specifies column coordinates and r for the rows. Pairs from c and r specify the origins of the repeated cells. The extrema of the ranges therefore do not specify the extrema of the resulting ArrayReference's bounding box; some care is required.
Keyword arguments specify x-reflection, magnification factor, and rotation, with synonyms allowed:
- X-reflection:
:xrefl,:xreflection,:refl,:reflect,:xreflect,:xmirror,:mirror - Magnification:
:mag,:magnification,:magnify,:zoom,:scale - Rotation:
:rot,:rotation,:rotate,:angle
DeviceLayout.flatten — Method
flatten(c::GeometryReference; depth::Integer=-1, name=uniquename("flatten_"*name(structure(c))), metadata_filter=nothing)Return a new structure with name name with recursively flattened references and arrays up to a hierarchical depth.
Flattening adds the elements of references to the top-level coordinate system with appropriate transformations, then discards those references. Deeper references and arrays are brought upwards and are not discarded. If depth=0, a new coordinate system is returned containing only the reference.
metadata_filter can be a function that takes a DeviceLayout.Meta and returns a Bool, like a function returned by layer_inclusion. In that case, only elements whose metadata m have metadata_filter(m) == true will be retained while flattening. Elements of deeper references and arrays are not filtered.
The reference c remains unmodified.
DeviceLayout.flat_elements — Function
flat_elements(geom::Union{GeometryStructure,GeometryReference}, only_layers=[], ignore_layers=[])
flat_elements(geom_layer::Pair{<:Union{GeometryStructure,GeometryReference}})Return a list of GeometryEntity elements in flatten(cs), optionally filtering metadata.
only_layers and ignore_layers can be layer name Symbols, DeviceLayout.Meta, or collections of either. The metadata filtering function is produced using layer_inclusion(only_layers, ignore_layers). This means that the default empty only_layers is the same as listing all layers.
Using an argument pair geom => layer is equivalent to flat_elements(geom, layer).
DeviceLayout.layer_inclusion — Function
layer_inclusion(only_layers, ignore_layers)Return a function f(m::Meta) that returns a Bool based on inclusion/exclusion rules.
Both only_layers and ignore_layers are DeviceLayout.Meta, layer name Symbols, and/or collections of either.
If only_layers is empty, then only ignore_layers is used, and f(m) checks that neither m nor layer(m) is in ignore_layers. Otherwise, f(m) also checks that m or layer(m) is in only_layers.
DeviceLayout.sref — Function
sref(x::GeometryStructure{T}, origin=zero(Point{T}); kwargs...)Convenience constructor for StructureReference{float(T), typeof(x)}.
Synonyms are accepted for these keywords:
- X-reflection: `:xrefl`, `:xreflection`, `:refl`, `:reflect`, `:xreflect`,
`:xmirror`, `:mirror`
- Magnification: `:mag`, `:magnification`, `:magnify`, `:zoom`, `:scale`
- Rotation: `:rot`, `:rotation`, `:rotate`, `:angle`DeviceLayout.structure — Function
structure(ref::GeometryReference)The GeometryStructure that ref points to.
DeviceLayout.transformation — Method
transformation(c::GeometryReference)Return the angle-preserving transformation to be applied to the referenced structure.
DeviceLayout.transformation — Method
transformation(c::GeometryStructure, d::GeometryReference)Given a GeometryStructure c containing GeometryReference d in its tree of references, this function returns a Transformations.ScaledIsometry object that lets you translate from the coordinate system of d to the coordinate system of c.
If the same exact GeometryReference (as in ===, same address in memory) is included multiple times in the tree of references, then the resulting transform will be based on the first time it is encountered. The tree is traversed using a depth-first search (but checking all references of a structure before looking inside each reference).
Example: You want to translate (2.0,3.0) in the coordinate system of the referenced coordinate system d to the coordinate system of c:
julia> trans = transformation(c,d)
julia> trans(Point(2.0,3.0))DeviceLayout.transformation — Method
transformation(c::GeometryStructure, d::GeometryReference, e::GeometryReference, f::GeometryReference...)Given a geometry structure c containing GeometryReference last(f) in its tree of references, this function returns a Transformations.ScaledIsometry object that lets you translate from the coordinate system of last(f) to the coordinate system of c. This method is needed when you want to specify intermediate GeometryReferences explicitly.
For example, suppose for instance you have a hierarchy of coordinate systems, where coordinate system A references B1 and B2, which both reference C. Schematically, it might look like this:
a -- b1 -- c
\ /
\ b2 /Coordinate system C appears in two places inside coordinate system A, owing to the fact that it is referenced by both B1 and B2. If you need to get the coordinate system of C via B2, then you need to do transformation(coordinatesystemA, coordsysrefB2, coordsysrefC), rather than simply transform(coordinatesystemA, coordsysrefC), because the latter will just take the first path to C available, via B1.
DeviceLayout.Transformations.origin — Method
origin(ref::GeometryReference)The origin of the structure that ref points to, in ref's parent coordinate system.
Equivalently, the translation part of transformation(ref) (the transformation that ref would apply to structure(ref)).
DeviceLayout.Transformations.mag — Method
mag(ref::GeometryReference)The magnification (uniform scaling factor) applied by transformation(ref).
DeviceLayout.Transformations.rotation — Method
rotation(ref::GeometryReference; α0=0)The change in angle when applying transformation(ref) to a line originally at α0 CCW from the x-axis.
Equivalent to rotation(transformation(ref); α0=α0).
DeviceLayout.Transformations.xrefl — Method
xrefl(ref::GeometryReference)A Bool indicating whether transformation(ref) includes a reflection.
Transformations
CoordinateTransformations.compose — Function
compose(trans1, trans2)
trans1 ∘ trans2Take 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).
CoordinateTransformations.Translation — Type
Translation(v) <: AbstractAffineMap
Translation(dx, dy) # 2D
Translation(dx, dy, dz) # 3DConstruct the Translation transformation for translating Cartesian points by an offset v = (dx, dy, ...)
DeviceLayout.Transformations.Reflection — Function
Reflection(α; through_pt=nothing)
Reflection(vec::Point; through_pt=nothing)
Reflection(p1::Point, p2::Point)Construct a reflection across a line.
The line can be specified by two points p1, p2 or by a direction and point through_pt the line passes through. The direction can be a vector or an angle made with the positive x axis (units accepted; no units => radians), and the through_pt is the origin by default.
DeviceLayout.Transformations.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} with indices SOneTo(2):
1
-1DeviceLayout.Transformations.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} with indices SOneTo(2):
-1
1DeviceLayout.Transformations.Rotation — Function
Rotation(Θ; around_pt=nothing)Construct a rotation about the origin or around_pt. Units accepted (no units ⇒ radians).
DeviceLayout.Transformations.RotationPi — Function
RotationPi(Θ_over_pi=1; around_pt=nothing)Construct a rotation about the origin or around_pt, with rotation in units of pi (180°).
This may be useful if you know your rotation will be a multiple of 90° but not necessarily which one, since it can be slightly more precise than Rotation (as sincospi is to sincos).
DeviceLayout.Transformations.ScaledIsometry — Type
struct ScaledIsometry{T<:Union{Point, Nothing}} <: AbstractAffineMap
ScaledIsometry(origin=nothing, rotation=0°, xrefl=false, mag=1.0)A coordinate transformation that preserves angles.
The equivalent transformation of f::ScaledIsometry is the composition of the following transformations, ordered with reflection applied first:
- If
xrefl(f)istrue, a reflection across thex-axis - Rotation by
rotation(f) - Magnification by
mag(f) - Translation by
origin(f)
May be also be constructed as
ScaledIsometry(f::Transformation) = ScaledIsometry(origin(f), rotation(f), xrefl(f), mag(f))but a DomainError will be thrown if f is not a scaled isometry (does not preserve angles).
Transformation compositions (with compose or ∘) involving a ScaledIsometry will return a ScaledIsometry if the other transformation also preserves angles.
DeviceLayout.centered — Function
centered(ent::AbstractGeometry; on_pt=zero(Point{T}))Centers a copy of ent on on_pt, with promoted coordinates if necessary. This function will not throw an InexactError(), even if ent had integer coordinates.
DeviceLayout.magnify — Function
magnify(geom, mag)Returns a copy of geom magnified by a factor of mag.
The origin is the center of magnification.
DeviceLayout.reflect_across_line — Function
reflect_across_line(geom, dir; through_pt=nothing)
reflect_across_line(geom, p0, p1)Return a copy of geom reflected across a line.
The line is specified through two points p0 and p1 that it passes through, or by a direction dir (vector or angle made with the x-axis) and a point through_pt that it passes through.
DeviceLayout.reflect_across_xaxis — Function
reflect_across_xaxis(geom)Return a copy of geom reflected across the x-axis.
DeviceLayout.rotate — Function
rotate(ent, rot)Return a copy of geom rotated counterclockwise by rot around the origin.
Units are accepted (no units => radians).
DeviceLayout.rotate90 — Function
rotate90(geom, n)Return a copy of geom rotated counterclockwise by n 90° turns.
DeviceLayout.translate — Function
translate(geom, displacement)Return a copy of geom translated by displacement.
DeviceLayout.Transformations.isapprox_angle — Function
isapprox_angle(α1, α2; atol=1e-9)Test whether angles α1 and α2 are approximately equivalent.
Units may be used for one or both angles (no units => radians).
DeviceLayout.Transformations.isapprox_cardinal — Function
isapprox_cardinal(α; atol=1e-9)Test whether α is approximately a cardinal direction (0°, 90°, 180°, or 270°).
Units may be used. If α has no units, it is treated as an angle in radians.
DeviceLayout.Transformations.mag — Function
mag(f::Translation)Return the magnification (uniform scaling factor) for f, if it is well defined.
Throws a DomainError if f does not preserve angles ("scaling" depends on direction).
mag(ref::GeometryReference)The magnification (uniform scaling factor) applied by transformation(ref).
DeviceLayout.Transformations.origin — Function
origin(f::Transformation)Return the transformed origin if it is translated, or nothing otherwise.
It's necessary to return nothing rather than a zero(Point{T}) if there's no translation, because such transformations (e.g., LinearMaps) may not supply a coordinate type T.
origin(ref::GeometryReference)The origin of the structure that ref points to, in ref's parent coordinate system.
Equivalently, the translation part of transformation(ref) (the transformation that ref would apply to structure(ref)).
origin(sch::Schematic, node::ComponentNode)
origin(sch::Schematic, node_idx::Int)The origin of node in the global coordinate system of sch.
DeviceLayout.Transformations.preserves_angles — Function
preserves_angles(f::Transformation)Return true if f is angle-preserving (has equal-magnitude eigenvalues) and false otherwise.
Uses approximate equality to allow for floating point imprecision.
DeviceLayout.Transformations.rotated_direction — Function
rotated_direction(angle, trans)Return the new direction that angle maps to under the transformation trans.
DeviceLayout.Transformations.rotation — Function
rotation(f::Transformation; α0=0)Return the change in angle when applying f to a line originally at α0 CCW from the x-axis.
By default, α0 is taken to be 0, and the result is equivalent to the rotation when decomposing the linear part of f into reflection across the x-axis followed by rotation.
Units are accepted for α0 (no units => radians).
If f does not preserve angles, a DomainError is thrown.
rotation(ref::GeometryReference; α0=0)The change in angle when applying transformation(ref) to a line originally at α0 CCW from the x-axis.
Equivalent to rotation(transformation(ref); α0=α0).
DeviceLayout.Transformations.rounding_safe — Function
rounding_safe(precision, f::Transformation)true when applying f gives the same results before or after rounding to precision.
Specifically, if f preserves angles, translates by integer precision, scales by an integer multiplier, and rotates by a multiple of 90°, it is "rounding safe".
precision should either be an integer type like Int32 or unitful type like typeof(1nm).
DeviceLayout.Transformations.xrefl — Function
xrefl(f::Transformation)Return true if f applies a reflection (has negative determinant) and false otherwise.
xrefl(ref::GeometryReference)A Bool indicating whether transformation(ref) includes a reflection.
Alignment
DeviceLayout.Align.above — Function
above(source, target; offset=0, centered=false)Align a copy of source with its bounding box bottom aligned with the top of target's.
DeviceLayout.Align.below — Function
below(source, target; offset=0, centered=false)Align a copy of source with its bounding box top aligned with the bottom of target's.
DeviceLayout.Align.leftof — Function
leftof(source, target; offset=0, centered=false)Align a copy of source with its bounding box right side aligned on the left of target's.
DeviceLayout.Align.rightof — Function
rightof(source, target; offset=0, centered=false)Align a copy of source with its bounding box left side aligned on the right of target's.
DeviceLayout.Align.flushbottom — Function
flushbottom(source, target; offset=0, centered=false)Align a copy of source with its bounding box bottom flush with that of target.
DeviceLayout.Align.flushtop — Function
flushtop(source, target; offset=0, centered=false)Align a copy of source with its bounding box top flush with that of target.
DeviceLayout.Align.flushleft — Function
flushleft(source, target; offset=0, centered=false)Align a copy of source with its bounding box left side flush with that of target.
DeviceLayout.Align.flushright — Function
flushright(source, target; offset=0, centered=false)Align a copy of source with its bounding box right side flush with that of target.
DeviceLayout.Align.centered_on — Function
centered_on(source::AbstractGeometry, target::AbstractGeometry)Centers a copy of source centered on the center of target, promoting coordinates if necessary.
DeviceLayout.Align.aligned_to — Function
aligned_to(source::AbstractGeometry{T}, target::AbstractGeometry{S},
align_source::RectAlignRule, align_target::RectAlignRule;
offset=convert(S, zero(T))) where {T,S}Aligns a copy of source with its align_source aligned to align_target of target.
For alignment in only one coordinate, the other coordinate is left unchanged. An optional offset will further displace the result in the aligned coordinate. Coordinates will be promoted if necessary when centering.
align_source and align_target must match coordinates; that is, both must refer to the x coordinate (Align.LeftEdge, Align.RightEdge, or Align.XCenter) or both to the y coordinate (Align.TopEdge, Align.BottomEdge, or Align.YCenter).
Convenience functions (leftof, rightof, above, below, flushleft, flushright, flushtop, flushbottom) are also defined as wrappers around aligned_to with pre-specified AlignRules.
Examples
julia> Align.aligned_to(Rectangle(2, 2), Rectangle(4, 4), Align.LeftEdge(), Align.XCenter())
Rectangle{Float64}((2.0,0.0), (4.0,2.0))aligned_to(source::AbstractGeometry{T}, target::AbstractGeometry{S},
align_source::Tuple{XAlignRule, YAlignRule},
align_target::Tuple{XAlignRule, YAlignRule};
offset::Point = zero(Point{promote_type(S, T)})) where {T,S}Align a copy of source to target in x and y coordinates simultaneously.
Polygons
DeviceLayout.AbstractPolygon — Type
abstract type AbstractPolygon{T} <: GeometryEntity{T} endAnything you could call a polygon regardless of the underlying representation. Currently only Rectangle, Polygon, and ClippedPolygon 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.
DeviceLayout.Polygons.Polygon — Type
struct Polygon{T} <: AbstractPolygon{T}
p::Vector{Point{T}}
Polygon(x) = new(x)
Polygon(x::AbstractPolygon) = convert(Polygon{T}, x)
endPolygon defined by list of coordinates. The first point should not be repeated at the end (although this is true for the GDS format).
DeviceLayout.Polygons.Polygon — Method
Polygon{T}(parr::AbstractVector{Point{T}})Convenience constructor for a Polygon{T} object.
DeviceLayout.Polygons.Polygon — Method
Polygon(p0::Point, p1::Point, p2::Point, p3::Point...)Convenience constructor for a Polygon{T} object.
DeviceLayout.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
endA 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.
DeviceLayout.bounds — Function
bounds(r::Rectangle)No-op (just returns r).
bounds(geo::AbstractGeometry)
bounds(geo0::AbstractGeometry, geo1::AbstractGeometry, geo::AbstractGeometry...)
bounds(geos)Return the minimum bounding Rectangle for geo or a collection/iterator geos.
If geo is empty or has no extent, a rectangle with zero width and height is returned.
For a collection or a structure that may contain multiple entities and references to other structures, geometries with bounds having zero width and height are excluded from the calculation.
bounds(s::GeometryStructure{T}) where {T <: Coordinate}Return a Rectangle{T} bounding box around all objects in a structure or structures. Return a rectangle with zero width and height if the structures are empty.
bounds(ref::GeometryReference)Return a Rectangle bounding box around all objects in ref. The bounding box respects reflection, rotation, and magnification specified by ref.
bounds(sch::Schematic, node::ComponentNode)
bounds(sch::Schematic, node_idx::Int)The Rectangle bounding the component in node in the global coordinate system of sch.
DeviceLayout.Polygons.circle_polygon — Function
circle_polygon(r, Δθ=10°)Return a circular Polygon centered about the origin with radius r and angular step Δθ.
DeviceLayout.Polygons.gridpoints_in_polygon — Function
gridpoints_in_polygon(poly::AbstractArray{<:AbstractPolygon},
dx::Coordinate, dy::Coordinate; b=nothing)Return a BitArray for the gridpoints in b with true for gridpoints in poly.
Only grid points in the bounding box b will be considered; if b is nothing, then bounds(poly) is used. dx and dy are the distances between adjacent points on the rectangular grid. The grid points represented by the BitArray start from the lower left point p0 = (m*dx, n*dy) with m and n integers and p0 lying in b.
All polygons should have the same orientation (clockwise or counterclockwise). A mix (for example to represent "holes") may not give the desired behavior on polygon or hole edges.
gridpoints_in_polygon(poly::AbstractArray{<:AbstractPolygon},
grid_x::AbstractArray, grid_y::AbstractArray)Return a BitArray with true for points lying in some polygon in poly.
The BitArray values correspond to points (x, y) with x ∈ grid_x, y ∈ grid_y, starting from the lower left.
All polygons should have the same orientation (clockwise or counterclockwise). A mix (for example to represent "holes") may not give the desired behavior on polygon or hole edges.
DeviceLayout.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 orientations of polygons must be consistent, such that outer polygons share the same orientation, and any holes have the opposite orientation. Additionally, any holes should be contained within outer polygons; offsetting hole edges may create positive artifacts at corners.
The first argument should be an AbstractPolygon. The second argument is how much to offset the polygon. Keyword arguments include a join type:
Clipper.JoinTypeMiterClipper.JoinTypeRoundClipper.JoinTypeSquare
and also an end type:
Clipper.EndTypeClosedPolygonClipper.EndTypeClosedLineClipper.EndTypeOpenSquareClipper.EndTypeOpenRoundClipper.EndTypeOpenButt
DeviceLayout.Polygons.perimeter — Function
perimeter(poly::AbstractPolygon)The (Euclidean) perimeter of an AbstractPolygon.
perimeter(poly::ClippedPolygon)The (Euclidean) perimeter of the outermost contour of a ClippedPolygon
perimeter(poly::Ellipse)Approximate (Euclidean) perimeter of an Ellipse using Ramanujan's approximation formula https://arxiv.org/pdf/math/0506384.pdf
DeviceLayout.Polygons.points — Function
points(x::Polygon)Return the array of Point objects defining the polygon.
points{T}(x::Rectangle{T})Return the array of Point objects defining the rectangle.
points(x::ClippedPolygon)Return the array of Point objects that define the keyhole polygon.
points(x::Clipper.PolyNode)Return the array of Point objects that make up the contour of the PolyNode
DeviceLayout.Polygons.sweep_poly — Function
sweep_poly(poly::Polygon, displacement::Point)Return a Polygon corresponding to the boundary formed by poly swept by displacement.
This is the result you would get by painting with a brush shaped like poly and moving it along a line by displacement.
DeviceLayout.Polygons.unfold — Function
unfold(v::Vector{Point{T}}, direction; through_pt=nothing) where {T}
unfold(v::Vector{Point{T}}, p0, p1) where {T}Return a vector of twice the length of v, where the first half is v and the second half is v in reverse order and reflected about an axis.
This can be used to construct polygons that have a mirror symmetry. The symmetry axis can be defined in either of two ways: as a line with a given direction passing through point through_pt (defaults to origin), or by two points p0, p1. direction can be passed either as an angle or as a Point representing a vector.
As a trivial example, to draw a centered square:
uy = Point(0μm, 1μm) # could also be passed as 90°
pts = [Point(-1μm, -1μm), Point(-1μm, 1μm)]
square = Polygon(unfold(pts, uy))DeviceLayout.Polygons.Rounded — Type
struct Rounded{T <: Coordinate} <: GeometryEntityStyle
abs_r::T = zero(T)
rel_r::Float64 = 0.0
min_side_len::T = r
min_angle::Float64 = 1e-3
p0::Vector{Point{T}} = []
inverse_selection::Bool = false
endRounded polygon style defined by either radius absolute radius abs_r or relative radius rel_r. Only one of abs_r or rel_r can be non-zero at once. Can't handle shapes with interior cuts, or shapes with too sharp of angles relative to segment length. If rel_r is non-zero the radius of curvature at each vertex is calculated with rel_r * min(l₁, l₂) where l₁ and l₂ denote the length of the two attached line segments.
Example usage:
r = Rectangle(10μm, 10μm)
rsty = Rounded(1μm)
# Create a rounded rectangle StyledEntity with different options for syntax
rounded_rect = rsty(r)
rounded_rect = styled(r, rsty)
rounded_rect = Rounded(r, 1μm)
# Turn the result into a plain Polygon
rounded_rect_discretized_poly = to_polygons(rounded_rect)Keyword arguments
min_side_len: The minimum side length that will get rounded (e.g. for 90-degree angles, it makes sense to havemin_side_len = 2 * rounding_radius). This currently uses exact comparison, so it may result in very short straight edges or failure to round a corner due to floating point imprecision.min_angle: If adjacent sides are collinear within the tolerance set bymin_angle, rounding will not be performed.p0: set of target points used to select vertices to attempt to round when applied to a polygon. Selected vertices wheremin_side_lenandmin_angleare satisfied will be rounded. If empty, all vertices will be selected. Otherwise, for each point inp0, the nearest point that satisfiesselection_tolerancein the styled polygon will be selected. Note that for aClippedPolygon, the samep0will be used for every contour; for different rounding styles on different contours, useStyleDict.inverse_selection: If true, the selection fromp0is inverted; that is, all corners will be rounded except those selected byp0.selection_tolerance: Selections usingp0will only be chosen if they are withinselection_tolerancedistance ofp0. The current default of infinite reflects the legacy behaviour of always finding the closest point, and will be replaced with a small non-zero tolerance to capture floating point precision in future (approximately 1.0nm).
Polygon clipping
DeviceLayout.Polygons.ClippedPolygon — Type
struct ClippedPolygon{T} <: AbstractPolygon{T}
tree::Clipper.PolyNode{Point{T}}
endCollection of polygons defined by a call to Clipper.
DeviceLayout.Polygons.difference2d — Function
difference2d(p1, p2)Return the geometric union of p1 minus the geometric union of p2 as a ClippedPolygon.
Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.
Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.
Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be used.
DeviceLayout.Polygons.intersect2d — Function
intersect2d(p1, p2)Return the geometric union of p1 intersected with the geometric union of p2 as a ClippedPolygon.
Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.
Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.
Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be used.
DeviceLayout.Polygons.union2d — Function
union2d(p1, p2)Return the geometric union of p1 and p2 as a ClippedPolygon.
Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.
Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.
Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will used.
This is not implemented as a method of union because you can have a set union of arrays of polygons, which is a distinct operation.
The Clipper polyfill rule is PolyFillTypePositive, meaning as long as a region lies within more non-hole (by orientation) than hole polygons, it lies in the union.
union2d(p)Return the geometric union of p or all entities in p.
DeviceLayout.Polygons.xor2d — Function
xor2d(p1, p2)Return the symmetric difference (XOR) of p1 and p2 as a ClippedPolygon.
The XOR operation returns regions that are in either p1 or p2, but not in both. This is useful for finding non-overlapping regions between two sets of polygons.
Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.
Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.
Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be used.
DeviceLayout.Polygons.clip — Function
clip(op::Clipper.ClipType, s, c; kwargs...) where {S<:Coordinate, T<:Coordinate}
clip(op::Clipper.ClipType, s::AbstractVector{A}, c::AbstractVector{B};
kwargs...) where {S, T, A<:Polygon{S}, B<:Polygon{T}}
clip(op::Clipper.ClipType,
s::AbstractVector{Polygon{T}}, c::AbstractVector{Polygon{T}};
pfs::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd,
pfc::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd) where {T}Return the ClippedPolygon resulting from a polygon clipping operation.
Uses the Clipper library and the Clipper.jl wrapper to perform polygon clipping.
Positional arguments
The first argument must be one of the following types to specify a clipping operation:
Clipper.ClipTypeDifferenceClipper.ClipTypeIntersectionClipper.ClipTypeUnionClipper.ClipTypeXor
Note that these are types; you should not follow them with ().
The second and third argument may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons. Each can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons. Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be taken from the flattened structure.
Keyword arguments
pfs and pfc specify polygon fill rules for the s and c arguments, respectively. These arguments may include:
Clipper.PolyFillTypeNegativeClipper.PolyFillTypePositiveClipper.PolyFillTypeEvenOddClipper.PolyFillTypeNonZero
See the Clipper docs for further information.
See also union2d, difference2d, and intersect2d.
DeviceLayout.Polygons.StyleDict — Type
struct StyleDict{S} <: GeometryEntityStyle where {S}
styles::Dict{Vector{Int}, GeometryEntityStyle},
default::S
endStyle used for applying differing styles to different Polygons at different levels within a ClippedPolygon or CurvilinearRegion. Styles are stored by the sequence of child indices required to find the corresponding Clipper.PolyNode within the ClippedPolygon. For a CurvilinearRegion only dictionaries of depth 2 (a single parent and one set of holes) are valid.
Shapes
DeviceLayout.Polygons.Circle — Function
Circle(center::Point{T}, r::T)Construct an Ellipse with major and minor radii equal to r at center.
DeviceLayout.Polygons.Ellipse — Type
struct Ellipse{T} <: GeometryEntity{T}
center::Point{T}
radii::NTuple{2, T}
angle::typeof(1.0°)
Ellipse{T}(c, r, a) where {T} = new{T}(c, r[1] < r[2] ? (r[2], r[1]) : r, a)
end
Ellipse(center::Point{T}, radii, angle) where {T} = Ellipse{T}(center, radii, angle)
Ellipse(center::Point{T}; r::T) where {T} = Ellipse{T}(center, (r, r), 0.0°)Represent an ellipse with a centroid, radii and major axis angle. The major axis radius is stored first within radii, and the axis angle is defined from the x-axis.
See Shapes.
Coordinate Systems
DeviceLayout.AbstractCoordinateSystem — Type
AbstractCoordinateSystem{S<:Coordinate} <: GeometryStructure{S}Abstract supertype for coordinate systems, including CoordinateSystem and Cell.
Also exists to avoid circular definitions involving the concrete AbstractCoordinateSystem types and subtypes of GeometryReference.
DeviceLayout.CoordinateSystems.CoordinateSystem — Type
mutable struct CoordinateSystem{S<:Coordinate} <: AbstractCoordinateSystem{S}
name::String
elements::Vector{GeometryEntity{S}}
meta::Vector{Meta}
refs::Vector{GeometryReference}
create::DateTime
CoordinateSystem{S}(x, y, ym, z, t) where {S} = new{S}(x, y, ym, z, t)
CoordinateSystem{S}(x, y, ym, z) where {S} = new{S}(x, y, ym, z, now())
CoordinateSystem{S}(x, y, ym) where {S} = new{S}(x, y, ym, GeometryReference[], now())
CoordinateSystem{S}(x) where {S} =
new{S}(x, GeometryEntity{S}[], Meta[], GeometryReference[], now())
CoordinateSystem{S}() where {S} = begin
c = new{S}()
c.elements = GeometryEntity{S}[]
c.meta = Meta[]
c.refs = GeometryReference[]
c.create = now()
c
end
endA CoordinateSystem has a name and contains geometry entities (Polygons, Rectangles) and references to GeometryStructure objects. It also records the time of its own creation.
To add elements, use place!, or use render! to be agnostic between CoordinateSystem and Cell. To add references, use addref! or addarr!.
DeviceLayout.CoordinateSystems.CoordinateSystemReference — Type
const CoordinateSystemReferenceAlias for StructureReferences to CoordinateSystems.
DeviceLayout.CoordinateSystems.CoordinateSystemArray — Type
const CoordinateSystemArrayAlias for ArrayReferences to CoordinateSystems.
DeviceLayout.SemanticMeta — Type
struct SemanticMeta <: DeviceLayout.Meta
layer::Symbol
index::Int = 1
level::Int = 1
end
SemanticMeta(layer::String; kwargs...)
SemanticMeta(meta::Meta; kwargs...)DeviceLayout-native representation of an object's layer information and attributes.
Semantic metadata refers to the meaning of an element without reference to a fixed encoding. For example, "this polygon is in the negative of the ground plane" is semantic, while "this polygon is in GDS layer 1, datatype 2" is not. The semantic metadata is used in the final render step, where a layout is converted from a CoordinateSystem to a representation corresponding to a particular output format (e.g., a Cell for GDSII). A call to render!(cell::Cell{S}, cs::CoordinateSystem; map_meta = default_meta_map, kwargs...) will use the map_meta function to map each GeometryEntity's metadata to GDSMeta.
By default, DeviceLayout.default_meta_map is used, which:
- Passes GDSMeta through unchanged
- Converts other metadata types to GDSMeta using a hash-based layer assignment (0-255)
The level and index fields do not have a strict interpretation imposed by DeviceLayout. (In this sense they are similar to GDS datatype.) The suggested use is as follows:
indexdistinguishes numbered instances within a layer, for example in greyscale lithography or port numberingleveldistinguishes instances of a layer occurring in different contexts, such as in a 3D stack where equivalent layers may be present in multiple levels
DeviceLayout.CoordinateSystems.addref! — Function
addref!(c1::AbstractCoordinateSystem, cr::GeometryReference)Add the reference cr to the list of references in c1.
addref!(c1::AbstractCoordinateSystem{T},
c2::GeometryStructure,
origin=zero(Point{T});
kwargs...)Add a reference to c2 to the list of references in c1.
The reference to c2 has origin origin; x-reflection, magnification factor, and rotation are set by keywords arguments.
Synonyms are accepted for these keywords:
- X-reflection:
:xrefl,:xreflection,:refl,:reflect,:xreflect,:xmirror,:mirror - Magnification:
:mag,:magnification,:magnify,:zoom,:scale - Rotation:
:rot,:rotation,:rotate,:angle
DeviceLayout.CoordinateSystems.addarr! — Function
addarr!(
c1::AbstractCoordinateSystem{T},
c2::GeometryStructure,
origin::Point=zero(Point{T});
kwargs...
)Add an ArrayReference to c2 to the list of references in c1.
The reference to c2 has origin origin. Keyword arguments specify the column vector, row vector, number of columns, number of rows, x-reflection, magnification factor, and rotation.
Synonyms are accepted for these keywords:
- Column vector
dc::Point{T}::deltacol,:dcol,:dc,:vcol,:colv,:colvec,:colvector,:columnv,:columnvec,:columnvector - Row vector:
:deltarow,:drow,:dr,:vrow,:rv,:rowvec,:rowvector - Number of columns:
:nc,:numcols,:numcol,:ncols,:ncol - Number of rows:
:nr,:numrows,:numrow,:nrows,:nrow - X-reflection:
:xrefl,:xreflection,:refl,:reflect,:xreflect,:xmirror,:mirror - Magnification:
:mag,:magnification,:magnify,:zoom,:scale - Rotation:
:rot,:rotation,:rotate,:angle
addarr!(
c1::AbstractCoordinateSystem,
c2::GeometryStructure,
c::AbstractRange,
r::AbstractRange;
kwargs...
)Add an ArrayReference to c2 to the list of references in c1, based on ranges.
c specifies column coordinates and r for the rows. Pairs from c and r specify the origins of the repeated cells. The extrema of the ranges therefore do not specify the extrema of the resulting ArrayReference's bounding box; some care is required.
Keyword arguments specify x-reflection, magnification factor, and rotation, with synonyms allowed:
- X-reflection:
:xrefl,:xreflection,:refl,:reflect,:xreflect,:xmirror,:mirror - Magnification:
:mag,:magnification,:magnify,:zoom,:scale - Rotation:
:rot,:rotation,:rotate,:angle
DeviceLayout.default_meta_map — Function
default_meta_map(meta::Meta) -> GDSMetaDefault metadata mapping function for rendering to Cell.
This map is for convenient graphical display and should not be relied on in production workflows.
GDSMeta passes through unchanged.
Other Meta types are converted to GDSMeta using a layer in (0-255) based on the hash of (layer(m), level(m)) and datatype layerindex(m)-1 (clamped to 0-255). This means that other metadata types are not guaranteed to be mapped to unique GDSMeta.
Examples
julia> default_meta_map(GDSMeta(10, 2))
GDSMeta(10, 2)
julia> default_meta_map(SemanticMeta(:metal))
GDSMeta(63, 0) # Hash-based layer, datatype from index
julia> default_meta_map(SemanticMeta(:metal, index=5))
GDSMeta(63, 4) # Same layer, different datatypeDeviceLayout.CoordinateSystems.flatten! — Method
flatten!(c::AbstractCoordinateSystem, depth::Integer=-1, metadata_filter=nothing, max_copy=Inf)Recursively flatten references and arrays up to a hierarchical depth, adding their elements to c with appropriate transformations.
The references and arrays that were flattened are then discarded. Deeper references and arrays are brought upwards and are not discarded.
This function has no effect for depth == 0, and unlimited depth by default.
DeviceLayout.Cells.gdslayers — Method
gdslayers(x::GeometryStructure)Returns the unique GDS layers of elements in x, using DeviceLayout.default_meta_map. Does not return the layers in referenced structures.
DeviceLayout.layer — Function
layer(m::Meta)The layer specified by m, as a Symbol.
For example, layer(GDSMeta(1, 2)) is :GDS1_2, and layername(SemanticMeta(:base)) is :base.
DeviceLayout.layerindex — Function
layerindex(m::Meta)The index specified by metadata m. Defaults to 1 for metadata types without an index.
DeviceLayout.layername — Function
layername(m::Meta)The layer specified by m, as a String.
For example, layer(GDSMeta(1, 2)) is "GDS1_2", and layername(SemanticMeta(:base)) is "base".
DeviceLayout.level — Function
level(m::Meta)The level specified by metadata s. Defaults to 1 for metadata types without a level.
DeviceLayout.CoordinateSystems.place! — Function
place!(cs::CoordinateSystem, ent::GeometryEntity, metadata)Place ent in cs with metadata metadata.
place!(cs::CoordinateSystem, s::GeometryStructure)Place a reference to s in cs.
place!(cs::CoordinateSystem, p::Path, metadata=p.metadata)Place a reference to p in cs and set metadata to metadata.
Cells
DeviceLayout.Cells.Cell — Type
mutable struct Cell{S<:Coordinate}A cell has a name and contains polygons and references to CellArray or CellReference objects. It also records the time of its own creation. As currently implemented it mirrors the notion of cells in GDSII files.
To add elements, use render!. To add references, use addref! or addarr!. To add text, use text!.
DeviceLayout.Cells.Cell — Method
Cell(name::AbstractString)Convenience constructor for Cell{typeof(1.0UPREFERRED)}.
DeviceLayout.UPREFERRED is a constant set according to the unit preference in Project.toml or LocalPreferences.toml. The default ("PreferNanometers") gives const UPREFERRED = DeviceLayout.nm, with mixed-unit operations preferring conversion to nm.
Unit preference does not affect the database scale for GDS export.
DeviceLayout.Cells.Cell — Method
Cell(cs::CoordinateSystem{S}) = Cell{S}(cs)
Cell(cs::CoordinateSystem, unit::CoordinateUnits) = Cell{typeof(1.0unit)}(cs)
Cell{S}(cs::CoordinateSystem) where {S}Construct a Cell from a CoordinateSystem by rendering its contents, reproducing the reference hierarchy.
DeviceLayout.Cells.dbscale — Method
dbscale(c::Cell)Give the database scale for a cell. The database scale is the smallest increment of length that will be represented in the output CAD file. This is different from the working coordinate type T of the Cell.
The database scale defaults to 1nm (1.0nm if T <: FloatCoordinate), but can be changed by updating c.dbscale to a new Unitful.Length quantity.
DeviceLayout.Cells.dbscale — Method
dbscale(cell::Cell...)Choose an appropriate database scale for a GDSII file given Cells of different types. The smallest database scale of all cells considered is returned.
DeviceLayout.Cells.CellArray — Type
const CellArrayAlias for ArrayReferences to Cells.
DeviceLayout.Cells.CellReference — Type
const CellReferenceAlias for StructureReferences to Cells.
DeviceLayout.GDSMeta — Type
struct GDSMeta <: DeviceLayout.Meta
layer::Int
datatype::Int
GDSMeta() = new(DEFAULT_LAYER, DEFAULT_DATATYPE)
GDSMeta(l) = new(l, DEFAULT_DATATYPE)
GDSMeta(l, d) = new(l, d)
endMetadata associated with GDSII format. Default layer and datatype are 0.
DeviceLayout.GDS.GDSWriterOptions — Type
@kwdef struct GDSWriterOptionsOptions controlling warnings and validation during GDS file writing.
Fields
max_layer::Int = 32767: Maximum layer number that will not throw a warning.max_datatype::Int = 32767: Maximum datatype number that will not throw a warning.warn_invalid_names::Bool = true: Whether to warn about cell/text names that violate the GDSII spec (must be ≤32 chars, only A-Z, a-z, 0-9, '_', '?', '$').rename_duplicates::Bool = false: Iftrue, automatically rename duplicate cell names during GDS save usinguniquenamewith a save-scoped counter. Renaming is case-insensitive (GDS readers like KLayout treat cell names case-insensitively). The originalCellobjects are not mutated; renamed names are only written to the file. New names may exceed the GDSII spec's 32 character limit.
Warnings for layer number and datatype are configurable because different tools may have different limits. In the GDSII specification, layer and datatype must be in the range 0 to 63, but modern tools are rarely so strict. The hard limit is that the layer and datatype records are each two bytes. In the specification, they are two-byte signed integers, and for tools that conform in that regard, the maximum value is 32767. For that reason, larger values will cause a warning to be shown by default. However, a common extension of the format interprets these records as unsigned integers, allowing values up to 65535.
Examples
# Default: modern limits, name warnings enabled
opts = GDSWriterOptions()
# Strict GDSII spec compliance
opts = GDSWriterOptions(max_layer=63, max_datatype=63)
# No warnings at all
opts = GDSWriterOptions(
max_layer=typemax(UInt16),
max_datatype=typemax(UInt16),
warn_invalid_names=false
)
# Auto-rename duplicate cell names on save
opts = GDSWriterOptions(rename_duplicates=true)DeviceLayout.Cells.gdslayers — Method
gdslayers(x::Cell)Returns the unique GDS layers of elements in cell x. Does not return the layers in referenced or arrayed cells.
DeviceLayout.render! — Method
render!(c::Cell, p::Polygon, meta::GDSMeta=GDSMeta())Render a polygon p to cell c, defaulting to plain styling. If p has more than 8190 (set by DeviceLayout's GDS_POLYGON_MAX constant), then it is partitioned into smaller polygons which are then rendered. Environment variable ENV["GDS_POLYGON_MAX"] will override this constant. The partitioning algorithm implements guillotine cutting, that goes through at least one existing vertex and in manhattan directions. Cuts are selected by ad hoc optimization for "nice" partitions.
DeviceLayout.render! — Method
render!(cell::Cell{S}, cs::GeometryStructure;
memoized_cells=Dict{GeometryStructure, Cell}(),
map_meta = default_meta_map,
kwargs...) where {S}Render a geometry structure (e.g., CoordinateSystem) to a cell.
Passes each element and its metadata (mapped by map_meta if a method is supplied) to render!(::Cell, element, ::Meta), traversing the references such that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places.
Rendering a GeometryStructure to a Cell uses the optional keyword arguments
map_meta, a function that takes aMetaobject and returns aGDSMetaobject (ornothing, in which case rendering is skipped). Defaults toDeviceLayout.default_meta_map, which passesGDSMetathrough unchanged. Other metadata types will be converted using hash-based layer assignment, but this conversion is provided for quick GDS viewing and should not be relied on in production workflows.memoized_cells, a dictionary used internally to make sure that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places. Calling this function with non-empty dictionarymemoized_cells = Dict{GeometryStructure, Cell}(geom => prerendered_cell)is effectively a manual override that forcesgeom(which may becsor any structure in its reference hierarchy) to render asprerendered_cell.
Additional keyword arguments are passed to to_polygons for each entity and may be used for certain entity types to control how they are converted to polygons.
DeviceLayout.save — Method
save(::Union{AbstractString,IO}, cell0::Cell{T}, cell::Cell...)
save(f::File{format"GDS"}, cell0::Cell, cell::Cell...;
name="GDSIILIB", userunit=1μm, modify=now(), acc=now(),
options=GDSWriterOptions(), spec_warnings=nothing, verbose=false)This bottom method is implicitly called when you use the convenient syntax of the top method: save("/path/to/my.gds", cells_i_want_to_save...)
Keyword arguments include:
name: used for the internal library name of the GDSII file and probably inconsequential for modern workflows.userunit: sets what 1.0 corresponds to when viewing this file in graphical GDS editors with inferior unit support.modify: date of last modification.acc: date of last accession. It would be unusual to have this differ fromnow().options: aGDSWriterOptionscontrolling validation ofCellnames and warnings for maximum layer/datatype numbers.spec_warnings: iffalse, disables all warnings for max layer/datatype and invalid namesverbose: monitor the output oftraverse!andorder!to see if something funny is happening while saving.
DeviceLayout.load — Method
load(f::File{format"GDS"}; verbose::Bool=false, nounits::Bool=false)A dictionary of top-level cells (Cell objects) found in the GDSII file is returned. The dictionary keys are the cell names. The other cells in the GDSII file are retained by CellReference or CellArray objects held by the top-level cells. Currently, cell references and arrays are not implemented.
The FileIO package recognizes files based on "magic bytes" at the start of the file. To permit any version of GDSII file to be read, we consider the magic bytes to be the GDS HEADER tag (0x0002), preceded by the number of bytes in total (0x0006) for the entire HEADER record. The last well-documented version of GDSII is v6.0.0, encoded as 0x0258 == 600. LayoutEditor appears to save a version 7 as 0x0007, which as far as I can tell is unofficial, and probably just permits more layers than 64, or extra characters in cell names, etc.
If the database scale is 1μm, 1nm, or 1pm, then the corresponding unit is used for the resulting imported cells. Otherwise, an "anonymous unit" is used that will display as u"2.4μm" if the database scale is 2.4μm, say.
Warnings are thrown if the GDSII file does not begin with a BGNLIB record following the HEADER record, but loading will proceed.
Property values and attributes (PROPVALUE and PROPATTR records) will be ignored.
Encountering an ENDLIB record will discard the remainder of the GDSII file without warning. If no ENDLIB record is present, a warning will be thrown.
The content of some records are currently discarded (mainly the more obscure GDSII record types, but also BGNLIB and LIBNAME).
If nounits is true, Cell{Float64} objects will be returned, where 1.0 corresponds to one micron.
DeviceLayout.CoordinateSystems.traverse! — Function
traverse!(a::AbstractArray, c::GeometryStructure, level=1)Given a coordinate system, recursively traverse its references for other coordinate systems and add to array a some tuples: (level, c). level corresponds to how deep the coordinate system was found, and c is the found coordinate system.
DeviceLayout.CoordinateSystems.order! — Function
order!(a::AbstractArray)Given an array of tuples like that coming out of traverse!, we sort by the level, strip the level out, and then retain unique entries. The aim of this function is to determine an optimal writing order when saving pattern data (although the GDSII spec does not require cells to be in a particular order, there may be performance ramifications).
For performance reasons, this function modifies a but what you want is the returned result array.
Texts
DeviceLayout.Texts.Text — Type
Text{S} <: GeometryEntity{S}Text element in a layout. Distinct from rendering text as polygons (PolyText).
Text rendering may be viewer or system dependent. Use PolyText for text with well-defined geometry.
Arguments:
text: the text string.origin: location of the text in parent coordinate system.width: character sizecan_scale: defaults tofalse, set totrueif the text size should not be affected by scaling of parent coordinate system.xalign: horizontal alignment of text with respect toorigin. Can be any instance of abstract typeAlign.XAlignRuleand defaults toLeftEdge().yalign: vertical alignment of text with respect toorigin. Can be any instance of abstract typeAlign.YAlignRuleand defaults toTopEdge().xrefl: Reflect across x-axis. Defaults tofalse.mag: Magnification factor.rot: Rotation in radians.
DeviceLayout.Cells.text! — Function
text!(c::Cell{S}, str::String, origin::Point=zero(Point{S}), meta::Meta=GDSMeta(); kwargs...) where {S}Annotate cell c with string str as a text element. See also polytext! for rendering strings as polygons.
text!(c::Cell, text::Texts.Text, meta)Annotate cell c with Texts.Text object.
PolyText
DeviceLayout.PolyText.DotMatrix — Type
DotMatrix(; pixelsize, pixelspacing=pixelsize,
rounding=zero(pixelsize), meta::Meta=GDSMeta(0,0))Keyword args
pixelsize: dimension for the width/height of each pixel.pixelspacing: dimension for the spacing between adjacent pixels. Should be ≥ pixelsize. Defaults topixelsize.rounding: rounding radius for sharp corners of pixels. Ifpixelsize == pixelspacing, individual pixels are not rounded, but rather the pixels are unioned and the entire letter will be rounded.meta: layer/datatype or similar info.
DeviceLayout.PolyText.PolyTextComic — Type
PolyTextComic(charwidth, meta)PolyText style derived from the Comic Neue Regular font (Open Font License).
DeviceLayout.PolyText.PolyTextSansMono — Type
PolyTextSansMono(charwidth, meta)PolyText style derived from the Noto Sans Mono Regular font (Open Font License).
DeviceLayout.PolyText.polytext — Function
polytext(str::String, sty::PolyText.Style;
scripting=false, linelimit=typemax(Int), verbose=false) where {T}Renders the string str to a new coordinate system in a given style.
Keyword args
scripting: boolean parameter for allocating special characters^,_,{, and}for superscripting and subscripting. Follows the same usage as LaTeX.linelimit: sets the maximum number of characters per line and continues on a new line ifstris longer thanlinelimit.verbose: prints out information about the character dictionary.
DeviceLayout.PolyText.polytext! — Function
polytext!(c::AbstractCoordinateSystem, str::String, sty::PolyText.Style;
scripting=false, linelimit=typemax(Int), verbose=false)Renders the string str to cell or coordinate system c in a given style.
Keyword args
scripting: boolean parameter for allocating special characters^,_,{, and}for superscripting and subscripting. Follows the same usage as LaTeX.linelimit: sets the maximum number of characters per line and continues on a new line ifstris longer thanlinelimit.verbose: prints out information about the character dictionary.
DeviceLayout.PolyText.characters_demo — Function
characters_demo(save_path = joinpath(homedir(),"Desktop","characters.gds"), flatten = false)Demo script for demonstrating the available characters in polytext! and the linelimit parameter in use. flatten can flatten the cells before saving (for SVG output).
DeviceLayout.PolyText.scripted_demo — Function
scripted_demo(save_path = joinpath(homedir(),"Desktop","scripted.gds"), flatten = false)Demo script for demonstrating the use of the scripting parameter in polytext!. flatten can flatten the cells before saving (for SVG output).
DeviceLayout.PolyText.referenced_characters_demo — Function
referenced_characters_demo(save_path = joinpath(homedir(),"Desktop","referenced_characters.gds");
verbose_override = false)Demo script for demonstrating the memory saving ability of keeping CellReferences for previously used characters in polytext!. Nothing is printed if verbose_override is true.
Rendering
DeviceLayout.render! — Function
render!(c::Cell, p::Polygon, meta::GDSMeta=GDSMeta())Render a polygon p to cell c, defaulting to plain styling. If p has more than 8190 (set by DeviceLayout's GDS_POLYGON_MAX constant), then it is partitioned into smaller polygons which are then rendered. Environment variable ENV["GDS_POLYGON_MAX"] will override this constant. The partitioning algorithm implements guillotine cutting, that goes through at least one existing vertex and in manhattan directions. Cuts are selected by ad hoc optimization for "nice" partitions.
render!(c::CoordinateSystem, ent, meta)Synonym for place!.
render!(cell::Cell{S}, cs::GeometryStructure;
memoized_cells=Dict{GeometryStructure, Cell}(),
map_meta = default_meta_map,
kwargs...) where {S}Render a geometry structure (e.g., CoordinateSystem) to a cell.
Passes each element and its metadata (mapped by map_meta if a method is supplied) to render!(::Cell, element, ::Meta), traversing the references such that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places.
Rendering a GeometryStructure to a Cell uses the optional keyword arguments
map_meta, a function that takes aMetaobject and returns aGDSMetaobject (ornothing, in which case rendering is skipped). Defaults toDeviceLayout.default_meta_map, which passesGDSMetathrough unchanged. Other metadata types will be converted using hash-based layer assignment, but this conversion is provided for quick GDS viewing and should not be relied on in production workflows.memoized_cells, a dictionary used internally to make sure that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places. Calling this function with non-empty dictionarymemoized_cells = Dict{GeometryStructure, Cell}(geom => prerendered_cell)is effectively a manual override that forcesgeom(which may becsor any structure in its reference hierarchy) to render asprerendered_cell.
Additional keyword arguments are passed to to_polygons for each entity and may be used for certain entity types to control how they are converted to polygons.
render!(sm::SolidModel, cs::AbstractCoordinateSystem{T}; map_meta=layer,
postrender_ops=[], zmap=(_) -> zero(T), gmsh_options = Dict(), skip_postrender = false, kwargs...) where {T}Render cs to sm.
Keywords
map_meta: Function (m::SemanticMeta) -> name ofPhysicalGroup(asStringorSymbol; may also returnnothingto skip renderingm)postrender_ops: Vector of Tuples(destination, op, args, op_kwargs...)specifying "postrendering" ofPhysicalGroups executed after entities have been rendered to tosm. Each operationopcreates a newPhysicalGroupdefined assm[destination] = op(sm, args...; op_kwargs...). That is,argsare the arguments toop(following the first argument, which is always the modelsmbeing rendered to). For most operations, these arguments include the names and dimensions of groups being operated on, andop_kwargsare the keyword arguments passed toop. For example,("base", difference_geom!, ("writeable_area", "base_negative"), :remove_object => true, :remove_tool => true)defines a postrendering step that subtracts thePhysicalGroupnamed"base_negative"from"writeable_area"(by default using dimension 2 for each group) to define a new group called"base". The keyword pairs:remove_object=>trueand:remove_tool=>truemean that the "object" (first argument) group"writeable_area"and the "tool" (second argument) group"base_negative"are both removed when"base"is created.retained_physical_groups: Vector of(name, dimension)tuples specifying which physical groups to keep after rendering. All other groups are removed.zmap: Function (m::SemanticMeta) ->zcoordinate of corresponding elements. Default: Map all metadata to zero.gmsh_options: Dictionary of gmsh option name-value pairs to set before meshing.meshing_parameters: Deprecated. Use individual mesh control functionsDeviceLayout.SolidModels.mesh_scale,DeviceLayout.SolidModels.mesh_orderandDeviceLayout.SolidModels.mesh_grading_default, along withgmsh_optionsinstead.skip_postrender: Whether or not to return early without performing any postrendering operations. This can be particularly helpful during debugging, as all two dimensional entities will be placed appropriately but will not have been combined.
Available postrendering operations include translate!, extrude_z!, revolve!, union_geom!, intersect_geom!, difference_geom!, fragment_geom!, and box_selection. (The geometric Boolean operations are only available for models using the OpenCASCADE kernel.)
Additional keyword arguments are passed to DeviceLayout.SolidModels.to_primitives (which falls back to to_polygons) and may be used for certain entity types to control how entities of cs are converted to primitives and added to sm.
render!(cs::AbstractCoordinateSystem, obj::GeometryEntity, meta::DeviceLayout.Meta,
target::LayoutTarget; kwargs...)Render obj to cs, with metadata mapped to layers and rendering options by target.
render!(cs::AbstractCoordinateSystem, cs2::GeometryStructure, target::LayoutTarget; kwargs...)Render cs2 to cs, with metadata mapped to layers and rendering options by target.
See LayoutTarget documentation for details.
render!(
cs::AbstractCoordinateSystem,
sch::Schematic,
target::LayoutTarget;
strict=:error,
kwargs...
)Render the schematic sch to cs using target's rendering options, without modifying sch.
Users must run check!(sch) before calling this method; otherwise, it will throw an error.
The strict keyword should be :error, :warn, or :no.
The strict=:error keyword option causes render! to throw an error if any errors were logged while building component geometries or while rendering geometries to cs. This is enabled by default, but can be disabled with strict=:no, in which case any component which was not successfully built will have an empty geometry, and any non-fatal rendering errors will be ignored as usual. Using strict=:no is recommended only for debugging purposes.
The strict=:warn keyword option causes render! to throw an error if any warnings were logged. This is disabled by default. Using strict=:warn is suggested for use in automated pipelines, where warnings may require human review.
render!(sm::SolidModel, sch::Schematic, target::Target; strict=:error, kwargs...)Render sch to sm, using rendering settings from target.
The strict keyword should be :error, :warn, or :no.
The strict=:error keyword option causes render! to throw an error if any errors were logged while building component geometries or while rendering geometries to cs. This is enabled by default, but can be disabled with strict=:no, in which case any component which was not successfully built will have an empty geometry, and any non-fatal rendering errors will be ignored as usual. Using strict=:no is recommended only for debugging purposes.
The strict=:warn keyword option causes render! to throw an error if any warnings were logged. This is disabled by default. Using strict=:warn is suggested for use in automated pipelines, where warnings may require human review.
Additional keyword arguments may be used for certain entity types for controlling how geometry entities are converted to primitives and added to sm.
DeviceLayout.adapted_grid — Function
adapted_grid(f, anchors;
max_recursions::Real = 7, max_change = 5°, rand_factor::Real = 0.05,
grid_step = 1.0μm)Computes a resampled grid given anchor points so that f.(grid) is sufficiently smooth. The method used is to create an initial grid around the anchor points and refine intervals. When an interval becomes "straight enough" it is no longer divided. Adapted from a contribution to PlotUtils.jl from Kristoffer Carlsson.
max_recursions: how many times each interval is allowed to be refined.max_change: specifies acceptable change between evaluations offon subsequent grid points, as estimated by the derivative times the distance between grid points. Typically,fis the angle of a path in the plane, so this is often an angle threshold. This condition is approximately valid in the end result, but may be weakly violated. This condition may be grossly violated ifmax_recursionsis too low.rand_factor: between anchor points,adapted_gridwill wiggle initial grid points a bit to prevent aliasing. The wiggling is sampled uniformly from the interval:[-rand_factor, rand_factor], times the distance between three grid points (e.g.i+1andi-1). A random number generator is given a fixed seed every timeadapted_gridis called, so the rendered results are deterministic.grid_step: Step size for initial grid points. If you set this to be larger than the maximum anchor point, then the lowest resolution consistent withmax_changeis used (unlessfhas some fast variations that the algorithm might miss).
DeviceLayout.discretize_curve — Function
discretize_curve(f, ddf, tolerance)Given a curve f and its second derivative ddf, discretize a curve into piecewise linear segments with an approximate absolute tolerance.
SolidModels
DeviceLayout.SolidModels.SolidModel — Type
struct SolidModel{T} where {T <: SolidModelKernel}
name::String
groups::NTuple{4,Dict{String,AbstractPhysicalGroup}}
end
SolidModel(name::String, kernel=OpenCascade; overwrite=false)A 3D geometry model.
Geometry rendering, boolean operations, and export are provided by the specified kernel.
Physical groups can be accessed by name using indexing with a String or Symbol and a dimension: mymodel["mygroup", 3] will return the PhysicalGroup with dimension 3 called mygroup.
Physical groups can also be assigned as mymodel["mygroup"] = dimtags, where dimtags is a list of NTuple{2, Int32} of entities identified by (dim, tag) in mymodel. If dimtags includes entities of multiple dimensions, then a group is created for each dimension.
If the constructor is called with overwrite=false (the default), then an error will be thrown if a model with the same name already exists. If overwrite=true, then any existing model with the same name will be deleted and a new model will be created.
A SolidModel can be saved to a file with FileIO.save(filename, sm). Supported filetypes for OpenCASCADE geometries are .brep and .stp. Meshes can be exported as .msh2 (compatible with Palace) or .msh (most recent Gmsh format) files. Other filetypes supported by gmsh.write() like .xao can be used with DeviceLayout.save.
DeviceLayout.SolidModels.SolidModelKernel — Type
abstract type SolidModelKernelSupertype for solid geometry kernels. Subtypes are OpenCascade and GmshNative.
Note that GmshNative does not support Boolean geometry operations.
DeviceLayout.SolidModels.attributes — Function
attributes(sm::SolidModel)Given a SolidModel construct a dictionary from physical group name to attribute number for use in specification of a configuration file for use with Palace.
DeviceLayout.SolidModels.to_primitives — Function
to_primitives(::SolidModel, ent::GeometryEntity; kwargs...)Return a GeometryEntity or a vector of entities equivalent to ent.
Called inside render! before adding entities to the SolidModel. Each resulting entity corresponds to a single entity in that SolidModel's geometry kernel.
If there is no special handling for ent in the kernel, then the result will be to_polygons(ent; kwargs...).
DeviceLayout.render! — Method
render!(sm::SolidModel, cs::AbstractCoordinateSystem{T}; map_meta=layer,
postrender_ops=[], zmap=(_) -> zero(T), gmsh_options = Dict(), skip_postrender = false, kwargs...) where {T}Render cs to sm.
Keywords
map_meta: Function (m::SemanticMeta) -> name ofPhysicalGroup(asStringorSymbol; may also returnnothingto skip renderingm)postrender_ops: Vector of Tuples(destination, op, args, op_kwargs...)specifying "postrendering" ofPhysicalGroups executed after entities have been rendered to tosm. Each operationopcreates a newPhysicalGroupdefined assm[destination] = op(sm, args...; op_kwargs...). That is,argsare the arguments toop(following the first argument, which is always the modelsmbeing rendered to). For most operations, these arguments include the names and dimensions of groups being operated on, andop_kwargsare the keyword arguments passed toop. For example,("base", difference_geom!, ("writeable_area", "base_negative"), :remove_object => true, :remove_tool => true)defines a postrendering step that subtracts thePhysicalGroupnamed"base_negative"from"writeable_area"(by default using dimension 2 for each group) to define a new group called"base". The keyword pairs:remove_object=>trueand:remove_tool=>truemean that the "object" (first argument) group"writeable_area"and the "tool" (second argument) group"base_negative"are both removed when"base"is created.retained_physical_groups: Vector of(name, dimension)tuples specifying which physical groups to keep after rendering. All other groups are removed.zmap: Function (m::SemanticMeta) ->zcoordinate of corresponding elements. Default: Map all metadata to zero.gmsh_options: Dictionary of gmsh option name-value pairs to set before meshing.meshing_parameters: Deprecated. Use individual mesh control functionsDeviceLayout.SolidModels.mesh_scale,DeviceLayout.SolidModels.mesh_orderandDeviceLayout.SolidModels.mesh_grading_default, along withgmsh_optionsinstead.skip_postrender: Whether or not to return early without performing any postrendering operations. This can be particularly helpful during debugging, as all two dimensional entities will be placed appropriately but will not have been combined.
Available postrendering operations include translate!, extrude_z!, revolve!, union_geom!, intersect_geom!, difference_geom!, fragment_geom!, and box_selection. (The geometric Boolean operations are only available for models using the OpenCASCADE kernel.)
Additional keyword arguments are passed to DeviceLayout.SolidModels.to_primitives (which falls back to to_polygons) and may be used for certain entity types to control how entities of cs are converted to primitives and added to sm.
DeviceLayout.save — Method
save(file::File, sm::SolidModel)
save(filename::String, sm::SolidModel)Save a SolidModel instance to a file or filename.
Using FileIO.save, supported filetypes using for OpenCASCADE geometries are .brep and .stp. Meshes can be exported as .msh2 (compatible with Palace) or .msh (most recent Gmsh format) files.
Using DeviceLayout.save, you can also choose any other extension supported by gmsh.write() like .xao.
Physical Groups
DeviceLayout.SolidModels.PhysicalGroup — Type
struct PhysicalGroup
name::String
model::SolidModel
dim::Int32
grouptag::Int32
endA named group of entities of dimension dim in a SolidModel.
DeviceLayout.SolidModels.dimtags — Function
dimtags(pg::AbstractPhysicalGroup)Return the (dimension, integer tag) tuples for SolidModel entities in pg.
DeviceLayout.SolidModels.entitytags — Function
entitytags(pg::AbstractPhysicalGroup)Return the integer tags for SolidModel entities in pg.
DeviceLayout.SolidModels.bounds3d — Function
bounds3d(group::AbstractPhysicalGroup; delta=0)
bounds3d(dimtags; delta=0)Return the rectangular prism defined bounding group or dimtags with an offset of delta.
Note that OpenCASCADE bounding boxes are not tight, and will typically extend beyond the exact bounding box by 1e-7μm at each face.
The result is returned as the tuple (xmin, ymin, zmin, xmax, ymax, zmax).
Postrendering
DeviceLayout.SolidModels.box_selection — Function
box_selection(x1, y1, z1, x2, y2, z2; dim=-1, delta=zero(x1))
box_selection(::SolidModel, x1, y1, z1, x2, y2, z2; dim=-1, delta=zero(x1))Get the model entities in the bounding box defined by the two points (xmin, ymin, zmin) and (xmax, ymax, zmax). If dim is >= 0, return only the entities of the specified dimension (e.g. points if dim == 0).
Return the selected entities as a vector of (dimension, entity_tag) Tuples.
DeviceLayout.SolidModels.difference_geom! — Function
difference_geom!(
object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
tag=-1,
remove_object=false,
remove_tool=false
)Create the geometric difference of the groups object and tool.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
The operator - can be used as a synonymous infix operator.
difference_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
tag=-1,
remove_object=false,
remove_tool=false)Create the geometric difference of groups with Symbol or String names object, tool in sm.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).
If the tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
If object is not a physical group in sm, will error and return an empty dimtag array. If tool is not a physical group in sm, will return dimtags of object.
difference_geom!(sm::SolidModel, object, tool, d1=2, d2=2; remove_tool=false,
remove_object=false, kwargs...)Create the geometric difference of groups object and tool which can be collections of Union{String, Symbol}.
DeviceLayout.SolidModels.extrude_z! — Function
extrude_z!(g::PhysicalGroup, dz; num_elements=[], heights=[], recombine=false)
extrude_z!(sm::SolidModel, groupname, dz, groupdim=2; num_elements=[], heights=[], recombine=false)Extrude the entities in g in the z direction by dz.
If the numElements vector is not empty, also extrude the mesh: the entries in numElements give the number of elements in each layer. If the height vector is not empty, it provides the (cumulative) height of the different layers, normalized to 1. If recombine is set, recombine the mesh in the layers.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
DeviceLayout.SolidModels.fragment_geom! — Function
fragment_geom!(
object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
tag=-1,
remove_object=false,
remove_tool=false
)Create the Boolean fragments (general fuse) of the groups object and tool, making all interfaces conformal.
When applied to entities of different dimensions, the lower dimensional entities will be automatically embedded in the higher dimensional entities if they are not on their boundary.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
fragment_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
tag=-1,
remove_object=false,
remove_tool=false)Create the Boolean fragments (general fuse) of groups with Symbol or String names object, tool in sm, making all interfaces conformal.
When applied to entities of different dimensions, the lower dimensional entities will be automatically embedded in the higher dimensional entities if they are not on their boundary.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).
If the tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
If only one of object or tool is a physical group in sm, will perform union of physical group with itself, if neither are present will return an empty array.
DeviceLayout.SolidModels.get_boundary — Function
get_boundary(group::AbstractPhysicalGroup; combined=true, oriented=true, recursive=false, direction="all", position="all")
get_boundary(sm::SolidModel, groupname, dim=2; combined=true, oriented=true, recursive=false, direction="all", position="all")Get the boundary of the model entities in group, given as a vector of (dim, tag) tuples.
Return the boundary of the individual entities (if combined is false) or the boundary of the combined geometrical shape formed by all input entities (if combined is true).
Return tags multiplied by the sign of the boundary entity if oriented is true.
Apply the boundary operator recursively down to dimension 0 (i.e. to points) if recursive is true.
If direction is specified, return only the boundaries perperdicular to the x, y, or z axis. If position is also specified, return only the boundaries at the min or max position along the specified direction.
DeviceLayout.SolidModels.intersect_geom! — Function
intersect_geom!(
object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
tag=-1,
remove_object=false,
remove_tool=false
)Create the geometric intersection (the common parts) of the groups object and tool.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
The operators * and ∩ can be used as synonymous infix operators.
intersect_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
tag=-1,
remove_object=false,
remove_tool=false)Create the geometric intersection (the common parts) of groups with Symbol or String names object, tool in sm.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).
If the tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
If tool or object are not physical groups in sm, will error and return an empty dimtag array.
DeviceLayout.SolidModels.remove_group! — Function
remove_group!(sm::SolidModel, group::Union{String, Symbol}, dim; recursive=true, remove_entities=true)
remove_group!(group::AbstractPhysicalGroup; recursive=true, remove_entities=true)Remove entities in group from the model, unless they are boundaries of higher-dimensional entities or part of another physical group.
If recursive is true, remove all entities on their boundaries, down to dimension zero (points).
Also removes the record of the (now-empty) physical group.
If remove_entities is false, only removes the record of the group from the model.
DeviceLayout.SolidModels.restrict_to_volume! — Function
restrict_to_volume(sm::SolidModel, volume)Checks if all surfaces and volumes are contained within sm[volume, 3], and if not performs an intersection operation replacing all entities and groups with their intersection with sm[volume, 3].
Embeds entities if they are on the boundary of higher-dimensional entities and removes duplicate entities.
Preserves the meaning of existing groups by assigning to them the (possibly new) entities corresponding to that group's intersection with the volume.
DeviceLayout.SolidModels.revolve! — Function
revolve!(g::PhysicalGroup, x, y, z, ax, ay, az, θ; num_elements=[], heights=[], recombine=false)
revolve!(sm::SolidModel, groupname, groupdim, x, y, z, ax, ay, az, θ; num_elements=[], heights=[], recombine=false)Extrude the entities in g using a rotation of θ radians around the axis of revolution through (x, y, z) in the direction (ax, ay, az).
If the numElements vector is not empty, also extrude the mesh: the entries in numElements give the number of elements in each layer. If the height vector is not empty, it provides the (cumulative) height of the different layers, normalized to 1. If recombine is set, recombine the mesh in the layers. When the mesh is extruded the angle should be strictly smaller than 2π.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
DeviceLayout.SolidModels.set_periodic! — Function
set_periodic!(group1::AbstractPhysicalGroup, group2::AbstractPhysicalGroup; dim=2)
set_periodic!(sm, group1, group2, d1=2, d2=2)Set the model entities in group1 and group2 to be periodic. Only supports d1 = d2 = 2 and surfaces in both groups need to be parallel and axis-aligned.
DeviceLayout.SolidModels.translate! — Function
translate!(group, dx, dy, dz; copy=true)
translate!(sm::SolidModel, groupname, dx, dy, dz, groupdim=2; copy=true)Translate the entities in physical group group by (dx, dy, dz).
If copy=true, then a copy of the entities in group are translated instead.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
DeviceLayout.SolidModels.union_geom! — Function
union_geom!(
object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
tag=-1,
remove_object=false,
remove_tool=false
)Create the geometric union (the fusion) of the groups object and tool.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
The operators + and ∪ can be used as synonymous infix operators.
union_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
tag=-1,
remove_object=false,
remove_tool=false)Create the geometric union of groups with Symbol or String names object, tool in sm.
Return the resulting entities as a vector of (dimension, entity_tag) Tuples.
The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).
If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.
If only one of object or tool is a physical group in sm, will perform union of physical group with itself, if neither are present will return an empty array.
DeviceLayout.SolidModels.staple_bridge_postrendering — Function
staple_bridge_postrendering(; levels=[], base, bridge, bridge_height=1μm, output="bridge_metal")Returns a vector of postrendering operations for creating air bridges from a base and bridge group. levels specifies the indices of levelwise layers to build bridges upon, for examples levels = [1,2] will attempt to form airbridges on the L1 and L2 layers. Representing air bridges as a metallic staple is a basic modeling simplification made for purposes of simulation. The support and bridge shapes are intersected to form a bridge platform which is then connected to the underlying surface with legs which run parallel to the path.
______
>| |< support
_____| |_____
> | |< bridge
> |_____ _____|
> | |
> |______|
> /> ||
> ||< pathOutputs a 2D physical group named output ("bridge_metal" by default) containing the rectangular bridge "legs" and "platform".
Meshing
DeviceLayout.SolidModels.MeshingParameters — Type
Base.@kwdef struct MeshingParameters
mesh_scale::Float64 = 1.0
mesh_order::Int = 1
α_default::Float64 = 0.75
apply_size_to_surfaces::Bool = false
high_order_optimize::Int = 1
surface_mesh_algorithm::Int = 6
volume_mesh_algorithm::Int = 1
options::Dict{String, Float64} = Dict{String, Float64}()
endα
This struct is deprecated. See render!
MeshingParameters contains high level parameters to specify mesh sizing fields throughout the domain.
mesh_scaleapplies multiplicatively to the smallest size specified by any size field function, comparing to the formula in theMeshSizedstyle, this results in all mesh size fields being rescaled whereh←mesh_scale*h.mesh_orderspecifies the order of polynomials to use in representing the geometry, this is important if curved geometric features are present,mesh_order == 1will represent the geometry with linear polynomials, whilstmesh_order == 2will represent it with quadratic polynomials, andmesh_order == 3with cubic polynomials. Increasing the value ofmesh_orderresults in greater geometric fidelity, whilst making meshing more difficult (and prone to errors).α_defaultspecifies the default value ofαto use forMeshSizedentities whereαis set to less than 0,α_default ∈ (0, 1]is particularly used for the default grading ofPathentities. A value closer to 1 can result in an unstable meshing algorithm in gmsh, particularly for complex geometries.apply_size_to_surfaces=truewill cause the mesh sizing field to specify the size within any sized entities, as opposed to only along the perimeter of the entity ifapply_size_to_surfaces=false. Settingapply_size_to_surfaces=truewill result in a larger number of elements.high_order_optimize=0flag to pass to gmsh if optimization of a higher order mesh is to be performed. (0: none, 1: optimization, 2: elastic+optimization, 3: elastic, 4: fast curving). Refer to the gmsh documentation for more details.surface_mesh_algorithmspecifies the algorithm gmsh should use when performing the surface mesh generation. Refer to the gmsh documentation for more details.volume_mesh_algorithmspecifies the algorithm gmsh should use when performing the volume mesh generation. Refer to the gmsh documentation for more details.optionsused to specify any additional options provided to gmsh, which will be set withgmsh.options.set_number(key, value)for eachkey => valuepair. Refer to the gmsh documentation for a list of available options. Will override any other options as is called last.
DeviceLayout.SolidModels.mesh_order — Function
mesh_order()
mesh_order(order, higher_order_optimize=1)Get or set the mesh element order and optimization level.
Higher order elements provide better geometric fidelity for curved boundaries but increase meshing complexity.
DeviceLayout.SolidModels.mesh_scale — Function
mesh_scale()
mesh_scale(s)Get or set the global mesh scaling factor.
The mesh scale adjusts the minimum for all size fields, from h adjacent to a sized entity, to mesh_scale * h. It does not reduce the size in the far field, and is most appropriate for refining geometric features such as curves, which might require additional local refinement to capture the geometry, but do not require refinement non-locally.
See DeviceLayout.MeshSized for more details and the explicit mesh sizing formula.
DeviceLayout.SolidModels.mesh_grading_default — Function
mesh_grading_default()
mesh_grading_default(α)Get or set the default mesh grading parameter.
Controls how rapidly mesh size changes with distance from control points. Must satisfy 0 < α ≤ 1.
See DeviceLayout.MeshSized for more details and the explicit mesh sizing formula.
DeviceLayout.SolidModels.set_gmsh_option — Function
set_gmsh_option(s, o::Number)
set_gmsh_option(s, o::AbstractString)
set_gmsh_option(s, d::Dict, default)
set_gmsh_option(d::Dict)Set gmsh configuration options.
Methods
set_gmsh_option(option_name, value): Set a single option to a numeric or string valueset_gmsh_option(option_name, dict, default): Set option from dict with fallback to defaultset_gmsh_option(option_name, dict): Set option from dict ifoption_nameis presentset_gmsh_option(dict): Set multiple options from a dictionary
Arguments
s: Option name as string (e.g., "Mesh.Algorithm", "General.NumThreads")o: Option value (Number or String)d: Dictionary containing option name-value pairsdefault: Default value if option not found in dictionary
Examples
set_gmsh_option("Mesh.Algorithm", 6)
set_gmsh_option("General.FileName", "output.msh")
set_gmsh_option("General.FileName", Dict("Mesh.Algorithm" => 6)) # does nothing
set_gmsh_option(Dict("Mesh.Algorithm" => 6, "General.NumThreads" => 4))DeviceLayout.SolidModels.get_gmsh_number — Function
get_gmsh_number(s)Get a numeric option value from gmsh.
Arguments
s: Option name as string (e.g., "Mesh.ElementOrder")
Returns the current numeric value of the specified gmsh option.
DeviceLayout.SolidModels.get_gmsh_string — Function
get_gmsh_string(s)Get a string option value from gmsh.
Arguments
s: Option name as string (e.g., "General.FileName")
Returns the current string value of the specified gmsh option.
DeviceLayout.SolidModels.mesh_control_points — Function
mesh_control_points()Get the dictionary of mesh size control points grouped by (h, α) parameters.
Returns a Dict{Tuple{Float64, Float64}, Vector{SVector{3, Float64}}} where keys are (mesh_size, grading_parameter) tuples and values are vectors of 3D points.
If this dictionary is modified, by erasing points or adding points using add_mesh_size_point, then it is necessary to call finalize_size_fields! to rebuild the KDTree from the data, else any resulting mesh will not reflect the change in data.
See DeviceLayout.MeshSized for details and the explicit mesh sizing formula utilizing the control points.
DeviceLayout.SolidModels.mesh_control_trees — Function
mesh_control_trees()Get the dictionary of KDTrees for efficient spatial queries of mesh size control points.
Returns a Dict{Tuple{Float64, Float64}, KDTree} where keys are (mesh_size, grading_parameter) tuples and values are KDTrees for fast nearest-neighbor lookups.
See DeviceLayout.MeshSized for details and the explicit mesh sizing formula computed using the control trees.
DeviceLayout.SolidModels.add_mesh_size_point — Function
add_mesh_size_point(; h, α=-1, p)Add a mesh size control point to the global mesh sizing parameters.
Arguments
p: 3D point coordinates where mesh size is controlled. Can be a single point, or array of concatenated points [x1,y1,z1,x2,y2,z2,...].h: Target mesh size at the pointα: Mesh grading parameter (α ≤ 1). If negative the default global value will be used when the size trees are regenerated. All negative values are mapped together for efficient KDTree calculations.
The point is added to a collection grouped by (h, α) values for efficient mesh size field computation. This is a manual override that occurs in addition to those control points generated by a geometry, in general mesh size points should be encoded directly within component definitions but manual additional points can be helpful in prototyping.
See DeviceLayout.MeshSized for details and the explicit mesh sizing formula.
DeviceLayout.SolidModels.finalize_size_fields! — Function
finalize_size_fields!()Rebuild KDTree data structures for mesh size field computation.
Must be called after manually adding mesh size points with add_mesh_size_point to enable efficient spatial queries during meshing. Creates KDTrees grouped by (h, α) parameters for fast nearest-neighbor lookups.
See DeviceLayout.MeshSized for details and the explicit mesh sizing formula.
DeviceLayout.SolidModels.clear_mesh_control_points! — Function
clear_mesh_control_points!()Clear all mesh size control points and associated KDTrees.
See DeviceLayout.MeshSized for details on how points are used.
DeviceLayout.SolidModels.reset_mesh_control! — Function
reset_mesh_control!()Reset the mesh scaling and grading to the original defaults: (s_g, α) ← (1.0, 0.75).
See DeviceLayout.MeshSized for details and the explicit mesh sizing formula.