教程 12:脚本报表导出

要访问 CityEngine 中的教程,请单击帮助 > 下载教程和示例。 在选择教程或示例后,系统会自动下载工程并将其添加到您的工作空间。

本教程介绍了如何将 CGA 报表变量与基于 Python 的导出器结合使用。 您将报告场景中所分布实例的信息,并使用该信息在简单的文本文件中生成实例地图。

有关详细信息,请参阅基于脚本的导出

环礁的渲染视图

实例化建筑物的报表信息

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

本教程要求用户具备 CGA 形状语法的基础知识以及编写 API 脚本的基础知识。

使用基于脚本的导出器

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

在本例中,您将执行以下操作:

  • 准备报告所需值的 CGA 命令。
  • 查询在 CGA 规则中为每个生成的模型报告的值。
  • 生成所有模型后,使用已采集的报表值编写一个文本文件。

目标

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

针对每个实例写入以下值:

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

采用以下格式写入值:

nrassetxposxrotxscale

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. 要创建规则文件,单击文件 > 新建 > CityEngine > CGA 规则文件
  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 屏幕截图:

Maya 中的建筑物资产显示枢轴和位置

在报告位置之前修改资产范围,将其缩放为一个很小的针 并以 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 规则添加到建筑物规则的末尾。 请确保在插入命令后添加 Asset. 叶规则,以确保生产资产。

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

生成建筑物,并查看检查器窗口的报表窗格,该窗格应该与以下示例类似:

“检查器”窗口中显示的报表变量

导出脚本

现在,您将使用基于脚本的导出器来处理准备好的报表数据。 为此,您需要创建一个 Python 脚本。 有关详细信息,请参阅基于脚本的导出

Python 脚本导出模板

  1. 要根据模板创建一个 Python 导出脚本,请单击文件 > 新建 > Python > Python 模块
  2. 选择工程的脚本文件夹,将其命名为 exportInstances,并选择模块:导出(报告)作为模板。
    Python 模块向导

模板脚本中包含四个函数。 您只需要 finishModel()finishExport(),所以请将其他两个函数删除。

访问 finishModel() 中的报表数据

您可以按如下方式访问当前处理的形状的报表变量数组,其中 asset 是报表变量的名称:

model.getReports()['asset']

并非所有生成的形状上都具有实例(例如空的地面形状或街道形状),因此您首先需要使用其中一个报表变量(本例中为 'asset')来检查是否存在报表数据:

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

如果仔细查看所生成建筑物的 CGA 规则,您会注意到某些形状包含多个实例。 您需要首先获取 'asset' 数组的长度,从而循环每个形状的所有已报告数据集。 作为第一次测试,请将报表数据数组打印到控制台:

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

运行基于脚本的导出器

  1. 选择一个小型的建筑物或地块形状集。
  2. 针对所选形状,单击文件 > 导出 > CityEngine > 导出模型以启动基于脚本的导出器,然后选择基于脚本的导出器 (Python)
  3. 其他选项选项卡上,浏览至 exportInstances.py 导出脚本,然后单击完成以运行导出器。
    已设置导出脚本的“基于脚本的导出器”对话框

    Python 控制台的输出应类似于以下内容:

    {'zpos': [-362.6108093261719], 'yrot': [-69.42008209228516], 'asset': ...
    {'zpos': [-362.6108093261719], 'yrot': [-69.42008209228516], 'asset': ...
    {'zpos': [-412.1033630371094], 'yrot': [165.30718994140625], 'asset': ...
    ...
    注:

    您可以通过单击菜单 > 窗口 > 显示控制台打开 Python 输出控制台。

    通过工具栏上的控制台切换下拉菜单选择输出控制台。

添加全局变量

现在,您不再将数据打印到控制台,而是添加了一个用于处理和采集报表值的新函数 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  = "%d\t" % count;
	text += "%s\t" % asset;
	text += "%.3f\t%.3f\t%.3f\t" % (reports['xpos'][index],reports['ypos'][index], reports['zpos'][index])
	text += "%.3f\t%.3f\t%.3f\t" % (reports['xrot'][index],reports['yrot'][index], reports['zrot'][index])
	text += "%.3f\t%.3f\t%.3f\n" % (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 = "nr\tasset\txpos\typos\tzpos\txrot\tyrot\tzrot\txscale\tyscale\tzscale\n"

	## combine header and content
	content = head + content

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

运行最终脚本

  1. 选择一个建筑物或地块形状集。
  2. 要启动基于脚本的导出器,单击文件 > 导出 > CityEngine > 导出所选形状的模型,然后选择基于脚本的导出器 (Python)
  3. 其他选项选项卡中,浏览到导出脚本 exportInstances.py 并单击完成以运行导出器。

    生成的文件 instanceMap.txt 随即保存在当前工程的模型目录中。

    nrassetxposxrotxscale

    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 的自定义格式。

其他元素

借助通用报表规则,您现在可以轻松地使用其他实例元素来扩展 CGA 规则集,以便用于报告和导出。

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

该规则文件包含了街道上的未来弧元素。

桥梁资产
沿街道分布的桥梁资产

打开 CGA 规则文件 instance_city_02.cga

使用报表规则

要将桥梁实例导出到 instanceMap,将 InstanceReport 规则添加到 Bridge 规则。

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)

nrassetxpos...

0

bridge3.obj

-363.586952209

...

1

bridge3.obj

-313.587295532

...

...