Creating a simple 3D model of the underground with CityEngine

Since the acquisition by Esri, I have been wanting to get my hands dirty with CityEngine. But only recently a good opportunity arose. I was asked to construct a 3D model of the underground for an area in the municipality of Hoogeveen. This also happens to be my last name, so I could this one not let me pass by!

CityEngine is a wonderful piece of software, but to get started with it can be quite a challenge. The learning curve is steep. So I want to share some of the lessons learned. It really helps if you are acquinted with the Eclipse environment, upon which CityEngine is based. Eclipse comes in many guises, Aptana (see also this post) and the Adobe Flash Builder being two that are sometimes used in GIS related activities.


It all starts with data. I had limited data to work with (“oh really, can’t you use this Word document with images of soil profiles as data source in ArcMap?”), so I started with four layers in a topographical map (TOP10NL in this case) containing buildings, roads, terrain and water. I selected the features in the area and saved them to a new file geodatabase, so I would not have to import the entire Netherlands into CityEngine later on. The topographical layers will serve as the surface of my 3D model.

Visualizing 3d underground is tricky. I have explored two or three possibilities to do this. First is a vertical column representing borehole data. In ArcMap, I created a point feature class with one attribute for each layer in the underground. In my case, there were five layers I wanted to show, so my feature class contains the attributes bottom_1 through bottom_5. The values of these attributes are the levels of the bottom of the layer, in meters below zero. In the screenshot, the table of contents of this layer is shown.

Screenshot ArcMap with feature class of boreholes

The second method is creating rasters. Each raster divides two layers of the underground. To construct these, use the point feature class. For each combination of layers, create a TIN, like shown in the screenshot below. Repeat this for every layer you want to visualize in CityEngine. Convert each TIN into a raster (.TIFF is easiest for importing into CityEngine).

Create TIN tool

The third method is to construct actual 3D features for each layer in the underground. In this blog entry I will limit myself to the first two methods, but maybe I will elaborate on the third method in another blog entry.

Getting started in CityEngine

Fire up CityEngine and open a new project. After giving it an appropriate name and location, you will see an empty scene, the navigator, the inspection window and perhaps some other windows. See the help item on the Eclipse environment to familiarize yourself with the interface, if necessary. If no scene is present, create a new scene in the folder “scenes” (right click on the folder, choose “new”, and choose “scene”).

Now, how to import your data? This is not too complicated. Choose File -> Import. Choose the option “file geodatabase” and point to the geodatabase created in ArcMap. You can specify a bounding box and a query for limiting the number of features, but we have taken care of that in ArcMap.

In the scene, you can now see some layers. Every feature class in the FGDB has been converted into a layer. If you inspect the layers in the scene, you will see a shape for each feature in the feature class. Later on, this gives you the possibility to manipulate each individual feature.

Going 3D: shapes

Up till now you have a flat surface in your scene. Let’s turn it into 3D. We are going to define some rules for that. Create a new CGA rule file in the folder “rules” and name it “landuse”. This rule file will be applied to the layer “landuse”. In the rule file, the attribute “TYPELANDGEBRUIK” will be used to construct 3D objects for each type of landuse. Here is the code in the rule file:

attr TYPELANDGEBRUIK = "overig"
attr opacityvalue = 0.6

TerreinStart --> case TYPELANDGEBRUIK == "grasland" : Grasland
case TYPELANDGEBRUIK == "akkerland" : Akker
case TYPELANDGEBRUIK == "bebouwd gebied" : Bebouwd
case TYPELANDGEBRUIK == "boomkwekerij" : Boomkwekerij
case TYPELANDGEBRUIK == "bos: gemengd bos" : Bos
case TYPELANDGEBRUIK == "bos: loofbos" : Bos
case TYPELANDGEBRUIK == "bos: naaldbos" : Bos
case TYPELANDGEBRUIK == "heide" : Heide
case TYPELANDGEBRUIK == "spoorbaanlichaam" : Spoorbaan
else : Overig

Grasland --> extrude(.5)
set(material.opacity, opacityvalue)

Akker --> extrude(1.5)
set(material.opacity, opacityvalue)

Bebouwd --> extrude(9)
set(material.opacity, opacityvalue)


(I have abbreviated the code, put you get the point)

What happens here? First of all I defined an attribute TYPELANDGEBRUIK. If you use the same attribute as present in the feature class, the values will be taken from the feature. Nice, eh? The opacity value is not an attribute in the feature class, so in this case, every shape gets the same value (0.6). Then follows a “case” statement, which tests for the value of TYPELANDGEBRUIK and switches to a different object for each value. So when TYPELANDGEBRUIK equals “Grasland” (pasture in Dutch), CityEngine jumps to the definition of the object “Grasland”. Grasland is extruded half a meter upwards, given a nice greenisch color and the opacity is set to opacityvalue. This latter I have choosen, because I want to see the objects underground later on.

Now the rule file is ready, assign the rule file to the layer (by right clicking on the layer “landuse” in the scene navigator) and generate the models (ctrl+G). You will see something like this:

CityEngine 3D Topo rendering

This was not so complicated, was it?

You can do the same with the boreholes, expanding them from points to a square (with the “s” operation), moving a copy from the square downward (with the “t” operation) and extruding them downward:

attr bottom_1 = -5
attr bottom_2 = -10
attr bottom_3 = -15

attr scalefactor = 5

attr dikte1 = bottom_1 * scalefactor
attr dikte2 = (bottom_2 – bottom_1) * scalefactor
attr dikte3 = (bottom_3 – bottom_2) * scalefactor

attr breedte = 5

Boreholes –> s(breedte, breedte, breedte) Ground1
t(0,dikte1,0) Ground2

Ground1–> extrude(dikte1)

Ground2 –> extrude(dikte2)

This is the result:

Cityengine Boreholes


Going 3D: rasters (a.k.a. terrain)

Now we want to visualize the layers in the underground. For this we will use the TIFF files we created in ArcMap. In the Layer menu, choose “New Map Layer…” and choose for the option “Terrain”. Provide a name for the layer and click next. For the heightmap file choose the TIFF we created. If you have a texture file you can use that, or you can use the same TIFF (giving you a black-and-white layer in your scene). I have created a single color TIFF file for each layer, with the same dimensions as the heightmap TIFF. Now comes the tricky part. IN the screenshot, you can see the values I entered in X-size,Z-size, X-offset and Z-offset. The offset I took from the world file (“raster.tfw”), by opening it in notepad and viewing the values on the last two lines. X-offset is the fifth line in the world file, Z-offset is the sixth line. But the X-size and Z-size, I had to establish by trial and error. If you have any better idea please let me know. I came up at the values displayed in the screenshot.

CityEngine Import Raster

After pressing “Finish” the layer is added to the scene. But for a more dramatic impact (my layer’s height is between 2 and 7 meters, which is nothing at this scale), you can add some extra height exaggeration. Click on the layer in the scene navigator, and look at the Inspector window. Below the layer attributes is a window to enter some logic. After importing, it shows:

attr elevation = map_01(brightness, 2.0, 6.9609923) + elevationDelta

Change this to:

attr elevation = -100*(map_01(brightness, 2.0, 6.9609923) + elevationDelta)

This will move the layer underground (because of the negative sign) and exaggerates the height by 100 times.

Our simple 3D model is finished! Time to pat yourself on the back!

Publishing it to ArcGIS Online

If you have a subscription to ArcGIS Online, you can publish the scene and share it with a broader audience. Select all objects by clicking in the Viewport and press ctrl+A. Choose “Export” in the File menu, and choose “Export models of selected shapes and terrain layers”. Choose for “CityEngine Web Scene” and choose a location and a name for the file. Tip: put the file in a subdir of your project, e.g. “Models”. Choose Next and then Finish. After the Web Scene has been created, right click on the 3WS-file in the Project Navigator (maybe refresh the view first if it’s not there yet). Choose the option “Share As” and provide the necessary meta data. Click on “Share” and the webscene will be published to ArcGIS Online.

If you want to see my version as published on ArcGIS Online, click here:

Be aware that published web scenes take some time to load, and are not compatible with Internet Explorer (without installing Google Frame Plugin).

The result:

CityEngine Webviewer


One final tip: if you add the postfix “__water” to any layer, it will render as water with moving waves in the Web Scene. Quite cool!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s