<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.9.0.css" />
<script src="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.9.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.1.css" />
<script src="https://maps-sdk.trimblemaps.com/addon/trimblemaps-draw-1.0.1.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
});
// https://stackoverflow.com/questions/37599561/drawing-a-circle-with-the-radius-in-miles-meters-with-mapbox-gl-js
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>