Use floor-aware maps

The term floor-aware refers to maps and scenes with indoor features that can be queried for their level inside a facility. Apps and APIs that support floor-awareness provide tools to visualize and interact with floor-aware indoor data. Once created and saved using ArcGIS Pro, a floor-aware map or scene can be consumed inside your app. You can filter data displayed by feature layers, point scene layers, and 3D object scene layers based on floor levels.

Refer to the Floor-aware maps topic in the ArcGIS Pro documentation for details about creating floor-aware maps and scenes.

Filter display by floor

Some common use cases for working with floor-aware data include:

  • Filter the display to only show features on a specified level (floor) of a facility.
  • Evaluate the availability and distribution of critical assets for a facility, such as fire extinguishers or defibrillators.
  • Apply a floor filter based on an indoor positioning system (IPS) location.
  • Track assets, such as mobile devices, that may move between facilities and levels.

For more information see:

Floor-aware data model

The floor-aware data model is organized into a hierarchy of layers that describe relevant indoor features and their relationships. Features are associated with a specific level (floor, in other words). Levels are contained within a facility (such as a building), and facilities can belong to a site (for example, a shopping center, industrial complex, or college campus).

A floor-aware map must include, at a minimum, a layer representing facilities and a layer representing levels. These layers must include specific fields that identify the features and define their hierarchical relationships, such as which levels are contained by a given facility. Indoor features can then be assigned the appropriate level within a facility.

Read floor-aware metadata

Floor filtering requires floor-awareness settings defined for the map. When a floor-aware map is loaded the floor-aware metadata populates the following classes.

These classes describe which layers and fields are used to support floor-aware mapping. While you could use this information to build queries to explore floor-aware relationships (facilities within a site, levels within a facility, and so on), the API abstracts this detail allowing you to read floor-aware metadata and implement floor filtering.

  • GeoModelFloorDefinition: exposes classes that define the sites, facilities, and levels configured in the map's floor-aware settings. This is null for maps that are not floor-aware.

  • SiteLayerDefinition: defines the layer and field properties for the (optional) site layer. A site layer defines the boundaries of managed sites (such as college campuses) that each contain one or more facilities.

  • FacilityLayerDefinition: defines the layer and field properties for the facility layer, which describes the footprints of managed facilities containing one or more levels.

  • LevelLayerDefinition: defines the layer and field properties for the level layer, which describes the footprint of each occupiable floor within a facility.

Floor-aware layers

Layers that contain features associated with a specific level within a facility expose floor-aware settings through a FloorAware interface. Layers that support floor-awareness, such as FeatureLayer, implement this interface.

FloorAware defines a read-write floorDefinition property of type LayerFloorDefinition that contains the properties that allow a layer to be floor-aware (such as the level at which a feature exists). Changing this property on-the-fly updates the floor filtering behavior. Setting or clearing this property toggles the floor filter rendering for the layer.

Iterate the floor-aware data model

You can iterate the floor-aware data model for a Map to find all available sites, facilities, and levels. You can also find all the facilities for a given site or all levels for a specific facility.

The FloorManager class exposes the sites, facilities, and levels of the floor-aware data model. You can get the FloorManager using the read-only floorManager() property of a map. This property returns null for maps that are not floor-aware. FloorManager inherits from Loadable and must be loaded before sites, facilities, and levels are available.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
    // Get all sites, facilities, and levels.
    QList<FloorSite*> allSites = m_floorManager->sites();
    QList<FloorFacility*> allFacilities = m_floorManager->facilities();
    QList<FloorLevel*> allLevels = m_floorManager->levels();

    // Get all facilities for a particular site.
    auto mainCampus = std::find_if(allSites.begin(), allSites.end(),
        [](FloorSite* site){return site->siteId() == "ESRI.RED.MAIN";});
    QList<FloorFacility*> mainCampusBuildings = (*mainCampus)->facilities();

    // Get all levels for a particular facility.
    auto buildingQ = std::find_if(mainCampusBuildings.begin(), mainCampusBuildings.end(),
        [](FloorFacility* facility){return facility->facilityId() == "ESRI.RED.MAIN.Q";});
    QList<FloorLevel*> buildingQLevels = (*buildingQ)->levels();

You can use the FloorManager to build a UI that allows your user to explore available sites, facilities, and levels in the map. For example, you can provide a tree view or set of list controls so the user can filter facilities by site, and then see all levels within a chosen facility.

Alternatively, the open source ArcGIS Maps SDK for Qt Toolkit provides a FloorFilter. If you pass the FloorManager to this component, it presents a UI control that allows your user to filter the floor plan data displayed in your map or scene view.

Floor control in the ArcGIS Online Map Viewer

Filter features by floor

FloorManager exposes a collection of FloorLevel, which includes properties that describe the following aspects of a level.

  • Associated facility: the facility that contains this level.
  • Visibility: whether or not the level is currently visible in the map.
  • Level ID: a string that uniquely identifies the level (across all levels in all facilities).
  • Level number: the number assigned to this level. This can differ from the actual order of the level. Some facilities, for example, don't designate a 13th floor. Instead, this level may be given a level number of 14.
  • Long name: a descriptive name of the level. A good convention for creating a clear description of the level is to use the facility name and level number for the long name.
  • Short name: a more succinct version of the long name. This is useful for showing a compact name in a UI element, such as a drop down list.
  • Vertical order: the actual position of the level in the collection of levels, sorted from low to high. The level order is zero-based. The ground floor is level 0, levels below it are negative, floors above positive.
  • Shape: a polygon geometry that describes the level.

Levels can be shown or hidden to filter the display for a specified level or levels in the map, either for a specific facility, multiple facilities, or across all facilities. The display of all floor-aware features is filtered according to the visibility of their associated level.

To display a single level for all facilities:

  1. Make sure the map is loaded.
  2. Get the map's FloorManager.
    • If the map is not floor-aware, the FloorManager will be null.
  3. Load the FloorManager to read the floor-aware data.
  4. Get the FloorLevel collection from the map's FloorManager.
    • This returns all levels for all facilities in the map.
  5. Iterate all FloorLevel objects in the collection.
    • Set the chosen level as visible.
    • Set all other levels as not visible.
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
    // Get all levels from FloorManager.
    QList<FloorLevel*> levels = m_floorManager->levels();

    // Iterate all levels in the collection.
    for (FloorLevel* lvl : levels)
    {
        // Set levels with the selected vertical order visible.
        lvl->setVisible(lvl->verticalOrder() == selectedVerticalPosition);
    }

To display a single level in a chosen facility:

  1. Make sure the map is loaded.
  2. Get the map's FloorManager.
    • If the map is not floor-aware, the FloorManager will be null.
  3. Load the FloorManager to read the floor-aware data.
  4. Get the chosen site, represented by a FloorSite object.
  5. Get the chosen facility from the collection of facilities for the site, represented by a FloorFacility object.
  6. Set the map view's viewpoint using the facility's geometry.
  7. Get the FloorLevel collection for the facility (exposed as a property on FloorFacility).
  8. Iterate all FloorLevel objects in the collection.
    • Set the chosen level as visible.
    • Set all other levels as not visible.
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
    // Get the chosen site from the FloorManager (using its unique site ID).
    QList<FloorSite*> sites = m_floorManager->sites();
    auto selectedSite =std::find_if(sites.begin(), sites.end(),
        [selectedSiteId](FloorSite* site){return site->siteId() == selectedSiteId;});

    // Get the chosen facility within the selected site (using its unique facility ID).
    QList<FloorFacility*> selectedFacilities = (*selectedSite)->facilities();
    auto building = std::find_if(selectedFacilities.begin(), selectedFacilities.end(),
        [selectedFacilityId](FloorFacility* facility){return facility->facilityId() == selectedFacilityId;});
    if (building == selectedFacilities.end()) { return; }

    // Set the viewpoint to center on this facility (to better see the levels).
    const Viewpoint facilityViewpoint((*building)->geometry());

    m_mapView->setViewpointAsync(facilityViewpoint);

    // Get all levels for this facility.
    QList<FloorLevel*> facilityLevels = (*building)->levels();

    // Iterate all levels in the collection.
    for (FloorLevel* lvl : facilityLevels)
    {
        // Set levels with the selected level number visible.
        lvl->setVisible(lvl->levelNumber() == selectedLevelNum);
    }

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.