Skip to content

Instantly share code, notes, and snippets.

@oscarlorentzon
Last active June 7, 2021 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oscarlorentzon/16946cb9eedfad2a64669cb1121e6c75 to your computer and use it in GitHub Desktop.
Save oscarlorentzon/16946cb9eedfad2a64669cb1121e6c75 to your computer and use it in GitHub Desktop.
LatLon, computedLatLon and originalLatLon explained
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link href='https://unpkg.com/mapillary-js@3.1.0/dist/mapillary.min.css' rel='stylesheet' />
<link href='https://unpkg.com/leaflet@1.0.1/dist/leaflet.css' rel='stylesheet' />
<script src='https://unpkg.com/mapillary-js@3.1.0/dist/mapillary.min.js'></script>
<script src='https://unpkg.com/leaflet@1.0.1/dist/leaflet.js'></script>
<style>
body { margin:0; padding:0; height: 100%; }
#mly { position: absolute; height: 100%; width: 66%; }
#map { position: absolute; width: 34%; top: 0; right: 0; bottom: 0; }
</style>
</head>
<body>
<div id='mly'></div>
<div id='map'></div>
<script>
var map = L.map('map').setView([55.608725, 13.0343], 19);
var osmUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
var osm = new L.TileLayer(osmUrl, { maxZoom: 19, attribution: osmAttrib});
map.addLayer(osm);
var mly = new Mapillary.Viewer({
apiClient: 'QjI1NnU0aG5FZFZISE56U3R5aWN4Zzo3NTM1MjI5MmRjODZlMzc0',
component: { cover: false },
container: 'mly',
imageKey: 'dZ8LOXMF4c3c8IhplqcjNw',
});
function setMarkerLatLng(marker, latLng) {
marker.setLatLng(latLng);
if (!map.hasLayer(marker)) {
marker.addTo(map);
}
}
/**
* When images are uploaded they will have GPS information in the EXIF, this is what
* we call `originalLatLon` on the Node class in MapillaryJS
* (https://mapillary.github.io/mapillary-js/classes/node.html#originallatlon).
*
* When Structure from Motions has been run for a node a `computedLatLon` that
* differs from the `originalLatLon` will be created. It is different because
* GPS positions are not very exact and SfM aligns the camera positions according
* to the 3D reconstruction
* (https://mapillary.github.io/mapillary-js/classes/node.html#computedlatlon).
*
* At last there exist a `latLon` property in MapilllaryJS which evaluates to
* the `computedLatLon` from SfM if it exists but falls back to the `originalLatLon`
* from the EXIF GPS otherwise
* (https://mapillary.github.io/mapillary-js/classes/node.html#latlon)
* Everything that is done in in the MapillaryJS Viewer is based on the SfM positions,
* i.e. `computedLatLon`. That is why the smooth transitions go in the right
* direction (and not strange directions because of bad GPS).
*
* E.g. when placing a marker in the Viewer it is relative to the SfM
* position i.e. the `computedLatLon`.
*
* The same concept as above also applies to the compass angle (or bearing) properties
* `originalCa`, `computedCa` and `ca` on the Node class.
*/
// Show a red marker for the original EXIF GPS position,
// a blue marker for the SfM computed position and a
// small yellow marker for the `latLon` property.
var originalLatLngMarker = L.circleMarker([0, 0], { radius: 8, color: '#f00', fillOpacity: 1, opacity: 1 });
var computedLatLngMarker = L.circleMarker([0, 0], { radius: 8, color: '#00f', fillOpacity: 1, opacity: 1 });
var latLngMarker = L.circleMarker([0, 0], { radius: 3, color: '#ff0', fillOpacity: 1, opacity: 1 });
mly.on(Mapillary.Viewer.nodechanged, function (node) {
// Set the position of the marker related to the original EXIF GPS
// position which always exist.
var originalLatLng = [node.originalLatLon.lat, node.originalLatLon.lon];
setMarkerLatLng(originalLatLngMarker, originalLatLng);
// Check if node has been merged (SfM has been run).
if (node.merged) {
// If SfM has been run, computed SfM position exists so
// set position and add to map.
var computedLatLng = [node.computedLatLon.lat, node.computedLatLon.lon];
setMarkerLatLng(computedLatLngMarker, computedLatLng);
} else {
// If SfM has not been run, computed SfM position does not exist
// so remove SfM computed marker from map for this node.
if (map.hasLayer(computedLatLngMarker)) {
map.removeLayer(computedLatLngMarker);
}
}
var latLng = [node.latLon.lat, node.latLon.lon];
setMarkerLatLng(latLngMarker, latLng);
map.setView(latLng);
});
window.addEventListener('resize', function() { mly.resize(); });
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment