Tutorial 10 - Python scripting-ArcGIS CityEngine Resources - Documentation
Tutorial 10 - Python scripting-ArcGIS CityEngine Resources - Documentation
2024.12024.02023.12023.02022.12022.02021.1
To access the tutorial projects in ArcGIS CityEngine, open CityEngine and click Help > Download Tutorials and Examples in the main menu. After
choosing a tutorial or example, the project is automatically downloaded and added to your CityEngine workspace.
In this tutorial, you'll learn the basic usage of the Python console and the editor and explore several examples of the automatization of CityEngine tasks.
5. Type ce.setS :
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 1/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
You'll notice as you start typing, a list of commands appear that you can choose from: Your first CityEngine Python command allows you to quickly
select scene objects with a specific name:
Press Ctrl+Space to show the command completion pop-up if it isn't already open.
6. Double-click ce.setSelection in the list to complete the entry in the console.
7. Extend ce.setSelection to the following full command:
8. Press Enter to select all the objects in the scene that contain the word "Broadway" in their name.
When you want to use longer and more advanced Python commands or a set of commands, it's helpful to write a script using the Python editor in
CityEngine.
1. Select File > New > Python > Python Module and click Next to open the Create a new Python module dialog box.
2. On the Create a new Python module dialog box, for Source Folder, browse to the \Tutorial_10_Python_Scripting\scripts\ folder and click OK.
3. in the Name box, type myHelpers.
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 2/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
6. Click OK.
The new myHelpers Python module is created as the myHelpers.py file in the scripts folder and opens in the Python editor:
7. Add the new selectByAttribute(attr, value) function after the line ce = CE(). Ensure that you insert the code above the main function.
objects = ce.getObjectsFrom(ce.scene)
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 3/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
selection = []
for o in objects:
if attrvalue == value:
selection.append(o)
ce.setSelection(selection)
This function loops through all objects in the scene and reads the value of the attribute passed as the first parameter. It then compares the value
to the value passed as the second parameter, and if they match, appends the object to the selection.
8. Select a street shape in the scene and click Object Attributes in the Inspector window to explore the available attributes:
9. Since you want the script to select all streets that are connected to a junction, add the function call with specific parameters to the main clause of
the script:
if __name__ == '__main__':
selectByAttribute("connectionStart","JUNCTION")
Alternatively, you can call functions in scripts directly in the Python console.
1. In the Python console, add the path containing the module you just created to the system path.
>>> sys.path.append(ce.toFSPath("scripts"))
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 4/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
To create and load the scripting.py script at the startup of CityEngine, do the following:
1. Create a file named scripting.py in your CityEngine workspace using the file browser of your operating system.
Save the scripting.py file in the CityEngine workspace root folder, such as \{CityEngine Workspace}\scripting.py.
Tip:
You can find the path under File > Workspace > Other or right-click a project in the Navigator window and select Show in File Manager.
2. Add the following lines to automatically map the helper script at startup:
ce = CE()
import sys
sys.path.append(ce.toFSPath("/Tutorial_10_Python_Scripting__2021_1/scripts"))
import myHelpers
3. Restart CityEngine and open the 01_PythonScripting.cej scene to automatically load the myHelpers module.
4. Directly call the helper function from the Python console to verify that the automatic loading is working:
>>> myHelpers.selectByAttribute("sidewalkWidthLeft", 4)
All streets in which the sidewalkWidthLeft object attribute has a value of 4 are selected.
Note:
You can add arbitrary code to the scripting.py file. The scripting module runs automatically when a new Python console is opened or a script is run
from the Python editor.
Ensure that your scripting.py file is valid and runs correctly; otherwise, Python code in CityEngine cannot be run. Open a Python console in
CityEngine after you create or modify a scripting.py file; problems with running the scripting file are displayed there.
The scripting.py file is read only once on CityEngine startup. If you modify the file, be sure to restart CityEngine.
If the script is not correctly updated on CityEngine startup, delete the Python cache directory
$USER_DIR/.cityengine/$CEVERSION_DIR/pythonCache/.
incrementStreetWidths() function
In this section, you'll create a function to increment the streetWidths attribute of all the selected street segments from a value specified by the user.
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 5/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
2. Create a new Python module called setStreetWidths.
To create a new module, follow Steps 1 through 6 in the Create a Python module in the editor section above.
def incrementStreetWidths(increment):
4. In the function, get all selected segments and loop over them:
5. In the for loop, in order to calculate the new street width, first get the current value using the ce.getAttribute() command:
Notice, that the syntax of the attribute name with the prefix /ce/street/ accesses the user attributes of the object. See Parameters and attributes
for more information.
6. Finally, calculate the new street width by adding the user-provided parameter increment and assigning the new value to the segment:
newWidth = oldWidth+increment
def incrementStreetWidths(increment):
newWidth = oldWidth+increment
7. In the main block of the script, add the function call and choose an increment:
if __name__ == '__main__':
incrementStreetWidths(10)
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 6/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
Running the previous script may take some time if there are many segments selected. This is because scripts in CityEngine run in a separate thread and
update the GUI and the Viewport window after every command. In this case, the street network is updated after every setAttribute() call and the viewport
is redrawn.
To make run time faster, add the @noUIupdate decorator above the function definition:
@noUIupdate
def incrementStreetWidths(increment):
Functions marked this way block GUI update during execution, and depending on what they do, run faster by factors.
Caution:
Some combination of scripting commands with the @noUIupdate decorator may freeze the user interface.
If you encounter a UI freeze or other unexpected behavior when using @noUIupdate, modify your scripts so that @noUIupdate only marks a small
specific function rather than marking your whole script.
multiplySegmentWidths() function
The multiplySegmentWidths() function sets several attributes at the same.time, specifically, the streetWidth, sidewalkWidthLeft, and sidewalkWidthRight
attributes.
def multiplySegmentWidths(factor):
newval = oldval*factor
2. Replace the function call in the main block with the following:
multiplySegmentWidths(1.5)
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 7/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
Notice that the street widths change much faster because the UI isn't refreshed after every change.
Click Yes when asked "Would you like to regenerate these models?"
If the building is not generated, select the lot and click Generate (Ctrl+G) on the toolbar.
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 8/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
The rule file includes attributes to change the dimensions of the building. Rather than manually setting these values in the Inspector window,
you'll write a script that changes the values and batch generates the different versions of the model.
Animation script
def growBuilding():
for i in range(1,14):
height = 20+i
doStep(i,height,1)
for i in range(15,35):
height = 34
width = i-14
doStep(i,height,width)
3. Use the doStep function to modify the height and width attributes on the lot object:
def doStep(i,height,width):
Generate(object)
def Generate(object):
ce.generateModels(object)
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 9/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
if __name__ == '__main__':
growBuilding()
8. To batch export the models. add the Export function. Ensure that it is before the main clause:
dir = ce.toFSPath("models")
settings = OBJExportModelSettings()
settings.setBaseName(file)
settings.setOutputPath(dir)
# do export
ce.export(object, settings)
#Generate(object)
Export(i, object)
The models are batch exported to the models folder in the project.
The Python script writes the rule file with the following structure:
Geometries -->
Geometry(assetpath)
Geometry(assetpath)
...
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 10/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
def writeCGAlib():
5. Write the Geometries rule and get all .obj files in the asset folder; prepare the Geometry(assetpath) rule call for each asset:
8. Open a file handle for the .cga file and write the CGA content:
cgafile = ce.toFSPath("rules/asset_lib.cga")
CGA.write(cga)
CGA.close()
def assignAndGenerateLib():
ce.refreshWorkspace()
ce.setRuleFile(object, "asset_lib.cga")
ce.setStartRule(object, "Lot")
ce.generateModels(object)
The function assigns the generated .cga file to a scene lot and generates the model.
if __name__ == '__main__':
writeCGAlib()
assignAndGenerateLib()
ce.newFile('/scenes/emptyScene.cej')
# load a database
importSettings = FGDBImportSettings()
importSettings.setDatasetFilter(['/'+layerName])
ce.importFile(ce.toFSPath(pathFGDB), importSettings)
ce.setRuleFile(shapes, ruleName)
ce.setStartRule(shapes, startRule)
exportSettings = KMLExportModelSettings()
exportSettings.setOutputPath(ce.toFSPath("models"))
exportSettings.setBaseName(layerName)
exportSettings.setCompression(True)
ce.export(shapes, exportSettings)
# close Scene
ce.waitForUIIdle()
ce.closeFile()
For testing, add a call to this function in the '__main__' section. The provided fgdbToKml example imports shapes from a fileGDB to generate
models and writes them out to KML:
if __name__ == '__main__':
fgdbToKml("data/CityData.gdb", "Footprints",
"/ESRI.lib/rules/Buildings/Building_From_Footprint.cga", "Generate")
pass
3. Save and press F9 to test whether everything is working properly. After completion, the models folder contains the Footprints.kmz file.
Delete the Footprints.kmz file, as you'll create this again in a later step.
4. To automate this process, you'll need to put all the function parameters, used for testing the function above, into a configuration file.
The tutorial project includes an example jobConfig.cfg file located in the data folder:
[config]
pathFGDB=data/CityData.gdb
layerName=Footprints
ruleName=/ESRI.lib/rules/Buildings/Building_From_Footprint.cga
startRule=Generate
5. In the automationJob.py script, add the run(cfg) and getCfgValue(cfg,name) functions below the fgdbToKml function in order to run the
automation job with the parameters stored in the configuration file:
def getCfgValue(cfg,name):
for c in cfg:
return None
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 12/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
def run(cfg):
pathFGDB = getCfgValue(cfg,'pathfgdb')
layerName = getCfgValue(cfg,'layername')
ruleName = getCfgValue(cfg,'rulename')
startRule = getCfgValue(cfg,'startrule')
For your reference, you can open the automationJob_dist.py file in the scripts folder.
6. Next, create a separate CityEngine workspace for automation by clicking File > Switch Workspace > Other.
7. Copy the \scripts\startup.py script from the tutorial project to the new C:\Automation Workspace\ root directory:
if __name__ == '__startup__':
ce = CE()
projectFolder = lang.System.getProperty("projectFolder")
configFilePath = lang.System.getProperty("configFilePath")
cp = ConfigParser.ConfigParser()
cp.read(configFilePath)
sys.path.append(ce.toFSPath("/automationProject/scripts"))
import automationJob
automationJob.run(cfg)
ce.exit()
Commands in the '__startup__' section of this Python script are automatically run at startup of CityEngine. The first startup argument defines the
CityEngine project containing the automation job. It is linked into the automation workspace. The second argument contains the config file. It is
parsed and handed over to the automation job as a list of (name,value) pairs. After the job finishes, CityEngine is safely shut down.
8. Open the command line and start CityEngine in the automation workspace, and hand over the job definition and parameters:
-DprojectFolder=<Project_Folder> -DconfigFilePath=<Configuration_FilePath>
@ Example:
-DprojectFolder="C:\CE_Workspace\Tutorial_10_Python_Scripting__2021_1"
-DconfigFilePath="C:\CE_Workspace\Tutorial_10_Python_Scripting__2021_1\data\jobConfig.cfg"
After the job has finished, the models folder contains the Footprints.kmz output file which you can then open if you like in ArcGIS Earth:
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 13/14
15/05/2025 11:01 Tutorial 10: Python scripting—ArcGIS CityEngine Resources | Documentation
Note:
The automationJob.py file contains a minimal job. Use the CityEnginePython reference to adapt it to your needs.
To continue your learning with CityEngine, see the complete CityEngine tutorial catalog.
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-10-python-scripting.htm 14/14