要访问教程CityEngine中,单击 帮助>下载教程和例子…。选择教程或示例后,项目会自动下载并添加到您的工作区。

本教程展示了如何将 CGA 报告变量与基于 Python 的导出器结合使用。我们将报告分布在我们场景中的实例的信息,并使用它在一个简单的文本文件中生成一个实例映射。

有关 CityEngine 特定 Python 命令集的更多信息,请参见 CityEngine 帮助:帮助>帮助内容>手册> Python 脚本

GUID-0ABBFA13-C90D-4C3F-AD23-800425355FAC-web
笔记:

Python 脚本接口并非在所有 CityEngine 版本中都可用。

第 1 部分:实例化建筑物的报告信息

在第一部分中,我们将使用现有的 CGA 文件,该文件在我们的场景中分布实例化建筑物,并添加报告变量以准备用于第 2 部分中基于脚本的导出器的实例的附加信息。

本教程需要 CGA Shape Grammar 的基本知识以及 Scripting API 的基础知识。

使用基于脚本的导出器

基于脚本的导出器基本上是一个通过导出触发的 CGA 生成过程。在导出设置中设置并在导出/生成过程中运行的 Python 脚本可以在生成期间和生成之后处理每个模型。

在这个例子中,我们将:

  • 准备报告所需值的 CGA 命令。
  • 为每个生成的模型查询 CGA 规则中报告的值。
  • 生成所有模型后,将收集的报告值写入一个文本文件。

目标

我们想写出一个包含必要数据的文本文件,以便能够在任意后续应用程序中加载分布式建筑实例。

对于每个实例,应写入以下值:

  • 资产标识符
  • 3轴位置
  • 3轴旋转
  • 3轴缩放

采用以下形式:

nr 资产 xpos xrot 比例尺

0

scifi_building_9.obj

-529.4803009

0

1.051229466

1

scifi_building_17.obj

236.6141357

0

0.933861537

2

scifi_building_5.obj

499.4240112

0

1.256899709

 

 

教程设置

  1. 将项目Tutorial_12_Scripted_Report_Export导入您的 CityEngine 工作区。
  2. 打开场景Tutorial_12_Scripted_Report_Export/scenes/reportInstances_01.cej

在外部 CGA 文件中准备通用报告规则

尽管我们可以直接在 CGA 文件instance_city_01.cga 中添加所有必要的报告命令,但我们将编写一个具有通用报告规则的外部 CGA 文件。这样,我们将能够对任意 CGA 文件使用报告规则。

  1. 创建一个新的规则文件File > New … > CityEngine > CGA Rule File
  2. 并将其命名为instanceReporting.cga

    创建一个新规则 InstanceReport。我们需要一个规则参数资产才能报告资产标识符。

    InstanceReport(asset) -->

报告转换数据

资产标识符

我们简单地报告规则参数资产。

## report asset identifier
	report("asset", asset)

规模

在大多数情况下,需要相对于原始资产大小的比例。因此,我们不能仅报告范围大小,而需要将其除以资产大小。可以使用assetInfo()命令查询原始资产大小。assetInfo(asset, “sx”)查询 x 轴的大小。

因此,规模的报告命令是:

## report scale values relative to asset
	report("xscale", scope.sx/assetInfo(asset, "sx"))
	report("yscale", scope.sy/assetInfo(asset, "sy")) 
	report("zscale", scope.sz/assetInfo(asset, "sz"))

回转

我们要报告世界坐标中的旋转,因此需要使用 convert() 命令在 CityEngine 中转换枢轴旋转:

## report rotation in world coords
	report("xrot", convert(x, pivot, world, orient, 0,0,0))
	report("yrot", convert(y, pivot, world, orient, 0,0,0))
	report("zrot", convert(z, pivot, world, orient, 0,0,0))

位置

位置是最棘手的部分。为了能够在后续应用程序中正确地实例化您的资产,重要的是要注意所用资产的枢轴和位置。在我们的例子中,资产的支点位于地平面上的中心,并位于世界原点。请参阅下面的 Maya 屏幕截图以进行说明:

GUID-ABCC7E6E-6687-4CE1-9C5B-5486646FBF6F-web

因此,在报告头寸之前,我们将按以下方式修改资产范围:范围被缩放为一个小“针”,并以 x 和 z 为中心。通过这种方式,我们确保报告的位置对应于 Maya 中资产的枢轴。

## scale and center scope
	s(0.0001,'1,0.0001) center(xz)

同样,位置需要转换为世界坐标:

## report position in world coords
	report("xpos", convert(x, scope, world, pos, 0,0,0))
	report("ypos", convert(y, scope, world, pos, 0,0,0))
	report("zpos", convert(z, scope, world, pos, 0,0,0))

我们现在已经报告了所有必需的值。为了确保视口中没有显示不需要的几何图形,我们在报告规则的末尾添加了一个 NIL 命令。最终报告规则:

InstanceReport(asset) -->

	## report instance ID
	report("asset", asset)	
	
	## report scale values relative to asset
	report("xscale", scope.sx/assetInfo(asset, "sx"))
	report("yscale", scope.sy/assetInfo(asset, "sy")) 
	report("zscale", scope.sz/assetInfo(asset, "sz"))

	## report rotation in world coords
	report("xrot", convert(x, pivot, world, orient, 0,0,0))
	report("yrot", convert(y, pivot, world, orient, 0,0,0))
	report("zrot", convert(z, pivot, world, orient, 0,0,0))

	## scale and center scope
	s(0.001,'1,0.001) center(xz)
	
	## report position in world coords
	report("xpos", convert(x, scope, world, pos, 0,0,0))
	report("ypos", convert(y, scope, world, pos, 0,0,0))
	report("zpos", convert(z, scope, world, pos, 0,0,0))

	NIL

使用报告规则

让我们回到原始 CGA 规则文件并使用准备好的报告规则。在文件instance_city_01.cga的开头,添加以下行以导入 ID 为instanceReporting的准备好的报告规则文件。

import instanceReporting:"instanceReporting.cga"

现在我们只需将 InstanceReport 规则添加到构建规则的末尾。确保还添加叶规则“资产”。在插入命令之后以确保生成资产。

Building(asset) --> 
	s('1,0,'1) 
	i(asset) Asset.
	instanceReporting.InstanceReport(asset)

现在生成一个建筑物,然后查看 Inspector 的 Reports 窗格,它应该类似于:

GUID-633E1235-B475-4722-BE63-430FAF3BBEDC-web

 

笔记:

Inspector 中的 Reports 窗格仅用于统计报告,并不显示所有值(例如不显示字符串)。但是,在我们的案例中可以使用它来确保报告所有必需的值。

第 2 部分:导出脚本

我们现在将使用基于脚本的导出器处理准备好的报告数据。为此,我们需要创建一个新的 Python 脚本来完成这项工作。

Python 脚本导出模板

  1. 从模板File > New … > Python > Python Module创建一个新的 python 导出脚本。
  2. 选择项目的脚本文件夹,将其命名为 exportInstances 并选择 Module:Export (Reporting) as template。
    GUID-9D3AB2EC-0F16-4F88-AD60-D485CA05F3D5-web

模板脚本包含四个函数。我们只需要finishModel()finishExport(),所以删除另外两个。

在 finishModel() 中访问报告数据

可以通过以下方式访问当前处理形状的报表变量数组:

model.getReports()['asset']

其中资产是报告变量的名称。

因为并非所有生成的形状都有一个实例(例如空的地面形状或街道形状),我们首先需要使用报告变量之一检查报告数据的存在,即“资产”:

if(model.getReports().has_key('asset')):

如果您详细查看生成的建筑物的 CGA 规则,您会注意到某些形状包含多个实例。因此,我们需要首先获取“资产”数组的长度,遍历每个形状的所有报告数据集。作为第一个测试,我们将报告数据数组打印到控制台:

l = len(model.getReports()['asset'])
		for i in range(0,l): 
			print model.getReports()

运行基于脚本的导出器

  1. 选择一小组建筑物或地块形状
  2. 启动基于脚本的导出器:文件>导出 … > CityEngine >导出选定形状的模型,然后选择基于脚本的导出器 (Python)
  3. 杂项。Options 选项卡,浏览到导出脚本 exportInstances.py并通过单击Finish运行导出器。
    GUID-E0554A0D-2EFA-4CE0-AA52-5845DCB48F51-web

    Python 控制台输出应读取以下形式的内容:

    {‘zpos’:[-362.6108093261719],’yrot’:[-69.42008209228516],’资产’:…

    {‘zpos’:[-412.1033630371094],’yrot’:[165.30718994140625],’资产’:…

    笔记:

    Python 输出控制台可以通过 Menu Window > Show Console打开。

    使用工具栏上的控制台开关下拉菜单选择输出控制台。

添加全局变量

我们现在没有将数据打印到控制台,而是添加一个新函数 processInstance() 来处理和收集报告值。此外,我们添加了两个全局变量(在完成模型函数之外),用于收集数据并跟踪实例计数:

# Globals
gInstanceData = "" # global string that collects all data to be written
gInstanceCount = 0 # global count to enumerate all instances

finishModel() 函数

完成的函数finishModel():

# Called for each initial shape after generation.
def finishModel(exportContextOID, initialShapeOID, modelOID):
	global gInstanceData, gInstanceCount
	model = Model(modelOID)
	if(model.getReports().has_key('asset')): # only write t3d entry if report data available
		# there might be more than one asset per model, therefore loop
		l = len(model.getReports()['asset'])
		for i in range(0,l):
			instanceData = processInstance(model.getReports(),gInstanceCount, i-1)
			gInstanceData = gInstanceData+instanceData
			gInstanceCount = gInstanceCount+1

processInstance() 函数

此函数仅以制表符分隔的字符串形式返回所有报告变量:

''' Collect the instance information in a tab-separated string''' 
def processInstance(reports, count, index):

	## remove path from asset string
	asset = reports['asset'][index]
	asset = asset.rpartition("/")[2]

	## prepare the string for the instance map
	text  = "%dt" % count;
	text += "%st" % asset;
	text += "%.3ft%.3ft%.3ft" % (reports['xpos'][index],reports['ypos'][index], reports['zpos'][index])
	text += "%.3ft%.3ft%.3ft" % (reports['xrot'][index],reports['yrot'][index], reports['zrot'][index])
	text += "%.3ft%.3ft%.3fn" % (reports['xscale'][index], reports['yscale'][index], reports['zscale'][index])
	return text

FinishExport() 函数

在所有形状生成完成后调用此函数。我们在这里定义包含实例映射的文本文件的文件名,并调用 writeFile() 函数:

# Called after all initial shapes are generated.
def finishExport(exportContextOID):
	global gInstanceData, gInstanceCount

	## path of the output file
	file = ce.toFSPath("models")+"/instanceMap.txt"


	## write collected data to file
	writeFile(file, gInstanceData)
	print str(gInstanceCount)+"instances written to "+file +"n"

writeFile() 函数

… 添加标题信息并将收集到的报告字符串写入磁盘:

''' combining data (header and content) and writing file '''
def writeFile(file, content):

	## prepare the head string
	head = "nrtassettxpostypostzpostxrottyrottzrottxscaletyscaletzscalen"

	## combine header and content
	content = head + content

	## write data to the file
	report = open(file, "w")
	report.write(content)
	report.close()

运行最终脚本

  1. 选择一组建筑物或地块形状。
  2. 启动基于脚本的导出器:File > Export … > CityEngine > Export Models of selected Shapes并选择Script Based Exporter (Python)
  3. 杂项。Options 选项卡,浏览到导出脚本exportInstances.py并通过单击Finish运行导出器。

    生成的文件 instanceMap.txt 保存在当前项目的模型目录中。

    nr 资产 xpos xrot 比例尺

    0

    scifi_building_9.obj

    -529.4803009

    0

    1.051229466

    1

    scifi_building_17.obj

    236.6141357

    0

    0.933861537

    2

    scifi_building_5.obj

    499.4240112

    0

    1.256899709

     

    您可以以任意方式处理报告的数据,而不是编写制表符分隔的文本文件:例如,为创建实例的 Maya 编写 Mel 脚本、将位置信息写入数据库或编写基于 ASCII 的自定义格式。

第 3 部分:附加元素

多亏了通用报告规则,我们现在可以使用额外的实例元素轻松扩展我们的 CGA 规则集以进行报告和导出。

  • instance_city_02.cga分配给场景中的所有形状。
  • 生成一些街道形状

此规则文件包括街道上的未来弧形元素。

GUID-6F29925C-88EF-4D55-B02F-00462A1D2475-web
GUID-35823839-A8C1-400A-A381-936830ECAEFE-web

打开 CGA 规则文件instance_city_02.cga

使用报告规则

为了将网桥实例也导出到 instanceMap,只需将 InstanceReport 规则添加到网桥规则即可。

Bridge --> 
	s(1,8,scope.sz+3.2) center(xz) 
	i(bridge_asset) 
	s(calcHeight2(scope.sx),calcHeight2(scope.sy),'1)
	Bridge.
	instanceReporting.InstanceReport(bridge_asset)

nr 资产 xpos

0

桥接3.obj

-363.586952209

1

桥接3.obj

-313.587295532