[029] How to Perform Vertical and Horizontal Splits in CityEngine
How First Edge Defines the X-Axis Direction Counter-Clockwise Polygon Construction Behavior
Transition from horizontal floor divisions to vertical facade splits by manipulating coordinate axes with alignScopeToGeometry.
In CityEngine, procedural modeling relies heavily on understanding the local
coordinate system of each shape. This tutorial explains how to use the
split command for vertical divisions and introduces the
alignScopeToGeometry(zUp) function. By reorienting the Z-axis
to the Y-axis, you can apply architectural logic using the more intuitive X
and Y plane, making it much easier to code complex building facades, floors,
and repeating window patterns.
Default Axis Orientation and Split Direction in CityEngine
The splits we have learned so far were mainly focused on horizontal divisions. Today, we will cover vertical splits.
Regarding the content mentioned in the previous session, I hope you haven't forgotten that "if you do not specify an axis, the first edge becomes the direction of the X-axis."
If you look at the image below, there are four squares, each with a different direction for its first edge.
When you select a shape, the edge displayed in orange is the first edge, and CityEngine connects segments in a counter-clockwise direction when constructing a polygon.
Performing Vertical and Horizontal Splits Using CGA split()
Let's apply the following code to the image above.
Lot -->
split(x){ 10 : A | 10 : B | 10 : C | 10 : D | 10 : E }
A --> color(1,0,0) X. #Red
B --> color(0,1,0) X. #Green
C --> color(0,0,1) X. #Blue
D --> color(1,1,0) X. #Yellow
E --> color(1,0,1) X. #Magenta
I split a 50m square into 10m fixed values along the X-axis and applied a color to each. Looking at the results:
You can see that the splits were performed in the order of Red-Green-Blue-Yellow-Magenta along the first edge direction, which is the X-axis direction.
This time, let's try splitting based on the Z-axis. You simply need to change
split(x) to split(z).
Lot -->
split(z){ 10 : A | 10 : B | 10 : C | 10 : D | 10 : E }
The result is as follows.
When viewed from the Y-axis direction, it is easier to understand if you think of the X-axis as 12 o'clock and the Z-axis as 3 o'clock.
Reorienting Axes with alignScopeToGeometry(zUp)
The problem is... we are not familiar with these axis directions. The axis direction we are usually familiar with is:
As shown in the image above, the origin is at the bottom-left, X increases to the right, and Y increases upward. This is similar to how we count building floors from the bottom: 1st floor, 2nd floor, 3rd floor.
However, if you look at the four shapes earlier, none of them match the direction we are used to. While you can use them as they are if you are comfortable, let's change the axes forming the plane to a more familiar orientation. Can you understand this by looking at the image?
The image on the left shows the axis directions of the plane we have seen so far.
The X and Z axes are on the plane, and the Y axis is in the height direction.
In that state, if you rotate the Z-axis toward the Y-axis direction using the X-axis as the rotation axis, the Y-axis, which was in the height direction, will now be positioned on the plane. Consequently, when splitting the plane, you can perform the splits using the X and Y axes instead of the X and Z axes.
There are two shapes with the same firstEdge as shown below. Imagine these are building facades.
In both cases above, the X-axis is in a familiar direction, but the Z-axis is not. Let's see what kind of result we get when we add the following code.
Lot1 -->
split(z){ '.5 : A | '.5 : B }
Lot2 -->
alignScopeToGeometry(zUp, 0, 0)
split(y){ '.5 : A | '.5 : B }
A --> color(1,0,0) X. #Blue
B --> color(0,1,0) X. #Green
Line 2: Lot1 splits the floors 1:1 without changing the axis and colors them Red-Green. Since the Z-axis points from top to bottom, it will likely be colored Red-Green from the top down.
Line 5: The Z-axis is changed to the height axis, and the axes forming the plane are changed to X and Y.
Line 6: Since the existing Z-axis has been changed to Y, we divide the floor
heights using split(y) instead of split(z). It will
be colored Red-Green from the bottom up. Let's look at the result.
In the case of Lot2, the axes are set to a familiar direction, and the split is performed from the bottom to the top. Let's open the Model Hierarchy panel to check how the actual axis directions have changed.
You can see that the colors of the axes have changed.
CityEngine displays the X-axis in red, the Y-axis in green, and the Z-axis in blue.
Axes... Scope... these are difficult to understand right now. I am just using them briefly to help you perform splits in directions familiar to you. Do you remember the Facade Wizard content where we created building facades with vertical and horizontal lines?
Recalling the massive amount of code generated by the Facade Wizard, let's practice splitting starting from simple forms.
Imagine the rectangle below is a building facade. We will divide it into two floors of equal height, leaving the 1st floor as a single block and splitting the 2nd floor in half.
Facade Modeling Practice: Multi-Level Split Structure
Shall we look at the code?
Lot -->
alignScopeToGeometry(zUp, 0, 0)
split(y){ '.5 : A | '.5 : B }
# Z-axis is rotated upward to change the workspace to the XY plane.
# Since the Y-axis is now the upward direction, we use split(y).
# The 1st floor is passed to rule A and colored red.
# The 2nd floor is passed to rule B
A --> Red
B --> split(x) { '0.5 : Grn | '0.5 : Blu }
Red --> color(1,0,0) X. #Red
Grn --> color(0,1,0) X. #Green
Blu --> color(0,0,1) X. #Blue
Simple, right?
This code can also be shortened as follows:
Lot -->
alignScopeToGeometry(zUp, 0, 0)
split(y){ '.5 : Red | '.5 : split(x) { '0.5 : Grn | '0.5 : Blu } }
Within the 2nd-floor area, split(x) is executed to divide the 2nd
floor into two sections. As such, you can separate and use rules one by one,
or you can simply express the rule in a single line.
You can use whichever method is more convenient as you get used to it.
Next, let's create a form like the one below.
Split Practice:
- The 1st floor is 10m high and has no internal splits.
- The 2nd floor occupies the remaining height after excluding the heights of the 1st and 3rd floors, and it is repeatedly split with a fixed width of 5m.
- The 3rd floor is 10m high, and the areas split into 2m and 3m are repeating.
Rather than actually typing out the code, it is enough to just visualize in your head, "I use ~ here and * there." Shall we look at the code?
Lot -->
alignScopeToGeometry(zUp, 0, 0)
split(y){ 10 : A | ~1 : B | 10 : C }
A --> Red
B -->
split(x){ 5 : BB }*
BB --> Grn
C -->
split(x){ 2 : CC | 3 : CCC }*
CC --> Blu
CCC --> Yll
Red --> color(1,0,0) X.
Grn --> color(0,1,0) X.
Blu --> color(0,0,1) X.
Yel --> color(1,1,0) X.
for Lot1 : The Z-axis is rotated into the Y-axis position so that the Y-axis, along with X, becomes the axis forming the plane. Since the Y-axis direction is from bottom to top, it becomes the 1st, 2nd, and 3rd floors in the order of the split. We split 10m from the bottom to proceed to rule A, split the last 10m for the 3rd floor (rule C), and proceed to rule B for the 2nd floor, which is the section excluding those two areas.
for B : Performed a repeating 5m fixed-value split along the X-axis and colored it green.
for C : Performed a repeating split of 2m and 3m fixed values along the X-axis
and colored them blue and yellow, respectively. Vertical and horizontal splits
are essentially repetitions of such combinations, so your skills will improve
if you practice by changing variables or symbols.
That's all for today. Next time, we will practice more complex splits.
- Learn previous workflow in [028] How to Select Specific Segments Using split.index in CityEngine
- Continue learning with [031] How to Create Nested Split Structures Esri 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.)