Filter 3D scene features out of a given geometry with a polygon filter.
Use case
You can selectively show or hide features within a scene view using setFeaturesVisible
to filter specific features or set a SceneLayerPolygonFilter
to filter features given a polygon. Through these methods, you can directly control what users see within a specific scene view to give a more focused or cleaner user experience.
How to use the sample
The sample initializes showing the 3D buildings OpenStreetMap layer. Click the "Load detailed buildings" button to load an additional scene layer that contains more detailed buildings. Notice how the two scene layers overlap and clip into each other. Click the "Filter OSM buildings in extent" button, to set a SceneLayerPolygonFilter
and filter out the OpenStreetMap buildings within the extent of the detailed buildings scene. Notice how the OSM buildings within and intersecting the extent of the detailed buildings layer are hidden. Click the "Reset scene" button to hide the detailed buildings scene layer and clear the OSM buildings filter.
How it works
- Construct a
Basemap
for the scene using an OpenStreetMap TopographicArcGISVectorTileLayer
and the OpenStreetMap 3D BuildingsArcGISSceneLayer
as baselayers. - Set the OSM buildings layer's
polygonFilter
property to aSceneLayerPolygonFilter
with an empty list of polygons and aSceneLayerPolygonFilterSpatialRelationshipDisjoint
enum to hide all features within the extent. - Create a
Surface
for the scene and set the World Elevation 3D as an elevation source. - Add the 3D San Francisco Buildings
ArcGISSceneLayer
to the scene's operational layers. - When the detailed buildings layer finishes loading, build a polygon from its extent and set that polygon to the OSM building's polygon filter to hide all OSM buildings within the extent.
Relevant API
- ArcGISSceneLayer
- SceneLayerPolygonFilter
- SceneLayerPolygonFilterSpatialRelationship
About the data
This sample uses the OpenStreetMap 3D Buildings which provides generic 3D outlines of buildings throughout the world. It is based on the OSM Daylight map distribution and is hosted by Esri. It uses the San Francisco 3D Buildings scene layer which provides detailed 3D models of buildings in San Francisco, California, USA.
Additional information
This sample uses SceneLayerPolygonFilterSpatialRelationship::Disjoint
to hide all features within the extent of the given geometry. You can alternatively use SceneLayerPolygonFilterSpatialRelationship::Contains
to only show features within the extent of the geometry.
You can also show or hide features in a scene layer using ArcGISSceneLayer.setFeatureVisible
or setFeaturesVisible
and pass in a feature or list of features and a boolean value to set their visibility.
Tags
3D, buildings, disjoint, exclude, extent, filter, hide, OSM, polygon
Sample Code
// [WriteFile Name=FilterFeaturesInScene, Category=Scenes]
// [Legal]
// Copyright 2023 Esri.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]
import QtQuick
import QtQuick.Controls
import Esri.ArcGISRuntime
Rectangle {
id: rootRectangle
clip: true
width: 800
height: 600
SceneView {
id: sceneView
anchors.fill: parent
Component.onCompleted: {
// Set and keep the focus on SceneView to enable keyboard navigation
forceActiveFocus();
}
Scene {
Basemap {
ArcGISVectorTiledLayer {
item: PortalItem {itemId: "1e7d1784d1ef4b79ba6764d0bd6c3150"}
}
ArcGISSceneLayer {
id: osmBuildingsSceneLayer
item: PortalItem {itemId: "ca0470dbbddb4db28bad74ed39949e25"}
polygonFilter: SceneLayerPolygonFilter {
id: osmSceneLayerPolygonFilter
polygons: []
spatialRelationship: Enums.SceneLayerPolygonFilterSpatialRelationshipDisjoint
}
}
}
Surface {
ArcGISTiledElevationSource {
url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"
}
}
ArcGISSceneLayer {
id: detailedBuildingsSceneLayer
url: "https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/SanFrancisco_Bldgs/SceneServer"
property Polygon extentPolygon: null
// Initially set visibility to false for sample demonstration
visible: false
onLoadStatusChanged: {
if (loadStatus !== Enums.LoadStatusLoaded)
return;
const extent = fullExtent;
// Create a polygon builder
const polygonBuilder = ArcGISRuntimeEnvironment.createObject("PolygonBuilder", {
spatialReference: Factory.SpatialReference.createWgs84()
});
polygonBuilder.addPointXY(extent.xMin, extent.yMin);
polygonBuilder.addPointXY(extent.xMax, extent.yMin);
polygonBuilder.addPointXY(extent.xMax, extent.yMax);
polygonBuilder.addPointXY(extent.xMin, extent.yMax);
// Save the extent polygon to later apply it to the osmSceneLayerPolygonFilter when the user clicks the button
extentPolygon = polygonBuilder.geometry;
// Create a red border to show the extent of the detailed buildings layer
const extentFillSymbol = ArcGISRuntimeEnvironment
.createObject("SimpleFillSymbol", {
style: Enums.SimpleFillSymbolStyleNull,
color: "transparent",
outline: ArcGISRuntimeEnvironment
.createObject("SimpleLineSymbol", {
style: Enums.SimpleLineSymbolStyleSolid,
color: "red",
width: 5
})
});
const extentGraphic = ArcGISRuntimeEnvironment
.createObject("Graphic", {
geometry: extentPolygon,
symbol: extentFillSymbol
});
graphicsOverlay.graphics.append(extentGraphic);
}
}
// set an initial viewpoint
ViewpointCenter {
Point {
id: initialPoint
x: -122.421
y: 37.7041
z: 207
spatialReference: SpatialReference { wkid: 4326 }
}
targetScale: 1000
Camera {
id: camera
location: initialPoint
heading: 60
pitch: 70
roll: 0
}
}
}
GraphicsOverlay {
id: graphicsOverlay
// Initially set visibility to false for sample demonstration
visible: false
}
}
Button {
anchors {
top: parent.top
right: parent.right
margins: 15
}
property int step: 0
text: ["Load detailed buildings","Filter OSM buildings in extent","Reset scene"][step]
onClicked: {
switch (step) {
case 0:
// Show the detailed buildings scene layer and extent graphic
detailedBuildingsSceneLayer.visible = true;
graphicsOverlay.visible = true;
step++;
break;
case 1:
// Set the osmSceneLayerPolygonFilter's polygons to the extent of the detailed buildings layer
// to hide all OSM buildings within that area
osmSceneLayerPolygonFilter.polygons = [detailedBuildingsSceneLayer.extentPolygon];
step++;
break;
case 2:
// Reset the scene to its original state
detailedBuildingsSceneLayer.visible = false;
graphicsOverlay.visible = false;
osmSceneLayerPolygonFilter.polygons = [];
step = 0;
break;
default:
step = 0;
break;
}
}
}
}