Feature Intersections
This example displays a map with 25 bounded random points, and one large circle polygon. Any points that intersect with the circle are colored blue, otherwise active features default to pink and inactive features default to light blue. You can also use the draw tool to add additional points and polygons to the map, which will also appear blue if they intersect with the circle. Requires Trimble Maps v3.0.0 or later.<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.css" /> <script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.js"></script> <script src="https://unpkg.com/@turf/turf@7/turf.min.js"></script> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-2.1.0.css" /> <script src="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-2.1.0.js"></script> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } </style> </head> <body> <div id="map"></div> <script> TrimbleMaps.setAPIKey('YOUR_API_KEY_HERE'); const map = (window.map = new TrimbleMaps.Map({ container: 'map', style: TrimbleMaps.Common.Style.TRANSPORTATION, // hosted style id center: [-109, 37.75], // starting position zoom: 6 // starting zoom })); const createGeoJSONCircle = function (center, radiusInKm, points) { if (!points) points = 64; const coords = {latitude: center[1], longitude: center[0]}; const km = radiusInKm; const ret = []; const distanceX = km / (111.32 * Math.cos((coords.latitude * Math.PI) / 180)); const distanceY = km / 110.574; let theta, x, y; for (let i = 0; i < points; i++) { theta = (i / points) * (2 * Math.PI); x = distanceX * Math.cos(theta); y = distanceY * Math.sin(theta); ret.push([coords.longitude + x, coords.latitude + y]); } ret.push(ret[0]); return { type: 'geojson', data: { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Polygon', coordinates: [ret], }, }, ], }, }; }; const randomNumber = function (min, max) { const nbr = Math.random() * (max - min) + min; return nbr.toFixed(5); }; const createFeature = function (id, coords) { return { type: 'Feature', properties: {id, intersect: 0}, geometry: { type: 'Point', coordinates: coords, }, }; }; const createFeatureCollection = function (features) { return { type: 'geojson', data: { type: 'FeatureCollection', features, }, }; }; const smallCircleStyle = { id: '', type: 'circle', source: '', paint: { 'circle-radius': 5, 'circle-color': [ 'match', ['get', 'intersect'], 1, '#0000FF', '#33C2FF', ], 'circle-stroke-color': [ 'match', ['get', 'intersect'], 1, '#0000FF', '#FFF', ], 'circle-stroke-width': 2, 'circle-opacity': 0.9, 'circle-stroke-opacity': 1, }, }; const drawStyles = [ { id: 'gl-draw-polygon-fill-inactive', type: 'fill', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Polygon'], ['!=', 'mode', 'static'], ], paint: { 'fill-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#33C2FF', ], 'fill-outline-color': '#33C2FF', 'fill-opacity': [ 'case', ['==', ['get', 'user_intersect'], 1], 0.9, 0.25, ], }, }, { id: 'gl-draw-polygon-fill-active', type: 'fill', filter: ['all', ['==', 'active', 'true'], ['==', '$type', 'Polygon']], paint: { 'fill-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#E555C9', ], 'fill-outline-color': '#E555C9', 'fill-opacity': [ 'case', ['==', ['get', 'user_intersect'], 1], 0.9, 0.25, ], }, }, { id: 'gl-draw-polygon-midpoint', type: 'circle', filter: ['all', ['==', '$type', 'Point'], ['==', 'meta', 'midpoint']], paint: { 'circle-radius': 5, 'circle-color': '#E555C9', }, }, { id: 'gl-draw-polygon-stroke-inactive', type: 'line', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Polygon'], ['!=', 'mode', 'static'], ], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#33C2FF', 'line-width': 2, }, }, { id: 'gl-draw-polygon-stroke-active', type: 'line', filter: ['all', ['==', 'active', 'true'], ['==', '$type', 'Polygon']], layout: { 'line-cap': 'butt', 'line-join': 'round', }, paint: { 'line-color': '#E555C9', 'line-dasharray': [3, 2], 'line-width': 2.5, }, }, { id: 'gl-draw-line-inactive', type: 'line', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'LineString'], ['!=', 'mode', 'static'], ], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#33C2FF', 'line-width': 2.5, }, }, { id: 'gl-draw-line-active', type: 'line', filter: [ 'all', ['==', '$type', 'LineString'], ['==', 'active', 'true'], ], layout: { 'line-cap': 'butt', 'line-join': 'round', }, paint: { 'line-color': '#E555C9', 'line-dasharray': [3, 2], 'line-width': 2.5, }, }, { id: 'gl-draw-polygon-and-line-vertex-stroke-inactive', type: 'circle', filter: [ 'all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 7, 'circle-color': '#fff', }, }, { id: 'gl-draw-polygon-and-line-vertex-inactive', type: 'circle', filter: [ 'all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 5, 'circle-color': '#E555C9', }, }, { id: 'gl-draw-point-point-stroke-inactive', type: 'circle', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Point'], ['==', 'meta', 'feature'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 7, 'circle-opacity': 1, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#FFF', ], }, }, { id: 'gl-draw-point-inactive', type: 'circle', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Point'], ['==', 'meta', 'feature'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 5, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#33C2FF', ], }, }, { id: 'gl-draw-point-stroke-active', type: 'circle', filter: [ 'all', ['==', '$type', 'Point'], ['==', 'active', 'true'], ['!=', 'meta', 'midpoint'], ], paint: { 'circle-radius': 7, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#FFF', ], }, }, { id: 'gl-draw-point-active', type: 'circle', filter: [ 'all', ['==', '$type', 'Point'], ['!=', 'meta', 'midpoint'], ['==', 'active', 'true'], ], paint: { 'circle-radius': 5, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#E555C9', ], }, }, { id: 'gl-draw-polygon-fill-static', type: 'fill', filter: ['all', ['==', 'mode', 'static'], ['==', '$type', 'Polygon']], paint: { 'fill-color': '#404040', 'fill-outline-color': '#404040', 'fill-opacity': 0.1, }, }, { id: 'gl-draw-polygon-stroke-static', type: 'line', filter: ['all', ['==', 'mode', 'static'], ['==', '$type', 'Polygon']], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#404040', 'line-width': 2.5, }, }, { id: 'gl-draw-line-static', type: 'line', filter: [ 'all', ['==', 'mode', 'static'], ['==', '$type', 'LineString'], ], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#404040', 'line-width': 2.5, }, }, { id: 'gl-draw-point-static', type: 'circle', filter: ['all', ['==', 'mode', 'static'], ['==', '$type', 'Point']], paint: { 'circle-radius': 7, 'circle-color': '#404040', }, }, ]; const bigCircleStyle = { id: 'bigCircle', type: 'fill', source: 'bigCircleSource', paint: { 'fill-color': '#FFFF00', 'fill-opacity': 0.4, 'fill-outline-color': '#FFFF00', }, }; map.on('load', () => { // Add a big circle const bigCircle = createGeoJSONCircle([-109, 37.75], 160, 128); map.addSource('bigCircleSource', bigCircle); map.addLayer(bigCircleStyle); // Add 25 random small circles const bounds = map.getBounds(); const sw = bounds.getSouthWest(); const ne = bounds.getNorthEast(); const features = []; for (let i = 0; i < 25; i++) { const rndLng = randomNumber(sw.lng, ne.lng); const rndLat = randomNumber(ne.lat, sw.lat); const circle = createFeature(`circle_${i}`, [rndLng, rndLat]); // Check if the point (small circle) is inside the big circle const isInside = turf.booleanPointInPolygon( circle.geometry, bigCircle.data.features[0] ); circle.properties.intersect = isInside ? 1 : 0; features.push(circle); } const pointsData = createFeatureCollection(features); map.addSource('smallCircleSource', pointsData); smallCircleStyle.id = 'smallCircle'; smallCircleStyle.source = 'smallCircleSource'; map.addLayer(smallCircleStyle); // Add Draw control to draw points and polygons. const draw = new TrimbleMapsControl.Draw({ styles: drawStyles, displayControlsDefault: false, controls: { polygon: true, point: true, }, defaultMode: 'draw_point', userProperties: true, }); map.addControl(draw, 'top-left'); const eventHandler = function (e) { const geometryType = e.features[0].geometry.type; const features = e.features; let intersect = false; if (geometryType !== 'Polygon') { // Check if the point is inside the big circle intersect = turf.booleanPointInPolygon( e.features[0].geometry, bigCircle.data.features[0] ); } features[0].properties.intersect = intersect ? 1 : 0; const polygon = createFeatureCollection(features); draw.add(polygon.data); }; map.on('draw.create', (e) => { eventHandler(e); }); map.on('draw.update', (e) => { eventHandler(e); }); }); </script> </body> </html>
Feature Intersections
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.css" /> <script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.js"></script> <script src="https://unpkg.com/@turf/turf@7/turf.min.js"></script> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-2.1.0.css" /> <script src="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-2.1.0.js"></script> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } </style> </head> <body> <div id="map"></div> <script> TrimbleMaps.setAPIKey('YOUR_API_KEY_HERE'); const map = (window.map = new TrimbleMaps.Map({ container: 'map', style: TrimbleMaps.Common.Style.TRANSPORTATION, // hosted style id center: [-109, 37.75], // starting position zoom: 6 // starting zoom })); const createGeoJSONCircle = function (center, radiusInKm, points) { if (!points) points = 64; const coords = {latitude: center[1], longitude: center[0]}; const km = radiusInKm; const ret = []; const distanceX = km / (111.32 * Math.cos((coords.latitude * Math.PI) / 180)); const distanceY = km / 110.574; let theta, x, y; for (let i = 0; i < points; i++) { theta = (i / points) * (2 * Math.PI); x = distanceX * Math.cos(theta); y = distanceY * Math.sin(theta); ret.push([coords.longitude + x, coords.latitude + y]); } ret.push(ret[0]); return { type: 'geojson', data: { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Polygon', coordinates: [ret], }, }, ], }, }; }; const randomNumber = function (min, max) { const nbr = Math.random() * (max - min) + min; return nbr.toFixed(5); }; const createFeature = function (id, coords) { return { type: 'Feature', properties: {id, intersect: 0}, geometry: { type: 'Point', coordinates: coords, }, }; }; const createFeatureCollection = function (features) { return { type: 'geojson', data: { type: 'FeatureCollection', features, }, }; }; const smallCircleStyle = { id: '', type: 'circle', source: '', paint: { 'circle-radius': 5, 'circle-color': [ 'match', ['get', 'intersect'], 1, '#0000FF', '#33C2FF', ], 'circle-stroke-color': [ 'match', ['get', 'intersect'], 1, '#0000FF', '#FFF', ], 'circle-stroke-width': 2, 'circle-opacity': 0.9, 'circle-stroke-opacity': 1, }, }; const drawStyles = [ { id: 'gl-draw-polygon-fill-inactive', type: 'fill', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Polygon'], ['!=', 'mode', 'static'], ], paint: { 'fill-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#33C2FF', ], 'fill-outline-color': '#33C2FF', 'fill-opacity': [ 'case', ['==', ['get', 'user_intersect'], 1], 0.9, 0.25, ], }, }, { id: 'gl-draw-polygon-fill-active', type: 'fill', filter: ['all', ['==', 'active', 'true'], ['==', '$type', 'Polygon']], paint: { 'fill-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#E555C9', ], 'fill-outline-color': '#E555C9', 'fill-opacity': [ 'case', ['==', ['get', 'user_intersect'], 1], 0.9, 0.25, ], }, }, { id: 'gl-draw-polygon-midpoint', type: 'circle', filter: ['all', ['==', '$type', 'Point'], ['==', 'meta', 'midpoint']], paint: { 'circle-radius': 5, 'circle-color': '#E555C9', }, }, { id: 'gl-draw-polygon-stroke-inactive', type: 'line', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Polygon'], ['!=', 'mode', 'static'], ], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#33C2FF', 'line-width': 2, }, }, { id: 'gl-draw-polygon-stroke-active', type: 'line', filter: ['all', ['==', 'active', 'true'], ['==', '$type', 'Polygon']], layout: { 'line-cap': 'butt', 'line-join': 'round', }, paint: { 'line-color': '#E555C9', 'line-dasharray': [3, 2], 'line-width': 2.5, }, }, { id: 'gl-draw-line-inactive', type: 'line', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'LineString'], ['!=', 'mode', 'static'], ], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#33C2FF', 'line-width': 2.5, }, }, { id: 'gl-draw-line-active', type: 'line', filter: [ 'all', ['==', '$type', 'LineString'], ['==', 'active', 'true'], ], layout: { 'line-cap': 'butt', 'line-join': 'round', }, paint: { 'line-color': '#E555C9', 'line-dasharray': [3, 2], 'line-width': 2.5, }, }, { id: 'gl-draw-polygon-and-line-vertex-stroke-inactive', type: 'circle', filter: [ 'all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 7, 'circle-color': '#fff', }, }, { id: 'gl-draw-polygon-and-line-vertex-inactive', type: 'circle', filter: [ 'all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 5, 'circle-color': '#E555C9', }, }, { id: 'gl-draw-point-point-stroke-inactive', type: 'circle', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Point'], ['==', 'meta', 'feature'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 7, 'circle-opacity': 1, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#FFF', ], }, }, { id: 'gl-draw-point-inactive', type: 'circle', filter: [ 'all', ['==', 'active', 'false'], ['==', '$type', 'Point'], ['==', 'meta', 'feature'], ['!=', 'mode', 'static'], ], paint: { 'circle-radius': 5, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#33C2FF', ], }, }, { id: 'gl-draw-point-stroke-active', type: 'circle', filter: [ 'all', ['==', '$type', 'Point'], ['==', 'active', 'true'], ['!=', 'meta', 'midpoint'], ], paint: { 'circle-radius': 7, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#FFF', ], }, }, { id: 'gl-draw-point-active', type: 'circle', filter: [ 'all', ['==', '$type', 'Point'], ['!=', 'meta', 'midpoint'], ['==', 'active', 'true'], ], paint: { 'circle-radius': 5, 'circle-color': [ 'case', ['==', ['get', 'user_intersect'], 1], '#0000FF', '#E555C9', ], }, }, { id: 'gl-draw-polygon-fill-static', type: 'fill', filter: ['all', ['==', 'mode', 'static'], ['==', '$type', 'Polygon']], paint: { 'fill-color': '#404040', 'fill-outline-color': '#404040', 'fill-opacity': 0.1, }, }, { id: 'gl-draw-polygon-stroke-static', type: 'line', filter: ['all', ['==', 'mode', 'static'], ['==', '$type', 'Polygon']], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#404040', 'line-width': 2.5, }, }, { id: 'gl-draw-line-static', type: 'line', filter: [ 'all', ['==', 'mode', 'static'], ['==', '$type', 'LineString'], ], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': '#404040', 'line-width': 2.5, }, }, { id: 'gl-draw-point-static', type: 'circle', filter: ['all', ['==', 'mode', 'static'], ['==', '$type', 'Point']], paint: { 'circle-radius': 7, 'circle-color': '#404040', }, }, ]; const bigCircleStyle = { id: 'bigCircle', type: 'fill', source: 'bigCircleSource', paint: { 'fill-color': '#FFFF00', 'fill-opacity': 0.4, 'fill-outline-color': '#FFFF00', }, }; map.on('load', () => { // Add a big circle const bigCircle = createGeoJSONCircle([-109, 37.75], 160, 128); map.addSource('bigCircleSource', bigCircle); map.addLayer(bigCircleStyle); // Add 25 random small circles const bounds = map.getBounds(); const sw = bounds.getSouthWest(); const ne = bounds.getNorthEast(); const features = []; for (let i = 0; i < 25; i++) { const rndLng = randomNumber(sw.lng, ne.lng); const rndLat = randomNumber(ne.lat, sw.lat); const circle = createFeature(`circle_${i}`, [rndLng, rndLat]); // Check if the point (small circle) is inside the big circle const isInside = turf.booleanPointInPolygon( circle.geometry, bigCircle.data.features[0] ); circle.properties.intersect = isInside ? 1 : 0; features.push(circle); } const pointsData = createFeatureCollection(features); map.addSource('smallCircleSource', pointsData); smallCircleStyle.id = 'smallCircle'; smallCircleStyle.source = 'smallCircleSource'; map.addLayer(smallCircleStyle); // Add Draw control to draw points and polygons. const draw = new TrimbleMapsControl.Draw({ styles: drawStyles, displayControlsDefault: false, controls: { polygon: true, point: true, }, defaultMode: 'draw_point', userProperties: true, }); map.addControl(draw, 'top-left'); const eventHandler = function (e) { const geometryType = e.features[0].geometry.type; const features = e.features; let intersect = false; if (geometryType !== 'Polygon') { // Check if the point is inside the big circle intersect = turf.booleanPointInPolygon( e.features[0].geometry, bigCircle.data.features[0] ); } features[0].properties.intersect = intersect ? 1 : 0; const polygon = createFeatureCollection(features); draw.add(polygon.data); }; map.on('draw.create', (e) => { eventHandler(e); }); map.on('draw.update', (e) => { eventHandler(e); }); }); </script> </body> </html>