Skip to content

Commit

Permalink
Allow the 3d map to better cooperate with the main map
Browse files Browse the repository at this point in the history
- Fix bug where the 3d map wasn't rendering on changes to selection
- Add move/moveend handlers so changing the 3d map will recenter the main map
- Calc the zoom diff and bearing diff and apply them as the user moves the main map
  (this prevents the 3dmap from snapping away from what the user is doing)
- Add some lodash throttle, to avoid updating maplibre on every move/draw
  • Loading branch information
bhousel committed May 6, 2024
1 parent b5206ae commit 91d2b33
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 23 deletions.
50 changes: 43 additions & 7 deletions modules/core/Map3dSystem.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { select as d3_select } from 'd3-selection';
import { RAD2DEG, vecEqual } from '@rapid-sdk/math';

import { AbstractSystem } from './AbstractSystem.js';

Expand Down Expand Up @@ -28,11 +29,18 @@ export class Map3dSystem extends AbstractSystem {
this._loadPromise = null;
this._startPromise = null;

// The 3d Map will stay close to the main map, but with an offset zoom and rotation
this.zDiff = 3; // by default, 3dmap will be at main zoom - 3
this.rDiff = 0; // by default, 3dmap bearing will match main map bearing

this.building3dlayerSpec = this.get3dBuildingLayerSpec('3D Buildings', 'osmbuildings');
this.roadStrokelayerSpec = this.getRoadStrokeLayerSpec('Roads', 'osmroads');
this.roadCasinglayerSpec = this.getRoadCasingLayerSpec('Roads', 'osmroads');
this.roadSelectedlayerSpec = this.getRoadSelectedLayerSpec('Roads', 'osmroads');
this.areaLayerSpec = this.getAreaLayerSpec('Areas', 'osmareas');

// Ensure methods used as callbacks always have `this` bound correctly.
this._moved = this._moved.bind(this);
}


Expand Down Expand Up @@ -83,6 +91,9 @@ export class Map3dSystem extends AbstractSystem {
});

return new Promise(resolve => {
maplibre.on('move', this._moved);
maplibre.on('moveend', this._moved);

maplibre.on('load', () => {
maplibre.setLight({
anchor: 'viewport',
Expand All @@ -91,13 +102,6 @@ export class Map3dSystem extends AbstractSystem {
intensity: 0.3,
});

// code in map3d_viewer will do this?
// const map = this.context.systems.map;
// maplibre.jumpTo({
// zoom: map.zoom() - 3,
// center: map.extent().center(),
// });

// sources
maplibre.addSource('osmareas', {
type: 'geojson',
Expand Down Expand Up @@ -133,6 +137,38 @@ export class Map3dSystem extends AbstractSystem {
}


/**
* _moved
* Respond to changes in the maplibre viewer
*/
_moved() {
const context = this.context;
const map = context.systems.map;
const maplibre = this.maplibre;
const viewport = context.viewport;
const transform = viewport.transform;

if (!maplibre) return; // called too early?

const mlCenter = maplibre.getCenter();
const mlCenterLoc = [mlCenter.lng, mlCenter.lat];
const mlZoom = maplibre.getZoom();
const mlBearing = maplibre.getBearing();

const mainCenterLoc = viewport.centerLoc();
const mainZoom = transform.zoom;
const mainBearing = transform.rotation * RAD2DEG;

this.zDiff = mainZoom - mlZoom;
this.rDiff = mainBearing - mlBearing;

// Recenter main map, if 3dmap center moved
if (!vecEqual(mainCenterLoc, mlCenterLoc, 1e-6)) {
map.center(mlCenterLoc);
}
}


/**
* _loadAssetsAsync
* Load the MapLibre JS and CSS files into the document head
Expand Down
43 changes: 27 additions & 16 deletions modules/ui/map3d_viewer.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Color } from 'pixi.js';
import { geomPolygonContainsPolygon } from '@rapid-sdk/math';
import { select as d3_select } from 'd3-selection';
import { RAD2DEG, geomPolygonContainsPolygon } from '@rapid-sdk/math';
import throttle from 'lodash-es/throttle.js';

import { uiCmd } from './cmd.js';


/**
* uiMap3dViewer is a ui panel containing a maplibre 3D Map
* uiMap3dViewer is a ui panel containing a MapLibre 3D Map
* @param {*} context
* @returns
*/
Expand All @@ -23,32 +25,38 @@ export function uiMap3dViewer(context) {
let _isHidden = !urlhash.getParam('map3d'); // depends on URL hash
let _lastv;


function redraw() {
if (_isHidden) return;
if (viewport.v === _lastv) return; // viewport hasn't changed
_lastv = viewport.v;
updateViewport();
featuresToGeoJSON();
}


/**
* updateViewport
* Adjust the 3d map to follow the main map, applying any zoom and rotation offsets.
*/
function updateViewport() {
// Since the bounds are intended to wrap a box around a perfectly orthogonal view,
// for a pitched, isometric view we need to enlarge the box a bit to display more buildings.
// bhousel comment out for now - growing this extent will not change its center?
// const extent = viewport.visibleExtent();
// const center = extent.center();
// extent.padByMeters(100);
//
const maplibre = map3d.maplibre;
if (!maplibre) return; // called too soon?
if (maplibre.isMoving()) return; // already moving for other reasons (user interaction?)
if (viewport.v === _lastv) return; // main map view hasn't changed

_lastv = viewport.v;
const transform = viewport.transform;
map3d.maplibre?.jumpTo({
maplibre.jumpTo({
center: viewport.centerLoc(),
bearing: transform.rotation,
zoom: transform.zoom - 3,
bearing: (RAD2DEG * transform.rotation) - map3d.rDiff,
zoom: transform.zoom - map3d.zDiff
});
}


/**
* featuresToGeoJSON
* Collect features in view and issue `setData` calls to update the data in the 3d map.
*/
function featuresToGeoJSON() {
const entities = editor.intersects(viewport.visibleExtent());
const noRelationEnts = entities.filter((ent) => !ent.id.startsWith('r'));
Expand Down Expand Up @@ -277,8 +285,11 @@ export function uiMap3dViewer(context) {
wrap = wrapEnter.merge(wrap);
map3d.startAsync();

map.on('draw', () => redraw());
map.on('move', () => redraw());

const deferredRedraw = throttle(redraw, 50, { leading: true, trailing: true });

map.on('draw', deferredRedraw);
map.on('move', deferredRedraw);
context.keybinding().on([uiCmd('⌘' + l10n.t('background.3dmap.key'))], toggle);

redraw();
Expand Down

0 comments on commit 91d2b33

Please sign in to comment.