FME Version
Files
Introduction
With various restricted areas, multiple terminals, and time constraints, navigating an airport can be a challenge for anyone. Passengers, in particular, need to get where they are going quickly and efficiently. Apple’s indoor mapping initiative can help passengers navigate a large airport complex, but to add such maps requires translating data to Apple’s Indoor Mapping Data Format (IMDF).
In this scenario, you will learn how map data of Victoria Airport (Esri Geodatabases) was transformed into IMDF. At the end of this example, you will have carried out the data transformation steps to produce a dataset ready for publishing to Apple Maps.
Note: this example shows how the data from Victoria Airport can be processed. Your own source data may vary in structure and format and so require different transformation techniques.
Requirements
FME 2018.1+
Python installed
Source Data Overview
The provided data is contained in three different geodatabases, one for each floor of the airport. These geodatabases contain data for the entire airport structure. Since we are only interested in the mapping the layout of the airport, and important features (like security zones, check-in counters, and baggage carousels) we can reduce the number of feature types (feature classes) we read.
The feature types we are interested in are:
- ATB_SURROUND: provides the venue boundary
- SECURITY/SECURITY_LINE: provides the line boundary between pre-security and post-security geofence
- OPENING: provides opening lines (doors and thresholds)
- ARCHITECTURAL/WALL POLYGON and ARCHITECTURAL/ROOM: provides unit polygons (rooms, stairs, elevators, and escalators), which are also used to create the level, section, geofence, and footprint polygons
- ARCHITECTURAL/COUNTER and ARCHITECTURAL/CAROUSEL: provides symbols for conversion to fixture polygons
- ARCHITECTURAL/PUBLIC_AMENITY: provides amenity points (washrooms, food, etc)
The above feature types viewed in the FME Data Inspector before processing
Workspace Overview
This scenario goes into as much detail as possible, while still maintaining readability. To learn more about each transformer’s specific parameters, please refer to the completed workspace.
Reading in the Geodatabases
The feature types listed under Source Data Overview have been added to the workspace using the File Geodatabase (File Geodb Open API) reader. For some feature types there is only one instance of it (i.e. ATB_SURROUND) for others there are two or three; this is because those features exist on multiple floors.
Data Cleaning
Each of the feature types needs to be cleaned before they can be prepared to write out to IMDF. Cleaning includes georeferencing, cleaning geometry, creating IDs, and manipulating attributes. The following section will details what steps are completed for each of the feature types.
ATB_SURROUND:
Workflow for data cleanup for ATB_SURROUND
A building ID is created from the ATB_SURROUND data. A Sampler selects a single surround feature, a UUIDGenerator creates the ID, and a VariableSetter creates a variable named building and giving it the value of id.
This variable is referenced throughout the workspace. If using Run with Feature Caching later in the workspace, ensure that the VariableSetter is part of any partial run, otherwise, the workspace will fail.
On a separate stream from the ID variable creation, a Dissolver is used to dissolve the surrounding areas into a single polygon. Then, using the DonutHoleExtractor, the donut holes created from the building are removed. Finally, the data is run through the ApplyGeoreferencing custom transformer which rotates, offsets, scales and sets a coordinate system. This custom transformer will be used multiple times throughout the workspace.
Within the ApplyGeoreferencing custom transformer the parameters are:
- Scaler transformer > Scale Factors X, Y & Z: 0.001
- Rotator transformer> Rotation Angle (degrees): -9.379
- Offsetter transformer> Offset X: 468164.386 Offset Y: 5387576.170 (meters)
- CoordinateSystemSetter transformer > Coordinate System: UTM83-10
Pre and post data cleaning for ATB_SURROUND. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
SECURITY/SECURITY_LINE:
Workflow for data cleanup for SECURITY/SECURITY_LINE
First, the arc geometry is converted into lines using the ArcStroker transformer, then the GeometryRefiner is used to condense the geometries. Next, the Deaggregator is used to break up aggregate lines and close small gaps. A combination of the Snapper and the LineCloser are used to combine lines into a single line, one for each level. Finally, the data is georeferenced using the ApplyGeoreferencing custom transformer.
Pre and post data cleaning for SECURITY/SECURITY_LINE. The pink line is the security line for the first floor, and the purple line is for the second floor. There is no security line for the third floor. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
OPENING:
Workflow for data cleanup for OPENING
For the OPENING, initially, all that needs to be done is that the openings on all three floors need to be georeferenced using the ApplyGeofreferecing custom transformer.
ARCHITECTURAL/WALL POLYGON:
Workflow for data cleanup for both ARCHITECTURAL/WALL POLYGON & ARCHITECTURAL/ROOM
All three ARCHITECTURAL/WALL POLYGON feature types are connected to an AttributeCreator transformer to create a category attribute with the value of structure. It is then georeferenced using the ApplyGeoreferencing custom transformer. Next, the geometry is cleaned up using a combination of the ArcStroker, Deaggregator, GeometryRefiner, and Snapper. Then any gaps or overlaps are removed using the AreaGapAndOverlayCleaner and another Deaggregator. Using a SpatialFilter and a Tester, any solo walls or non-public areas are filtered out.
ARCHITECTURAL/ROOM:
Another variable is created for each of the rooms using a combination of the Sampler, UUIDGenerator, and VariableSetter transformers. This variable used the fme_basename value, which is the level of the airport (ATB1, ATB2, and ATB3). In a second data stream, an AttributeValueMapper is used to condense the room (unit) categories based on the NOTES attribute. The room types are as follows:
- room
- mothersroom
- restroom
- restroom.family
- restroom.male
- restroom.female
- walkway
- foodservice
- escalator
- elevator
- stairs
- nonpublic
- lobby
After the AttributeValueMapper, the data is connected to the ARCHITECTURAL/WALL POLYGON workflow via the ApplyGeoreferencing custom transformer.
Pre ARCHITECTURAL/WALL POLYGON & Pre ARCHITECTURAL/ROOM data cleanup and merged polygons post data cleanup. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
ARCHITECTURAL/COUNTER:
Workflow for data cleanup for ARCHITECTURAL/COUNTER
The counters are very detailed drawings of each of the check-in counters at the airport. Each needs the attributes of the room they reside in, and this is best done using a simplified geometry. First, a GeometryExtractor transformer records a copy of the original (detailed) data, then a CenterPointReplacer is used to create a simple center point for each of the counters. Next, using the SpatialFilter, the room attributes are merged onto each check-in counter. A GeometryReplacer is used to retrieve the stored geometry from the GeometryExtractor.
A VertexCounter and AggregateFilter are used to sort the data for filtering. The TestFilter is then used to filter the data by:
- Checkin Kiosk
- Checkin Desk
- Security Equipment
- Immigration Desk
- <Unfiltered>
Once the data is filtered, a new category is created using an AttributeCreator for each output port on the TestFilter.
The Checkin Kiosk and Immigration Desk are both sent to a custom transformer called MakePolygon, which makes polygons using several geometry transformers. The Checkin Desk and Security Equipment are sent to a BoundingBoxReplacer to simplify the geometry into a rectangle. Finally, the counters are georeferenced using the ApplyGeoreferencing custom transformer.
ARCHITECTURAL/CAROUSEL:
Workflow for data cleanup for ARCHITECTURAL/CAROUSEL
A Tester transformer is used to extract only the baggage pickup carousels from all of the different carousel features. Then using an AttributeCreator the category and a name is created. Then using the ArcStroker, Snapper, and AreaBuilder, polygons are created for each of the carousels. The carousels are routed to the same ApplyGeoreferencing custom transformer connected to the counters workflow. Finally, the central carousel is used for both international and domestic baggage based on a set schedule, this information needs to be added in. The AreaBuilder_2 is also connected to the ARCHITECTURAL/PUBLIC_AMENITY data cleanup workflow to add this schedule information.
Pre and post data cleanup for both ARCHITECTURAL/COUNTER and ARCHITECTURAL/CAROUSEL. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
ARCHITECTURAL/PUBLIC_AMENITY:
Workflow for data cleanup for ARCHITECTURAL/PUBLIC_AMENITY
The central baggage claim area with carousel switches between domestic and international through the use of moving walls. Victoria Airport has supplied the schedule for the carousel usage.
To model this, two amenities are created for the combined carousel: one for domestic use and one for international use. The schedule is for each usage type on the appropriate amenity.
The AttributeKeeper keeps only the baggage carousel name and fme_basename attributes. Then the PointOnAreaOverlayer is used to overlay the baggage carousel amenities over the baggage carousel polygons and merges the attributes. The Tester is used to find the combined international/domestic carousel. Then an AttributeCreator is used to set the domestic schedule. An Offsetter is used to create a second amenity to contain the international schedule, which is created using the AttributeCreator. Finally, all ARCHITECTURAL/PUBLIC_AMENITY feature types are georeferenced using the ApplyGeoreferencing custom transformer.
Snap Features
Using the AnchoredSnapper, the SECURITY/SECURITY_LINE, OPENING, ARCHITECTURAL/COUNTER and ARCHITECTURAL/CAROUSEL are all snapped together. The ARCHITECTURAL/WALL POLYGON and ARCHITECTURAL/ROOM features are the anchor that other data is snapped to. This will snap the security line and fixtures to the units.
Then using the Snapper, security vertices are snapped to unit boundaries using segment snapping. Common vertices between all polygonal features ensure that the data is aligned visually when viewed in navigational applications and when the data is reprojected to latitude/longitude when writing out to IMDF.
Snapped features viewed with the basemap turned off
Using the Snapper, security vertices will be snapped to unit boundaries using segment snapping. After the Snapper, the features are then filtered back into their individual types using the FeatureTypeFilter.
Prepare Data to Write Out to IMDF
Once the data is clean, it needs to be prepared to IMDF specifications before being written. This means that unique IDs need to be added to each feature, the geometry type must be correct, and all attributes follow the appropriate naming convention. When writing to IMDF, the FME writer automatically reprojects the data to the LL84 coordinate system.
Due to the complex nature of the following section, the process description might reference feature types and transformers that have not been mentioned yet. For clarity, it is recommended to have the example workspace open while reading.
Venue:
Workflow to prepare to write venue out to IMDF
The venue is the boundary containing the building which must have an id and must be a polygon.
To create the venue, a unique ID is created using the UUIDGenerator. Then specific attributes about the venue are created using the AttributeCreator. These attributes include the name of the building, category, website, alternate name, hours and a phone number. When setting the category, there is a specific naming convention that must be followed. See the Apple Indoor Mapping Data Format Unit Category Documentation for more information.
Next, the address_id is merged onto the venue id using the FeatureMerger. Then using the CenterPointExtractor, a center point is created. Then the venue is written out using the Indoor Mapping Data Format (IMDF) writer.
Output for venue viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Address:
Workflow to prepare to write out address and building out to IMDF
The address is the postal address which must have an ID and must have a null geometry.
To create the address, a unique address_id is created using the UUIDGenerator. Then the address_id is renamed to id, using the AttributeRenamer, this is done for the purpose of merging with the venue id. Next, the address attributes are created with the AttributeCreator, this includes street address, locality (city or town name), province (or state), country, and postal code (or zip code). Then the address is written out to the same IMDF writer, as the venue. This can be done easily by going to Writers > Add Feature Type then in the Feature Type Dialog renaming the Feature Type Name to address and ensuring that the IMDF writer is selected.
Output for address viewed in the FME Data Inspector
Building:
The building is the physical building contained within the venue which must have an ID and must have a null geometry. This feature type only stores attribute information, the actual building polygon is stored in the footprint feature type.
Using the address_id previously created, an AttributeCreator is used to create the building name and category. Then using the VariableRetriever, the building id, which was created with ATB_SURROUND, is retrieved. A center point is created using the CenterPointExtractor transformer, which will be stored as an attribute and then the building is written out to IMDF using the same writer.
Output for building viewed in the FME Data Inspector
Level:
Workflow to prepare to write level out to IMDF
The level represents each level (or floor) of the building. The level must have an ID and must be a polygon.
From the FeatureTypeFilter, all the units are dissolved into levels using the Dissolver; in this case, three levels are created. Then using two VariableRetrievers, the level id and the building id are retrieved. Using the StringSearcher, the level number is extracted from the fme_basename; this is because each of the starting geodatabases represented a level (ATB1, ATB2, ATB3).
An AttributeCreator is used to create the attributes specific to each level, this includes category, whether the level is outdoors (Yes/No), the ordinal, the level name and the short name. Then the center point is extracted and empty name and short_name attributes are mapped to <missing> using the NullAttributeMapper. Finally, the levels are written out to IMDF.
Output for level viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Footprint:
Workflow to prepare to write footprint out to IMDF
The footprint is the approximate polygon of the building(s). The footprint must have an ID and must be a polygon.
Connecting to the AttributeCreator that created the level attributes, an AttributeRemover is used to remove the level name. Then using the TestFilter, the levels are organized by ordinal (aerial, ground and subterranean). A Dissolver connected to the aerial and ground output ports are used to dissolve the levels into footprints. Then a DonutHoleExtractor is used to remove any donut holes that were created. Then an AttributeCreator is used to give the footprint the category of aerial.
Next, an AttributeCreator is connected to the ground output port on the TestFilter to give the footprint the category of ground.
Finally, another Dissolver, DonutHoleExtractor, and AttributeCreator are connected to the subterranean output port on the TestFilter, and the footprint is given the category of subterranean.
All three AttributeCreators are then connected to an UUIDGenerator to create a footprint_id, which is then written out to IMDF.
Output for footprint viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Geofence:
Workflow to prepare to write geofence out to IMDF
A geofence separates one or more areas by a set restriction. In the case of an airport, this would be pre- and post-security. The geofence must have an ID and must be a polygon.
An Intersector transformer is connected to the AttributeCreator that created the levels attributes is used to separate the units by the security line. Then an AreaBuilder is used to create new polygons for each level for either side of the security line. The geometry is then saved using a GeometryExtactor; this is done so that the attributes can be manipulated and merged with other attributes without affecting the geometry. A CenterPointReplacer is used to create a single point which contains all the attributes for each polygon. Then that point is clipped using the Clipper only to keep the new polygons within the levels. A LeftRightSpatialCalculator is used to determine which side of the security line each of the polygons fall, this is grouped by fme_basename so it keeps each of the levels separate. A ListSearcher is used to classify the polygons; if the polygon is to the right of the line, it is pre-security, if it is to the left, it is post-security. Then AttributeCreators are used to set the category.
Finally, a GeometryReplacer is used to bring back the polygons, and then an AttributeRemover is used to remove any of the level specific attributes. IDs are retrieved using two VariableRetrievers and a geofence id is created using the UUIDGenerator. A center point is created then the geofence is written out to IMDF.
Output for geofence viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Opening:
Workflow to prepare to write opening out to IMDF
An opening represents an entrance to a room or building an can be both a door or a threshold. An opening must have an ID and must have line-string as a geometry.
To create the openings, a UUIDGenerator is connected to the FeatureTypeFilter, and then a VariableRetriever is connected to create and retrieve ids. A GeometryCoercer is connected to the Dissolver which created the levels; this is used to coerce level boundaries to opening lines. A SpatialFilter is then connected to both the GeometryCoercer and the VariableRetriever to find openings on level boundaries; this will determine whether the opening is internal or external. Then two AttributeCreators are used to create the categories of either pedestrian (internal) or pedestrian.principal (external). Then a midpoint is calculated which will be used as the display point; this is accomplished by using a GeometryExtractor, Snipper, CoordinateExtractor and a GeometryReplacer. Once the display point is created, empty name attributes are set to <missing> and the openings are written out to IMDF.
Output for opening viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Unit:
Workflow to prepare to write unit out to IMDF
A unit represents a room or corridor and is an enclosed space. A unit must have an ID and must be a polygon.
A UUIDGenerator is used to create an ID, and is connected to the FeatureTypeFilter. Then an AttributeCreator is used to create an attribute called _predicate which will be used in the SpatialRelator; this is connected to the VariableRetriever used to create the openings. A SpatialRelator is connected to the UUIDGenerator and the AttributeCreator and the _predicate attribute is used to test the relationship. A VariableRetriever is used to get the level_id. Another AttributeCreator is used to copy the NOTES attribute to an attribute called name; this will be the name of each of the units. A center point is created, empty name attributes are set to <missing> and then the units are written out to IMDF.
Output for unit viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Amenities and Anchors:
Workflow to prepare to write amenity and anchor out to IMDF
An amenity is a feature that is provided as a convenience service like a washroom or a water fountain. Amenities must have an ID and must have a point geometry.
An amenity id is created using the UUIDGenerator and then amenities are overlaid on top of the units to get the unit IDs using the PointOnAreaOverlayer. Name, category and unit_id attributes are then created using the AttributeCreator. Empty name attributes are set to <missing>, and then using a Tester amenities are separated from anchors. Finally, anchor and amenity are written out to IMDF.
Output for amenity viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
An anchor is a specified point used to display a specific address or non-addressable location. The anchor serves as a point in which another feature can inherit the anchor’s attributes.
Anchors follow the same workflow as the amenity except that a Tester is used to test for a category. Any amenities that are unspecified, service, foodservice, or carrental are considered an anchor.
Output for anchor viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Occupant:
Workflow to prepare to write out occupant to IMDF
An occupant is the location of a business that provides goods or services. These occupants are represented by the anchor.
Once the anchors have been determined, unique ids are renamed and created, then the attributes are remapped using the AttributeValueMapper to the specific IMDF categories. A DatabaseJoiner is used to join a CSV file containing business information with the anchors to create the occupant. A attribute is created to contain the data validity.modified date, then the empty attributes are mapped to <missing> before finally writing out to IMDF.
Output for occupant viewed in the FME Data Inspector
Section:
Workflow to prepare to write section out to IMDF
A section is an area that serves a specific purpose. For example, an airport would have baggage claim, check-in area, gate and security sections. A section must have an ID and must be a polygon.
An AttributeValueMapper is connected to the FeatureTypeFilter to remap units to a section category, for this example these are:
- retail
- baggageclaim
- baggageclaim.int
- immigration
- gatearea
- security
- eatingdrinking
- checkin
Once the names have been remapped, a Tester is used to remove any units without a section category. Then the boundaries of the units with a section are dissolved using the Dissolver to create one polygon for each section. Then the ids are created and retrieved using the UUIDGenerator and VariableRetriever. A center point is created and any polygon holes are removed using the CenterPointReplacer and the DonutHoleExtractor. Finally, empty name attributes are set to <missing> and then sections are written out to IMDF.
Output for section viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Fixtures:
Workflow to prepare to write fixture out to IMDF
A fixture represents a physical object contained within a unit that can be moved or is semi-permanent. For this example, this would represent the baggage carousels or check-in counters. A fixture must have an ID and must be a polygon.
Fixtures are filtered again after the FeatureTypeFilter by using another FeatureTypeFilter to separate out carousel and counters. A Tester is used to determine whether the fixture is nonpublic or it is a structure. Then a Clipper is used to clip out any carousel parts that are nonpublic. Ids are then created and retrieved, as well as a center point is created. Once the empty name attributes are renamed to <missing>, the fixtures are written out to IMDF.
Output for fixture viewed in the FME Data Inspector. Background map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Relationships:
A relationship is an association between two map elements with the option to include an intermediate element. In this example, this would be an elevator, stairs or escalator, which connect multiple levels. In addition, a transversal relationship is added to define the partitions that can be moved when the central baggage carousel switches between international or domestic. A relationship must have an ID and must contain null geometry.
Workflow to prepare to write elevator relationship out to IMDF
The elevator relationship is first created by using a Tester to extract only the elevator units. Then using the NeighborFinder, the elevators are linked together by creating a list of ids in a stack. A ListSorter and a ListConcatenator sorts the elevator list by level and then creates a stack id. A DuplicateFilter is then used to remove duplicate stacks. A PythonCaller is used to create a function that extracts the relationship info from the list. Finally, an AttributeCreator is used to create a direction attribute.
Workflow to prepare to write out stair and escalator relationship out to IMDF
The escalator and stair relationships are more complex than elevators and are created by using a Tester to extract only the stair, and escalator units. Then an AttributeCreator is used to set the feature type (stairs or escalator) and then set the opening_id. A NeighborFinder is used to link the stacks and create a list of ids, as previously done with the elevators. The escalator direction is mapped using the AttributeValueMapper. Then the lists are sorted bottom to top (stairs or escalators) or top to bottom (down escalators). A copy of the stack is then made up for each unique combination of levels, with the list sliced to cover only those levels and any in between them. Next, each stack copy is turned into a relationship feature, with openings on the top and bottom levels as source and destination. All the transversal units are set as intermediaries.
Workflow to prepare to write out the moving partition relationships out to IMDF
The moving partition relationships control the flow of people based on the baggage carousel schedule. The partitions are extracted using the Tester failed port from the stair and escalator relationships. Then using the ListExploder the relationships are expanded using the openings list element. Then the units are grouped together by connecting opening using the Aggregator. The ListSearchers are used to search for the units list element for Baggage Pickup International/ Domestic, then further by Baggage Pickup Domestic and then finally by Arrivals Concourse. Then using the AttributeCreators the hours of operation are set. Finally, the IMDF attributes are added.
Once the relationships for the elevators, escalators, stairs, and partitions are created, they are given a unique id and then written out to IMDF.
Output for relationship viewed in the FME Data Inspector
IMDF Validation
After running the translation, the completed IMDF file can be validated using the Safe Software IMDF Validation page which will email you a report indicating any warnings or errors. This file should validate without any errors but there will be some warnings. These warnings are mostly due to the line segments being shorter than the specification threshold. There will also be warnings about features not being within building footprints. These are due to coordinate rounding in the footprint check and can be ignored.
For more information about IMDF Validation, please see the Validating IMDF Datasets article.
Data Attribution
Data is © Victoria Airport Authority
Comments
0 comments
Please sign in to leave a comment.