Rule interfaces

Region Partitioning Rules

All of the rules described below do not alter the area of the input region, but instead partition it into a set of subregions all entirely contained within the input region.

No holes are present in the resulting subregions – that is every subregion has boundary either shared with another region or with the outside world.

Partitioning results with a set of non-walkable regions, for example grassy areas of the park, path network and optionally centres at the path crossroads/junctions.

We should now the sizes of the resulting elements at the point of a partitioning rule evaluation, and unambiguously so – because each of the resulted subregions should know it’s size when they are evaluated further. For example we should specify the size of the path crossroads/centres because they affect how much space is subtracted from the neighbouring regions.

Note that the crossing centre region could be partitioned to contain another non-walkable region inside of it which could be used to construct an arbitrary sub-park. However because the size of the crossing is known during the partitioning rule, other regions are unaffected by what actually happens in the centre (it can be considered as a single node).

Grid rule

Partitions region into a regular x,y grid elements with paths in between.

Grid(dim_x, dim_y) { region_operations }
Grid(dim_x, dim_y) { region_operations } { path_operations }
Grid(dim_x, dim_y) { region_operations } { path_operations } { path_centre_operations }

  • dim_{x, y} = range [ “a” range ]    // optionally angle values
    range = num | “[” num, num “]” // either a number of a real range of numbers
  • region_operations – to construct the non-walkable region, i.e. everything other then the path
  • path_operation (optional) – rules that construct the path; defaults create standard paths
  • path_centre_operations (optional) – rules for path crossings. If omitted normal regular crossroads are created. The following

Region -> Grid(2, 2) { ParkQuarter }
{ ParkPath }
{ Romb(3) Fountain }

Alternative would be to have two symbolic region parameters for the ‘grid’ rule. For example:

Region -> Grid(2, 2) { ParkQuarter }
{ ParkPathCentered }
ParkPathCentered ->
joined { RombCenter(..) ParkPath(..) }

However in this case the ParkQuarter does not have a region geometry fixed when it is mentioned in Grid rule.

Implicit Attributes

Each non-walkable region may differ based on the proximity of either of the region’s sides/boundaries/edges. The output attributes will be discussed in the later post in detail.

Alternative Notation

To stay in tune with CGA grammar of CityEngine, alternative notation may:

Grid(dim_x, dim_y) { region_operations | path_operations | path_centre_operations }

Questions remaining
  • Variation of the crossing centres – should happen within the grid rule for non-walkable regions to know their sizes

VoronoiRegions Rule

Partitions a region using Voronoi algorithm and optionally smoothing algorithm/function.

VoronoiRegions(point_set, smooth_function) { region_operations}
VoronoiRegions(point_set, smooth_function) { region_operations} { path_operations }

  • point_set – set of input points to grow from
  • smooth_function -(optional) how to smooth the resulting regions; if unspecified, (2x) average function is applied
  • region_operations – sequence of rules from the non-walkable regions
  • path_operations – (optional) sequence of rules for the path; if unspecified


Region -> VoronoiRegions(CircleRegions)
{ SmoothRegions } { Path }
CircleRegions -> ScatterCircles(5 {[5-10]})

Regions are reduced by path_width/2 to give way to the paths. Path amalgamated region is what is left when the on-walkable regions are shrunk.

Questions remaining
  • How to incorporate smoothing
  • What kind of smoothing functions available
    • no smoothing should also be possible
  • It should also be possible to build something at the region centres.

CastRays Rule

Partitions the region using ray-cast principle taking centre the source and the destination into account.

CastRays(source_point, target_point_set) { region_operations }
CastRays(source_point, target_point_set) { region_operations } { path_operations }

  • source_point – the origins of the rays, where the rays are cat from
  • target_point_set – where to cast rays to, which could be directions where the roads will go to
  • region_operations – non-walkable region rules
  • path_operations – (optional) walkable region rules


Region -> VoronoiSmoothed(CircleRegions)
{ SmoothRegions } { Path }
CircleRegions -> ScatterCircles(5 {[5-10]})

Peel rule

Extrude the subset of the boundary inwards (normally) of the region.

Peel(boundary_selection, size1, Flags…) { region1_operations | region2_operations }

  • boundary_selection – subset of iregion boundary
    • subset of edge line segments
    • whole edge selection OR
    • parametric edge selection
  • region1_operations, region2_operations – rules for the two regions, the first one being the newly created region and the second region taking the remaining space
  • size1 – how much to peel; can be absolute (meters) or relative (0..1)
  • flags
    • CornersOrthogonal – when true the corners are moved perpendicular to the edge extruded. By default corners follow the adjacent edges

Output always produces two closed regions, with one shared boundary.

CGA grammar has a number of similar rules: setback, shapeL, shapeU, shapeO and offset.



ParkQuarter -> Peel(OuterEdgesSelection, 0.75, CornersOrthogonal) { TreeStrip | GrassRegion }

Questions remaining
  • Is it possible to apply smoothing to the pealed region?

Area-modifying Rules

Contract Rule

Contract(units, centre)

  • units – amount to contract by towards the centre
  • centre – contract towards this point

Contracts the region towards the centre (of mass).  Centre can also be specified as a parameter

TODO find out if s rule would be sufficient.

Placement/Additive Rules

Scatter and Place rules are responsible for distributing objects of non-zero volume along the surface of the park

Place and Rule

(Also includes Distribute functionality)

TODO determine how to use selectors

Place( CENTRE) { TreeRegion }

Scatter Rule

(also includes scatter circles functionality)

Sweep Rule

(Previously called SmoothDistribute)

Sweep(line_segments)  { Operations }

  • line_segments – where to instantiate the operation

Creates a volume over the defined area or defined line segment when width is specified.

Non-mutating Rules

Parametrise Rule

Parametrises perimeter of the region by continuous edge segments

  • Input – region who’s boundary should be parametrised
    • alternatively a set of edges
  • input2 – list of ranges
    • each range subset of range [0..1], represents the subsegment of the current edge
  • output – list of ranges mapped to the context of the input


Parametrise([0.1, 0.9] [] [0.1, 0.9], Square(10))
Results in two line segments…

Questions remaining
  • Edge indexing determined by the partitioning algorithm
    • symmetry is specified then – will be discussed in the latter post(s)

IO Functions

loadModel Function

loads a static mesh from the file.

Ideas To develop (TODO)

Polygon Spit hints

We should delay splitting the polygon as much as possible.
Even more abstract would allow polygons with holes in the system. However that is unnecessarily complex and is potentially a problem. For instance non-trivial triangulation.


Edge selectors, vertex selectors, indexed based on the symmetry relationships.