[024] How to Use the Split Command with Fixed and Ratio Values in CityEngine
Learn the fundamental concepts of dividing shapes into exact architectural dimensions and relative ratios using CityEngine's most essential command.
This tutorial covers everything from the basic syntax of the
split command to advanced techniques like repeating splits,
nested divisions, and relative ratio splitting (~). By the end
of this guide, you will understand how to precisely control the subdivision
of your procedural models to prepare them for detailed architectural
detailing.
Understanding the Basics of the Split Command
In CGA, creating form begins with effective subdivision. Whether it’s recessed areas, protruding elements, decorative inserts, door placements, or color zones—it is all about defining regions so that everything is positioned at the desired size in the planned location.
This is where the split command comes into play.
If you look at the CGA reference, there are two additional commands derived from split as shown below:
- split
- splitArea
- splitAndSetbackPerimeter
To explain briefly: splitArea is a method of dividing a shape by
area, and splitAndSetbackPerimeter allows setback and split to be
performed together on a shape. We will deal with those two later when time
permits; in the basic course, we will only deal with split.
Split Syntax Types in CGA
The following are the syntax usage principles for split:
XYZ Split (Cartesian Space)
split(axis) { size1 : operations1 | size2 : operations2 | ... | size_n-1 : operations_n-1 }
split(axis) { size1 : operations1 | ... | size_n-1 : operations_n-1 }*
split(axis, adjustMode) { size1 : operations1 | ... }
UV Split (Texture Space)
split(direction, surfaceParameterization, uvSet) { size1 : operations1 | ... }
XYZ split is a method of dividing in the direction of a specific axis, and UV split is a method of dividing a shape in a way that maps UV textures. A proper example of UV split is used when placing sidewalk blocks or streetlights on a model created based on a linear path like a road.
Since you don't know the parameters yet, just think "For now, just be aware that these options exist." and move on.
Preparing the Viewport for Split Practice
In the basic stage, we start with the most basic split syntax. First, before coding, check the items underlined in red in the View Setting as follows.
You must check "Wireframe on shaded/textured" to be able to see the split lines. Next, I will show you how to switch the Viewport using shortcuts.
The x, y, and z keys on the keyboard are shortcuts pointing to the direction of each axis. Every time you click inside the 3D View panel and press the x, y, or z keys, the viewport switches. Look at the shortcuts on the left side of the video and observe how the axis display in the bottom left and the compass display in the bottom right change.
how to instantly snap your perspective to the primary axes using the X, Y, and Z keys.
While learning split, there is no need to raise the form into a 3D volume, so press the z and y keys in order to work on a 2D plane. (This does not apply when in Korean input mode. Please set it to English input mode.)
Once the View setting and Viewport setting are finished, create a rectangle with a width (X-axis) of 40m and a height (Z-axis) of 10m.
Using the Tab key allows you to draw a rectangle of an exact size by entering numerical values. Remember how to use the Tab key well.
how to use the 'Tab' key shortcut during the Rectangular Shape Creation
Splitting Shapes with Fixed Values
If you have drawn it correctly, create code that divides the rectangle by 10m in the X-axis direction.
Lot -->
split(x){ 10 : A | 10 : A | 10 : A | 10 : A }
A --> color(1,0,0) X.
Since we are in the stage of learning CGA, I will explain the code.
Line 1: Lot is the name of the Start Rule for
the shape where the rule is applied. If you click the shape you just drew and
look at the Inspector tab, you will see "Lot" written in the Start Rule. This
means that the shape starts from the rule declared as Lot in the CGA code. We
have dealt with this content in the Inspector before. After the '-->' symbol,
you write the contents of the rule. The contents of the rule can be written on
a new line or written straight across.
Line 2: split(x) means that you will divide in
the X-axis direction. { 10 : A | 10 : A | 10 : A | 10 : A }: '10
: A' means 'split by 10m and send to rule A'. '|' can be seen as the same as
'and'. In other words, the shape is split into 10m segments sequentially along
the X-axis until no space remains.
The rectangle currently drawn is 40m along the X-axis, so in conclusion, it is split into a total of four and passed to rule A.
Line 3: color(1,0,0) means that the model passed
to A will be painted red. These are (R,G,B) values. (It's not important. It's
code added so that it can be easily distinguished after being split.)
X.: Usually, when one rule ends, it proceeds to the next rule,
but when there is no more rule to proceed to, you can write any label followed
by a period (.). This code means that it does not proceed further from rule A.
(You don't have to use X; you can use any name you want.)
Let's look at the result of applying the rule to the shape.
The thick black lines are the places divided by split. Now let's try dividing it into ten 4m segments like this.
Lot -->
split(x){ 4 : A | 4 : A | 4 : A | 4 : A | 4 : A | 4 : A | 4 : A | 4 : A | 4 : A | 4 : A }
A --> color(1,0,0) X.
Repeating Splits with the '*' Operator
It has been split into 10 parts. So, now if we split 40 parts by 1m... you
might think this is not right. That would be inefficient, right? When the same
split is repeated, you use '*' after {...}.
Let's recreate the code above using '*'.
Lot -->
split(x){ 4 : A }*
A --> color(1,0,0) X.
The code has become very simple. split(x){ 4 : A }* means that
the procedure of dividing the entire area in 4m units and sending it to A will
be repeated. (The case of a polygon that is not a rectangle or when the scope
has changed is a matter to be dealt with later.) Let's see the result.
The same result came out. Then this time, let's repeat splitting by 9m. Since the length of the X-axis is 40m, there will be a remainder.
Lot -->
split(x){ 9 : A }*
A --> color(1,0,0) X.
Four 9m segments are split, and a remainder is created. Even if the last one is not 9m, it is passed to the A rule. Hmm... but I said it's the X-axis direction, so why was it split from right to left instead of left to right? If you had that thought, you have a keen eye.
Currently, as shown in the bottom left of the figure above, only the axis of the space is set, not the axis of the shape, so the split direction follows the first edge of the shape. (If you created it according to the video I showed, it will come out like the above.)
Since axis and scope require a lot of explanation, we will ignore them at this stage and move on. For now, focus only on split.
Combining Fixed and Repeating Segments
This time, let's divide the both ends by 10m and the middle part by 5m. The total width is 40m, and since both ends occupy 10m each, a length of 20m remains in the middle, so four splits by 5m will be possible.
Lot -->
split(x){ 10 : A | 5 : A | 5 : A | 5 : A | 5 : A | 10 : A }
A --> color(1,0,0) X.
Since the number of '|' is 5, it means splitting into a total of 6 areas. It is sending '10m split to A, 5m split to A, 5m split to A, 5m split to A, 5m split to A, 10m split to A'. Looking at the result...
Yes. It was drawn as expected. However, as we did above, repeated splitting
can be grouped with {...} and '*' can be added, so modify the
code by using '*' for the 5m split repeating in the middle as follows.
Lot -->
split(x){ 10 : A | { 5 : A }* | 10 : A }
A --> color(1,0,0) X.
Since the number of '|' is two, the area is split into a total of three areas,
but the middle area means that the 5m unit split will be repeated. If you
group the repeated part with { } again and add *,
the remaining area, excluding fixed parts like the first '10 : A' and the last
'10 : A', will be repeatedly split by 5m. Looking at the result...
Yes, it's the same. Now, try to predict the result of the following code.
Lot -->
split(x){ 10 : A | { 5 : A }* | { 3 : A }* | 10 : A }
A --> color(1,0,0) X.
Since the number of '|' is three, the area is broadly divided into a total of four parts, and the middle two areas mean that they will be repeatedly split by 5m and 3m respectively. 10m each on the left and right are fixed values, so it means dividing the 20m in the middle into 5m and 3m. In what ratio will they share the area? Let's see the result.
Using Relative Ratio Splits with '~'
Unless a specific ratio is designated like above, it will be divided equally. You might be wondering: "Is splitting by ratio also possible?" Yes. It is possible.
Splitting 40m into four in a ratio of 3:2:2:3 is possible, splitting into three in a ratio of 1:2:1 is possible, splitting into two in a ratio of 1:3 is possible, and splitting into ten, twenty, or a hundred is also possible. Here is the code to divide into two equal parts in a 1:1 ratio.
Lot -->
split(x){ ~1 : A | ~1 : B }
A --> color(1,0,0) X.
B --> color(0,1,0) X.
Since there is one '|', it is divided into a total of two parts, but each area
is split in the same ratio based on the X-axis. The '~' symbol means splitting
by ratio. One thing to note is that this ratio does not point to the ratio of
the size of the shape, but to the ratio of the split areas. In other words,
{ ~2 : A | ~2 : B } also means dividing by 2:2, so you can see
that it eventually means dividing by a 1:1 ratio. Then what about
{ ~3 : A | ~6 : B }...? It means the same as dividing by a 1:2
ratio.
In line 4, I created a rule called B to distinguish colors. B is expressed in green. Looking at the result, yes, it was divided into equal parts in a 1:1 ratio.
Understanding Ratio Logic
Next, let's distinguish by 1:1:1.
Lot -->
split(x){ ~1 : A | ~1 : B | ~1 : C }
A --> color(1,0,0) X.
B --> color(0,1,0) X.
C --> color(0,0,1) X.
Since the number of '|' is two, it means dividing into a total of three areas, but each is split in the same ratio. In line 5, blue was applied to distinguish the additionally split areas. Looking at the result, yes, it was 1:1:1, i.e., divided into three equal parts. The logic becomes quite intuitive once you understand the pattern. Then try to predict how the next code will be split.
Lot -->
split(x){ ~1 : A | ~2 : B | ~3 : C }
A --> color(1,0,0) X.
B --> color(0,1,0) X.
C --> color(0,0,1) X.
Looking at the contents inside the { }, it's ~1, ~2, ~3. In other
words, it means splitting in a ratio of 1:2:3. Looking at the result, yes, it
came out as expected. Then try to predict how the result will come out for the
code below.
Lot -->
split(x){ ~2 : A | ~4 : B | ~6 : C }
A --> color(1,0,0) X.
B --> color(0,1,0) X.
C --> color(0,0,1) X.
As I mentioned above, since it's a ratio, 2:4:6 would be the same as 1:2:3, right? Shall we look at the result? Yes, the same result came out.
Approximate Splits with ~ and *
Here, there is one more thing you should know. While ~ is treated
as a simple ratio when used alone inside
{ }, it is treated as an
approximation of the input value when * is
attached behind { }. Approximation - as the word implies, it's a
way of handling it roughly.
Let's think about a case like this. Splitting a width of 10m in 3m units
results in 1m remaining. But there is no rule to appropriately apply to the
part divided by 1m, and it has become a state where only polygons increase
unnecessarily. If you distribute this leftover 1m into the 3m in a certain
ratio so that it becomes 3.33333m, the leftover 1m will disappear. At this
time, ~ and * are used together. At this time,
~ means to split into an approximate value rather than a ratio.
I just got back from fieldwork and haven’t eaten yet. I should eat and rest. The following content will be moved to the next one.
- Learn previous workflow in [023] Let's start Learning CGA in Esri CityEngine
- Continue learning with [025] How to Split Shapes Using Relative Ratios (~) in CityEngine
Comments
Post a Comment
Feel free to leave a comment if you have any questions about Global Mapper or CityEngine. I will get back to you with a sincere response as soon as possible. (Please note that all comments are moderated and manually approved to maintain a high-quality community. Promotional or spam content will not be published.)