Learn how to execute a spatial query to access polygon features
A feature layer
In this tutorial, you sketch a feature
Prerequisites
You need an ArcGIS Location Platform or ArcGIS Online account.
Steps
Get the starter app
Select a type of authentication and follow the steps to create a new app.
Choose API key authentication if you:
- Want the easiest way to get started.
- Want to build public applications
A public application is an application that allows anonymous access without requiring users to sign in with an ArcGIS account. It supports API key or app authentication. that access ArcGIS Location ServicesArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. and secure itemsAn item, also known as a content item, is a resource stored in a portal such as a web map, hosted layer, style, script tool, file, or notebook. . - Have an ArcGIS Location Platform or ArcGIS Online account.
Choose user authentication if you:
- Want to build private applications.
- Require application users to sign in with their own ArcGIS account
An ArcGIS account is an identity with a user type and set of privileges that can access specific ArcGIS products, tools, APIs, services, and resources. The main account types that can be used for development are an ArcGIS Location Platform account, ArcGIS Online account, and ArcGIS Enterprise account. ArcGIS Location Platform and ArcGIS Online accounts are also associated with a subscription. and access resources their behalf. - Have an ArcGIS Online account.
To learn more about both types of authentication, go to Authentication.
Set up authentication
Set developer credentials
Get a Cesium ion access token
All Cesium applications must use an access token provided through Cesium ion. This token allows you to access assets such as Cesium World Terrain in your application.
-
Go to your Cesium ion dashboard to generate an access token. Copy the key to your clipboard.
-
Create a
cesiumvariable and replaceAccess Token YOURwith the access token you copied from the Cesium ion dashboard._CESIUM _ACCESS _TOKEN Use dark colors for code blocks <script> /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URI", // The redirect URL registered in your OAuth credentials // portal: "YOUR_PORTAL_URL" // Your portal URL // }) // const accessToken = session.token; Cesium.ArcGisMapService.defaultAccessToken = accessToken; const cesiumAccessToken = "YOUR_CESIUM_ACCESS_TOKEN"; </script> -
Configure
Cesium.with the Cesium access token to validate the application.Ion.default Access Token Use dark colors for code blocks <script> /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URI", // The redirect URL registered in your OAuth credentials // portal: "YOUR_PORTAL_URL" // Your portal URL // }) // const accessToken = session.token; Cesium.ArcGisMapService.defaultAccessToken = accessToken; const cesiumAccessToken = "YOUR_CESIUM_ACCESS_TOKEN"; Cesium.Ion.defaultAccessToken = cesiumAccessToken; </script>
Add references to ArcGIS REST JS
-
In the
<headelement, reference the> feature-serviceandrequestpackages from ArcGIS REST JS.Use dark colors for code blocks <script src="https://cesium.com/downloads/cesiumjs/releases/1.140/Build/Cesium/Cesium.js"></script> <link href="https://cesium.com/downloads/cesiumjs/releases/1.140/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> <script src="https://unpkg.com/@esri/arcgis-rest-request@4/dist/bundled/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-feature-service@4/dist/bundled/feature-service.umd.js"></script> -
In the
<body, create an> arcgisusing your access token to authenticate requests to the feature serviceRest. Api Key Manager A feature service is a data service that provides access to spatial and non-spatial data in feature layers, feature layer views, and tables. .Use dark colors for code blocks /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URI", // The redirect URL registered in your OAuth credentials // portal: "YOUR_PORTAL_URL" // Your portal URL // }) // const accessToken = session.token; Cesium.ArcGisMapService.defaultAccessToken = accessToken; const authentication = arcgisRest.ApiKeyManager.fromKey(accessToken);
Create a drawing mode selector
-
Create a
<selectHTML element to provide a list of spatial operations for drawing features such as points, lines, or polygons.> Use dark colors for code blocks <div id="cesiumContainer"></div> <select id="mode-select"> <option value="">Choose a type of feature to draw...</option> <option value="Point">Draw point</option> <option value="Polyline">Draw line</option> <option value="Polygon" selected>Draw polygon</option> </select> -
Style the
<selectelement so that it displays properly in your application.> Use dark colors for code blocks <script src="https://unpkg.com/@terraformer/arcgis@2.0.7/dist/t-arcgis.umd.js"></script> <style> html, body, #cesiumContainer { width: 100%; height: 100%; padding: 0px; margin: 0px; } #mode-select { position: absolute; top: 8px; left: 8px; padding: 4px 8px; font-size: 16px; border-radius: 0; } </style>
Add a feature layer
Reference the LA County Parcels hosted feature layer
-
Copy the URL of the LA County Parcels feature layer.
Use dark colors for code blocks const layerName = "LA_County_Parcels"; const layerURL = "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/" + layerName + "/FeatureServer/0"; -
Add the data attribution
Data attribution is the requirement to display the names of data source providers in all applications when accessing ArcGIS content, layers, or services. for the feature layer source.- Go to the LA County Parcels item
An item, also known as a content item, is a resource stored in a portal such as a web map, hosted layer, style, script tool, file, or notebook. . - Scroll down to the Acknowledgments section and copy its value.
- Paste the copied value to the
creditproperty.Use dark colors for code blocks // Attribution text retrieved from https://arcgis.com/home/item.html?id=a6fdf2ee0e454393a53ba32b9838b303 viewer.creditDisplay.addStaticCredit(new Cesium.Credit("County of Los Angeles Office of the Assessor", false));
- Go to the LA County Parcels item
Create drawing tools
A spatial query is performed by passing a geometryx,y coordinates and a spatial reference.
-
Add methods to draw points, lines, and polygons on the map. The methods will be called based on the drawing mode the user selects.
Use dark colors for code blocks if (!viewer.scene.pickPositionSupported) { window.alert("This browser does not support pickPosition."); } viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction( Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK ); function createPoint(worldPosition) { const point = viewer.entities.add({ position: worldPosition, point: { color: Cesium.Color.WHITE, pixelSize: 5, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND } }); return point; } let drawingMode; function drawShape(positionData) { let shape; if (drawingMode === "Polyline") { shape = viewer.entities.add({ polyline: { positions: positionData, clampToGround: true, width: 3 } }); } else if (drawingMode === "Polygon") { shape = viewer.entities.add({ polygon: { hierarchy: positionData, outline: true, outlineWidth: 10, material: new Cesium.ColorMaterialProperty( Cesium.Color.WHITE.withAlpha(0.4) ) } }); } return shape; } -
Set up event handlers to initiate drawing in the selected mode (point, polyline, or polygon) when the user clicks. Dynamically update the shape based on mouse clicks and movements.
Use dark colors for code blocks let activeShapePoints = []; let activeShape; let floatingPoint; let newShape = true; const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas); handler.setInputAction(function (event) { if (!drawingMode) return; if (newShape) { viewer.entities.removeAll(); newShape = false; } const earthPosition = viewer.camera.pickEllipsoid(event.position); // `earthPosition` will be undefined if our mouse is not over the globe. if (Cesium.defined(earthPosition)) { // Points if (drawingMode === "Point") { activeShapePoints.push(earthPosition); createPoint(earthPosition); performQuery(); } else { if (activeShapePoints.length === 0) { floatingPoint = createPoint(earthPosition); activeShapePoints.push(earthPosition); const dynamicPositions = new Cesium.CallbackProperty(function () { if (drawingMode === "Polygon") { return new Cesium.PolygonHierarchy(activeShapePoints); } return activeShapePoints; }, false); activeShape = drawShape(dynamicPositions); } activeShapePoints.push(earthPosition); createPoint(earthPosition); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.setInputAction(function (event) { if (Cesium.defined(floatingPoint)) { const newPosition = viewer.camera.pickEllipsoid(event.endPosition); if (Cesium.defined(newPosition)) { floatingPoint.position.setValue(newPosition); activeShapePoints.pop(); activeShapePoints.push(newPosition); } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); -
Add code to terminate the drawing when the user double clicks.
Use dark colors for code blocks handler.setInputAction(function (event) { if (Cesium.defined(floatingPoint)) { const newPosition = viewer.camera.pickEllipsoid(event.endPosition); if (Cesium.defined(newPosition)) { floatingPoint.position.setValue(newPosition); activeShapePoints.pop(); activeShapePoints.push(newPosition); } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // Redraw the shape so it's not dynamic and remove the dynamic shape. function terminateShape() { viewer.entities.remove(floatingPoint); viewer.entities.remove(activeShape); floatingPoint = undefined; activeShape = undefined; activeShapePoints = []; newShape = true; } // Event listeners handler.setInputAction(function (event) { if (drawingMode === "Point" || !drawingMode) return; activeShapePoints.pop(); }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); const select = document.getElementById("mode-select"); select.addEventListener("change", () => { terminateShape(); viewer.entities.removeAll(); drawingMode = select.value; }); -
Create a helper function that converts the resulting geometries into ArcGIS format. This will be used to query the feature layer
A hosted feature layer is a hosted layer (item) in a portal that is used to manage the properties and settings of a spatially-enabled feature layer in a feature service. .Use dark colors for code blocks // Process features function getArcGISFeature(points) { //convert each point to cartesian latlng const degrees = []; for (point of points) { const cartographic = Cesium.Cartographic.fromCartesian(point); degrees.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]); } let coords; let type = drawingMode; if (drawingMode === "Point") { coords = degrees[0]; } else if (drawingMode === "Polyline") { type = "LineString"; coords = degrees; } else { coords = [degrees]; } const result = Terraformer.geojsonToArcGIS({ coordinates: coords, type: type }); return result; }
Query the feature layer
-
Create an
executefunction that usesQuery arcgisto query theRest.query Features Lfeature layer with a geometry. Set theA County Parcels spatialparameter of the request toRel esrito find parcels that intersect the geometry.Spatial Rel Intersects Use dark colors for code blocks function executeQuery(geometry) { arcgisRest.queryFeatures({ url: layerURL, authentication, f: "geojson", geometry: geometry, geometryType: "esriGeometry" + drawingMode, inSR: 4326, spatialRel: "esriSpatialRelIntersects", returnGeometry: true }) } -
Call
executeusing the drawn geometry when the user is finished drawing.Query Use dark colors for code blocks } function performQuery() { viewer.dataSources.removeAll(); const geometry = getArcGISFeature(activeShapePoints); executeQuery(geometry); drawShape(activeShapePoints); terminateShape(); } // Redraw the shape so it's not dynamic and remove the dynamic shape. function terminateShape() { viewer.entities.remove(floatingPoint); viewer.entities.remove(activeShape); floatingPoint = undefined; activeShape = undefined; activeShapePoints = []; newShape = true; } // Event listeners handler.setInputAction(function (event) { if (drawingMode === "Point" || !drawingMode) return; activeShapePoints.pop(); performQuery(); }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); -
Load the resulting features onto the map as a
Cesium..Geo Json Data Source Use dark colors for code blocks function executeQuery(geometry) { arcgisRest.queryFeatures({ url: layerURL, authentication, f: "geojson", geometry: geometry, geometryType: "esriGeometry" + drawingMode, inSR: 4326, spatialRel: "esriSpatialRelIntersects", returnGeometry: true }) .then((response) => { Cesium.GeoJsonDataSource.load(response).then((data) => { viewer.dataSources.add(data); }); }); }
Run the app
Run the app.
You should be able to draw features on the map and perform spatial queries against the feature layer.What's next?
Learn how to use additional location services in these tutorials:


