Skip to content

Commit

Permalink
seprate projection from type for internal use
Browse files Browse the repository at this point in the history
  • Loading branch information
ansis committed Oct 29, 2018
1 parent cd3e462 commit 0d4c2ca
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 21 deletions.
45 changes: 34 additions & 11 deletions src/geo/mercator_coordinate.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,31 @@ function circumferenceAtLatitude(latitude: number) {
return circumference * Math.cos(latitude * Math.PI / 180);
}

export function mercatorXfromLng(lng: number) {
return (180 + lng) / 360;
}

export function mercatorYfromLat(lat: number) {
return (180 - (180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360)))) / 360;
}

export function mercatorZfromAltitude(altitude: number, lat: number) {
return altitude / circumferenceAtLatitude(lat);
}

export function lngFromMercatorX(x: number) {
return x * 360 - 180;
}

export function latFromMercatorY(y: number) {
const y2 = 180 - y * 360;
return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;
}

export function altitudeFromMercatorZ(z: number, y: number) {
return z * circumferenceAtLatitude(latFromMercatorY(y));
}

/**
* A `MercatorCoordinate` object represents a projected three dimensional position.
*
Expand Down Expand Up @@ -57,25 +82,24 @@ class MercatorCoordinate {
static fromLngLat(lngLatLike: LngLatLike, altitude: number = 0) {
const lngLat = LngLat.convert(lngLatLike);

const x = (180 + lngLat.lng) / 360;
const y = (180 - (180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lngLat.lat * Math.PI / 360)))) / 360;
const z = altitude / circumferenceAtLatitude(lngLat.lat);
return new MercatorCoordinate(x, y, z);
return new MercatorCoordinate(
mercatorXfromLng(lngLat.lng),
mercatorYfromLat(lngLat.lat),
mercatorZfromAltitude(altitude, lngLat.lat));
}

/**
* Returns the `LatLng` for the coordinate.
*
* @returns {LngLat} The `LngLat` object.
* @example
* var coord = new mapboxglMercatorCoordinate(0.5, 0.5, 0);
* var coord = new mapboxgl.MercatorCoordinate(0.5, 0.5, 0);
* var latLng = coord.toLatLng(); // LngLat(0, 0)
*/
toLngLat() {
const lng = this.x * 360 - 180;
const y2 = 180 - this.y * 360;
const lat = 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;
return new LngLat(lng, lat);
return new LngLat(
lngFromMercatorX(this.x),
latFromMercatorY(this.y));
}

/**
Expand All @@ -87,8 +111,7 @@ class MercatorCoordinate {
* coord.toAltitude(); // 6914.281956295339
*/
toAltitude() {
const lat = this.toLngLat().lat;
return this.z * circumferenceAtLatitude(lat);
return altitudeFromMercatorZ(this.z, this.y);
}
}

Expand Down
19 changes: 9 additions & 10 deletions src/geo/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import LngLat from './lng_lat';
import LngLatBounds from './lng_lat_bounds';
import MercatorCoordinate from './mercator_coordinate';
import MercatorCoordinate, {mercatorXfromLng, mercatorYfromLat, mercatorZfromAltitude} from './mercator_coordinate';
import Point from '@mapbox/point-geometry';
import { wrap, clamp } from '../util/util';
import {number as interpolate} from '../style-spec/util/interpolate';
Expand Down Expand Up @@ -281,8 +281,9 @@ class Transform {
project(lnglat: LngLat) {
const lat = clamp(lnglat.lat, -this.maxValidLatitude, this.maxValidLatitude);
const clamped = new LngLat(lnglat.lng, lat);
const coord = MercatorCoordinate.fromLngLat(clamped);
return new Point(coord.x * this.worldSize, coord.y * this.worldSize);
return new Point(
mercatorXfromLng(lnglat.lng) * this.worldSize,
mercatorYfromLat(lat) * this.worldSize);
}

unproject(point: Point): LngLat {
Expand Down Expand Up @@ -459,15 +460,15 @@ class Transform {

if (this.latRange) {
const latRange = this.latRange;
minY = this.project(new LngLat(0, latRange[1])).y;
maxY = this.project(new LngLat(0, latRange[0])).y;
minY = mercatorYfromLat(latRange[1]) * this.worldSize;
maxY = mercatorYfromLat(latRange[0]) * this.worldSize;
sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0;
}

if (this.lngRange) {
const lngRange = this.lngRange;
minX = this.project(new LngLat(lngRange[0], 0)).x;
maxX = this.project(new LngLat(lngRange[1], 0)).x;
minX = mercatorXfromLng(lngRange[0]) * this.worldSize;
maxX = mercatorXfromLng(lngRange[1]) * this.worldSize;
sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0;
}

Expand Down Expand Up @@ -548,9 +549,7 @@ class Transform {
this.mercatorMatrix = mat4.scale([], m, [this.worldSize, this.worldSize, this.worldSize]);

// scale vertically to meters per pixel (inverse of ground resolution):
// worldSize / (circumferenceOfEarth * cos(lat * π / 180))
const verticalScale = this.worldSize / (2 * Math.PI * 6378137 * Math.abs(Math.cos(this.center.lat * (Math.PI / 180))));
mat4.scale(m, m, [1, 1, verticalScale, 1]);
mat4.scale(m, m, [1, 1, mercatorZfromAltitude(1, this.center.lat) * this.worldSize, 1]);

this.projMatrix = m;

Expand Down

0 comments on commit 0d4c2ca

Please sign in to comment.