Select Rule

Re-write incoming geometry to a different set of labels.

select { RegionList }

RegionList – label selector list, list of selector expressions applied on the input shape.

No geometry is modified, only labels are assigned and attributes set. The purpose of this rule is to remove redundancy of repeating the same operations on one label in different selector blocks, for instance:

InputLabel --> place(CENTRE) 
 { 50%: Border1 | else: Border2  } 
 { i("circle", 10) Inserted } 
 { 50%: Border1 | else: Border2  }

can be rewritten as:

InputLabel --> place(CENTRE) 
{ Border } { i("circle", 10) Inserted } { Border } 

Border --> select { 50%: Border1 | else: Border2 }

Rule application makes even more sense when selector expression lists are longer, or when the same label is assigned in a number of different rules.

Insert Operator

Insert operator creates new geometry. Depending on the rule it is either ignored (e.g. Peel rule), optional (Centres of the Grid rule) or required (Insert and Place rules).

i(geometry_path, r1)
i(geometry_path, r1, r2)
  • geometry_path – a string that specifies new geometry to be inserted, either
    • builtin:<primtive_shape>” – a predefined shape based on primitives where <primitive_shape> is either circle, square or rhombus. r1 is the size of the shape. If r2 is specified, it is passed as size2 along y axis; in such case circle becomes an ellipse, and square – a rectangle.
    • iregion:shrink” – iregion is shrunk by r1 and used as the inserted shape
    • iregion:smoothen” – iregion is shrunk by r1 (see above) and then smoothed with r2 weight; if r1 is not given value 0.5 is used.
  • r1, r2 – extra parameters (mentioned above)

Insert a circle with radius 15% of the input region (provided rule accepts shape insertion) into a shape labelled InsertedCircle:

{ i("builtin:circle", %15) InsertedCircle }

…rhombus 20 wide and 15 high:

i("builtin:rhombus", 20, 15)

Label Selectors and Operators

Label Selector List

{ Selector1 | Selector2 | ... SelectorN }

One label selector is chosen for each shape at the rule output (derived shape). More than one may match, but only the first one matching is selected. The last selector SelectorN is expected to be a plain/default selector – otherwise, rule applications fails.

Label Selector

Evaluates to a label, matching condition and optimally additional operations (see below).

A plain selector is simply a label, and it always matches:


Alternatively, if label selection should be limited to a particular condition:

MatchCondition: Label

Additional attribute modifications or shape insertion can be requested before the label:

MatchCondition: SelectorOperatorOperations Label
  • Label – label assigned to a derives shape
  • MatchCondition – a match condition expression should evaluate to true to match the label
  • SelectorOperatorOperations – operations based on selector operators.

Match Conditions

Border Keyword (NEW)

Regions that are touching a boundary at an edge are selected (however, regions sharing a vertex with iregion boundary are not!).

Index Match
idx(x_expr, y_expr)
  • x_expr, y_expr – integer expression that is either a number or a keyword, optionally prefixed with “!” which negates the meaning. Available keywords:
    • odd – all odd indices are selected. Even indices selected with “!odd”
Stochastic Match

Selector is chosen with a probability of percent value. For instance “50%” would accept the label roughly half of the time.

Default Match Keyword

Default match condition always matches (the keyword it can also be omitted).

Selector Operators

Insert Operator

Considered separately.

Set Operator

Creates a new attribute or changes a propagated attribute that is inherited from the rule input shape. For instance type attribute is assigned using set.

set(attribute_name, attribute_value)
  • attribute_name – an attribute name, of the same format as shape label.
  • attribute_value – a number or a string. The number is stored in double precision floating point format.


Selects Label2 half of the time, and Label1 and Label3 equally quarter of the time each:

{ 25%: Label1 | 50%: Label2 | else: Label3 }

Checkerboard pattern:

{ idx(odd, odd): LabelWhite | 
  idx(!odd, !odd): LabelWhite | LabelBlack }

Change path width to a third for any further productions on QuarterLabel:

{ set(path_width, %33.3) QuarterLabel }