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/v3/trimblemaps-3.21.0.css" /> <script src="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.21.0.js"></script> <script src="https://unpkg.com/@turf/turf/turf.min.js"></script> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-1.0.3.css" /> <script src="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-1.0.3.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.APIKey = 'YOUR_API_KEY_HERE'; const map = window.map = new TrimbleMaps.Map({ container: 'map', // container id 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.320 * 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: id, intersect: 0 }, geometry: { type: 'Point', coordinates: coords } }; } const createFeatureCollection = function(features) { return { type: 'geojson', data: { type: 'FeatureCollection', features: 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', function() { // 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]) const isInside = turf.inside(circle, 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 takes an optional second argument to set the position of the control. // If no position is specified the control defaults to `top-right`. 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') { intersect = turf.inside(e.features[0], bigCircle.data.features[0]); } else { const intersection = turf.intersect(e.features[0], bigCircle.data.features[0]); intersect = intersection !== null ? 1 : 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/v3/trimblemaps-3.21.0.css" /> <script src="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.21.0.js"></script> <script src="https://unpkg.com/@turf/turf/turf.min.js"></script> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-1.0.3.css" /> <script src="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-1.0.3.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.APIKey = 'YOUR_API_KEY_HERE'; const map = window.map = new TrimbleMaps.Map({ container: 'map', // container id 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.320 * 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: id, intersect: 0 }, geometry: { type: 'Point', coordinates: coords } }; } const createFeatureCollection = function(features) { return { type: 'geojson', data: { type: 'FeatureCollection', features: 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', function() { // 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]) const isInside = turf.inside(circle, 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 takes an optional second argument to set the position of the control. // If no position is specified the control defaults to `top-right`. 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') { intersect = turf.inside(e.features[0], bigCircle.data.features[0]); } else { const intersection = turf.intersect(e.features[0], bigCircle.data.features[0]); intersect = intersection !== null ? 1 : 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>