[046] How to Use the s() Scale Command in CityEngine CGA

Learn how to use the s() command for fixed and relative scaling, and understand how CGA handles model reproduction during transformations.

This tutorial explains the s() command in CityEngine, covering fixed dimensions, relative scaling using the quote (') operator, and the fundamental concept of how instructions automatically copy models within the rule hierarchy.

It is used for scaling the size of a model, and the usage is as follows.

CityEngine s command documentation
img 1 : https://doc.arcgis.com/en/cityengine/latest/cga/cga-s.htm

It uses three variables and increases or decreases the size in the direction of each axis based on the scope origin.

Absolute vs Relative Scaling

The input values can be entered as simple numbers or numbers preceded by a single quote (').

If you enter only a number, it creates the model at that specific size; if you use the ' operator, it becomes a value multiplied by the scope length of that axis.

 

For example, if there is a cube with a width, length, and height of 100m each:

Using s(2, 2, 2) reduces the size of the cube to 2 × 2 × 2m based on the scope origin.

Using s('2, '2, '2) expands it to 200 × 200 × 200m based on the scope origin.

 

As always, it is best to understand this through an example.

Example: Dynamic Scaling with @Range

@Range(min =0.5, max=5, stepsize=0.1)
attr x_scale =1

@Range(min =0.5, max=5, stepsize=0.1)
attr y_scale =1

@Range(min =0.5, max=5, stepsize=0.1)
attr z_scale =1

Lot -->
    extrude(10) # 10m extrusion
    Lot1 # Send to Lot1

    translate(rel, world, 10, 0, 0)
    Lot2
    # Copy the extruded model, 
    # move it 10m along the X-axis of the world coordinate system,
    # and then send it to Lot2 Lot1 --> s(x_scale, y_scale, z_scale) # Adjust scale by absolute values X. Lot2 --> s('x_scale, 'y_scale, 'z_scale) # Adjust scale by ratio (relative values) using ' X.

Using the @Range annotation, the range of variables was limited to 0.5–5, allowing increments and decrements in units of 0.1.

Implicit Shape Duplication in CGA

Now, I will share a unique point regarding CGA rules.

CGA also has an implicit shape duplication behavior.

In CGA, each sequential operation continues from the previous shape state, effectively creating independent shape branches during rule evaluation.

In lines 12–13, the initial shape was extruded by 10m and then sent to Lot1.

In lines 15–16, translate() was used to move the model 10m relative to the x-axis based on the world coordinate system, and then it was sent to Lot2.

This is how copying works.

After sending the 10m extrusion to Lot1, performing a translation in the next instruction does not move the version corresponding to Lot1; Instead, CGA keeps the previous result intact and evaluates the next operation as a separate shape state.

 Case Study: Overlapping vs Sequential Translation

What would happen with the following code?


Lot --> extrude(10) A B C D

This results in four models, each extruded by 10m, overlapping at the exact same location.

 

What about the following?


Lot -->
    extrude(10) A
    t(10,0,0) B
    t(10,0,0) s('2,'2,'2) C
    t(20,0,0) D

A exists at the 10m extrusion point.

B is created 10m along the x-axis of the scope.

C is scaled to twice the size and created 10m further along the scope x-axis from B.

D is created 20m along the x-axis of the scope from C's position.

 

You will use this frequently later, so you can just skim through it for now.

 

Shall we continue and look at the initial screen?

Initial viewport with one lot
img 2 : Initial viewport with one lot

There is only one Lot on the screen.

 

However, when the rule is executed,

Viewport showing two lots after rule execution
img 3 : Viewport showing two lots after rule execution

As shown above, the rule creates an additional duplicated shape, resulting in two models.

 

Previously, when showing examples using two models, I created each shape separately.

From now on, I will use one shape by copying it like this.

 

Now, let's see how the scaling works.

Adjusting model scale in CityEngine

Adjusting each scale variable slider applies the changes to both models simultaneously.

Lot1 on the left uses absolute scale values, while Lot2 on the right multiplies the scale relative to the current scope size. 

Advanced: Scaling with rotateScope()

The next code is an example of checking s() while rotating the scope.

Since the size is adjusted in the direction of the scope axes, the direction of scaling also changes when the scope is rotated.

@Angle
attr rotate_Scope = 0 # Scope rotation

@Range(min =0.5, max=2, stepsize=0.1)
attr x_scale =1

@Range(min =0.5, max=2, stepsize=0.1)
attr y_scale =1

@Range(min =0.5, max=2, stepsize=0.1)
attr z_scale =1

@Range(min =0, max=30, stepsize=2)
attr x_distance =1


Lot -->
    rotateScope(0,rotate_Scope,0)
    # Rotate scope around the Y-axis
    extrude(10) 
    # 10m extrusion t(x_distance, 0, 0)
    # t() uses the scope coordinate system. A A --> s('x_scale, 'y_scale, 'z_scale) # The scale is adjusted using ratios. X.

 

Let's take a look at the scaling according to scope rotation. It might be slightly different from what you expect.

CityEngine s() rotateScope() demo

When there was no scope rotation, it was easy to expect changes relative to the x, y, and z axes.

After scope rotation is applied, it becomes a bit confusing.

This is because the concept that "the model does not rotate even if the scope rotates" is unfamiliar. 

This concludes the content regarding s().

It is much easier to understand if you type the code above yourself and adjust the variable values. 

Next, we will cover rotation. 

“Boredom acts as an emotional signal that pushes us toward goals different from the ones we are currently pursuing. Without such signals, we would repeat the same things throughout our lives and remain trapped within limited experiences.”
— From I Wonder Why I Don’t Want to Do Anything by Bae Jong-bin
Continue Learning
Explore complete tutorial collections for CityEngine and Global Mapper.

Comments

Popular posts from this blog

029] How to Split Polygon Areas with Intersecting Lines in Global Mapper

[008] How to Understand CGA Rule Structure in CityEngine (Beginner Guide)

046] How to Create Parallel Offset Lines in Global Mapper