Skip to content

Mesh Map

Overview

The Mesh Map prefab takes a GeoJson and d3-geo projection input and generates a Extruded Polygon mesh for each polygon or multi-polygon GeoJSON feature. This prefab also utilize topoJson for mesh simplification. The createMeshMap() method returns an instance of the MeshMap object which contains the relevant properties for the mesh creation and manipulation. Each polygon metadata.data property will be set with the data from its features.properties GeoJSON.

Usage

js
//name (required), options (geojson required), babylon scene (optional) 
// returns instance of MeshMap
let map = anu.createMeshMap(name: String, options: {}, scene: BABYLON.Scene);

//The transformed input d3-geo projection
let projection = map.projection

// A selection object containing all the generated polygons
let selection = map.selection

Options

OptionValueDefault
geoJson (required)a valid geoJSON filenull
projection(d3.GeoProjection) such as d3.geoAlbers()d3.geoAlbers()
size([number, number]) an array with the max height and width of the projection[10,10]
transform([number, number]) and array with the center coordinates of the projection in render space[0,0]
simplification(number) the simplification factor relative to the projection size0
depth(number) the height of the extruded the polygons1
cot(Babylon.Node) The node to be the parent of all the polygons, if not set a transform node "meshMapCOT" will be createdTransformNode('meshMapCOT')

Methods and Properties

Property / MethodDescription
projectionthe transformed d3.geoProjection which can be used map position from longitude and latitude as projection([lon, lat])
selectiona selection object containing all the generated polygons with their respective geoJSON properties data binded to them

Examples

js
// SPDX-License-Identifier: Apache-2.0
// Copyright : J.P. Morgan Chase & Co.

import * as anu from '@jpmorganchase/anu';
import * as d3 from "d3";
import { Scene, HemisphericLight, ArcRotateCamera, Vector3, Color4 } from '@babylonjs/core';
import data from './data/airports.csv'; //Our data
import geoJ from "./data/gz_2010_us_040_00_5m.json";  //GeoJSON

//Create and export a function that takes a Babylon engine and returns a Babylon Scene
export function meshMap(engine) {

  //Create an empty Scene
  const scene = new Scene(engine);

  //Add some lighting
  new HemisphericLight('light1', new Vector3(0, 10, 0), scene);

  //Add a camera that rotates around the origin and adjust its properties
  const camera = new ArcRotateCamera("Camera", -(Math.PI / 4) * 3, Math.PI / 4, 10, new Vector3(0, 0, 0), scene);
  camera.wheelPrecision = 100; // Adjust the sensitivity of the mouse wheel's zooming
  camera.minZ = 0;            // Adjust the distance of the camera's near plane
  camera.attachControl(true); // Allow the camera to respond to user controls
  camera.position = new Vector3(0, 1.25, -1);

  //createMeshMap() is an Anu prefab that easily allows us to create a mesh map using geoJSON data
  let meshMap = anu.createMeshMap('meshMap', { geoJson: geoJ, depth: 0.05, projection: d3.geoAlbers().reflectY(true), size: [2, 2], simplification: 0.00001 });

  //Get the newly created meshes that correspond to US states as an Anu selection
  let states = meshMap.selection;

  //Create a D3 color scale to assign colors to these states
  let scaleC = d3.scaleOrdinal(anu.ordinalChromatic('d310').toStandardMaterial());

  //Set their color
  states.material((d) => scaleC(d.NAME))
        .prop("isPickable", false);   //Turn off picking to improve performance of our complex mesh geometry
                                      //If picking of the mesh map is necessary, wrap it in an empty mesh that is sized to the bounding box

  //Get the CoT of the mesh map
  let CoT = anu.selectName("meshMap", scene);

  //Because our data has over 3000 points, we will use mesh instancing for better performance
  //Create a mesh to be our root instance, and register a buffer for color
  let rootSphere = anu.create('sphere', 'sphere', {diameter: 0.003})
  rootSphere.isVisible = false;
  rootSphere.registerInstancedBuffer("color", 4);
  rootSphere.instancedBuffers.color = new Color4(0, 0, 0, 1);

  //Create our spheres for our data
  let spheres =  CoT.bindInstance(rootSphere, data)
                    .positionX((d) => meshMap.projection([d.longitude, d.latitude])[0]) //The meshMap prefab object contains a projection() function that will convert
                    .positionZ((d) => meshMap.projection([d.longitude, d.latitude])[1]) //a longitude and latitude into the correct position on the meshMap
                    .setInstancedBuffer("color", new Color4(0,0,0,1));

  return scene;
}