在 CityEngine 中使用 Python

​ CityEngine的同义词几乎就是“规则建模”,规则指的是CGA脚本。说到脚本,很多用户又会联想到 Python, 衍生出来的问题就是,“CityEngine中是用python脚本建模吗?” 答案是No。

​ CityEngine中确实也引入了python,只不过使用python的姿势不是建模,而是自动化。通过python脚本,可以增强CityEngine的建模功能,自动化驱动脚本建模工作流,提高建模效率。我们既可以在控制台交互式执行python命令,也可以在python editor 中书写python执行文件,甚至可以将一些自定义功能扩展到CityEngine中。如下是CityEngine官方教程中的几个示例代码:

Example 1 选择部分对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'''
Created on 2018-4-9
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

def selectByAttribute(attr, value):
objects = ce.getObjectsFrom(ce.scene)
selection = []
for o in objects:
attrvalue = ce.getAttribute(o, attr)
if attrvalue == value:
selection.append(o)
ce.setSelection(selection)

if __name__ == '__main__':
selectByAttribute("connectionStart","JUNCTION")

Example 2 修改对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'''
Created on 2018-4-9
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

''' increment the street width parameter of all selected street segments'''
# @noUIupdate
def incrementStreetWidths(increment):
selectedSegments = ce.getObjectsFrom(ce.selection, ce.isGraphSegment)
for segment in selectedSegments:
oldWidth = ce.getAttribute(segment, "/ce/street/streetWidth")
newWidth = oldWidth+increment
ce.setAttribute(segment, "/ce/street/streetWidth", newWidth)

if __name__ == '__main__':
incrementStreetWidths(10)

Example 3 动态模拟建筑物生长

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
'''
Created on 2018-4-12
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

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)

def doStep(i,height,width):
object = ce.getObjectsFrom(ce.scene, ce.withName("'Lot1'"))
ce.setAttributeSource(object, "height", "OBJECT")
ce.setAttributeSource(object, "width", "OBJECT")
ce.setAttribute(object, "height", height)
ce.setAttribute(object, "width", width)
Generate(object)

def Generate(object):
ce.generateModels(object)

if __name__ == '__main__':
growBuilding()

Example 4 陈列资源库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
'''
Created on 2018-4-12
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

def writeCGAlib():
# open the cga file to be written
cga = "/*Asset Library Loader : Generated by asset_lib.py*/\n version \"2014.0\"\n\n"
# write start rule
cga += "Lot --> Geometries Textures"
# write rule showing geometries
cga += "\n\nGeometries --> "
# get all .obj files from asset directory, and call their loader
for obj in ce.getObjectsFrom("/", ce.isFile, ce.withName("/Tutorial_10*/assets/*.obj")):
# and write
cga += "\n\t t(2,0,0) Geometry(\""+obj+"\")"
print obj
# write rule showing jpg textures
cga += "\n\nTextures --> \n\ts(1,0,0) set(scope.tz,0) set(scope.ty,3) i(\"facades/xy-plane.obj\")"
# get all .jpg files from asset directory, and call their loader
for jpg in ce.getObjectsFrom("/", ce.isFile, ce.withName("/Tutorial_10*/assets/*.jpg")):
cga += "\n\tt(2,0,0) Texture(\""+jpg+"\")"
#write geometry loader rule
cga += "\n\n Geometry(asset) --> s(1,0,0) i(asset) set(scope.ty,0) set(scope.tz,0)"
#write texture loader rule
cga += "\n\n Texture(asset) --> set(material.colormap, asset)"
cgafile = ce.toFSPath("rules/asset_lib2.cga")
CGA = open(cgafile, "w")
CGA.write(cga)
CGA.close()
print "written file "+cgafile

def assignAndGenerateLib():
object = ce.getObjectsFrom(ce.scene, ce.withName("'Lot2'"))
ce.refreshWorkspace()
ce.setRuleFile(object, "asset_lib2.cga")
ce.setStartRule(object, "Lot")
ce.generateModels(object)

if __name__ == '__main__':
writeCGAlib()
assignAndGenerateLib()

Example 5 扩展CityEngine功能

相关的python功能实现后,确保在CityEngine的python editor中可以正常运行。然后,在CityEngine的工作空间根目录创建 scripting.py 文件,内容如下:

1
2
3
4
5
6
7
import sys

sys.path.append({PATH_TO_YOUR_SCRIPTS_DIRECTORY})
# e.g. sys.path.append("C:\user\CityEngine\MyProject\scripts")

# import customized python module
import myEfficiencyModule

重启CE之后,可以在python编辑器或控制台中直接使用此模块的功能。

1
>>> myEfficiencyModule.selectByAttribute("connectionEnd", "JUNCTION")