Skip to content

Commit

Permalink
map's center support altitude (#2217)
Browse files Browse the repository at this point in the history
  • Loading branch information
liubgithub authored Mar 14, 2024
1 parent fc320b4 commit 005ec9d
Show file tree
Hide file tree
Showing 14 changed files with 9,264 additions and 9,167 deletions.
9,154 changes: 4,586 additions & 4,568 deletions docs/api/0.x/renderer.CanvasRenderer.html

Large diffs are not rendered by default.

9,114 changes: 4,566 additions & 4,548 deletions docs/api/1.x/renderer.CanvasRenderer.html

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions src/core/util/vec3.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,16 @@ function hypot() {
while (i--) y += arguments[i] * arguments[i];
return Math.sqrt(y);
}

export function angle(a, b) {
normalize(a, a);
normalize(b, b);
const cosine = dot(a, b);
if (cosine > 1.0) {
return 0;
} else if (cosine < -1.0) {
return Math.PI;
} else {
return Math.acos(cosine);
}
}
71 changes: 47 additions & 24 deletions src/map/Map.Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Map from './Map';
import Point from '../geo/Point';
import Coordinate from '../geo/Coordinate';
import * as mat4 from '../core/util/mat4';
import { subtract, add, scale, normalize, dot, set, distance } from '../core/util/vec3';
import { subtract, add, scale, normalize, dot, set, distance, angle } from '../core/util/vec3';
import { clamp, interpolate, isNumber, isNil, wrap, toDegree, toRadian } from '../core/util';
import { applyMatrix, matrixToQuaternion, quaternionToMatrix, lookAt, setPosition } from '../core/util/math';
import Browser from '../core/Browser';
Expand All @@ -11,6 +11,7 @@ const RADIAN = Math.PI / 180;
const DEFAULT_FOV = 0.6435011087932844;
const TEMP_COORD = new Coordinate(0, 0);
const TEMP_POINT = new Point(0, 0);
const SOUTH = [0, -1, 0], BEARING = [];

const altitudesHasData = (altitudes) => {
if (isNumber(altitudes)) {
Expand Down Expand Up @@ -287,26 +288,10 @@ Map.include(/** @lends Map.prototype */{
* @property {Number} pitch
* @property {Number} bearing
*/
setCameraPosition(params) {
setCameraOrientation(params) {
const { position, pitch, bearing } = params;

const cameraAltitude = position[2] * this._meterToGLPoint;

const centerAltitude = this.centerAltitude || 0;
const centerPointZ = centerAltitude * this._meterToGLPoint;

const cz = cameraAltitude - centerPointZ;

const pitchRadian = pitch * RADIAN;

const cameraToGroundDistance = cz / Math.cos(pitchRadian);

const dist = Math.sin(pitchRadian) * cameraToGroundDistance;

const cameraToCenterDistance = cameraToGroundDistance + centerPointZ;

const zoom = this._getZoomFromCameraToCenterDistance(cameraToCenterDistance);

const { zoom, cameraToGroundDistance } = this.getFitZoomForCamera(position, pitch);
const dist = Math.sin(pitch * RADIAN) * cameraToGroundDistance;
const wrapBearing = wrap(bearing, -180, 180);
const bearingRadian = wrapBearing * RADIAN;

Expand All @@ -329,7 +314,43 @@ Map.include(/** @lends Map.prototype */{
return this;
},

_getZoomFromCameraToCenterDistance(distance) {
//设置相机的坐标, 根据地图中心点和相机位置,反算地图的bearing、pitch、zoom
setCameraPosition(coordinate) {
const glRes = this.getGLRes();
const cameraPoint = this.coordToPointAtRes(coordinate, glRes);
cameraPoint.z = this.altitudeToPoint(coordinate.z || 0, glRes);
const center = this.getCenter();
const centerPoint = this.coordToPointAtRes(center, glRes);
centerPoint.z = this.altitudeToPoint(center.z, glRes);
const direction = subtract([], cameraPoint.toArray(), centerPoint.toArray());
set(this.cameraUp || [0, 0, 0], 0, 0, 1);
this._pitch = angle(direction, this.cameraUp);
set(BEARING, direction[0], direction[1], 0);
this._angle = -angle(BEARING, SOUTH);
this._zoomLevel = this.getFitZoomForCamera(coordinate, this._pitch).zoom;
this._calcMatrices();
},

getFitZoomForCamera(cameraPosition, pitch) {
const z = Array.isArray(cameraPosition) ? cameraPosition[2] : cameraPosition.z;
const cameraAltitude = z * this._meterToGLPoint;

const centerAltitude = this.centerAltitude || 0;
const centerPointZ = centerAltitude * this._meterToGLPoint;

const cz = cameraAltitude - centerPointZ;

const pitchRadian = pitch * RADIAN;

const cameraToGroundDistance = cz / Math.cos(pitchRadian);

const cameraToCenterDistance = cameraToGroundDistance + centerPointZ;

const zoom = this._getFitZoomForDistance(cameraToCenterDistance);
return { zoom, cameraToGroundDistance };
},

_getFitZoomForDistance(distance) {
const ratio = this._getFovRatio();
const scale = distance * ratio * 2 / (this.height || 1) * this.getGLRes();
const resolutions = this._getResolutions();
Expand Down Expand Up @@ -712,7 +733,8 @@ Map.include(/** @lends Map.prototype */{
}

const center2D = this._prjToPointAtRes(this._prjCenter, glRes, TEMP_POINT);
const centerAltitude = this.centerAltitude || 0;
const altitude = this.getCenter().z;
const centerAltitude = altitude !== undefined ? altitude : this.centerAltitude || 0;
const centerPointZ = centerAltitude * this._meterToGLPoint;
this.cameraLookAt = set(this.cameraLookAt || [0, 0, 0], center2D.x, center2D.y, centerPointZ);

Expand Down Expand Up @@ -749,7 +771,8 @@ Map.include(/** @lends Map.prototype */{
// let up = new vec3(0,1,0);
// up.rotateZ(target,radians);
const d = dist || 1;
const up = this.cameraUp = set(this.cameraUp || [0, 0, 0], Math.sin(bearing) * d, Math.cos(bearing) * d, 0);
// const up = this.cameraUp = set(this.cameraUp || [0, 0, 0], Math.sin(bearing) * d, Math.cos(bearing) * d, 0);
const up = this.cameraUp = this.getPitch() > 0 ? set(this.cameraUp || [0, 0, 0], 0, 0, 1) : set(this.cameraUp || [0, 0, 0], Math.sin(bearing) * d, Math.cos(bearing) * d, 0);
const m = this.cameraWorldMatrix = this.cameraWorldMatrix || createMat4();
lookAt(m, this.cameraPosition, this.cameraLookAt, up);

Expand All @@ -775,7 +798,7 @@ Map.include(/** @lends Map.prototype */{
},

_recenterOnTerrain() {
if (this.centerAltitude === undefined) {
if (this.centerAltitude === undefined || this._centerZ !== undefined) {
return;
}
let queriedAltitude = this._queryTerrainByProjCoord(this._prjCenter);
Expand Down
4 changes: 4 additions & 0 deletions src/map/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ class Map extends Handlerable(Eventable(Renderable(Class))) {

this._zoomLevel = zoom;
this._center = center;
this._centerZ = center.z;

this.setSpatialReference(opts['spatialReference'] || opts['view']);

Expand Down Expand Up @@ -488,6 +489,7 @@ class Map extends Handlerable(Eventable(Renderable(Class))) {
const center = projection.unproject(this._prjCenter);
center.x = Math.round(center.x * 1E8) / 1E8;
center.y = Math.round(center.y * 1E8) / 1E8;
center.z = this._centerZ;
if (this.centerAltitude) {
center.z = this.centerAltitude;
}
Expand Down Expand Up @@ -521,6 +523,7 @@ class Map extends Handlerable(Eventable(Renderable(Class))) {
this._center = center;
return this;
}
this._centerZ = center.z || 0;
this.onMoveStart();
this._setPrjCenter(pcenter);
this.onMoveEnd(this._parseEventFromCoord(this.getCenter()));
Expand Down Expand Up @@ -2005,6 +2008,7 @@ class Map extends Handlerable(Eventable(Renderable(Class))) {
delete this._glRes;
const projection = this.getProjection();
this._prjCenter = projection.project(this._center);
this._prjCenter.z = this._center.z;
this._calcMatrices();
const renderer = this._getRenderer();
if (renderer) {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/geometry/Painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ class Painter extends Class {
return;
}
//Multiplexing offset
this.containerOffset = offset || mapStateCache.offset || map._pointToContainerPoint(renderer.southWest)._add(0, -map.height);
this.containerOffset = offset || mapStateCache.offset || map._pointToContainerPoint(renderer.middleWest)._add(0, -map.height / 2);
this._beforePaint();
const ctx = context || renderer.context;
if (!ctx.isHitTesting) {
Expand Down
22 changes: 11 additions & 11 deletions src/renderer/layer/CanvasRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class CanvasRenderer extends Class {
remove() {
this.onRemove();
delete this._loadingResource;
delete this.southWest;
delete this.middleWest;
delete this.canvas;
delete this.context;
delete this.canvasExtent2D;
Expand Down Expand Up @@ -266,7 +266,7 @@ class CanvasRenderer extends Class {
return null;
}
// size = this._extent2D.getSize(),
const containerPoint = map._pointToContainerPoint(this.southWest)._add(0, -map.height);
const containerPoint = map._pointToContainerPoint(this.middleWest)._add(0, -map.height / 2);
return {
'image': this.canvas,
'layer': this.layer,
Expand Down Expand Up @@ -392,16 +392,16 @@ class CanvasRenderer extends Class {

/**
* Prepare rendering
* Set necessary properties, like this._renderZoom/ this.canvasExtent2D, this.southWest
* Set necessary properties, like this._renderZoom/ this.canvasExtent2D, this.middleWest
* @private
*/
prepareRender() {
delete this._renderComplete;
const map = this.getMap();
this._renderZoom = map.getZoom();
this.canvasExtent2D = this._extent2D = map._get2DExtent();
//change from northWest to southWest, because northwest's point <=> containerPoint changes when pitch >= 72
this.southWest = map._containerPointToPoint(new Point(0, map.height));
//change from northWest to middleWest, because northwest's point <=> containerPoint changes when pitch >= 72
this.middleWest = map._containerPointToPoint(new Point(0, map.height / 2));
}

/**
Expand Down Expand Up @@ -575,10 +575,10 @@ class CanvasRenderer extends Class {
if (!mask) {
return false;
}
const old = this.southWest;
const old = this.middleWest;
const map = this.getMap();
//when clipping, layer's southwest needs to be reset for mask's containerPoint conversion
this.southWest = map._containerPointToPoint(new Point(0, map.height));
//when clipping, layer's middleWest needs to be reset for mask's containerPoint conversion
this.middleWest = map._containerPointToPoint(new Point(0, map.height / 2));
context.save();
const dpr = map.getDevicePixelRatio();
if (dpr !== 1) {
Expand Down Expand Up @@ -607,20 +607,20 @@ class CanvasRenderer extends Class {
context.restore();
}
context.clip();
this.southWest = old;
this.middleWest = old;
return true;
}

/**
* Get renderer's current view extent in 2d point
* @return {Object} view.extent, view.maskExtent, view.zoom, view.southWest
* @return {Object} view.extent, view.maskExtent, view.zoom, view.middleWest
*/
getViewExtent() {
return {
'extent': this._extent2D,
'maskExtent': this._maskExtent,
'zoom': this._renderZoom,
'southWest': this.southWest
'middleWest': this.middleWest
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ class VectorLayerRenderer extends OverlayLayerCanvasRenderer {

_updateMapStateCache() {
const map = this.getMap();
const offset = map._pointToContainerPoint(this.southWest)._add(0, -map.height);
const offset = map._pointToContainerPoint(this.middleWest)._add(0, -map.height / 2);
const resolution = map.getResolution();
const pitch = map.getPitch();
const bearing = map.getBearing();
Expand Down
2 changes: 1 addition & 1 deletion test/layer/CanvasLayerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Layer.CanvasLayer', function () {

layer.draw = function (context, view, w, h) {
expect(view.extent.isValid()).to.be.ok();
expect(view.southWest).to.be.ok();
expect(view.middleWest).to.be.ok();
expect(view.zoom).to.be.eql(map.getZoom());
expect(w).to.be.eql(size.width);
expect(h).to.be.eql(size.height);
Expand Down
26 changes: 19 additions & 7 deletions test/map/MapCameraSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ describe('Map.Camera', function () {

map.setPitch(70);
var size3 = geometry.getSize();
expect(size3.width).to.be.above(size2.width);
expect(size2.width).to.be.above(size3.width);
expect(size3.height).to.be.below(size2.height);
});
});
Expand Down Expand Up @@ -455,7 +455,7 @@ describe('Map.Camera', function () {

describe('Set camera position', function () {
it('pitch 0, bearing 0', function () {
map.setCameraPosition({
map.setCameraOrientation({
position: [0, 0, 10000],
pitch: 0,
bearing: 0,
Expand All @@ -468,7 +468,7 @@ describe('Map.Camera', function () {
});

it('pitch 45, bearing 45', function () {
map.setCameraPosition({
map.setCameraOrientation({
position: [0, 0, 10000],
pitch: 45,
bearing: 45,
Expand All @@ -481,7 +481,7 @@ describe('Map.Camera', function () {
});

it('pitch 45, bearing 135', function () {
map.setCameraPosition({
map.setCameraOrientation({
position: [0, 0, 10000],
pitch: 45,
bearing: 135,
Expand All @@ -494,7 +494,7 @@ describe('Map.Camera', function () {
});

it('pitch 45, bearing -45', function () {
map.setCameraPosition({
map.setCameraOrientation({
position: [0, 0, 10000],
pitch: 45,
bearing: -45,
Expand All @@ -507,7 +507,7 @@ describe('Map.Camera', function () {
});

it('pitch 45, bearing -135', function () {
map.setCameraPosition({
map.setCameraOrientation({
position: [0, 0, 10000],
pitch: 45,
bearing: -135,
Expand All @@ -520,7 +520,7 @@ describe('Map.Camera', function () {
});

it('position z', function () {
map.setCameraPosition({
map.setCameraOrientation({
position: [0, 0, 100],
pitch: 0,
bearing: 0,
Expand Down Expand Up @@ -629,5 +629,17 @@ describe('Map.Camera', function () {
// expect(maptalks.Util.join(map.domCssMatrix)).to.be.eql([31.819805153394643, -8.235571585149868, 0.7139488752261732, 0.6830127018922193, 31.819805153394636, 8.23557158514987, -0.7139488752261733, -0.6830127018922194, 0, -43.466662183008076, -0.27054191763364316, -0.25881904510252074, 0, 0, 46.83368719036461, 45].join());
expect(maptalks.Util.join(map.domCssMatrix)).to.be.eql([31.819805153394643,-8.235571585149868,0.693731297039628,0.6830127018922193,31.819805153394636,8.23557158514987,-0.6937312970396281,-0.6830127018922194,0,-43.466662183008076,-0.2628807214860012,-0.25881904510252074,0,0,45.635325850044154,45].join());
});

it('setCameraPosition', function() {
const center = map.getCenter();
const position = new maptalks.Coordinate(center.x + 0.01, center.y + 0.01, 100);
map.setCameraPosition(position);
const zoom = map.getZoom();
const pitch = map.getPitch();
const bearing = map.getBearing();
expect(zoom).to.be.eql(14.899641034986649);
expect(pitch).to.be.eql(85.67228588474566);
expect(bearing).to.be.eql(139.8095157874954);
});
});

9 changes: 9 additions & 0 deletions test/map/MapSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ describe('Map.Spec', function () {
map._getRenderer()._checkSizeInterval = 10;
// this.timeout(map._getRenderer()._checkSizeInterval * 3);
var center = map.getCenter();
center.z = center.z || 0;
map.once('resize', function (param) {
expect(param).to.be.ok();
//center remains
Expand Down Expand Up @@ -918,4 +919,12 @@ describe('Map.Spec', function () {
done();
}, 100);
});

it('map\'s center has altitude', function() {
const center = map.getCenter();
center.z = 100;
map.setCenter(center);
const viewMatrix = map.viewMatrix;
expect(viewMatrix).to.be.eql([-1, 0, 0, -0, 0, 1, 0, 0, 0, 0, -1, 0, 173083.2338488889, -49314.063792176465, 0.0703125, 1]);
});
});
2 changes: 1 addition & 1 deletion test/map/MapViewHistorySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('Map View History', function () {
renderer.callInNextFrame(function () {
map.zoomToPreviousView();
var next = map.zoomToNextView();
expect(next.center).to.be.eql([0, 0]);
expect(next.center).to.be.eql([0, 0, 0]);
expect(next.zoom).to.be.eql(zoom - 1);

expect(map.hasNextView()).not.to.be.ok();
Expand Down
2 changes: 1 addition & 1 deletion test/map/control/Control.OverviewSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('Control.Overview', function () {
var overview = new maptalks.control.Overview();
overview.addTo(map);
map.on('viewchange', function () {
expect(overview._overview.getCenter().toArray()).to.be.eql([0, 0]);
expect(overview._overview.getCenter().toArray()).to.be.eql([0, 0, 0]);
done();
});
map.setCenter([0, 0]);
Expand Down
Loading

0 comments on commit 005ec9d

Please sign in to comment.