核心概念:CGA 与 Python 的关系
首先要明确一个关键点:在 CityEngine 中,CGA (计算机生成建筑) 语言是用于生成 3D 模型的核心脚本语言,而 Python 在 CityEngine 中扮演着“元脚本”(Meta-Script)的角色,它不直接生成几何体,而是用来:

- 控制 CGA 脚本:动态地修改 CGA 文件中的参数、属性或规则。
- 管理场景和文件:批量创建、删除、重命名场景中的对象,或读写文件。
- 自动化工作流:将一系列重复的手动操作(如导入数据、生成模型、导出模型)整合成一个 Python 脚本一键执行。
- 与外部系统交互:通过 API 获取外部数据(如数据库、Web API),并驱动 CityEngine 场景。
你可以这样理解它们的关系:
- CGA:是“设计师”,负责根据蓝图(规则)和材料(属性)建造具体的房子(3D模型)。
- Python:是“项目经理”,负责告诉设计师用什么蓝图、用什么材料、建多少栋房子,并管理整个建筑工地的流程。
Python 脚本的主要应用场景
1 参数化控制
这是最常用的功能,你可以在 CGA 规则中定义参数,然后在 Python 脚本中动态地修改这些参数,从而在不重新编写 CGA 代码的情况下,生成形态各异的建筑。
CGA 示例 (building.cga):
@StartRule Lot --> extrude(height) // 使用 height 参数进行拉伸
Python 示例:

# 获取场景中选中的对象
selected = ce.getSelection()
# 遍历选中的对象
for obj in selected:
# 获取对象关联的 CGA 规则文件
rule_file = obj.getRuleFile()
# 设置 CGA 参数 'height' 的值为 50.0
ce.setRuleParameters(rule_file, {"height": 50.0})
# 重新生成模型
obj.generate()
2 批量处理
当你需要对成百上千个地块或建筑进行统一操作时,Python 的威力就体现出来了。
Python 示例 (批量设置地块高度):
# 获取场景中所有类型为 'Street' 的对象
streets = ce.getObjects("Street")
for street in streets:
# 获取其关联的规则
rule_file = street.getRuleFile()
# 设置参数
ce.setRuleParameters(rule_file, {"streetWidth": 10.0, "streetHeight": 2.0})
# 重新生成
street.generate()
print(f"已处理 {len(streets)} 条街道。")
3 场景与文件管理
Python 可以让你以编程方式管理整个 CityEngine 项目。
Python 示例 (批量导入 Shapefile):

import os
# 定义要导入的文件夹路径
data_folder = r"C:\path\to\your\shapefiles"
# 遍历文件夹
for filename in os.listdir(data_folder):
if filename.endswith(".shp"):
shp_path = os.path.join(data_folder, filename)
# 创建一个新的图层来导入数据
layer_name = os.path.splitext(filename)[0]
new_layer = ce.createLayer(layer_name)
# 执行导入操作
ce.importShapefile(new_layer, shp_path)
print(f"已导入: {shp_path}")
print("所有 Shapefile 导入完成。")
4 自定义工具与 UI
你可以创建带有图形用户界面的 Python 脚本,将其作为插件嵌入到 CityEngine 中,方便非技术人员使用。
Python 示例 (创建一个简单的对话框):
from javax.swing import JOptionPane
# 弹出一个输入对话框
user_input = JOptionPane.showInputDialog(
ce.getUI(),
"请输入建筑高度:",
"批量设置高度",
JOptionPane.QUESTION_MESSAGE
)
# 检查用户是否点击了“取消”
if user_input is not None:
try:
height = float(user_input)
# 获取选中对象并设置参数 (同上)
selected = ce.getSelection()
for obj in selected:
ce.setRuleParameters(obj.getRuleFile(), {"height": height})
obj.generate()
print(f"已将 {len(selected)} 个对象的高度设置为 {height}")
except ValueError:
JOptionPane.showMessageDialog(ce.getUI(), "请输入有效的数字!", "错误", JOptionPane.ERROR_MESSAGE)
CityEngine Python API 核心模块
CityEngine 提供了一个强大的 Python API,主要包含以下几个模块:
ce: 核心模块,提供最常用的功能,如场景操作、对象管理、规则控制等。90% 的日常操作都通过这个模块完成。ce.gui: 图形用户界面模块,用于创建自定义对话框、按钮等。ce.script: 脚本相关模块,提供一些辅助功能。math,os,sys: Python 标准库,可以直接使用。
ce 模块常用函数列表:
| 功能类别 | 函数 | 说明 |
|---|---|---|
| 场景与图层 | ce.getScene() |
获取当前场景对象。 |
ce.createLayer(name) |
创建一个新的图层。 | |
ce.getObjects(type) |
根据类型(如 "Building", "Street")获取场景中的对象列表。 | |
| 对象操作 | ce.getSelection() |
获取当前选中的对象列表。 |
obj.getShape() |
获取对象的几何形状。 | |
obj.getRuleFile() |
获取对象关联的 CGA 规则文件路径。 | |
obj.generate() |
重新生成对象。 | |
| 规则与参数 | ce.setRuleParameters(rule_file, params_dict) |
设置 CGA 文件的参数。params_dict 是一个字典,如 {"height": 30, "color": "red"}。 |
ce.getRuleParameters(rule_file) |
获取 CGA 文件的当前参数。 | |
| 文件与路径 | ce.resolvePath(path) |
将相对路径解析为绝对路径。 |
ce.export(filepath, obj, format) |
导出对象到指定格式的文件(如 obj, objk, glb)。 |
|
| UI 交互 | ce.getUI() |
获取 CityEngine 的主窗口对象。 |
ce.warning(msg), ce.info(msg) |
在 CityEngine 的脚本控制台显示信息或警告。 |
如何编写和运行 Python 脚本
-
打开脚本编辑器:
- 在 CityEngine 界面顶部菜单栏选择
Windows > Scripting。 - 或者使用快捷键
Ctrl + 6(Windows/Linux) 或Cmd + 6(macOS)。
- 在 CityEngine 界面顶部菜单栏选择
-
编写脚本:
- 脚本编辑器会打开一个新的 Python 文件。
- 将上面的示例代码粘贴进去。
-
运行脚本:
- 点击脚本编辑器工具栏上的 "Run" 按钮(一个绿色的播放图标)。
- 脚本的输出和错误信息会显示在底部的 "Console" 窗口中。
实战案例:创建一个随机城市
这个案例将结合前面提到的知识点,创建一个简单的脚本来批量生成不同高度的建筑。
步骤 1: 准备 CGA 规则 (simple_building.cga)
创建一个简单的 CGA 文件,至少包含一个 height 参数。
@StartRule
Building -->
# 将 height 参数赋值给局部变量 h
h = scope.height
extrude(h)
# 可以添加一个简单的屋顶
Roof -->
Roof -->
primitiveCube()
s('1, 1, 0.1) // 缩小一点,作为屋顶
t(0, 0, scope.sy) // 向上移动到建筑顶部
步骤 2: 在场景中创建一些地块
在 CityEngine 场景中手动创建几个 Building 类型的地块,并将 simple_building.cga 规则文件拖拽到它们上面。
步骤 3: 编写 Python 脚本
在脚本编辑器中运行以下 Python 代码:
import random
# 1. 获取场景中所有类型为 'Building' 的对象
buildings = ce.getObjects("Building")
if not buildings:
ce.warning("场景中没有找到 'Building' 对象,请先创建一些地块。")
else:
print(f"找到 {len(buildings)} 个建筑对象,开始处理...")
# 2. 遍历每个建筑对象
for i, building in enumerate(buildings):
# 3. 生成一个随机高度 (20 到 80 米之间)
random_height = random.uniform(20, 80)
# 4. 获取该建筑的规则文件
rule_file = building.getRuleFile()
# 5. 设置 CGA 参数 'height'
# 注意:参数名必须与 CGA 文件中的 scope.height 完全一致
params = {"height": random_height}
ce.setRuleParameters(rule_file, params)
# 6. 重新生成建筑模型
building.generate()
print(f"建筑 {i+1}/{len(buildings)}: 高度已设置为 {random_height:.2f} 米")
print("所有建筑随机化完成!")
运行结果: 运行脚本后,你会看到场景中的所有建筑高度都发生了变化,并且每个建筑的高度都是随机生成的,这个简单的例子展示了 Python 如何高效地控制 CGA 规则,实现复杂的批量自动化任务。
CityEngine 的 Python 脚本是连接数据、逻辑和 3D 模型的强大桥梁,它让你能够:
- 解放生产力:将手动、重复的工作自动化。
- 实现真正的参数化设计:不仅仅是调整几个滑块,而是通过数据驱动整个场景的生成。
- 扩展 CityEngine 的能力:通过自定义工具和与外部系统集成,打造专属的工作流。
对于希望从 CityEngine 用户迈向高级用户或技术美术的人来说,熟练掌握 Python 是一项必备技能,建议从简单的参数控制和批量处理开始,逐步尝试更复杂的场景管理和 UI 开发。
