Writing CityGML from FME
The FME CityGML writer maps any feature type definitions that are not defined in CityGML into GenericCityObject(s). This topic explains how the FME CityGML writer can be used to output datasets with predefined thematic CityGML feature types, such as Building, CityFurniture, WaterBody, Road, Railway, etc…
CityGML feature types in FME
The simplest way to get CityGML writer feature type definitions for the supported CityGML features is to import them from an existing CityGML dataset.
FME ships with two sample CityGML datasets that can be used to populate FME Workbench with the required CityGML writer feature types. These file are located under the “xml/CityGML/writer_feature_types” folder of the FME installation. The “CityGML_feature_types.xml” and “CityGML_NoiseADE_feature_types.xml” sample datasets have the feature type definitions for CityGML (0.4 and 1.0) and CityGML-NoiseADE (0.4 and 1.0), respectively.
Note: These CityGML sample files are not complete datasets in the GML sense; they do not contain any meaningful data for reading, and are only meant to be used for importing feature type definitions into a writer.
CityGML levels of detail
CityGML specifies five different Levels of Detail (LODs), ranging from 0 (general topology) to 4 (detailed architectural features and furniture). Most features may contain geometry models for different LODs. LOD0 generally models terrain features. LOD1 models simple prismatic buildings and general landscape features. L0D2 incorporates some architectural features in building models, greater detail in transportation, vegetation, and outdoor furniture features. LOD3 models buildings and outdoor objects as they would actually appear. And LOD4 models detailed interior structures.
In order for various applications to correctly interpret the multiple geometries of a feature, GML geometries are enclosed in an element that indicates the geometry role. As an example, a Building feature with a solid geometry at LOD2 is shown below:
<cityObjectMember>
<bldg:Building gml:id="building890384">
<bldg:lod2Solid>
<gml:Solid gml:id="aebd7312">
...
FME Geometries in CityGML features types must be tagged with their intended geometry role in order to be written out correctly. The geometry role is specified through the geometry trait “citygml_lod_name”. The geometry roles that are valid for each feature type are given in Table 1, and the valid FME geometry types for each geometry role are shown in Table 2.
Setting the geometry role in FME Workbench
The geometry role can be set using the AttributeCreator and the GeometryPropertySetter transformers in tandem.
The reason we are using an AttributeCreator here is to set citygml_lod_name as an attribute, and then transforming it into a trait using the GeometryPropertySetter.
Since we've passed in a valid FME geometry for the geometry role (an extrusion as a “lod2Solid”), we end up with a Building feature containing this geometry in our output:
<cityObjectMember>
<bldg:Building gml:id="boring_building_11">
<bldg:lod2Solid>
<gml:Solid srsDimension="3">
...
All of the other CityGML-specific attributes can also be easily set on an FME feature through the AttributeCreator, though many of these attributes have a restricted set of values that are defined in the CityGML external code lists. See Tables 1-4 for more details.
Writing multiple geometry roles to one feature
Creating additional geometry roles for a feature is not much more difficult. Simply label a copy of the same, or any other geometry with the appropriate role, and aggregate all of the geometries for the feature into a single geometry:
Here is the CityGML Road feature:
<tran:Road gml:id="2nd_west_boring_street">
<tran:lod0Network>
<gml:LineString srsDimension="3">
<gml:posList>12 0 0 12 12 0 0 12 0</gml:posList>
</gml:LineString>
</tran:lod0Network>
<tran:lod1MultiSurface>
<gml:MultiSurface srsDimension="3">
<gml:surfaceMember>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>13 0 0 11 0 0 11 11 0 0 11 0 0 13 0 13 13 0 13 0 0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</tran:lod1MultiSurface>
<tran:lod2MultiSurface>
<!--The same gml:MultiSurface as for the lod1MultiSurface-->
</tran:lod2MultiSurface>
</tran:Road>
Generally, the geometry at LOD2 should have more detail than the geometry at LOD1, but using the same geometry works for this example. In the case of this Road, it may have extra curves representing the separate lanes of the road.
Geometry validation in FME Workbench
Note that in the above example, we tagged a polygon as a lodXMultiSurface, though it only represents a single area. The CityGML writer will check that the FME geometry can actually be written out as the specified geometry role. If it is unable to, and it is easy to convert the geometry to a type that is valid, the writer will make the conversion. For example, our polygon was converted to a surface and then wrapped in a multi-surface. If the FME geometry is not valid for the specified geometry role and cannot be converted to a valid geometry (Eg. a point tagged with “lod3MultiCurve”), it will not be written out.
Setting CityGML attributes and properties in FME
The non-geometric attributes and properties of the CityGML features are specified through certain attributes of the FME feature types. Most of these attributes are prefixed with “citygml_”. For example, the value of the “citygml_roof_type” attribute of an FME Building feature will be written as the value of the “roofType” element of a CityGML Building feature.
The full list of valid attributes for a CityGML feature type will appear on feature types defined by importing feature types from a CityGML document that contains those features.
Most of the CityGML attributes and properties that take a string value have an enumerated list of valid values that are listed in the CityGML external code lists. For example, for the “roofType” element of a Building feature, “1070” indicates a pavilion roof. The corresponding attributes of CityGML features in FME should be set to one of these valid values, though FME currently does no validation of the values.
Writing CityGML Appearances from FME
FME 2010 supports reading and writing of CityGML appearances. In FME, Appearance objects are stored in a common library, and surfaces contain a reference to the Appearance that is applied to them. The FME Appearance contains information about both constant (material) and non-constant (texture) surface properties. Any FME Appearances that are referenced by a surface passed into the CityGML Writer will be written out as a ParameterizedTexture or an X3DMaterial, depending on whether or not the Appearance contains textural information. The writer will try to re-use any existing elements in the case that ParameterizedTexture or X3DMaterial features are passed in (Eg. during a CityGML to CityGML translation). In this case, the elements will be written out as members of the original CityGML Appearance and under their original theme. If new elements must be created, they will be members of a new Appearance under the CityModel. The default theme name is “FMETheme”, but it can be changed through the advanced FME Workbench parameter “Theme name”. ParameterizedTexture and X3DMaterial elements can belong to the same theme even under different Appearance features.
If any of the referenced FME Appearances contain texture information, the image files will be written out to a subfolder of the destination folder. By CityGML convention, this folder is named “appearance” by default. The folder name may be specified through the advanced FME Workbench parameter “Texture subfolder”.
CityGML Feature Hierarchy
Many CityGML features are aggregations of other features. In FME, this relationship can be specified through the “gml_id” and “gml_parent_id” attributes. The value of the “gml_parent_id” of a child element should be equal to the value of the “gml_id” of its parent element. The gml:id attribute must be unique for all features in a CityGML document. Using the UUIDGenerator transformer will ensure that these values are unique, but they must be prefixed with a non-numeric character. Note that the CityGML Writer will dynamically generate gml:id attribute values for all features it writes (essentially using the same method shown below), so it is not necessary to use these transformers unless the value of the gml_id attribute must be accessed.
This workspace produces the following output:
<bldg:Building gml:id="exciting_building_123">
<bldg:boundedBy>
<bldg:RoofSurface gml:id="UUID_47be0fd6-ccec-45ab-96f7-0868ff9208d0">
<bldg:lod3MultiSurface>
...
</bldg:lod3MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="UUID_dafb5306-41aa-4e07-8f58-80874167a2a7">
<bldg:lod3MultiSurface>
...
</bldg:lod3MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<!--Three more WallSurfaces-->
</bldg:Building>
Valid Geometry Role Lists
Note: Only one of the listed values for “citygml_lod_name Value” is needed.
Table 1: Valid LOD types for CityGML Feature Types
CityGML Feature Type |
citygml_lod_name Value |
GenericCityObject |
lod[0-4]Geometry lod[0-4]TerrainIntersection |
Address |
multiPoint |
Building BuildingPart |
lod[1-4]Solid lod[1-4]MultiSurface lod[2-4]MultiCurve lod[1-4]TerrainIntersection |
BuildingInstallation |
lod[2-4]Geometry |
RoofSurface WallSurface GroundSurface ClosureSurface FloorSurface InteriorWallSurface CeilingSurface |
lod[2-4]MultiSurface |
Door Window |
lod[3-4]MultiSurface |
Room |
lod4Solid lod4MultiSurface |
BuildingFurniture IntBuildingInstallation |
lod4Geometry |
WaterBody |
lod[0-1]MultiCurve lod[0-1]MultiSurface lod[1-4]Solid |
WaterSurface WaterGroundSurface |
lod[2-4]Surface |
TransportationComplex Track Road Railway Square |
lod0Network lod[1-4]MultiSurface |
TrafficArea AuxiliaryTrafficArea |
lod[2-4]MultiSurface |
SolitaryVegetationObject |
lod[1-4]Geometry |
PlantCover |
lod[1-4]MultiSurface lod[1-3]MultiSolid |
CityFurniture |
lod[1-4]Geometry lod[1-4]TerrainIntersection |
LandUse |
lod[0-4]MultiSurface |
GeoreferencedTexture |
referencePoint |
TINRelief |
extent |
MassPointRelief |
reliefPoints |
BreaklineRelief |
ridgeOrValleyLines breaklines |
NoiseRoadSegment NoiseRailwaySegment NoiseCityFurnitureSegment |
lod0BaseLine |
Table 2: Valid geometries for the citygml_lod_name attribute values
LOD name |
Valid FME Geometries |
GML Geometry |
lod0Geometry lod1Geometry lod2Geometry lod3Geometry lod4Geometry relativeGMLGeometry geometry |
all except null, raster, and empty aggregates |
gml:GeometryType |
lod1MultiSolid lod2MultiSolid lod3MultiSolid |
all solids all surfaces homogeneous aggregates of surfaces or areas |
gml:MultiSolidType |
lod0MultiSurface lod1MultiSurface lod2MultiSurface lod3MultiSurface lod4MultiSurface |
all surfaces all areas homogeneous aggregates of surfaces or areas |
gml:MultiSurfaceType |
lod0MultiCurve lod1MultiCurve lod2MultiCurve lod3MultiCurve lod4MultiCurve |
line arc all surfaces all solids homogeneous aggregates of lines, arcs, surfaces, or solids |
gml:MultiCurveType |
lod1Solid lod2Solid lod3Solid lod4Solid |
all solids all surfaces aggregates containing a single solid or surface |
gml:SolidType |
lod2Surface lod3Surface lod4Surface |
all surfaces all areas aggregates containing a single surface or area |
gml:SurfaceType |
lod0TerrainIntersection lod1TerrainIntersection lod2TerrainIntersection lod3TerrainIntersection lod4TerrainIntersection |
line arc all surfaces all solids homogeneous aggregates of lines, arcs, surfaces, or solids |
gml:MultiCurveType |
lod0Network |
all points line arc all areas all surfaces all solids aggregates containing a single point, line, arc, area, surface, or solid |
gml:GeometricComplexType |
noise:lod0BaseLine(move me) |
line arc aggregates containing a single line or arc |
gml:CurveType |
referencePoint |
point aggregates containing a single point |
gml:PointType |
reliefPoints |
point homogenous aggregates of points |
gml:MultiPointType |
extent |
face rectangular face all areas aggregates containing a single face, rectangular face, or area |
gml:PolygonType |
ridgeOrValleyLines |
line arc all surfaces all solids homogeneous aggregates of lines, arcs, surfaces, or solids |
gml:MultiCurveType |
breaklines |
line arc all surfaces all solids homogeneous aggregates of lines, arcs, surfaces, or solids |
gml:MultiCurveType |
multiPoint |
point aggregate containing a single point |
gml:MultiPointType |
Table 3: CityGML Feature Roles
CityGML Feature Type |
citygml_feature_role Value |
Appearance |
appearance * appearanceMember * |
GeoreferencedTexture ParameterizedTexture X3DMaterial |
surfaceDataMember |
TINRelief MassPointRelief BreaklineRelief |
reliefComponent |
BuildingInstallation |
outerBuildingInstallation |
IntBuildingInstallation |
interiorBuildingInstallation roomInstallation |
RoofSurface WallSurface GroundSurface ClosureSurface CeilingSurface InteriorWallSurface FloorSurface |
Building/boundedBy ** |
Room |
interiorRoom |
BuildingPart |
consistsOfBuildingPart |
Address |
address |
Door Window |
opening |
BuildingFurniture |
interiorFurniture |
WaterSurface WaterGroundSurface |
WaterBody/boundedBy ** |
TrafficArea |
trafficArea |
AuxiliaryTrafficArea |
auxiliaryTrafficArea |
noise:NoiseRailwaySegment |
noise:noiseRailwaySegmentProperty |
noise:NoiseRoadSegment |
noise:noiseRoadSegmentProperty |
noise:NoiseCityFurnitureSegment |
noise:noiseCityFurnitureSegmentProperty |
noise:Train |
noise:usedBy |
Table 4: CityGML Feature Properties
CityGML Parent Feature Type |
Valid properties |
all feature types except Address X3DMaterial ParameterizedTexture GeoreferencedTexture noise:Train |
appearance * appearanceMember * |
Appearance |
surfaceDataMember |
ReliefFeature |
reliefComponent |
Building BuildingPart |
outerBuildingInstallation interiorBuildingInstallation Building/boundedBy ** interiorRoom consistsOfBuildingPart address |
RoofSurface WallSurface GroundSurface ClosureSurface FloorSurface InteriorWallSurface CeilingSurface |
opening |
Door |
address |
Room |
Building/boundedBy ** interiorFurniture roomInstallation |
WaterBody |
WaterBody/boundedBy ** |
TransportationComplex Track Square |
trafficArea auxiliaryTrafficArea |
Road |
trafficArea auxiliaryTrafficArea noise:noiseRoadSegmentProperty |
Railway |
trafficArea auxiliaryTrafficArea noise:noiseRailwaySegmentProperty |
CityFurniture |
noise:noiseCityFurnitureSegmentProperty |
noise:NoiseRailwaySegment |
noise:usedBy |
* |
Appearance features that are properties of other features in CityGML v0.4 are enclosed in an “appearanceMember” element. In v1.0, Appearances that are properties of features are enclosed in an “app:appearance” element, but those that are properties of the CityModel are enclosed in an “app:appearanceMember” element. |
** |
“boundedBy” is a property of both the AbstractBuildingType and of the WaterBodyType, though the allowed values differ by module. The recognized “citygml_feature_role” value for both of these properties is “boundedBy”. |