Skip to main content

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>
Last updated March 3, 2025.