Shape Primitives
The built-in shapes of the laylight DSL, their parameters and variants, and their counterparts in gdsfactory, gdstk, Luceda IPKISS and Nazca.
Every piece of geometry in a laylight cell is a shape: a primitive with arguments, defined inside a layer block and placed once.
cell Demo {
layer si {
shape rect with width = 10um, height = 500nm as core # named arguments
shape rect with 10um, 500nm as copy # the same, positional
place core.left_center at self.origin
place copy.bottom_left at core.top_left offset (0, 1um)
}
}
The primitive set is the union of the geometric primitives of gdsfactory, gdstk, Luceda IPKISS and Nazca Design. Where those tools offer several functions for closely related shapes (a rectangle, a rounded rectangle, a rectangular frame), laylight has one primitive with optional parameters. The reference at the end maps every function of the four tools to its laylight form.
The examples on this page are the bodies of a layer block. Each one is compiled in your browser; the drawing next to it is the result, and + marks the shape's local origin.
| Family | Primitives |
|---|---|
| Closed shapes | rect, polygon, regular_polygon, circle, ellipse, ring, racetrack, cross, trapezoid |
| Waveguides and paths | path, arc, euler, sbend, bezier, taper |
| Text | text |
Conventions
Arguments. Arguments can be positional, in the order of the signatures below, or named (key = value). Parameters marked ? are optional. Lengths need a unit (500nm, 2um), angles too (90deg); the literal 0 works as any zero. String options such as ends and profile are checked while you type when you write them as literals.
Local coordinates and anchors. Each primitive is defined in its own coordinate system, described per primitive below. Every shape has the anchors origin, center, left_center, right_center, top_center, bottom_center, bottom_left, bottom_right, top_left and top_right (from its bounding box, all pointing along +x), and the sizes width and height. Waveguide primitives also have start and end: frames whose direction is the tangent of the waveguide there, pointing downstream, so place b.start at a.end chains two pieces.
Curves. Curved outlines are written as polygons. segments sets the number of straight segments of each curved part: the whole circle or arc, each rounded corner, each half circle of a racetrack, each rounded path corner, the whole Euler, S-bend or Bézier curve, or each edge of a curved taper. Without it, the segment count follows from a chord error of at most 1 DBU (1 nm by default), with at most 45° per segment on circles; free-form curves are sampled more densely where they bend more.
Shared variants. Closed shapes take corner_radius, which rounds the corners, and line_width, which draws the boundary as a line of that width centered on it, as one polygon. Circles and ellipses take angle and start_angle for sectors (positive angles are counter-clockwise).
Closed shapes
rect
rect(width, height, corner_radius?, line_width?, segments?)
A rectangle centered at the origin. It stays a GDS box under right-angle placements.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
width, height | size | required | Size along x and y. |
corner_radius | size | 0 | Radius of the rounded corners, at most half the shorter side; half the shorter side gives a stadium. |
line_width | size | — | Draw a frame of this width centered on the outline instead of a filled rectangle. |
segments | integer | auto | Segments per rounded corner. |
shape rect with 12um, 6um as box
place box at (0, 0)shape rect with 12um, 6um, corner_radius = 2um as rounded
shape rect with 12um, 6um, corner_radius = 3um as stadium
shape rect with 12um, 6um, corner_radius = 1um, line_width = 1um as frame
place rounded at (0, 0)
place stadium at (0, -9um)
place frame at (0, -18um)To give a rectangle by two corners (x1, y1) and (x2, y2), place its corner anchor: shape rect with x2 - x1, y2 - y1 as r and place r.bottom_left at (x1, y1).
polygon
polygon(points, corner_radius?, line_width?, segments?)
A polygon through points (at least 3), in local coordinates.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
points | [point] | required | The vertices. |
corner_radius | size | 0 | Round every corner. Where the adjacent edges are too short, that corner's radius is reduced so that the arcs never pass the middle of an edge. |
line_width | size | — | Draw the outline as a line of this width centered on the boundary, with mitered corners. |
segments | integer | auto | Segments per rounded corner. |
shape polygon with [(0, 0), (14um, 0), (4um, 10um)] as plain
shape polygon with [(0, 0), (14um, 0), (4um, 10um)], corner_radius = 2um as rounded
shape polygon with [(0, 0), (14um, 0), (4um, 10um)], line_width = 800nm as outline
place plain at (0, 0)
place rounded at (18um, 0)
place outline at (36um, 0)Points can be computed in a loop, which covers parametric shapes that have no primitive of their own:
define star: [point] = []
for i in 0..10 {
define r = 6um - 3um * (i % 2)
star.append((r * cos(i * 36deg + 90deg), r * sin(i * 36deg + 90deg)))
}
shape polygon with star as s
place s at (0, 0)regular_polygon
regular_polygon(sides, radius?, side_length?, rotation?, corner_radius?, line_width?, segments?)
A regular polygon centered at the origin. Give either the circumradius radius or the side_length, not both. Unrotated, the bottom edge is horizontal: vertex k sits at −90° + 180°/n + k·360°/n. So an unrotated square is axis-aligned and a triangle points up.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
sides | integer | required | Number of sides, 3 to 4096. |
radius | size | — | Circumradius. |
side_length | size | — | Edge length; the circumradius is side_length / (2 sin(180°/n)). |
rotation | angle | 0 | Counter-clockwise rotation about the center. |
corner_radius, line_width, segments | As for polygon. |
shape regular_polygon with 3, radius = 5um as triangle
shape regular_polygon with 6, side_length = 5um as hexagon
shape regular_polygon with 8, radius = 5um, rotation = 22.5deg, line_width = 1um as octagon
shape regular_polygon with 5, radius = 5um, corner_radius = 1um as pentagon
place triangle at (0, 0)
place hexagon at (12um, 0)
place octagon at (24um, 0)
place pentagon at (36um, 0)circle
circle(radius, segments?, angle?, start_angle?)
A disk centered at the origin, or with angle a sector (a pie slice, including the center) that starts at start_angle and sweeps angle counter-clockwise; negative angles sweep clockwise.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
radius | size | required | Radius. |
segments | integer | auto | Segments of the circle or of the sector's arc. |
angle | angle | 360deg | Sweep of a sector, non-zero and at most 360°. |
start_angle | angle | 0 | Where the sector (or the vertex list of a full circle) starts. |
shape circle with 5um as disk
shape circle with 5um, angle = 270deg, start_angle = 45deg as pie
shape circle with 5um, angle = 60deg as slice
place disk at (0, 0)
place pie at (13um, 0)
place slice at (22um, -3um)ellipse
ellipse(rx, ry, segments?, angle?, start_angle?, line_width?)
An ellipse centered at the origin with semi-axes rx along x and ry along y. Sector angles are polar angles, as in gdstk: angle = 90deg covers exactly the first quadrant.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
rx, ry | size | required | Semi-axes. |
segments | integer | auto | Segments of the ellipse or of the sector's arc. |
angle, start_angle | angle | full, 0 | Sector, as for circle. |
line_width | size | — | Draw the curve as a line of this width, offset along the normal. A full ellipse gives a closed outline; with angle, an elliptical arc band. Half the width must be less than the smallest radius of curvature, min(rx, ry)² / max(rx, ry). |
shape ellipse with 8um, 4um as oval
shape ellipse with 8um, 4um, angle = 90deg as quadrant
shape ellipse with 8um, 4um, line_width = 800nm as outline
shape ellipse with 8um, 4um, angle = 180deg, line_width = 800nm as arch
place oval at (0, 0)
place quadrant at (12um, -2um)
place outline at (0, -11um)
place arch at (20um, -11um)ring
ring(radius, width, segments?, angle?, start_angle?)
An annulus centered at the origin. radius is the centerline radius, as in gdsfactory: the ring spans radius ± width/2. A full ring is one polygon with a zero-width cut at start_angle; with angle it is an annular sector.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
radius | size | required | Centerline radius. |
width | size | required | Ring width, less than 2 · radius. |
segments | integer | auto | Segments of the (outer) circle or arc. |
angle, start_angle | angle | full, 0 | Annular sector, as for circle. |
shape ring with 5um, 1um as full
shape ring with 5um, 2um, angle = 120deg, start_angle = 30deg as segment
place full at (0, 0)
place segment at (13um, -3um)racetrack
racetrack(radius, length, width, segments?)
A closed waveguide loop centered at the origin: two half circles of centerline radius joined by straight sections of length along x, drawn with width. The zero-width cut is at the middle of the bottom straight. length = 0 gives a ring.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
radius | size | required | Centerline radius of the bends. |
length | size | required | Length of each straight section (may be 0). |
width | size | required | Waveguide width, less than 2 · radius. |
segments | integer | auto | Segments per half circle. |
shape racetrack with 5um, 10um, 1um as track
place track at (0, 0)A filled racetrack (a stadium) is a rect whose corner_radius is half its height.
cross
cross(length, arm_width)
A plus sign centered at the origin: two arms of arm_width, each length long from tip to tip, as one 12-vertex polygon.
shape cross with 10um, 3um as plus
place plus at (0, 0)trapezoid
trapezoid(width, height, top_width, offset?)
A trapezoid height tall, centered on y = 0. The bottom edge is width long and centered on x = 0; the top edge is top_width long and centered on x = offset. A top_width of 0 gives a triangle; a top_width equal to width with an offset gives a parallelogram.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
width | size | required | Bottom edge. |
height | size | required | Height. |
top_width | size | required | Top edge (0 for a triangle). |
offset | size | 0 | Shift of the top edge's center along x. |
shape trapezoid with 10um, 6um, 4um as trapezoid
shape trapezoid with 10um, 6um, 0 as triangle
shape trapezoid with 10um, 6um, 10um, offset = 3um as parallelogram
shape trapezoid with 10um, 6um, 0, offset = -5um as right_triangle
place trapezoid at (0, 0)
place triangle at (13um, 0)
place parallelogram at (27um, 0)
place right_triangle at (42um, 0)Shapes described by base angles convert directly. Nazca's trapezoid(length, height, angle1, angle2) is trapezoid with length, height, length - height / tan(angle1) - height / tan(angle2), offset = (height / tan(angle1) - height / tan(angle2)) / 2, and a parallelogram with base angle a has offset = height / tan(a).
Waveguides and paths
All of these have the start and end anchors.
path
path(points, width, ends?, bend_radius?, segments?)
A polyline of width through points. The start and end anchors are at the first and last points, facing along the first and last segments.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
points | [point] | required | The vertices (at least 2). |
width | size | required | Line width. |
ends | string | "flush" | "flush" ends at the points (GDS path type 0); "square" extends each end by half the width (path type 2); "round" closes the ends with half circles and is written as a polygon. |
bend_radius | size | — | Replace every corner by a circular arc of this radius. The arcs must fit: at each segment, the tangent lengths of its two corners must not add up to more than its length. |
segments | integer | auto | Segments per rounded corner or round end. |
shape path with [(0, 0), (8um, 0), (8um, 6um)], 1um as flush
shape path with [(0, 0), (8um, 0), (8um, 6um)], 1um, ends = "square" as square
shape path with [(0, 0), (8um, 0), (8um, 6um)], 1um, ends = "round" as round
place flush at (0, 0)
place square at (12um, 0)
place round at (24um, 0)shape path with [(0, 0), (10um, 0), (10um, 10um), (20um, 10um)], 1um, bend_radius = 4um as route
place route at (0, 0)Joins are mitered, as in GDS. L- and C-shaped outlines (gdsfactory's L and C) are flush paths through the arm centerlines.
arc
arc(radius, width, angle, segments?)
A circular bend that starts at the origin heading +x, with its center of curvature at (0, radius) for positive angles: positive angles turn left, negative angles turn right. end lies at (radius · sin angle, radius · (1 − cos angle)).
| Parameter | Type | Default | Meaning |
|---|---|---|---|
radius | size | required | Centerline radius, more than width / 2. |
width | size | required | Waveguide width. |
angle | angle | required | Turn, non-zero and at most 360°. |
segments | integer | auto | Segments of the bend. |
shape arc with 8um, 1um, 90deg as left
shape arc with 8um, 1um, -45deg as right
place left.start at (0, 0)
place right.start at (12um, 0)euler
euler(radius?, width, angle, p?, segments?, min_radius?)
An Euler bend: from the origin heading +x, the curvature grows linearly with arc length (a clothoid), stays constant through a circular section, and falls back to zero. The ends therefore join straight waveguides without a curvature jump. p is the fraction of the turn spent in the two clothoids; p = 1 is a pure Euler bend, p = 0 the circular arc.
Give the size in one of two ways:
radius: the effective radius. The bend ends exactly where anarcof that radius would, so the two are drop-in replacements. This is gdsfactory'sbend_eulerdefault (with_arc_floorplan=True).min_radius: the smallest radius of curvature, reached in the circular section. This is IPKISS's default and gdsfactory'swith_arc_floorplan=False. For a 90° bend withp = 1, the effective radius is 1.8701 times the minimum radius.
| Parameter | Type | Default | Meaning |
|---|---|---|---|
radius | size | — | Effective radius. |
width | size | required | Waveguide width; half of it must be less than the minimum radius. |
angle | angle | required | Turn, non-zero and less than 360°; positive turns left. |
p | number | 0.5 | Euler fraction, from 0 to 1. |
segments | integer | auto | Segments of the bend (auto: denser where it bends more). |
min_radius | size | — | Minimum radius of curvature. |
shape arc with 10um, 800nm, 90deg as circular
shape euler with 10um, 800nm, 90deg as half
shape euler with 10um, 800nm, 90deg, p = 1 as full
place circular.start at (0, 0)
place half.start at (0, 0)
place full.start at (0, 0)The three bends above share their end points; the Euler bends swing further into the corner.
sbend
sbend(length, offset, width, profile?, segments?)
An S-bend from the origin heading +x to (length, offset), level at both ends. Positive offsets go to the left. With t = x / length and H = offset, the profiles are:
profile | Centerline | Notes |
|---|---|---|
"bezier" (default) | Cubic Bézier with control points (0, 0), (L/2, 0), (L/2, H), (L, H) | gdsfactory's bend_s. |
"sine" | y = H · (t − sin(2πt) / 2π) | Zero curvature at both ends; Nazca's sinebend. |
"cosine" | y = H · (1 − cos(πt)) / 2 | Raised cosine. |
"circular" | Two opposite circular arcs of equal radius | Each arc turns A = 2·atan(H/L) with radius L / (2 sin A); no straight section. |
The radius of curvature must stay above half the width; a bend that is too short for its offset is an error.
shape sbend with 20um, 6um, 800nm as bezier
shape sbend with 20um, 6um, 800nm, profile = "sine" as sine
shape sbend with 20um, 6um, 800nm, profile = "cosine" as cosine
shape sbend with 20um, 6um, 800nm, profile = "circular" as circular
place bezier.start at (0, 0)
place sine.start at (0, -4um)
place cosine.start at (0, -8um)
place circular.start at (0, -12um)bezier
bezier(points, width, segments?)
A waveguide of width along the Bézier curve with control points points, of any degree (2 points is a straight line, 3 a quadratic, 4 a cubic curve). The curve passes through the first and last points; start and end face along the first and last distinct control-point directions.
shape bezier with [(0, 0), (12um, 0), (0, 12um), (12um, 12um)], 1um as cubic
shape bezier with [(0, 0), (10um, 10um), (20um, 0)], 1um as quadratic
place cubic.start at (0, 0)
place quadratic.start at (18um, 0)taper
taper(length, width1, width2, profile?, segments?)
A width transition from width1 at x = 0 to width2 at x = length, symmetric about the x axis. start is at the origin and end at (length, 0), both facing +x.
profile | Width at t = x / length | Notes |
|---|---|---|
"linear" (default) | w1 + (w2 − w1) · t | A trapezoid. |
"parabolic" | √(w1² + (w2² − w1²) · t) | The square of the width changes linearly (the classic adiabatic taper). The same law as IPKISS's ParabolicWedge and Nazca's ptaper. |
"exponential" | w1 · (w2 / w1)^t | Constant relative change of width per length. |
shape taper with 16um, 1um, 6um as linear
shape taper with 16um, 1um, 6um, profile = "parabolic" as parabolic
shape taper with 16um, 1um, 6um, profile = "exponential" as exponential
place linear.start at (0, 0)
place parabolic.start at (0, -8um)
place exponential.start at (0, -16um)gdsfactory's taper_parabolic uses another law, w1 + (w2 − w1) · t^0.5 (its exp parameter); write that as a polygon from a loop if you need it exactly.
Text
text
text(text, size)
Polygon text in a built-in 5×7 pixel font: printable ASCII and \n for new lines. size is the height of a capital letter (7 pixels). Characters advance by 6 pixels, lines by 11, and descenders reach 2 pixels below the baseline. The origin is at the start of the first line's baseline. Each run of pixels is written as a GDS box.
shape text with "laylight\nDSL 0.1", 3500nm as label
place label at (0, 0)Align text with its anchors, for example place label.top_center at device.bottom_center offset (0, -2um). Text that should not be fabricated belongs in a marker, which is written as a GDS TEXT on the marker layer.
Recipes
Some shapes of the other tools are compositions rather than primitives:
- Spiral. Compute the centerline in a loop and draw it with
path. An Archimedean spiral (gdsfactory'sspiral_archimedean):
define turns: [point] = []
for i in 0..200 {
define a = i * 9deg
define r = 2um + 1500nm * i * 9 / 360
turns.append((r * cos(a), r * sin(a)))
}
shape path with turns, 500nm as spiral
place spiral.start at (0, 0)- Parametric curves (gdstk's
parametric,Curve): the same pattern, feeding the points topolygon,pathorbezier. - L, C and die frames: flush
paths, orrectwithline_width. - Rectangle from two corners: size the
rectfrom the corners and place itsbottom_left. - Boolean operations and offsets (gdstk's
booleanandoffset, KLayout regions) are derived shapes; see Boolean and Morphological Operations.
Reference: equivalents in other tools
One table per tool maps its shape functions to the laylight primitive and the arguments that give the same geometry. Versions: gdsfactory 9, gdstk 0.9, Luceda IPKISS 3 (import ipkiss3.all as i3) and Nazca Design 0.6 (nazca.geometries as geom, interconnects as ic). width in the laylight column is the waveguide width, which the other tools often take from a cross-section. A dash means laylight has no counterpart yet.
gdsfactory
| gdsfactory | laylight |
|---|---|
rectangle(size=(w, h), centered=True), compass(size) | rect with w, h. The default centered=False puts the lower-left corner at the origin: place bottom_left. |
rounded_rectangle(width, height, corner_radius_x) | rect with width, height, corner_radius = corner_radius_x (circular corners only) |
circle(radius) | circle with radius |
ellipse(radii=(rx, ry)) | ellipse with rx, ry |
ring(radius, width, angle) | ring with radius, width, angle = angle |
regular_polygon(sides, side_length), hexagon, octagon | regular_polygon with sides, side_length = side_length; add rotation = 180deg for odd sides (gdsfactory's flat edge is on top) |
triangle(x, xtop, y) | trapezoid with x, y, xtop, offset = (xtop - x) / 2 |
ramp(length, width1, width2) | polygon with [(0, width1), (length, width2), (length, 0), (0, 0)] |
cross(length, width) | cross with length, width |
L(width, size), C(width, size) | a flush path through the arm centerlines |
straight(length) | rect with length, width |
taper(length, width1, width2) | taper with length, width1, width2 |
taper_parabolic(length, width1, width2, exp) | a polygon from a loop; it is not profile = "parabolic" (see below) |
bend_circular(radius, angle), gf.path.arc | arc with radius, width, angle |
bend_euler(radius, angle, p) | euler with radius, width, angle, p = p |
bend_euler(..., with_arc_floorplan=False), gf.path.euler(radius, angle, p) | euler with min_radius = radius, width = width, angle = angle, p = p |
bend_s(size=(dx, dy)) | sbend with dx, dy, width |
bezier(control_points) | bezier with control_points, width |
gf.path.smooth(points, radius, bend=gf.path.arc) | path with points, width, bend_radius = radius |
gf.path.spiral_archimedean(...) | the spiral recipe |
text(text, size) | text with text, size |
text_rectangular(text, size) | text with text, 7 * size (same pixel size, different glyphs) |
Component.add_polygon(points, layer) | polygon with points in the layer's block |
Component.add_label(text) | a marker |
gdstk
gdstk angles are radians; laylight angles carry a unit, so write a * 1rad or convert to degrees.
| gdstk | laylight |
|---|---|
rectangle(corner1, corner2) | rect sized from the corners, placed by bottom_left |
Polygon(points) | polygon with points |
Polygon.fillet(radius) | polygon with points, corner_radius = radius (the same reduction on short edges) |
regular_polygon(center, side_length, sides, rotation) | regular_polygon with sides, side_length = side_length, rotation = rotation |
ellipse(center, r) | circle with r |
ellipse(center, (rx, ry)) | ellipse with rx, ry |
ellipse(center, r, initial_angle=a0, final_angle=a1) | circle with r, angle = a1 - a0, start_angle = a0 (also for (rx, ry) with ellipse) |
ellipse(center, ro, inner_radius=ri) | ring with (ro + ri) / 2, ro - ri |
ellipse(center, ro, inner_radius=ri, initial_angle=a0, final_angle=a1) | ring with (ro + ri) / 2, ro - ri, angle = a1 - a0, start_angle = a0 |
racetrack(center, straight_length, radius, inner_radius) | racetrack with (radius + inner_radius) / 2, straight_length, radius - inner_radius |
racetrack(center, straight_length, radius) | rect with straight_length + 2 * radius, 2 * radius, corner_radius = radius |
cross(center, full_size, arm_width) | cross with full_size, arm_width |
text(text, size, position) | text with text, 0.75 * size (about the same capital height, different glyphs) |
FlexPath(points, width) | path with points, width |
FlexPath(..., ends="extended"), ends="round" | path with ..., ends = "square", ends = "round" |
FlexPath(..., bend_radius=r) | path with ..., bend_radius = r |
FlexPath.turn(radius, angle), .arc(...) | arc with radius, width, angle |
.bezier(xy), .quadratic, .cubic, Curve.bezier | bezier |
RobustPath with a width function | taper profiles |
.parametric(f), Curve.parametric | points from a loop, see recipes |
Label(text, origin) | a marker |
offset, boolean | dilate / erode, union / intersection / difference / xor (Boolean Operations) |
Luceda IPKISS
| IPKISS | laylight |
|---|---|
i3.Rectangle(layer, center, box_size=(w, h)), i3.Box | rect with w, h placed at center |
i3.RoundedRectangle(..., radius) | rect with w, h, corner_radius = radius |
i3.RectanglePath(..., line_width) | rect with w, h, line_width = line_width |
i3.RoundedRectanglePath(..., radius, line_width) | rect with w, h, corner_radius = radius, line_width = line_width; a stadium-shaped one is a racetrack |
i3.Boundary(layer, shape) | polygon with points |
i3.Path(layer, closed_shape, line_width) | polygon with points, line_width = line_width |
i3.ShapeRound(shape, radius) | corner_radius (closed shapes) or bend_radius (paths) |
i3.RegularPolygon(center, radius, n_o_sides), i3.Hexagon | regular_polygon with n, radius = radius; add rotation = 180deg for odd n |
i3.RegularPolygonPath, i3.HexagonPath | regular_polygon with ..., line_width = line_width |
i3.Circle(center, radius) | circle with radius |
i3.CirclePath(center, radius, line_width) | ring with radius, line_width |
i3.Ellipse(center, box_size=(a, b)) | ellipse with a / 2, b / 2 |
i3.EllipsePath(..., line_width) | ellipse with a / 2, b / 2, line_width = line_width |
i3.EllipseArcPath(..., start_angle, end_angle, line_width) | ellipse with ..., angle, start_angle, line_width; IPKISS angles are parametric, laylight's polar |
i3.ArcPath(center, radius, start_angle, end_angle, line_width) | ring with radius, line_width, angle = end_angle - start_angle, start_angle = start_angle |
i3.RingSegment(center, angle_start, angle_end, inner_radius, outer_radius) | ring with (inner_radius + outer_radius) / 2, outer_radius - inner_radius, angle = angle_end - angle_start, start_angle = angle_start |
i3.Cross(center, box_size, thickness), i3.CrossPath | cross with box_size, thickness |
i3.Wedge(begin_coord, end_coord, begin_width, end_width) | taper with length, begin_width, end_width, placed along the wedge's axis |
i3.ParabolicWedge(...) | taper with length, begin_width, end_width, profile = "parabolic" |
i3.Path(layer, shape, line_width, path_type=NORMAL), EXTENDED, ROUNDED | path with points, line_width, with ends = "square", ends = "round" |
i3.ShapeBend, i3.ShapeBendRelative | arc with radius, width, angle |
i3.EulerRoundingAlgorithm(p), i3.ShapeRoundEuler(..., radius, p) | euler with min_radius = radius, width = width, angle = angle, p = p |
i3.EulerRoundingAlgorithm(p, use_effective_radius=True) | euler with radius, width, angle, p = p |
i3.ShapeSineSBend, i3.ShapeCosineSBend, i3.ShapeRadialSBend | sbend with profile = "sine", "cosine", "circular" (similar curves; compare the definitions before relying on them) |
i3.ShapeBezier | bezier |
i3.PolygonText(text, coordinate, height) | text with text, size (IPKISS upper-cases the text) |
i3.Label | a marker |
Nazca Design
| Nazca | laylight |
|---|---|
geom.box(length, width) | rect with length, width, placed by left_center |
geom.rectangle(length, height, position), geom.square | rect with length, height; position=5 is the center, 1 the bottom_left corner at the origin |
geom.rounded_rect(length, height, shrink) | rect with length, height, corner_radius = shrink * min(length, height) |
geom.frame(sizew, sizel, sizeh) | rect with sizel, sizeh, line_width = sizew, centered at ((sizel - sizew) / 2, (sizeh - sizew) / 2) |
geom.circle(radius, N) | circle with radius, N |
geom.pie(radius, angle) | circle with radius, angle = -angle, start_angle = 90deg (Nazca runs clockwise from +y) |
geom.ring(radius, width) | ring with radius - width / 2, width (Nazca's radius is the outer one) |
geom.arc(radius, width, angle) | ring with radius - width / 2, width, angle = angle, start_angle = -90deg |
geom.trapezoid(length, height, angle1, angle2) | trapezoid with length, height, length - height / tan(angle1) - height / tan(angle2), offset = (height / tan(angle1) - height / tan(angle2)) / 2 |
geom.parallelogram(length, height, angle) | trapezoid with length, height, length, offset = height / tan(angle) |
geom.rhombus(length, angle) | trapezoid with length, length * sin(angle), length, offset = length * cos(angle) |
geom.taper(length, width1, width2), ic.taper | taper with length, width1, width2 |
ic.ptaper(length, width1, width2) | taper with length, width1, width2, profile = "parabolic" |
ic.strt(length) | rect with length, width |
ic.bend(radius, angle) | arc with radius, width, angle |
ic.euler_arc_euler(...) | euler (ic.euler is only the half from straight to curved) |
ic.sinebend(distance, offset) | sbend with distance, offset, width, profile = "sine" |
ic.sbend(radius, offset) | two arcs with a straight section; sbend with profile = "circular" when no straight section is wanted |
nd.Polygon(points) | polygon with points |
nd.Polyline(points, width, pathtype) | path with points, width; pathtype=1 is ends = "round" |
nd.text(text, height) | text with text, size (Nazca's height includes the line spacing) |
nd.Annotation | a marker |
Conventions that differ
Watch these when you port a layout. They are the places where the same name means different geometry.
- Angles. gdstk takes radians everywhere; laylight, gdsfactory, IPKISS and Nazca use degrees.
- Ring radius. laylight
ringand gdsfactoryringuse the centerline radius. Nazca'sring(radius, width)takes the outer radius and grows inward, so it equals laylightring with radius - width / 2, width. IPKISSCirclePathis centered on its radius, like laylight. - Racetrack radius. gdstk's
racetrack(radius, inner_radius)takes the outer radius:racetrack with (radius + inner_radius) / 2, straight_length, radius - inner_radius. - Regular polygon orientation. laylight and gdstk put a flat edge at the bottom. gdsfactory and IPKISS put a flat edge at the top, which differs for odd numbers of sides: add
rotation = 180deg. - Parabolic taper. laylight, IPKISS and Nazca change the square of the width linearly. gdsfactory's
taper_parabolicchanges the width with the square root of the length instead. - Euler bend size. gdsfactory's
bend_eulerdefaults to the effective radius (laylightradius). IPKISS'sEulerRoundingAlgorithmdefaults to the minimum radius (laylightmin_radius). Nazca'seuleris a half bend from straight to curved;euler_arc_euleris the symmetric one. - S-bend. gdsfactory's
bend_sis laylight's default"bezier"profile. Nazca'ssinebendis the"sine"profile. Nazca'ssbend(radius, offset)uses two arcs of a given radius with a straight section between them. The"circular"profile instead picks the radius that fillslengthwithout a straight section. - Ellipse angles. laylight and gdstk take polar angles; IPKISS's
EllipseArcPathtakes parametric ones. - Text size. laylight's
sizeand gdsfactory'stextsize are the height of a capital letter. gdstk'ssizeis the full font height, with capitals about 0.75 of it. Nazca'sheightis scaled by the font's line height. gdsfactory'stext_rectangularsize is one pixel. - Rectangle origin. laylight shapes are centered (
rect) or start at the origin (waveguides). gdsfactory'srectangledefaults to its lower-left corner at the origin, and Nazca's rectangles take a keypadposition(1 = lower left, 5 = center). - Point density.
segmentscorresponds to gdsfactory'snpoints/angle_resolution, gdstk'stolerance, IPKISS'sangle_step(1° by default) and Nazca'sN(20 by default).
laylight DSL
A concise, declarative language for layouts that compiles to GDSII.
Boolean and Morphological Operations
Combine shapes with union, intersection, difference and xor, grow and shrink them with dilate and erode, and the equivalent calls in gdsfactory, KLayout, gdstk, Luceda IPKISS and Nazca.