前言
本示例根据先前示例中使用的interopolis 3DS模型创建了一个简单的纹理化CityGML模型。CityGML是用于表示3D城市和景观的OGC标准化GML应用模式,它具有非常严格的对象类型的分层表示,可以通过不同的细节级别在单个文件中表示城市模型的多种层次。例如,您可以在单个模型中构建具有不同细节级别的建筑模型和带有家具的建筑内部。
在上一个示例“向3D城市模型中添加不同的纹理”中,我们获取了interopolis的3DS模型,并向屋顶和墙壁添加了不同的纹理,写入了3D PDF中。而现在,我们将使用相同的完整工作空间,并对其进行修改以创建纹理化的CityGML模型。
步骤说明
1. 下载工作空间模板
下载文末提供的3ds-to-3dpdf-textures.fmwt作为您的开始工作空间,并在FMEWorkbench中打开它。这是在先前示例中已完成的工作空间,而我们将以此为基础创建纹理化的CityGML模型。
2. 替换Adobe PDF写模块
用CityGML写模块替换已有的Adobe PDF写模块。在添加CityGML写模型时,请设置参数如下:
在“添加写模块”对话框中,确保在“添加要素类型”下将“要素类型定义”设置为“从数据集导入”。此外CityGML具有预定义的架构,必须用于数据合规性和正确的CityGML写入。设置好之后,选择确定即可。
在随后弹出的“导入写模块要素类型”对话框中,点击parameter,进入CityGML Parameters对话框,检查是否将CityGML Version设置为CityGML1.0。使用不同的版本将会为我们提供不同的CityGML模式设置,在此我们希望能够写出1.0版本中的屋顶表面和墙壁表面,故而选择1.0版本。之后点击确定,返回上一对话框,将数据集留空,选择OK即可。
之后将弹出选择要素类型对话框,此处只需勾选建筑、屋顶表面和墙壁表面即可。
3. 删除GeometryCoercer转换器
接下来,删除最后一个GeometryCoercer转换器,因为我们不再希望将所有对象组合在一起作为一个单一的网格。CityGML的数据模型将使我们能够将屋顶和墙壁分开,作为建筑对象的子元素。
4. 为“Building”要素类型连接新的CityGML ID
每一个CityGML要素都需要一个唯一的ID,在此我们将使用BuildingID属性(该属性可以判定哪些要素隶属于哪个建筑)来为我们的“Building”要素类型创建ID。由于CityGML要素ID不能以数字开头,因此我们将使用StringConcatenator转换器在BuildingID之前添加字符串“GML_”。将Aggregator转换器输出端口与StringConcatenator进行连接。打开StringConcatenator参数对话框,设置New Attribute为gml_id,在String Parts栏,请设置如下:
5. 删除几何
实际操作中,我们并不想将任何几何写入CityGML Building要素类型,恰恰相反,我们只是想创建一个空的高级类,去作为屋顶和墙壁表面的父ID属性,若有需要,此ID也可以允许我们将建筑的屋顶和墙壁表面组合在一起。通过将GeometryRemover转换器与StringConcatenator转换器进行连接,可以达到删去几何的目的。
之后,连接GeometryRemover的输出端口到Building要素类型的写模块即可。
创建自定义转换器
在接下来的几个步骤中,我们将创建自定义转换器。
6. 通过Building ID聚合墙壁要素
我们需要将每个建筑的所有墙壁组合成单个的多表面几何。具体操作为,将一个Aggegator转换器连接到构建墙壁纹理的AppearanceSetter转换器的输出端口,并确保“group by”设置为BuildingID。
7. 创建CityGML属性
CityGML要素需要定义它们的细节级别和几何类型。在FME中,这些信息都存储在“GeometryTraits”中。在往几何中添加特征之前,我们需要使用AttributeCreator转换器创建属性,参数填写如下:
创建第一个属性citygml_level_of_detail,并将其值设置为2。这意味着我们希望我们的墙壁要素细节级别为2。在本文示例中,我们只有一个细节级别,但在单个CityGML文件中可以有多个细节级别。
创建第二个属性citygml_lod_name,并将其赋值为lod2MultiSurface。这是CityGML的几何类型,表明我们使用的是细节级别为2的多面几何。
创建第三个属性citygml_feature_role,并将其赋值为boundedBy。该属性定义了要素与其父类要素之间的关系。
8. 将几何类型属性复制到Geometry Traits中
现在我们已经将几何类型存储到属性中,接下来需要使用GeometryPropertySetter转换器将其复制到Geometry Traits中。Geometry Traits与属性类似,但存储在几何中,而不是与几何并行。具体操作为,打开GeometryPropertySetter参数对话框,下拉选择设置“Source Attribute”为citygml_lod_name
9. 创建唯一ID
CityGML要求每个要素都必须具有唯一的ID,使用UUIDGenerator转换器将为要素创建唯一ID,并将其分配到属性_uuid。
10. 将前缀“GML_”与属性“_uuid”连接起来
UUIDGenerator转换器创建的唯一ID是以数字开头的,而这在CityGML中是无效的。与上述的建筑类设置操作类似,我们将使用StringConcatenator转换器在每个ID的开头添加“GML_”,并在转换器参数中设置New Attribute为“gml_id”,然后设置String Parts栏内容如下:
填写参数后自动生成的ID连接结果应如下所示:
11. 使用另一个StringConcatenator定义父ID
我们需要定义父要素的ID,以便FME能够在CityGML模型中正确构建层次结构。复制为上面的建筑类创建的gml_id,添加另一个StringConcatenator转换器,将“New Attribute”重命名为gml_parent_id,并如下设置String Parts栏:
12. 创建自定义转换器
确保构建墙壁纹理的AppearanceSetter转换器的输出端口连接到Aggregator_2。选中步骤6(Aggregator2)到步骤11(StringConcatenator3)中的所有转换器,右键单击并选择“创建自定义转换器”,将其命名为CityGMLBuilder,将Category设置为3D,然后点击OK即可。现在,您将在界面顶部功能区选项卡中的main选项卡旁边看到它,而在这里您将转到组成自定义转换器的转换器。
在自定义转换器界面,右键点击InsertTransformer Input,添加转换器输入端口Aggregator_2_Input,并确保在“External Attribute to Expose”下勾选了BuildingID。这一步很重要,因为CityGMLBuilder的最后一个StringConcatenator转换器依赖于此属性作为其参数的一部分。由于该属性是在自定义转换器外部创建的,因此StringConcatenator转换器在BuildingID作为外部属性被勾选公开前,无法将该属性识别为有效属性。
您可能会注意到您的转换器还没有设置输出端口。要添加输出端口只需右键点击工作空间,并选择Insert Transformer Output,即可生成。设置好后,将输出端口连接到String_Concatenator_3。同样,如果您缺少输入端口,也可据此添加,但切记要检查输入端口参数中是否公开了BuildingID。
接下来返回main选项卡,检查GityGMLBuilder的参数,并确保已将属性BuildingID作为用户参数的一个属性选中。之后,将输出端口连接到main工作空间中的CityGML要素类型WallSurface。
选项卡GityGMLBuilder中的自定义转换器
13. 复制GityGMLBuilder
复制自定义转换器,并将其连接到屋顶的AppearanceSetter转换器输出端口,然后将自定义转换器的输出端口与“RoofSurface”要素类型进行连接。
14. 写出到CityGML
在运行工作空间之前,请先清理要素类型中的不必要属性。在WallSurface写模块的要素类型对话框里,删除用户属性中除“citygml_feature_role”以外的所有属性,之后,在格式属性中确保“citygml_lod_name”、“gml_id”以及“gml_parent_id”被勾选以公开。对RoofSurface要素类型做相同处理。而对于Building要素类型,需删除其所有用户属性,确保“gml_id”在其格式属性中被公开,然后取消勾选格式属性下的“citygml_lod_name”和“gml_parent_id”。
运行您的工作空间,在确保创建了有效的CityGML之后,请在CityGML写模块参数的导航窗口中,尝试将“验证输出文件”更改为“否”以提高性能。
删除不必要的属性,仅保留已连接的属性(绿色三角形)
完整的工作空间
运行结果
生成的CityGML在本机FZKViewer中输出显示。
如果要使用FZKViewer进行查看,您需要在源读模块要素类型interopolis之后添加一个reprojector转换器,将数据重新投影到LL84坐标系。该步骤是必需的,因为我们的数据当前在德克萨斯州平面坐标系中,而FZKViewer无法识别此坐标系,因此我们需要将其重新投影到可以被识别的坐标系中,以便我们可以对其进行查看。
如果您要在FZKViewer中查看原始纹理,请转到菜单栏中的“显示”,然后选择“纹理”,并选择“来自实体”即可。
恭喜您!我们已经成功地将3DS模型写出到纹理化CityGML模型中。由于模型已在本机CityGML查看器中正确显示,因此我们可以得知我们已经正确编写了CityGML的必要结构。
数据来源
本文中使用的数据来自德克萨斯州奥斯汀市的公开数据,它包含根据公共领域专用许可-奥斯汀市许可的数据。
模板下载
链接:
https://pan.baidu.com/s/1Fe9TGzEERQykpmt59sBGhw
提取码:2020