Usage of mxdraw with Mapbox
mxcad 8/16/2022
# How do Mapbox maps and CAD drawings appear together?
Mapbox is an interactive map rendered through webgl, and mxdraw is also implemented with webgl rendering.
Therefore, we can combine the custom layers provided by Mapbox with the control instances of mxdraw to display CAD layers and maps together.
If you are not familiar with Mapbox, please refer to official documentation in Chinese (opens new window) / International site (opens new window)
The following code is the simplest example of using Mapbox and mxdraw together.
# Install the corresponding dependencies first
npm install mapbox-gl mxdraw
<div id="map"></div>
import mapboxgl from "mapbox-gl";
import Mx from "mxdraw"
import * as THREE from "three"
// Token needs to be applied for on the Mapbox official website
mapboxgl.accessToken = "pk.eyJ1IjoibWFvcmV5IiwiYSI6ImNqNWhrenIwcDFvbXUyd3I2bTJxYzZ4em8ifQ.KHZIehQuWW9AsMaGtATdwA"
// GPS location of Beijing
const center = [116.391305, 39.90553]
const map = new mapboxgl.Map({
// The HTML element that Mapbox GL JS renders the map in, or the element's string ID. This specified element cannot have children.
container: 'map',
// Map location
center,
// Map style
style: 'mapbox://styles/mapbox/streets-v11',
zoom: 16
})
// Height of the drawing or model
const modelAltitude = 100;
// Convert LngLat projection to Mercator projection coordinates
const point = mapboxgl.MercatorCoordinate.fromLngLat(
center,
modelAltitude
);
// Returns the distance of 1 meter in Mercator coordinate units at this latitude.
// For real-world coordinates using meters, this naturally provides a scale for converting to Mercator projection coordinates.
const lDistForM = point.meterInMercatorCoordinateUnits();
// The range of the CAD drawing in reality is currently determined to be 1 kilometer
const lCADArea = 1000 * lDistForM * 1;
// Provide some necessary Mapbox information and give some core methods provided by mxdraw
let mxMap = {
// Canvas element generated by Mapbox
canvas: null,
// gl context provided by custom layers
gl: void 0,
// Location 1 of the CAD drawing
cadLocation1: new THREE.Vector3(),
// Location 2 of the CAD drawing
cadLocation2: new THREE.Vector3(),
// Elevation
elevation: 0,
// Custom layer information
customLayer: {},
// CAD drawing control object
mxObj: null,
// Coordinate transformation matrix 1
matCadToMap: new THREE.Matrix4(),
// Coordinate transformation matrix 2
matMapToCad: new THREE.Matrix4(),
// Matrix for custom layer
matrix: undefined,
// Rendering function
render(gl, matrix){
},
// Method for mutual transformation of coordinates
cadToMercatorCoord(pt) {
pt.applyMatrix4(this.matCadToMap);
return new mapboxgl.MercatorCoordinate(pt.x,pt.y,pt.z);
},
mercatorCoordToCad(pt){
let ptRet = new THREE.Vector3(pt.x,pt.y,pt.z);
ptRet.applyMatrix4(this.matMapToCad);
return ptRet;
},
cadLongToMercatorCoord(len){
let pt1 = new THREE.Vector3(0,0,0);
let pt2 = new THREE.Vector3(len,0,0);
pt1.applyMatrix4(this.matCadToMap);
pt2.applyMatrix4(this.matCadToMap);
return pt1.distanceTo(pt2);
}
}
// With the above information, you can determine the specific location of the CAD drawing
mxMap.cadLocation1 = new THREE.Vector3(point.x - lCADArea / 2, point.y - lCADArea, point.z);
mxMap.cadLocation2 = new THREE.Vector3(point.x + lCADArea, point.y + lCADArea / 2, point.z);
// Add a Mapbox custom layer
const customLayer = {
id: "3d-model", // Any unique ID
type: "custom",
renderingMode: "3d",
async onAdd(map, gl) {
// Load mxdraw core library synchronously
await Mx.loadCoreCode()
// Get the canvas element of Mapbox
mxMap.canvas = map.getCanvas();
// Get the webgl context as well
mxMap.gl = gl
// Create a drawing control object
Mx.MxFun.createMxObject({
// Parameters required by MapBox
mapBox: mxMap,
// Drawing to be opened
cadFile: "../../demo/buf/$hhhh.dwg",
callback: (mxObj) => {
mxMap.mxObj = mxObj;
mxObj.addEvent("loadComplete", () => {
// Update Mapbox
map.triggerRepaint()
});
}
});
},
render(gl, matrix) {
// Assign matrix information
mxMap.matrix = matrix
// After creating the drawing, a rendering function will be provided to update the drawing
mxMap.render(gl, matrix);
// Refresh Mapbox
map.triggerRepaint()
}
};
// Assign the information of this custom layer
mxMap.customLayer = customLayer
// Add the custom layer
map.on('style.load', ()=> {
map.addLayer(customLayer)
})
Effect: