Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map's center support altitude #2217

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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