Filters

Filters

Keeps shapes whose measure lies in the given bounds. One number is exact (area tolerance 0.5 dbu²). Two numbers are [min, max) with max exclusive, except inf. Length is the exception: its max is inclusive.

← Language overview

with_area(a, min, max)

Available · yields polygons

layer s = with_area(m1, 0, 0.09)
layer s = with_area(m1, 0.09)
layer s = with_area(m1, 0.09, inf)

Area in dbu². One argument = exact (tolerance 0.5 dbu²). Two arguments: v ≥ min and v < max. inf as max = minimum only.

Input Result Only the small area is in the window

One argument is exact, not a minimum.

Notes

  • Use with_area(a, x, inf) for “at least x”. One value is not a minimum.
  • max is exclusive (v < max). An area exactly equal to max is dropped.
  • A negative min: every smaller positive area lies above it.
  • Holes: the area is net (hull minus holes), not the hull alone.
  • An empty polygon / area 0: only with min≤0 and (exact 0 or a range).

without_area(a, …)

Available · yields polygons

layer w = without_area(m1, 0, 0.09)

a minus the shapes kept by with_area (identity per polygon equality).

Input Result

Notes

  • The same measure window as with_area, inverted.
  • Two identical shapes, one in the window: comparison is polygon equality — raw duplicates with the same contour go together.

with_perimeter(a, …)

Available · yields polygons

layer p = with_perimeter(m1, 0, 2.0)

Perimeter including every ring. Same min/max/exact rules as area; the unit is length.

Input Result

Notes

  • A hole increases the perimeter (inside + outside).
  • A very narrow long rectangle: large perimeter, small area — not interchangeable with with_area.

with_holes(a, n)

Available · yields polygons

layer h = with_holes(m1, 1)
layer h = with_holes(m1, 1, inf)

Number of clockwise rings after the rings are separated. One argument = exactly n holes.

Input Result

Notes

  • with_holes(a, 0): polygons without a hole, not “any number”.
  • A donut: 1. Two holes: 2.
  • Self-touch that is not split: 0 or 1 depending on ring orientation.

with_angle(a, …)

Available · yields edges or edge pairs

layer e = with_angle(edges, 0, 1)
layer p = with_angle(m1, 90)

On edges: orientation atan2 in [0,180) — horizontal 0°, vertical 90°. On polygons: interior angle at each corner as an edge pair (prev–curr, curr–next). One value = exact (edges: 1e-6°, not 0.5 dbu).

Input Result Polygon form: pair at the 90° corner

Notes

  • The opposite direction of an edge (flipped 180°) lands in the same [0,180) class.
  • A 45° diagonal: with_angle(e, 45) is exact; 45.0001 is out.
  • Polygon interior angle: a CCW hull uses 180-turn, a clockwise hole 180+turn — 90° rectangle corners stay 90°.
  • A collinear corner (~180°): only in a window around 180.

with_internal_angle(pairs, …)

Available · yields edge pairs

layer p = with_internal_angle(width(m1) < 0.2 um, 0, 10)

Angle between the two edges of a pair: acos(|cos|)0…90° (acute angle; sign/direction dropped). Non-pairs become markers first.

Input Result The pair is kept when the angle is in the window

Notes

  • Parallel edges: 0°.
  • Perpendicular: 90°.
  • An obtuse geometric position appears as 180-α, but |cos| never exceeds 90 — obtuse pairs cannot be told from acute complements.

with_length(e, min, max)

Available · yields edges

layer k = with_length(edges(m1), 0.2 um, inf)

Keeps edges whose length lies in the interval. Implementation: all minus without_length. A missing min/max is unbounded.

Input Result

Length max is inclusive; area max is exclusive.

Notes

  • Zero length does not appear in edges() (skipped).
  • Exactly max: max is inclusive here (unlike with_area).
  • Exactly min: inclusive.

without_length(e, min, max)

Available · yields edges

layer k = without_length(edges(m1), 0, 0.5 um)

Keeps edges outside [min, max]. Both unbounded: the interval is “everything” → empty output.

Input Result

Notes

  • Typical without_length(e, 0, x): edges longer than x (short ones dropped).
  • Polygon input is split into edges — the original shape is not returned.

ongrid(a, g) (Layer)

Available · yields edge pairs

layer v = ongrid(m1, 0.005 um)
layer v = ongrid(m1)

Per off-grid vertex a degenerate pair (a point, distance 0). Without g: setup grid. Not the whole polygons.

Input Result Only the off-grid vertex, not the rectangle

As a layer, ongrid yields off-grid vertices, not whole off-grid shapes.

Notes

  • Off in X or in Y is enough.
  • g ≤ 0: no hits.
  • A negative coordinate modulo is computed as a positive remainder.
  • The check form ongrid(a) != g uses the same point pairs as markers.

rectangles / non_rectangles

Available · yields polygons

layer r = rectangles(m1)
layer n = non_rectangles(m1)

An axis-aligned quad, 4 unique corners, area = bounding-box area (not a diamond, not a rotated rectangle, not a 45° rectangle).

Input Result

Notes

  • 5 points with one collinear corner: not a rectangle (n != 4).
  • 0 height or 0 width: no.
  • An L-shape: no.
  • A 45° quad: no (edges are not axis-aligned).

squares / non_squares

Available · yields polygons

layer s = squares(m1)

First rectangles, then bounding-box width == height.

Input Result

Notes

  • A 1 dbu difference: not a square.
  • A non-axis-aligned diamond with equal edges: not a square (already dropped by rectangles).

rectilinear / non_rectilinear

Available · yields polygons

layer m = rectilinear(m1)

Every edge is axis-aligned (each step changes only X or only Y). L-shapes yes, 45° no. At least 3 edges.

Input Result

Notes

  • A single diagonal edge sends the whole polygon to non_rectilinear.
  • Degenerate, fewer than 3 edges: not rectilinear.
  • Holes: cleaner after holes / hulls than on a mixed stored ring.

with_width(a, min, max)

Available · yields polygons

layer w = with_width(m1, 0.5 um, inf)

Shapes whose local width (RelWidth per polygon, else bbox min side) lies in [min, max]. An L with a thin arm drops when min is above that arm, even if the bbox is large.

Input Result

Notes

  • A width table: filter first, then space(wide) — not a new operator.
  • Maximum width as a check: width(a) > x, not this filter.
  • No opposite-edge pair: fallback is the smaller bbox side.

with_bbox / with_area_ratio / with_vertex_count

Available · yields polygons

layer b = with_bbox(a, width=1 um, height=2 um)

with_bbox filters on the bounding box. with_area_ratio keeps shapes whose area/bbox-area is in [min, max]. with_vertex_count filters by vertex count (ring without a duplicated close). width= / height=: bbox width or height within 1 dbu. min=: smaller side ≥ min. max=: larger side ≤ max. aspect=: width/height (5 % relative tolerance).

Input Result

Notes

  • No hit: empty.
  • Only width=: tall and flat rectangles of the same width both stay.
  • min=1.5 um keeps 2×2, not 2×1 (min side 1).

path_length(e, min, max)

Available · yields edges

layer p = path_length(e, 1.0 um, inf)

Length of a chain of connected edges (shared endpoints, union-find), not a single segment. with_length stays per segment.

Input Result

Notes

  • A branch: every edge of the same connected component shares the summed length.
  • A closed ring: perimeter of the contour.

with_distance(pairs, min, max)

Available · yields edge pairs

layer p = with_distance(space(m1) < 1 um, 0, 0.2 um)

Filter on the measured pair distance. The input must be edge pairs (e.g. space(a) < x). Other layer kinds: empty.

Input Result

Notes

  • Useful for bands: too close and not kissing (0.001 .. 0.2).
  • Without pairs: empty.