split operation

Synopsis

XYZ Split (Cartesian Space)

  • split (splitAxis) { size1 : operations1 | size2 : operations2 | ... | size(n-1) : operations(n-1) }
  • split (splitAxis) { size1 : operations1 | size2 : operations2 | ... | size(n-1) : operations(n-1) }*
  • split (splitAxis, adjustSelector) { size1 : operations1 | size2 : operations2 | ... | size(n-1) : operations(n-1) }
  • split (splitAxis, adjustSelector) { size1 : operations1 | size2 : operations2 | ... | size(n-1) : operations(n-1) }*

UV Split (Texture Space)

  • split(splitDirection, surfaceParameterization, uvSet) { size1 : operations1 | ... | size(n-1) : operations(n-1) }*

Parameters

XYZ Split (Cartesian Space)

  1. splitAxisselstr
    { x | y | z }—Name of axis to split along. This is relative to the local coordinate system (i.e. the scope).
  2. adjustSelectorselstr
    { adjust | noAdjust }—Optional selector to control scope calculation of the calculated shapes. The default is to adjust the scope to the geometry's bounding box. Using noAdjust avoids this, and therefore, the scopes of the resulting shapes fill the parent's scope without gaps.

UV Split (Texture Space)

  1. splitDirectionselstr
    { u | v }—Name of axis to split along.
  2. surfaceParameterizationselstr
    { uvSpace | unitSpace }—uvSpace is the planar texture space, defined by the uv coordinates; unitSpace is the 2d space on the 3d geometry surface, measured in units (e.g. meters).
  3. uvSetinteger (range[0,5])
    Number of texture a set/layer. The numbering corresponds to the texture layers of the material attribute.

See Texturing for more information about the texture layer IDs.

General

  1. sizefloat
    Split width. Depending on the prefix, the widths along axis are interpreted in the following way:
    • no prefix(absolute)—the new shape will have exactly the same size.
    • '(relative)—the new shape's size will be size * current scope size
    • ~(floating)—with the ~prefix the remaining spaces between the split parts with absolute dimensions are automatically adapted. If multiple floating parts are defined within a split, the dimensions are weighed proportionally.
  2. operations
    A sequence of shape operations to execute on the newly created shape.
  3. *
    Repeat switch: the repeat switch triggers the repetition of the defined split into the current shape's scope, as many times as possible. The number of repetitions and floating dimensions are adapted to the best solution (best number of repetitions and least stretching).

Description

XYZ Split (Cartesian Space)

The split operation subdivides the current shape along the specified scope axis into a set of smaller shapes. For each size-operation block inside the curly brackets, a new shape is pushed onto the shape stack, a number of shape operations is executed and the shape on top of the shape stack is popped again.

If the optional repeat switch * is appended to the split operation, the content of {...} is repeated as often as it fully fits into the scope's dimension along the selected axis.

The geometry of the current shape is cut with a plane perpendicular to the split axis at every intersection between two blocks (i.e. at size1, size2, ... size(n-1)). Hollow meshes are closed after the cut, i.e. cutting planes introduce new surfaces to preserve the volume.

Splits can be nested, i.e. a size : operation block can be replaced by a {...} block. In theory, the nested level is unlimited.

UV Split (Texture Space)

Splits can also be applied in the 2d uv texture domain. Texture coordinates define a 2d parameter space on a 3d surface. Examples of such parameterizations are streets (u along the w street direction, v along the width) and facades (generated with setupProjection() and projectUV(), u along the width and v along the height). This permits to operate directly on the surface. In general, uv coordinates are in the [0,1] range and not connected to a unit like meters or yards on the surface (defined by the underlying mesh). Setting the splitDirection parameter to unitSpace permits to operate directly on the surface, i.e. work in units (e.g. meters or yards). Depending on the geometry and type of parameterization there is some inherent distortion in this conversion.

Borders (start, end) of the uv split are defined by the minimal and maximal values found in the selected uv coordinates. The general syntax of the split is the same as in the cartesian case described above, i.e. relative and floating operators (' and ~) can be used as well as the repeat operator (*). See the examples below.

Shape attributes

Each generated shape will have a number of attributes set:

  • split.index: The zero-based index of the selected component.
  • split.total: The total number of components selected by the selector.

Index and total are global; for instance

...
     primitiveCube()
     split(x) { '0.1 : A | '0.1 : B }*

will create 5 shapes with rule A interleaved with 5 shapes with rule B where split.index goes from 0 to 9 with all even numbers on rule A and all odd numbers on rule B while split.total will be 10.

For more information see split attribute.

Related

Examples

Setup

This is the initial shape before the split. We will present a number of split examples along the x axis, the current shape's scope.sx is 10.

Below are the rules used to color and size the shapes created in the split:

X(h)-->
   s('1,'h,'1)
   color("#0000ff")
	
Y(h)-->
   s('1,'h,'1)
   color("#ffff00")
	
Z(h)-->
   s('1,'h,'1)
   color("#00ff00")
Initial shape before split

Relative Sizes

This example shows the usage of the relative prefix. The green Z shape takes half of the initial shape's size (5 units) and so on. The total sum of all shape sizes in x-direction is 8, therefore the gap at the end.

A-->
   split(x){ '0.5 : Z 
           | '0.1 : Y(2) 
           | '0.2 : X(1) }
Split with usage prefix

Floating Sizes only: Ratios

The same example as above, but all sizes with the floating prefix. Note how the whole initial scope is filled (no gap at the end), and the ratios are kept.

A-->
   split(x){ ~0.5 : Z 
           | ~0.1 : Y(2) 
           | ~0.2 : X(1) }
Split with floating prefix

Absolute and Floating Sizes

Here, a floating sized shape is framed between two absolute sized shapes. Its size is adjusted from 3 to 1.7 to fulfill the absolute constraints.

A-->
   split(x){ 3.3  : Z(1) 
           | ~3   : Y(2) 
           | 5    : X(1) }
Floating sized shape between absolute shapes

Oversized

The first shape Z (green) fits in, but the second one Y (yellow) is cut at size 5. The X never gets created because there is no space left.

A-->
   split(x){ '0.5 : Z(1) 
           | '0.6 : Y(2) 
           | 3    : X(1) }
Oversized split shapes

Repeat Split with Absolute Sizes

A repeat split example. All sizes are absolute. The XY pattern is repeated 3 times, and the remaining unit is filled with half a X, i.e. the geometry of the last X is cut off.

A--> 
   split(x){ 2 : X(2) 
           | 1 : Y(1) }*
Repeat split with absolute sizes

Repeat Split with Floating Sizes

If floating sizes are used in the repeat split, no shape is cut but the sizes are adjusted such that the ratio between the elements is kept and the whole scope can be filled.

A--> 
   split(x){ ~2 : X(2) | 
             ~1 : Y(1) }*
Repeat split with floating sizes

Interleaved Repeat Split

A interleaved split consisting of two absolute-sized shapes at both ends and a repeat split in-between. Note: the green shapes Z have absolute sizes, while the yellow Y shapes have floating sizes which turn out to be 0.9.

A-->
   split(x) { 1 : X(3) 
            | {  ~1 : Y(2) 
              | 0.2 : Z(1) 
              | ~1  : Y(2) }*
            | 1 : X(3) }
Interleaved repeat split

Rhythm

Here it is demonstrated how a pattern ABABABA etc. can be achieved. Note the floating size of the yellow Y shapes.

A-->
   split(x) { { 1  : X(3) 
              | ~3 : Y(1) }* 
            | 1 : X(3) }
Rhythm split

Cutting Geometry

Here it is demonstrated how a the geometry of the current shape is cut into a number of smaller shapes. A cylinder model is inserted into the current shape.

A-->
   i("cylinder.hor.obj")
   t(0,'0.5,0)
Geometry before cut

Splitting the shape and using NIL in the split rule results in holes. Note how the cut surfaces are closed.

A-->
   i("cylinder.hor.obj")
   t(0,'0.5,0)
   split(x) { { ~0.75 : XX 
              | ~1    : NIL }*  
            | ~0.5 : XX }
Geometry after cut with closed faces

UV Split Basics

u split in uvSpace - the split happens at u = 0.5, independent of facade size.

Init-->
   extrude(scope.sx * 0.5)
   comp(f) { front : Facade }
	
Facade-->
   setupProjection(0, scope.xy, '1, '1)
   projectUV(0)
   texture("builtin:uvtest.png")
   split(u, uvSpace, 0) { 0.5 : X }*
UV split

u split in unitSpace - the splits happen at u = 5, dependent of facade size.

Init-->
   extrude(scope.sx * 0.5)
   comp(f) { front : Facade }
	
Facade-->
   setupProjection(0, scope.xy, '1, '1)
   projectUV(0)
   texture("builtin:uvtest.png")
   split(u, unitSpace, 0) { 5 : X }*
UV split with unitSpace applied

UV Split on Streets

The test texture on a street with two segments. The street's texture coordinates are automatically generated; note that the two street segments have different lengths but are both covered by a [0,1] uv space, the u axis following the street direction and the v axis, perpendicular to u, along the width.

Street-->
   texture("builtin:uvtest.png")
UV split on street

The same street after a u-split in unitSpace. Every 20 meters a 3 meter wide band is drawn across the street.

Street-->
   split(u, unitSpace, 0) { ~10 : NIL 
                          | ~3  : color("#ff0000") 
                                  X  
                          | ~10 : NIL }*
UV split on street with unitSpace applied

In this topic