Moon CSR example file - leaflet

I'm trying to make an moon CRS JS file, but my géo-mathematics are not very good, in fact, i don't understand ! But i've a to do a scientifics experience, can you help me ? Peraphs it can be done with just configuration.
Let me explain, i need to set magnetic north pole on moon map.
I use moon map from: https://cartocdn-gusc.global.ssl.fastly.net/opmbuilder/api/v1/map/named/opm-moon-basemap-v0-1/all/{z}/{x}/{y}.png
I need to change pole north, because when i set a marker to [0,0], the marker appear not where i want. In other manner, i need to move north pole where i want. On earth, and moon if i want.
After that, i ll set pointer from public data and whatch what it done. On moon, on earth, on personal photo.

thanks i'll try to find it
const map = L.map('map', {
// crs: L.CRS.EPSGMoonMercator, // MoonMercator
// crs: L.CRS.EPSGMoonSphericalMercator, // MoonMercator
// crs: L.CRS.EPSG3395, // Mercator
crs: L.CRS.EPSG3857, // SphericalMercator
center: [-70,0],
zoom: 4,
// minZoom: 3,
// maxZoom: 8,
});

Related

MapboxGL Render Function Issue

I'm using mapboxgl and I'm also using ThreeJS be able to import 3D model to the scene. The 3D model that I used has very high polygon count. Due to MapboxGl's render function triggering in each frame my browser is being very laggy. Is it possible to trigger the render function only once or which function must use at this point istead of render function ? I would like to render my 3D model only once on the map.
Here is my codes:
mapBoxGLSetup: function () {
mapboxgl.accessToken = "";
oOriginPoint = [29.400261610397465, 40.87692013157027, 1];
oMap = new mapboxgl.Map({
logoPosition: "bottom-right",
container: oSceneContainer.id,
style: 'mapbox://styles/mapbox/streets-v11',
center: oOriginPoint,
zoom: 15,
pitch: 0,
antialias: true
});
var modelOrigin = oOriginPoint;
var modelAltitude = 0;
var modelRotate = [Math.PI / 2, Math.PI / 6.5, 0];
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
modelOrigin,
modelAltitude
);
o3DModelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
scale: (modelAsMercatorCoordinate.meterInMercatorCoordinateUnits() / 1000) * 0.85
};
},
oSceneMapSetup: function () {
oMap.on('style.load', function () {
oMap.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (oMapElement, oGlElement) {
base.oMapElement = oMapElement;
base.setupRenderer(oMapElement, oGlElement);
base.setupLayout(); // I'm loading 3D model in this function
base.setupRayCaster();
},
render: function (gl, matrix) {
// This render function is triggering each frame
var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), o3DModelTransform.rotateX);
var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), o3DModelTransform.rotateY);
var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), o3DModelTransform.rotateZ);
var oMatrix = new THREE.Matrix4().fromArray(matrix);
var oTranslation = new THREE.Matrix4().makeTranslation(o3DModelTransform.translateX, o3DModelTransform.translateY, o3DModelTransform.translateZ)
.scale(new THREE.Vector3(o3DModelTransform.scale, -o3DModelTransform.scale, o3DModelTransform.scale))
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
oCamera.projectionMatrix = oMatrix.multiply(oTranslation);
oRenderer.resetState();
oRenderer.render(oScene, oCamera);
base.oMapElement.triggerRepaint();
}
})
});
},
Thanks for your help and support.
As long as you still calling triggerRepaint on each layer render loop, you will repaint the full map, it’s inherent to the way CustomLayerInterface and update layer work in Mapbox.
When I did my first research on the TriggerRepaint topic, I found a quite old issue in Mapbox where a guy tested all the different options, including having a fully separated context and even 2 mapbox instances, one of them empty. Here is the link
The performance was obviously better in terms of FPS/memory, but there were other collaterals that I personally wouldn't assume for threebox, like losing the depth calculation between mapbox fill-extrusions and 3D custom layer.
Sharing context
Different contexts & canvas
The second issue is the delay between the movement of both cameras. While current sharing context ensures the objects are fixed and stuck to a coords set, creating different contexts will produce a soft dragging effect where the delay between the 2 contexts render can be visually perceived when the map moves first and the 3D objects follow. It's perceivable even with ne single cube, so with thousands of objects will be definitely clearer.

Leaflet - Could it be possible to center the coordinates with a set point in the image

Yellow is the image, cyan is the coords, red is the centre for both. Coords are like that because that is the allowable area in the map.
Ive got coordinates where the actual center of them is not the middle point of the coordinates. That means each side is a little wonky from the center.
As i know the exact center from the coordinates, could it be possible to anchor that center to the middle of the image where it is the actual center for those coordinates. Would be a blast to just slap it there.
Or could i somehow add a margin towards each direction so with a little fiddling i could make it like in the illustration.
I have attempted to play with the coordinates themselves to make it fit the image, but that feels impossible to make it right, the image either goes wonky or the markers that i add go off their right spots whenever i get one of the edges right.
Edit: and im using CRS.Simple here.
The best solution is using the turf library
const map = L.map('mapid').setView([52.308478623663355, 19.281005859375004], 5);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
const test = [
[15.3369140625, 49.55372551347579],
[23.97216796875, 49.55372551347579],
[23.97216796875, 54.316523240258256],
[15.3369140625, 54.316523240258256],
[15.3369140625, 49.55372551347579]
];
const polygon = turf.polygon([test]);
const centroid = turf.centroid(polygon);
const featCollection = {
features: [polygon, centroid]
}
const polu = L.geoJSON(featCollection).addTo(map);
map.fitBounds(poly.getBounds());
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
body {
min-height: 100%;
}
#mapid {
width: 100%;
height: 100%;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#turf/turf#5/turf.min.js"></script>
<div id="mapid"></div>
I don't recommand to use turf if it is not necessary.
You can use the Leaflet built-in getCenter() function.
getCenter() is working for Polyline, Polygon and Rectangles.
getCenter(): Returns the center (centroid) of the polyline / polygon / rectangle.
Resolved by making calibration points to the imageOverlay, taking coords from those points, adding them into leaflet as markers, then fiddling around once again but with those calibration points i got them centered in under an hour. Still not perfect but i guess im happy with it.

Adding a three.js scene in Mapbox as custom layer

I am trying to visualise a three.js scene in Mapbox, using an approach based on this tutorial: https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/
I have a prepared scene named "threescene", which I added to the scene of the custom layer. It contains geometries of buildings. The coordinates are in WGS84, and it seems like they would be transformed properly in the tutorial code.
However, the layer simply does not show up. I don't know if I should do something else with the coordinates, or if there is another problem. I have already attempted to normalise the coordinates within the scene.
My code is as follows:
mapboxgl.accessToken = 'pk.eyJ1IjoiamxpZW1wdCIsImEiOiJjanpzZHNhOGwxZ3RjM2JuenBpcjN4eTh3In0.dnO_1v0NDfRMZBhv-hVvjQ';
var map = window.map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 18,
center: [6.8309373573, 53.0475174735], // min of bbox
pitch: 60,
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
});
// parameters to ensure the model is georeferenced correctly on the map
var modelOrigin = [6.8309373573, 53.0475174735]; // min of bbox
var modelAltitude = 0;
var modelRotate = [Math.PI / 2, 0, 0];
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude);
// transformation parameters to position, rotate and scale the 3D model onto the map
var modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};
var THREE = window.THREE;
// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
id: '3d-model',
type: 'custom',
renderingMode: '3d',
onAdd: function(map, gl) {
this.camera = new THREE.Camera();
this.scene = new THREE.Scene();
this.scene.add(threescene); // here I include my scene
// create two three.js lights to illuminate the model
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(0, -70, 100).normalize();
this.scene.add(directionalLight);
var directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(0, 70, 100).normalize();
this.scene.add(directionalLight2);
this.map = map;
// use the Mapbox GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
},
render: function(gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX);
var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY);
var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4().makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ)
.scale(new THREE.Vector3(modelTransform.scale, -modelTransform.scale, modelTransform.scale))
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix.elements = matrix;
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
};
map.on('style.load', function() {
map.addLayer(customLayer, 'waterway-label');
});
You say your coordinates are in WGS84 so you're saying your model is in WGS84, which has units of degrees, yet later on in the code you've inherited the modelScale as in meters.
So which units is your model in, meters or degrees, and which coordinate reference system is it? As you'll need to apply the correct scale transform depending on this.

Leaflet : how to resize SVG marker according to zoom (i.e. marker constant size in meters)

I have a map with 20 markers on a geojson layer. They are all from the same SVG and represent a certain area on the map (meaning they represent a circle of constant radius in meter on the map). I need these marker to adapt their size according to zoom level.
I've tried to use a circle as a marker. But my marker needs to be a SVG because it is complex graphic and radius doesn't apply to markers.
Here's the piece of code used to display the markers. Latitude, Longitude and rotationAngle are parsed from a .csv sheet:
for (i in chapters) {
var c = chapters[i];
if (!isNaN(parseFloat(c['Latitude'])) && !isNaN(parseFloat(c['Longitude']))) {
var lat = parseFloat(c['Latitude']);
var lon = parseFloat(c['Longitude']);
var cercleDirection = parseFloat(c['Direction']);
var photoIcon = L.icon({
iconUrl: 'media/Cercle.svg',
iconSize: [220, 220],
iconAnchor: [110, 110],
});
markers.push(
L.marker([lat, lon], {
icon: photoIcon,
rotationAngle: cercleDirection
}));
}

LeafletJS lock map center

Is there an easy way to lock the center of a map?
You can disable dragging / panning easily with map.dragging.disable(); but that doesn't make the center of the map fixed. Searched for it in the documentations and on the web but can't find anything.
The maxBounds option (paired with maxBoundsViscosity) should do the trick - just convert the LatLng you want to be centered into a zero-area LatLngBounds.
Use the option scrollWheelZoom: "center" to fix zooming with the scroll wheel to the center of the map.
var map = L.map('map', {
center: [0,0],
dragging: false,
scrollWheelZoom: "center",
});