Subdivision split

The split operation can be used to model shapes and to set up geometry by splitting a larger geometry object to smaller ones. The split operation is central to creating designs with the CGA shape rules. The basic definition for split is split(axis) { selector : operations }. See CGA split operation for detailed information.

The following examples show the different types of the split operation:

  • absolute split,
  • relative split,
  • floating split and
  • repeat split.

The following are examples that start with an introductory rule and proceed with examples for each split type.

Lot --> s(5, 1, 1)
        primitiveCube()
        Blue(1)
Blue(height) --> s(’1, ’height, ’1)
                 color("#84C0fC")

In this introductory rule we resize the initial scope and insert a cube in that scope. The scopes’ x-dimension (the length of the cube) is set to 5. The y- and z-dimensions of the scope are set to 1. The Blue rule resizes the scopes’ y-dimension (the height of the cube) relative to scope.sy using the relative operator ’. Because the rule parameter height is set to 1, the height of the cube remains unchanged.

Resized scope with cube inserted

Absolute split

The absolute split cuts the geometry at absolute values.

The operation split(x) { 3 : Blue } splits the geometry along the x-dimension of the scope. The cube of length 5 is cut at an absolute value of 3 units and replaced with the successive cube shape Blue.

Lot --> s(5, 1, 1)
        primitiveCube()
        split(x) { 3 : Blue(1) }
Absolute split

This example shows what happens if two absolute split values are used (3 units in green and 1 unit in blue). After the split the total resulting length is 3+1=4.

Lot --> s(5, 1, 1)
        primitiveCube()
        split(x) { 3 : Blue(1) }
Two absolute splits

This example shows the effect of absolute values within a (limited) scope. The resulting shape Yellow has a length of 1 instead of 2 since there is a total length of 5. The rightmost shape Blue will not be generated.

split(x) { 2 : Green(1)  |
           1 : Green(1)  |
           1 : Blue(0.5) |
           2 : Yellow(2) |
           1 : Blue(1)   }
Absolute values within a limited scope

No splits will be produced with negative or zero-sized values. Both Yellow shapes are not generated. Blue starts at 1.5. The last Green shape stops at the total length of 5.

split(x) { 1.5 : Green(1)  |
            -2 : Yellow(1) |
           1.5 : Blue(0.5) |
           1.5 : Green(1)  |
             0 : Yellow(1) |
           1.5 : Green(1)  }
No splits with negative or zero-sized values

Relative split

The relative split uses scales relative to the scope size instead of absolute values. Relative values are denoted by the operator followed by a value between 0 and 1.

This example cuts the scope using the Golden Ratio.

split(x) { ’0.382 : A | ’0.618 : B }

A --> split(x) { ’0.382 : Green(1) | 
               ’0.618 : Yellow(2)  }
B --> split(x) { ’0.382 : Green(1) | 
                ’0.618 : Yellow(2) }
Recursive split with scope cut with Golden Ratio

This example shows a recursive split using the Golden Ratio. The recursion stops when the geometry gets too small for a further split.

split(x) { ’0.382 : A | ’0.618 : B }

A --> split(x) { ’0.382 : A         | 
                 ’0.618 : C         }
B --> split(x) { ’0.382 : B         | 
                 ’0.618 : D         }
C --> split(x) { ’0.382 : Green(1)  | 
                 ’0.618 : Yellow(2) }
D --> split(x) { ’0.382 : Green(1)  | 
                 ’0.618 : Yellow(2) }
Recursive split with Golden Ratio

Floating split

A floating split adapts values such that the entire space is filled. Floating splits are denoted by an operator ~.

In this example the split operation splits the cube of length 5 at 3 units (green). The remainder geometry is then cut at 1 unit. This time the floating operator ~ is used which expands the 1 unit over the remaining space of the first cut, i.e. 5-3=2 units (blue).

split(x) { 3 : Green(1) |
          ~1 : Blue(2)  }
Floating split

The floating value 2 fills the space (3 units in yellow) between two absolute values (1 unit in blue).

split(x) { 1 : Blue(1.5) |
          ~2 : Yellow(1) |
           1 : Blue(0.5) }
Floating value fills the space

Multiple floating splits with same unit (each 1.5) are distributed evenly over the remaining scope space (2 units).

split(x) {  3 : Green(1)  |
         ~1.5 : Blue(0.5) |
         ~1.5 : Blue(2)   }
Multiple floating splits distributed evenly

Three floating splits are distributed evenly.

split(x) { 3 : Green(1)  |
          ~2 : Blue(0.5) |
          ~2 : Blue(2)   |
          ~2 : Blue(1)   }
Three floating splits

If there is no space left for a floating split the corresponding shape is not generated (Blue in this case).

split(x) { 5 : Green(1) |
          ~1 : Blue(1)  }
Floating split with shape not generated

Repeat split

The repeat split is used to repeat geometry within a given scope. It creates a rhythm: the repetitive use of a group of geometric objects in order to establish a recognizable pattern. A typical scenario is the alternating arrangement of windows and columns in the facades of common high rise office buildings. An asterisk * after the bracket denotes the repetitive split.

In the first example, a scope of length 10 is filled repetitively with a green shape with absolute length 2. Exactly 5 cubes of length 2 fit in the scope.

Lot --> s(10, 1, 1)
        primitiveCube()
        split(x) { 2 : Green(1) }*

A floating value of 2.1 generates the same result because a split to 5 successor shapes (with a length of 2 each) still approximates the target length of 2.1 best.

split(x) { ~2.1 : Green(1) }*
Repeat split with scope filled by 5 cubes of length 2

A floating repeat split (green) is bordered by two absolute splits (blue). Note that the resulting length of the floating splits is (10-2)/3≈2.66 which is the best approximation for the target value 2.5.

split(x) {    1 : Blue(2)     | 
         { ~2.5 : Green(1) }* | 
              1 : Blue(3)     }
Repeat split bordered by two absolute splits

The repetitive absolute split (green) will be evaluated first independently on which side of the split the repetition is denoted. The floating splits do not get any space to be generated.

split(x) {  { 2 : Green(1) }* | 
             ~1 : Blue(2)     }
split(x) {   ~1 : Blue(2)     | 
         {    2 : Green(1)    }*
Repeat split without space for floating splits

This example shows that a repeat split with absolute (or relative) values can be bordered by two neighboring floating (or absolute) splits.

split(x) { ~1 : Green(1)     | 
        {  2 : Blue(0.5) }* | 
          ~1 : Green(1)     }
Repeat split bordered by two absolute splits

The size of the first floating split and the size of the repetitive floating split is the same. The 2 units are equally distributed 4 times (blue) to the resulting length of (10-3)/4=1.75.

split(x) { ~2 : Blue(1)    | 
          {  1 : Green(2)   | 
            ~2 : Blue(1) }* }
Repeat split with floating and repeat split same size

Repeat split - Patterns

Repeat operations can be used to create patterns. The following example shows that geometric objects can be grouped into a bracket and repeated.

A pattern is created and repeated.

split(x) { ~1 : Yellow(2) | 
           0.25 : Green(1)  | 
             ~1 : Yellow(2) }*
Repeat split with repeating pattern

Repeating patterns can be inserted within other geometries.

split(x) {  1 : Blue(3)
        { ~1 : Yellow(2)    | 
         0.2 : Green(1)     | 
          ~1 : Yellow(2) }* |
           1 : Blue(3)      }
Repeating patterns inserted within other geometries

Repeat split - Parallel

Repeat splits can be performed in parallel.

Two repeat splits (yellow and blue) bordered by floating splits (green).

split(x) { ~1 : Green(1)     | 
         { ~1 : Yellow(2) }* |
           ~1 : Green(1)     | 
         { ~1 : Blue(2)   }* |
           ~1 : Green(1)     }
Two repeat splits bordered by floating splits

Two successive repeat splits (green and yellow) bordered by absolute splits (blue).

split(x) { 1 : Blue(2)      | 
         { 2 : Green(1) }*  | 
         { 1 : Yellow(1) }* |
           1 : Blue(3)      }
Two repeat splits bordered by absolute splits