Search

Filter Trajectories

GeoJSON Boundaries

Create an interactive GeoJSON layer to filter trajectories.

Filter Trajectories
View live example →

Click a region to filter out any trajectories that do not pass through the clicked region.

You can add event handlers to the GeoJSON layer and create a filtering interaction such as the one in this example.

Use the click event with overrideStyle() to update the styling.

Clear the styling override by calling the returned StyleReset function.

Use the onClick event prop with overrideStyles to update the styling.

import { MapWeave } from "mapweave/mapbox";
import { GeoJsonLayer, ObservationsLayer } from "mapweave/layers";
import { observationsData, geojsonData, shipsPerRegion, getRegionColor } from "./data";

const observationsLayerOptions = {
  trajectory: {
    maximumInterval: 60 * 60 * 1000,
  },
  individual: {
    autoRange: { min: 0 },
    minimumRadiusMeters: 1000,
  },
};

const hoveredAlpha = 0.4;
const selectedAlpha = 0.5;

let selectedRegionId = null;

const filterEntries = (obj, filterFn) => Object.fromEntries(Object.entries(obj).filter(filterFn));

function filterObservationsData() {
  if (selectedRegionId === null) {
    return observationsData;
  }
  const entitiesToInclude = shipsPerRegion.get(selectedRegionId);
  const { entities, observations } = observationsData;
  return {
    entities: filterEntries(entities, ([entityId]) => entitiesToInclude.has(entityId)),
    observations: filterEntries(observations, ([, { entityId }]) =>
      entitiesToInclude.has(entityId)
    ),
  };
}

// Return id if it is a valid region id, otherwise null
function getRegionId(id) {
  return shipsPerRegion.has(id) ? id : null;
}

const mapweave = new MapWeave({
  container: "mw",
  options: { accessToken: VITE_MAPBOX_API_KEY },
});

const observationsLayer = new ObservationsLayer({
  data: observationsData,
  options: observationsLayerOptions,
});

const geoJsonLayer = new GeoJsonLayer({ data: geojsonData });

mapweave.layers([observationsLayer, geoJsonLayer]);

let selectStyleReset;

mapweave.on("click", ({ id }) => {
  selectStyleReset?.();
  const regionId = getRegionId(id);
  selectedRegionId = regionId;
  observationsLayer.data(filterObservationsData());
  if (selectedRegionId !== null) {
    const color = getRegionColor(selectedAlpha);
    selectStyleReset = geoJsonLayer.overrideStyle(selectedRegionId, { color });
  }
});

let hoverStyleReset;

mapweave.on("hover", ({ id }) => {
  hoverStyleReset?.();
  const regionId = getRegionId(id);
  if (regionId !== null && regionId !== selectedRegionId) {
    const color = getRegionColor(hoveredAlpha);
    hoverStyleReset = geoJsonLayer.overrideStyle(regionId, { color });
  }
});

mapweave.fitBounds();
export const observationsData = {
  entities: {
    blueShip: {
      color: "rgb(83, 131, 236)",
    },
    redShip: {
      color: "rgb(216, 81, 64)",
    },
    yellowShip: {
      color: "rgb(241, 191, 66)",
    },
    greenShip: {
      color: "rgb(88, 166, 92)",
    },
  },
  observations: {
    "blue-0": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.578355,
      longitude: -5.197542,
      time: 1746489600000,
    },
    "blue-1": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.406994,
      longitude: -5.210292,
      time: 1746493200000,
    },
    "blue-2": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.272794,
      longitude: -5.208974,
      time: 1746496800000,
    },
    "blue-3": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.142754,
      longitude: -5.184721,
      time: 1746500400000,
    },
    "blue-4": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.97328,
      longitude: -5.185769,
      time: 1746504000000,
    },
    "blue-5": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.837737,
      longitude: -5.164967,
      time: 1746507600000,
    },
    "blue-6": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.670558,
      longitude: -5.192878,
      time: 1746511200000,
    },
    "blue-7": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.504643,
      longitude: -5.186715,
      time: 1746514800000,
    },
    "blue-8": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.365212,
      longitude: -5.17317,
      time: 1746518400000,
    },
    "blue-9": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.2161,
      longitude: -5.162903,
      time: 1746522000000,
    },
    "blue-10": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.052743,
      longitude: -5.226897,
      time: 1746525600000,
    },
    "blue-11": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.892953,
      longitude: -5.333351,
      time: 1746529200000,
    },
    "blue-12": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.711297,
      longitude: -5.375885,
      time: 1746532800000,
    },
    "blue-13": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.568214,
      longitude: -5.457204,
      time: 1746536400000,
    },
    "blue-14": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.409118,
      longitude: -5.529224,
      time: 1746540000000,
    },
    "blue-15": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.242918,
      longitude: -5.60549,
      time: 1746543600000,
    },
    "blue-16": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.071092,
      longitude: -5.692136,
      time: 1746547200000,
    },
    "blue-17": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.899728,
      longitude: -5.787732,
      time: 1746550800000,
    },
    "blue-18": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.739952,
      longitude: -5.85027,
      time: 1746554400000,
    },
    "blue-19": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.602765,
      longitude: -5.974733,
      time: 1746558000000,
    },
    "blue-20": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.474164,
      longitude: -6.114349,
      time: 1746561600000,
    },
    "blue-21": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.362769,
      longitude: -6.264626,
      time: 1746565200000,
    },
    "blue-22": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.204582,
      longitude: -6.360486,
      time: 1746568800000,
    },
    "blue-23": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.084279,
      longitude: -6.526525,
      time: 1746572400000,
    },
    "blue-24": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.941434,
      longitude: -6.627714,
      time: 1746576000000,
    },
    "blue-25": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.815822,
      longitude: -6.768253,
      time: 1746579600000,
    },
    "blue-26": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.68009,
      longitude: -6.922329,
      time: 1746583200000,
    },
    "blue-27": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.56413,
      longitude: -7.037884,
      time: 1746586800000,
    },
    "blue-28": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.406445,
      longitude: -7.036782,
      time: 1746590400000,
    },
    "blue-29": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.247185,
      longitude: -7.004507,
      time: 1746594000000,
    },
    "blue-30": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.08487,
      longitude: -7.014869,
      time: 1746597600000,
    },
    "blue-31": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.937541,
      longitude: -6.993953,
      time: 1746601200000,
    },
    "blue-32": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.784533,
      longitude: -6.984443,
      time: 1746604800000,
    },
    "blue-33": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.639579,
      longitude: -6.960981,
      time: 1746608400000,
    },
    "blue-34": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.467846,
      longitude: -6.961437,
      time: 1746612000000,
    },
    "blue-35": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.32475,
      longitude: -6.92981,
      time: 1746615600000,
    },
    "blue-36": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.152295,
      longitude: -6.93082,
      time: 1746619200000,
    },
    "red-0": {
      type: "observation",
      entityId: "redShip",
      latitude: 52.370025,
      longitude: 3.706578,
      time: 1746489600000,
    },
    "red-1": {
      type: "observation",
      entityId: "redShip",
      latitude: 52.215551,
      longitude: 3.465443,
      time: 1746493200000,
    },
    "red-2": {
      type: "observation",
      entityId: "redShip",
      latitude: 52.06524,
      longitude: 3.234558,
      time: 1746496800000,
    },
    "red-3": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.919175,
      longitude: 2.966129,
      time: 1746500400000,
    },
    "red-4": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.736291,
      longitude: 2.750087,
      time: 1746504000000,
    },
    "red-5": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.575317,
      longitude: 2.48578,
      time: 1746507600000,
    },
    "red-6": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.418045,
      longitude: 2.244322,
      time: 1746511200000,
    },
    "red-7": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.263755,
      longitude: 1.993267,
      time: 1746514800000,
    },
    "red-8": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.140054,
      longitude: 1.762104,
      time: 1746518400000,
    },
    "red-9": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.971223,
      longitude: 1.516238,
      time: 1746522000000,
    },
    "red-10": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.852823,
      longitude: 1.357977,
      time: 1746525600000,
    },
    "red-11": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.741735,
      longitude: 1.215997,
      time: 1746529200000,
    },
    "red-12": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.631068,
      longitude: 1.037502,
      time: 1746532800000,
    },
    "red-13": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.53398,
      longitude: 0.888554,
      time: 1746536400000,
    },
    "red-14": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.428207,
      longitude: 0.717581,
      time: 1746540000000,
    },
    "red-15": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.30806,
      longitude: 0.549199,
      time: 1746543600000,
    },
    "red-16": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.196893,
      longitude: 0.41216,
      time: 1746547200000,
    },
    "red-17": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.11447,
      longitude: 0.251521,
      time: 1746550800000,
    },
    "red-18": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.001293,
      longitude: 0.076072,
      time: 1746554400000,
    },
    "red-19": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.976381,
      longitude: -0.224351,
      time: 1746558000000,
    },
    "red-20": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.953019,
      longitude: -0.49948,
      time: 1746561600000,
    },
    "red-21": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.941289,
      longitude: -0.756986,
      time: 1746565200000,
    },
    "red-22": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.922577,
      longitude: -1.06356,
      time: 1746568800000,
    },
    "red-23": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.919638,
      longitude: -1.322502,
      time: 1746572400000,
    },
    "red-24": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.864749,
      longitude: -1.595358,
      time: 1746576000000,
    },
    "red-25": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.843586,
      longitude: -1.889306,
      time: 1746579600000,
    },
    "red-26": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.86042,
      longitude: -2.184169,
      time: 1746583200000,
    },
    "red-27": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.822904,
      longitude: -2.451595,
      time: 1746586800000,
    },
    "red-28": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.717736,
      longitude: -2.732433,
      time: 1746590400000,
    },
    "red-29": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.587322,
      longitude: -3.005417,
      time: 1746594000000,
    },
    "red-30": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.45591,
      longitude: -3.266489,
      time: 1746597600000,
    },
    "red-31": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.319815,
      longitude: -3.515813,
      time: 1746601200000,
    },
    "red-32": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.199566,
      longitude: -3.802024,
      time: 1746604800000,
    },
    "red-33": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.107795,
      longitude: -4.089816,
      time: 1746608400000,
    },
    "red-34": {
      type: "observation",
      entityId: "redShip",
      latitude: 48.968048,
      longitude: -4.332165,
      time: 1746612000000,
    },
    "red-35": {
      type: "observation",
      entityId: "redShip",
      latitude: 48.84175,
      longitude: -4.635675,
      time: 1746615600000,
    },
    "red-36": {
      type: "observation",
      entityId: "redShip",
      latitude: 48.729006,
      longitude: -4.887932,
      time: 1746619200000,
    },
    "yellow-0": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.742687,
      longitude: -5.517006,
      time: 1746489600000,
    },
    "yellow-1": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.77585,
      longitude: -5.174162,
      time: 1746493200000,
    },
    "yellow-2": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.859453,
      longitude: -4.812579,
      time: 1746496800000,
    },
    "yellow-3": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.887234,
      longitude: -4.482283,
      time: 1746500400000,
    },
    "yellow-4": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.969189,
      longitude: -4.153157,
      time: 1746504000000,
    },
    "yellow-5": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.996704,
      longitude: -3.79536,
      time: 1746507600000,
    },
    "yellow-6": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.062269,
      longitude: -3.458585,
      time: 1746511200000,
    },
    "yellow-7": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.110711,
      longitude: -3.103859,
      time: 1746514800000,
    },
    "yellow-8": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.177785,
      longitude: -2.747572,
      time: 1746518400000,
    },
    "yellow-9": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.219657,
      longitude: -2.413479,
      time: 1746522000000,
    },
    "yellow-10": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.225445,
      longitude: -2.173332,
      time: 1746525600000,
    },
    "yellow-11": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.27729,
      longitude: -1.883357,
      time: 1746529200000,
    },
    "yellow-12": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.268126,
      longitude: -1.636639,
      time: 1746532800000,
    },
    "yellow-13": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.293733,
      longitude: -1.368887,
      time: 1746536400000,
    },
    "yellow-14": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.309745,
      longitude: -1.121686,
      time: 1746540000000,
    },
    "yellow-15": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.33365,
      longitude: -0.863134,
      time: 1746543600000,
    },
    "yellow-16": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.349588,
      longitude: -0.589228,
      time: 1746547200000,
    },
    "yellow-17": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.376335,
      longitude: -0.357044,
      time: 1746550800000,
    },
    "yellow-18": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.395133,
      longitude: -0.088295,
      time: 1746554400000,
    },
    "yellow-19": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.460482,
      longitude: 0.086023,
      time: 1746558000000,
    },
    "yellow-20": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.550902,
      longitude: 0.238852,
      time: 1746561600000,
    },
    "yellow-21": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.611105,
      longitude: 0.411044,
      time: 1746565200000,
    },
    "yellow-22": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.694637,
      longitude: 0.578058,
      time: 1746568800000,
    },
    "yellow-23": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.77433,
      longitude: 0.737261,
      time: 1746572400000,
    },
    "yellow-24": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.853582,
      longitude: 0.898914,
      time: 1746576000000,
    },
    "yellow-25": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.922793,
      longitude: 1.071283,
      time: 1746579600000,
    },
    "yellow-26": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.997163,
      longitude: 1.246802,
      time: 1746583200000,
    },
    "yellow-27": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.061204,
      longitude: 1.421502,
      time: 1746586800000,
    },
    "yellow-28": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.179615,
      longitude: 1.491568,
      time: 1746590400000,
    },
    "yellow-29": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.331974,
      longitude: 1.535249,
      time: 1746594000000,
    },
    "yellow-30": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.446136,
      longitude: 1.606495,
      time: 1746597600000,
    },
    "yellow-31": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.577289,
      longitude: 1.67907,
      time: 1746601200000,
    },
    "yellow-32": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.712057,
      longitude: 1.730155,
      time: 1746604800000,
    },
    "yellow-33": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.842222,
      longitude: 1.787359,
      time: 1746608400000,
    },
    "yellow-34": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.967187,
      longitude: 1.847835,
      time: 1746612000000,
    },
    "yellow-35": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 52.110784,
      longitude: 1.920065,
      time: 1746615600000,
    },
    "yellow-36": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 52.220649,
      longitude: 1.988451,
      time: 1746619200000,
    },
    "green-0": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.642166,
      longitude: -0.206432,
      time: 1746489600000,
    },
    "green-1": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.72148,
      longitude: -0.045392,
      time: 1746493200000,
    },
    "green-2": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.773523,
      longitude: 0.094019,
      time: 1746496800000,
    },
    "green-3": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.812568,
      longitude: 0.246296,
      time: 1746500400000,
    },
    "green-4": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.89297,
      longitude: 0.393587,
      time: 1746504000000,
    },
    "green-5": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.922868,
      longitude: 0.517232,
      time: 1746507600000,
    },
    "green-6": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.015095,
      longitude: 0.678897,
      time: 1746511200000,
    },
    "green-7": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.0724,
      longitude: 0.813281,
      time: 1746514800000,
    },
    "green-8": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.130035,
      longitude: 0.976137,
      time: 1746518400000,
    },
    "green-9": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.177675,
      longitude: 1.110818,
      time: 1746522000000,
    },
    "green-10": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.242837,
      longitude: 1.146687,
      time: 1746525600000,
    },
    "green-11": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.336519,
      longitude: 1.199466,
      time: 1746529200000,
    },
    "green-12": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.396971,
      longitude: 1.248527,
      time: 1746532800000,
    },
    "green-13": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.493277,
      longitude: 1.311625,
      time: 1746536400000,
    },
    "green-14": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.589783,
      longitude: 1.326871,
      time: 1746540000000,
    },
    "green-15": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.668123,
      longitude: 1.401063,
      time: 1746543600000,
    },
    "green-16": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.746436,
      longitude: 1.422752,
      time: 1746547200000,
    },
    "green-17": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.826394,
      longitude: 1.484131,
      time: 1746550800000,
    },
    "green-18": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.893871,
      longitude: 1.529005,
      time: 1746554400000,
    },
    "green-19": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.967241,
      longitude: 1.67732,
      time: 1746558000000,
    },
    "green-20": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.013555,
      longitude: 1.84518,
      time: 1746561600000,
    },
    "green-21": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.086254,
      longitude: 2.040142,
      time: 1746565200000,
    },
    "green-22": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.174896,
      longitude: 2.184954,
      time: 1746568800000,
    },
    "green-23": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.239722,
      longitude: 2.367642,
      time: 1746572400000,
    },
    "green-24": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.291813,
      longitude: 2.526876,
      time: 1746576000000,
    },
    "green-25": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.368212,
      longitude: 2.66567,
      time: 1746579600000,
    },
    "green-26": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.438635,
      longitude: 2.857788,
      time: 1746583200000,
    },
    "green-27": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.511591,
      longitude: 3.003932,
      time: 1746586800000,
    },
    "green-28": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.573699,
      longitude: 3.11906,
      time: 1746590400000,
    },
    "green-29": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.660869,
      longitude: 3.197849,
      time: 1746594000000,
    },
    "green-30": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.728586,
      longitude: 3.320669,
      time: 1746597600000,
    },
    "green-31": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.828897,
      longitude: 3.432333,
      time: 1746601200000,
    },
    "green-32": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.902916,
      longitude: 3.548628,
      time: 1746604800000,
    },
    "green-33": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.965803,
      longitude: 3.648003,
      time: 1746608400000,
    },
    "green-34": {
      type: "observation",
      entityId: "greenShip",
      latitude: 52.045515,
      longitude: 3.761248,
      time: 1746612000000,
    },
    "green-35": {
      type: "observation",
      entityId: "greenShip",
      latitude: 52.135806,
      longitude: 3.87378,
      time: 1746615600000,
    },
    "green-36": {
      type: "observation",
      entityId: "greenShip",
      latitude: 52.215531,
      longitude: 3.963111,
      time: 1746619200000,
    },
  },
};

const regions = {
  region1: { south: 49.2, west: -7.5, north: 50.6, east: -4.5 },
  region2: { south: 49.3, west: -2.7, north: 50.9, east: -0.7 },
  region3: { south: 50.6, west: 1.2, north: 52, east: 3.1 },
};

const standardAlpha = 0.3;

const shipIds = Object.keys(observationsData.entities);

export function getRegionColor(alpha) {
  return `rgba(0, 255, 0, ${alpha})`;
}

// Does a ship have any observations in the specified region?
function isShipInRegion(shipId, { south, west, north, east }) {
  return Object.values(observationsData.observations).some(
    ({ entityId, latitude, longitude }) =>
      entityId === shipId &&
      longitude >= west &&
      longitude <= east &&
      latitude >= south &&
      latitude <= north
  );
}

// Determine which ships pass through which regions
export const shipsPerRegion = new Map();
for (const [regionId, region] of Object.entries(regions)) {
  const shipsInThisRegion = new Set();
  for (const shipId of shipIds) {
    if (isShipInRegion(shipId, region)) {
      shipsInThisRegion.add(shipId);
    }
  }
  shipsPerRegion.set(regionId, shipsInThisRegion);
}

function makeGeoJsonData() {
  return {
    type: "FeatureCollection",
    features: Object.entries(regions).map(([id, { south, west, north, east }]) => {
      return {
        type: "Feature",
        id,
        properties: {
          color: getRegionColor(standardAlpha),
        },
        geometry: {
          type: "Polygon",
          coordinates: [
            [
              [west, south],
              [west, north],
              [east, north],
              [east, south],
              [west, south],
            ],
          ],
        },
      };
    }),
  };
}

export const geojsonData = makeGeoJsonData();
<!doctype html>
<html>
  <body>
    <div id="mw"></div>
    <script type="module" src="./code.js"></script>
  </body>
</html>
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { MapWeave } from "mapweave/react/mapbox";
import { observationsData, geojsonData, shipsPerRegion, getRegionColor } from "./data";
import { GeoJsonLayer, ObservationsLayer } from "mapweave/react/layers";

const mapWeaveOptions = { accessToken: VITE_MAPBOX_API_KEY };

const observationsLayerOptions = {
  trajectory: {
    maximumInterval: 60 * 60 * 1000,
  },
  individual: {
    autoRange: { min: 0 },
    minimumRadiusMeters: 1000,
  },
};

const hoveredAlpha = 0.4;
const selectedAlpha = 0.5;

const filterEntries = (obj, filterFn) => Object.fromEntries(Object.entries(obj).filter(filterFn));

function filterObservationsData(selectedRegionId) {
  if (selectedRegionId === null) {
    return observationsData;
  }
  const entitiesToInclude = shipsPerRegion.get(selectedRegionId);
  const { entities, observations } = observationsData;
  return {
    entities: filterEntries(entities, ([entityId]) => entitiesToInclude.has(entityId)),
    observations: filterEntries(observations, ([, { entityId }]) =>
      entitiesToInclude.has(entityId)
    ),
  };
}

// Return id if it is a valid region id, otherwise null
function getRegionId(id) {
  return shipsPerRegion.has(id) ? id : null;
}

function Demo() {
  const [selectedRegionId, setSelectedRegionId] = useState(null);
  const [hoveredRegionId, setHoveredRegionId] = useState(null);

  const overrideStyles = [];

  if (hoveredRegionId) {
    overrideStyles.push({
      ids: hoveredRegionId,
      overrideStyle: { color: getRegionColor(hoveredAlpha) },
    });
  }

  if (selectedRegionId) {
    overrideStyles.push({
      ids: selectedRegionId,
      overrideStyle: { color: getRegionColor(selectedAlpha) },
    });
  }

  return (
    <MapWeave
      options={mapWeaveOptions}
      onClick={({ id }) => {
        setSelectedRegionId(getRegionId(id));
      }}
      onHover={({ id }) => {
        setHoveredRegionId(getRegionId(id));
      }}
    >
      <ObservationsLayer
        data={filterObservationsData(selectedRegionId)}
        options={observationsLayerOptions}
      />
      <GeoJsonLayer data={geojsonData} overrideStyles={overrideStyles} />
    </MapWeave>
  );
}

const root = createRoot(document.getElementById("mw"));
root.render(<Demo />);
export const observationsData = {
  entities: {
    blueShip: {
      color: "rgb(83, 131, 236)",
    },
    redShip: {
      color: "rgb(216, 81, 64)",
    },
    yellowShip: {
      color: "rgb(241, 191, 66)",
    },
    greenShip: {
      color: "rgb(88, 166, 92)",
    },
  },
  observations: {
    "blue-0": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.578355,
      longitude: -5.197542,
      time: 1746489600000,
    },
    "blue-1": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.406994,
      longitude: -5.210292,
      time: 1746493200000,
    },
    "blue-2": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.272794,
      longitude: -5.208974,
      time: 1746496800000,
    },
    "blue-3": {
      type: "observation",
      entityId: "blueShip",
      latitude: 54.142754,
      longitude: -5.184721,
      time: 1746500400000,
    },
    "blue-4": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.97328,
      longitude: -5.185769,
      time: 1746504000000,
    },
    "blue-5": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.837737,
      longitude: -5.164967,
      time: 1746507600000,
    },
    "blue-6": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.670558,
      longitude: -5.192878,
      time: 1746511200000,
    },
    "blue-7": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.504643,
      longitude: -5.186715,
      time: 1746514800000,
    },
    "blue-8": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.365212,
      longitude: -5.17317,
      time: 1746518400000,
    },
    "blue-9": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.2161,
      longitude: -5.162903,
      time: 1746522000000,
    },
    "blue-10": {
      type: "observation",
      entityId: "blueShip",
      latitude: 53.052743,
      longitude: -5.226897,
      time: 1746525600000,
    },
    "blue-11": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.892953,
      longitude: -5.333351,
      time: 1746529200000,
    },
    "blue-12": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.711297,
      longitude: -5.375885,
      time: 1746532800000,
    },
    "blue-13": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.568214,
      longitude: -5.457204,
      time: 1746536400000,
    },
    "blue-14": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.409118,
      longitude: -5.529224,
      time: 1746540000000,
    },
    "blue-15": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.242918,
      longitude: -5.60549,
      time: 1746543600000,
    },
    "blue-16": {
      type: "observation",
      entityId: "blueShip",
      latitude: 52.071092,
      longitude: -5.692136,
      time: 1746547200000,
    },
    "blue-17": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.899728,
      longitude: -5.787732,
      time: 1746550800000,
    },
    "blue-18": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.739952,
      longitude: -5.85027,
      time: 1746554400000,
    },
    "blue-19": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.602765,
      longitude: -5.974733,
      time: 1746558000000,
    },
    "blue-20": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.474164,
      longitude: -6.114349,
      time: 1746561600000,
    },
    "blue-21": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.362769,
      longitude: -6.264626,
      time: 1746565200000,
    },
    "blue-22": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.204582,
      longitude: -6.360486,
      time: 1746568800000,
    },
    "blue-23": {
      type: "observation",
      entityId: "blueShip",
      latitude: 51.084279,
      longitude: -6.526525,
      time: 1746572400000,
    },
    "blue-24": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.941434,
      longitude: -6.627714,
      time: 1746576000000,
    },
    "blue-25": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.815822,
      longitude: -6.768253,
      time: 1746579600000,
    },
    "blue-26": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.68009,
      longitude: -6.922329,
      time: 1746583200000,
    },
    "blue-27": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.56413,
      longitude: -7.037884,
      time: 1746586800000,
    },
    "blue-28": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.406445,
      longitude: -7.036782,
      time: 1746590400000,
    },
    "blue-29": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.247185,
      longitude: -7.004507,
      time: 1746594000000,
    },
    "blue-30": {
      type: "observation",
      entityId: "blueShip",
      latitude: 50.08487,
      longitude: -7.014869,
      time: 1746597600000,
    },
    "blue-31": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.937541,
      longitude: -6.993953,
      time: 1746601200000,
    },
    "blue-32": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.784533,
      longitude: -6.984443,
      time: 1746604800000,
    },
    "blue-33": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.639579,
      longitude: -6.960981,
      time: 1746608400000,
    },
    "blue-34": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.467846,
      longitude: -6.961437,
      time: 1746612000000,
    },
    "blue-35": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.32475,
      longitude: -6.92981,
      time: 1746615600000,
    },
    "blue-36": {
      type: "observation",
      entityId: "blueShip",
      latitude: 49.152295,
      longitude: -6.93082,
      time: 1746619200000,
    },
    "red-0": {
      type: "observation",
      entityId: "redShip",
      latitude: 52.370025,
      longitude: 3.706578,
      time: 1746489600000,
    },
    "red-1": {
      type: "observation",
      entityId: "redShip",
      latitude: 52.215551,
      longitude: 3.465443,
      time: 1746493200000,
    },
    "red-2": {
      type: "observation",
      entityId: "redShip",
      latitude: 52.06524,
      longitude: 3.234558,
      time: 1746496800000,
    },
    "red-3": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.919175,
      longitude: 2.966129,
      time: 1746500400000,
    },
    "red-4": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.736291,
      longitude: 2.750087,
      time: 1746504000000,
    },
    "red-5": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.575317,
      longitude: 2.48578,
      time: 1746507600000,
    },
    "red-6": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.418045,
      longitude: 2.244322,
      time: 1746511200000,
    },
    "red-7": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.263755,
      longitude: 1.993267,
      time: 1746514800000,
    },
    "red-8": {
      type: "observation",
      entityId: "redShip",
      latitude: 51.140054,
      longitude: 1.762104,
      time: 1746518400000,
    },
    "red-9": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.971223,
      longitude: 1.516238,
      time: 1746522000000,
    },
    "red-10": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.852823,
      longitude: 1.357977,
      time: 1746525600000,
    },
    "red-11": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.741735,
      longitude: 1.215997,
      time: 1746529200000,
    },
    "red-12": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.631068,
      longitude: 1.037502,
      time: 1746532800000,
    },
    "red-13": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.53398,
      longitude: 0.888554,
      time: 1746536400000,
    },
    "red-14": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.428207,
      longitude: 0.717581,
      time: 1746540000000,
    },
    "red-15": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.30806,
      longitude: 0.549199,
      time: 1746543600000,
    },
    "red-16": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.196893,
      longitude: 0.41216,
      time: 1746547200000,
    },
    "red-17": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.11447,
      longitude: 0.251521,
      time: 1746550800000,
    },
    "red-18": {
      type: "observation",
      entityId: "redShip",
      latitude: 50.001293,
      longitude: 0.076072,
      time: 1746554400000,
    },
    "red-19": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.976381,
      longitude: -0.224351,
      time: 1746558000000,
    },
    "red-20": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.953019,
      longitude: -0.49948,
      time: 1746561600000,
    },
    "red-21": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.941289,
      longitude: -0.756986,
      time: 1746565200000,
    },
    "red-22": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.922577,
      longitude: -1.06356,
      time: 1746568800000,
    },
    "red-23": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.919638,
      longitude: -1.322502,
      time: 1746572400000,
    },
    "red-24": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.864749,
      longitude: -1.595358,
      time: 1746576000000,
    },
    "red-25": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.843586,
      longitude: -1.889306,
      time: 1746579600000,
    },
    "red-26": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.86042,
      longitude: -2.184169,
      time: 1746583200000,
    },
    "red-27": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.822904,
      longitude: -2.451595,
      time: 1746586800000,
    },
    "red-28": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.717736,
      longitude: -2.732433,
      time: 1746590400000,
    },
    "red-29": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.587322,
      longitude: -3.005417,
      time: 1746594000000,
    },
    "red-30": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.45591,
      longitude: -3.266489,
      time: 1746597600000,
    },
    "red-31": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.319815,
      longitude: -3.515813,
      time: 1746601200000,
    },
    "red-32": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.199566,
      longitude: -3.802024,
      time: 1746604800000,
    },
    "red-33": {
      type: "observation",
      entityId: "redShip",
      latitude: 49.107795,
      longitude: -4.089816,
      time: 1746608400000,
    },
    "red-34": {
      type: "observation",
      entityId: "redShip",
      latitude: 48.968048,
      longitude: -4.332165,
      time: 1746612000000,
    },
    "red-35": {
      type: "observation",
      entityId: "redShip",
      latitude: 48.84175,
      longitude: -4.635675,
      time: 1746615600000,
    },
    "red-36": {
      type: "observation",
      entityId: "redShip",
      latitude: 48.729006,
      longitude: -4.887932,
      time: 1746619200000,
    },
    "yellow-0": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.742687,
      longitude: -5.517006,
      time: 1746489600000,
    },
    "yellow-1": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.77585,
      longitude: -5.174162,
      time: 1746493200000,
    },
    "yellow-2": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.859453,
      longitude: -4.812579,
      time: 1746496800000,
    },
    "yellow-3": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.887234,
      longitude: -4.482283,
      time: 1746500400000,
    },
    "yellow-4": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.969189,
      longitude: -4.153157,
      time: 1746504000000,
    },
    "yellow-5": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 49.996704,
      longitude: -3.79536,
      time: 1746507600000,
    },
    "yellow-6": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.062269,
      longitude: -3.458585,
      time: 1746511200000,
    },
    "yellow-7": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.110711,
      longitude: -3.103859,
      time: 1746514800000,
    },
    "yellow-8": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.177785,
      longitude: -2.747572,
      time: 1746518400000,
    },
    "yellow-9": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.219657,
      longitude: -2.413479,
      time: 1746522000000,
    },
    "yellow-10": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.225445,
      longitude: -2.173332,
      time: 1746525600000,
    },
    "yellow-11": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.27729,
      longitude: -1.883357,
      time: 1746529200000,
    },
    "yellow-12": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.268126,
      longitude: -1.636639,
      time: 1746532800000,
    },
    "yellow-13": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.293733,
      longitude: -1.368887,
      time: 1746536400000,
    },
    "yellow-14": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.309745,
      longitude: -1.121686,
      time: 1746540000000,
    },
    "yellow-15": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.33365,
      longitude: -0.863134,
      time: 1746543600000,
    },
    "yellow-16": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.349588,
      longitude: -0.589228,
      time: 1746547200000,
    },
    "yellow-17": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.376335,
      longitude: -0.357044,
      time: 1746550800000,
    },
    "yellow-18": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.395133,
      longitude: -0.088295,
      time: 1746554400000,
    },
    "yellow-19": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.460482,
      longitude: 0.086023,
      time: 1746558000000,
    },
    "yellow-20": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.550902,
      longitude: 0.238852,
      time: 1746561600000,
    },
    "yellow-21": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.611105,
      longitude: 0.411044,
      time: 1746565200000,
    },
    "yellow-22": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.694637,
      longitude: 0.578058,
      time: 1746568800000,
    },
    "yellow-23": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.77433,
      longitude: 0.737261,
      time: 1746572400000,
    },
    "yellow-24": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.853582,
      longitude: 0.898914,
      time: 1746576000000,
    },
    "yellow-25": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.922793,
      longitude: 1.071283,
      time: 1746579600000,
    },
    "yellow-26": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 50.997163,
      longitude: 1.246802,
      time: 1746583200000,
    },
    "yellow-27": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.061204,
      longitude: 1.421502,
      time: 1746586800000,
    },
    "yellow-28": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.179615,
      longitude: 1.491568,
      time: 1746590400000,
    },
    "yellow-29": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.331974,
      longitude: 1.535249,
      time: 1746594000000,
    },
    "yellow-30": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.446136,
      longitude: 1.606495,
      time: 1746597600000,
    },
    "yellow-31": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.577289,
      longitude: 1.67907,
      time: 1746601200000,
    },
    "yellow-32": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.712057,
      longitude: 1.730155,
      time: 1746604800000,
    },
    "yellow-33": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.842222,
      longitude: 1.787359,
      time: 1746608400000,
    },
    "yellow-34": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 51.967187,
      longitude: 1.847835,
      time: 1746612000000,
    },
    "yellow-35": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 52.110784,
      longitude: 1.920065,
      time: 1746615600000,
    },
    "yellow-36": {
      type: "observation",
      entityId: "yellowShip",
      latitude: 52.220649,
      longitude: 1.988451,
      time: 1746619200000,
    },
    "green-0": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.642166,
      longitude: -0.206432,
      time: 1746489600000,
    },
    "green-1": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.72148,
      longitude: -0.045392,
      time: 1746493200000,
    },
    "green-2": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.773523,
      longitude: 0.094019,
      time: 1746496800000,
    },
    "green-3": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.812568,
      longitude: 0.246296,
      time: 1746500400000,
    },
    "green-4": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.89297,
      longitude: 0.393587,
      time: 1746504000000,
    },
    "green-5": {
      type: "observation",
      entityId: "greenShip",
      latitude: 49.922868,
      longitude: 0.517232,
      time: 1746507600000,
    },
    "green-6": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.015095,
      longitude: 0.678897,
      time: 1746511200000,
    },
    "green-7": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.0724,
      longitude: 0.813281,
      time: 1746514800000,
    },
    "green-8": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.130035,
      longitude: 0.976137,
      time: 1746518400000,
    },
    "green-9": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.177675,
      longitude: 1.110818,
      time: 1746522000000,
    },
    "green-10": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.242837,
      longitude: 1.146687,
      time: 1746525600000,
    },
    "green-11": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.336519,
      longitude: 1.199466,
      time: 1746529200000,
    },
    "green-12": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.396971,
      longitude: 1.248527,
      time: 1746532800000,
    },
    "green-13": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.493277,
      longitude: 1.311625,
      time: 1746536400000,
    },
    "green-14": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.589783,
      longitude: 1.326871,
      time: 1746540000000,
    },
    "green-15": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.668123,
      longitude: 1.401063,
      time: 1746543600000,
    },
    "green-16": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.746436,
      longitude: 1.422752,
      time: 1746547200000,
    },
    "green-17": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.826394,
      longitude: 1.484131,
      time: 1746550800000,
    },
    "green-18": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.893871,
      longitude: 1.529005,
      time: 1746554400000,
    },
    "green-19": {
      type: "observation",
      entityId: "greenShip",
      latitude: 50.967241,
      longitude: 1.67732,
      time: 1746558000000,
    },
    "green-20": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.013555,
      longitude: 1.84518,
      time: 1746561600000,
    },
    "green-21": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.086254,
      longitude: 2.040142,
      time: 1746565200000,
    },
    "green-22": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.174896,
      longitude: 2.184954,
      time: 1746568800000,
    },
    "green-23": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.239722,
      longitude: 2.367642,
      time: 1746572400000,
    },
    "green-24": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.291813,
      longitude: 2.526876,
      time: 1746576000000,
    },
    "green-25": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.368212,
      longitude: 2.66567,
      time: 1746579600000,
    },
    "green-26": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.438635,
      longitude: 2.857788,
      time: 1746583200000,
    },
    "green-27": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.511591,
      longitude: 3.003932,
      time: 1746586800000,
    },
    "green-28": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.573699,
      longitude: 3.11906,
      time: 1746590400000,
    },
    "green-29": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.660869,
      longitude: 3.197849,
      time: 1746594000000,
    },
    "green-30": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.728586,
      longitude: 3.320669,
      time: 1746597600000,
    },
    "green-31": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.828897,
      longitude: 3.432333,
      time: 1746601200000,
    },
    "green-32": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.902916,
      longitude: 3.548628,
      time: 1746604800000,
    },
    "green-33": {
      type: "observation",
      entityId: "greenShip",
      latitude: 51.965803,
      longitude: 3.648003,
      time: 1746608400000,
    },
    "green-34": {
      type: "observation",
      entityId: "greenShip",
      latitude: 52.045515,
      longitude: 3.761248,
      time: 1746612000000,
    },
    "green-35": {
      type: "observation",
      entityId: "greenShip",
      latitude: 52.135806,
      longitude: 3.87378,
      time: 1746615600000,
    },
    "green-36": {
      type: "observation",
      entityId: "greenShip",
      latitude: 52.215531,
      longitude: 3.963111,
      time: 1746619200000,
    },
  },
};

const regions = {
  region1: { south: 49.2, west: -7.5, north: 50.6, east: -4.5 },
  region2: { south: 49.3, west: -2.7, north: 50.9, east: -0.7 },
  region3: { south: 50.6, west: 1.2, north: 52, east: 3.1 },
};

const standardAlpha = 0.3;

const shipIds = Object.keys(observationsData.entities);

export function getRegionColor(alpha) {
  return `rgba(0, 255, 0, ${alpha})`;
}

// Does a ship have any observations in the specified region?
function isShipInRegion(shipId, { south, west, north, east }) {
  return Object.values(observationsData.observations).some(
    ({ entityId, latitude, longitude }) =>
      entityId === shipId &&
      longitude >= west &&
      longitude <= east &&
      latitude >= south &&
      latitude <= north
  );
}

// Determine which ships pass through which regions
export const shipsPerRegion = new Map();
for (const [regionId, region] of Object.entries(regions)) {
  const shipsInThisRegion = new Set();
  for (const shipId of shipIds) {
    if (isShipInRegion(shipId, region)) {
      shipsInThisRegion.add(shipId);
    }
  }
  shipsPerRegion.set(regionId, shipsInThisRegion);
}

function makeGeoJsonData() {
  return {
    type: "FeatureCollection",
    features: Object.entries(regions).map(([id, { south, west, north, east }]) => {
      return {
        type: "Feature",
        id,
        properties: {
          color: getRegionColor(standardAlpha),
        },
        geometry: {
          type: "Polygon",
          coordinates: [
            [
              [west, south],
              [west, north],
              [east, north],
              [east, south],
              [west, south],
            ],
          ],
        },
      };
    }),
  };
}

export const geojsonData = makeGeoJsonData();
<!doctype html>
<html>
  <body>
    <div id="mw"></div>
    <script type="module" src="./code.jsx"></script>
  </body>
</html>

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.