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

refactor distance calculations #9202

Merged
merged 34 commits into from
Jan 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9c3b2b7
refactor distance calculations
Meekohi Jan 17, 2020
e8961f4
update LngLat test
Meekohi Jan 17, 2020
2ce2d77
updated render-tests
Meekohi Jan 17, 2020
f8d0055
missed one?
Meekohi Jan 17, 2020
756b094
missed a bunch
Meekohi Jan 17, 2020
e6e1f3d
Update src/geo/lng_lat.js
Meekohi Jan 19, 2020
615dced
better comments
Meekohi Jan 19, 2020
003ac59
update tests again
Meekohi Jan 19, 2020
428a861
updated inline comment
Meekohi Jan 19, 2020
2384d75
better error messages in tests
Meekohi Jan 19, 2020
87f3393
fix promoteId spec definitions (#9212)
mourner Jan 21, 2020
a13efc0
upgrade earcut to v2.2.2 (#9214)
mourner Jan 21, 2020
c09c9ec
move earthRadius definition to named export
Meekohi Jan 22, 2020
28603d1
Fix promoteId for line layers (#9210)
mourner Jan 22, 2020
980d1fb
Fix line distances breaking gradient across tile boundaries (#9220)
karimnaaji Jan 23, 2020
b7e8fb3
Update image expression SDK support table (#9228)
Jan 24, 2020
8cd474e
Refactor style._load function, move sprite loading to a private metho…
webdeb Jan 24, 2020
8c9ace1
[tests][tile mode] Add left-top-right-buttom-offset-tile-map-mode test
pozdnyakov Jan 27, 2020
be4f189
Reduce size of line atlas by removing unused channels (#9232)
karimnaaji Jan 27, 2020
99bfc7f
Fix a bug where lines with duplicate endpoint disappear on z18+ (#9218)
mourner Jan 27, 2020
c913aed
refactor distance calculations
Meekohi Jan 17, 2020
53aee40
update LngLat test
Meekohi Jan 17, 2020
4167d3e
updated render-tests
Meekohi Jan 17, 2020
2da4971
missed one?
Meekohi Jan 17, 2020
c79cd91
missed a bunch
Meekohi Jan 17, 2020
8b1dabd
Update src/geo/lng_lat.js
Meekohi Jan 19, 2020
e40b6e4
better comments
Meekohi Jan 19, 2020
74abf1d
update tests again
Meekohi Jan 19, 2020
896c33f
updated inline comment
Meekohi Jan 19, 2020
9d63de4
better error messages in tests
Meekohi Jan 19, 2020
c8edf1c
move earthRadius definition to named export
Meekohi Jan 22, 2020
c573758
Merge branch 'lnglat-distance' of github.com:Meekohi/mapbox-gl-js int…
Meekohi Jan 27, 2020
25657f0
update modified render test:
Meekohi Jan 27, 2020
d7ff0fa
wiggle room for HW differences
Meekohi Jan 31, 2020
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@mapbox/vector-tile": "^1.3.1",
"@mapbox/whoots-js": "^3.1.0",
"csscolorparser": "~1.0.2",
"earcut": "^2.2.0",
"earcut": "^2.2.2",
"geojson-vt": "^3.2.1",
"gl-matrix": "^3.0.0",
"grid-index": "^1.1.0",
Expand Down
18 changes: 11 additions & 7 deletions src/data/bucket/line_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class LineBucket implements Bucket {
const lineSortKey = this.layers[0].layout.get('line-sort-key');
const bucketFeatures = [];

for (const {feature, index, sourceLayerIndex} of features) {
for (const {feature, id, index, sourceLayerIndex} of features) {
if (!this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) continue;

const geometry = loadGeometry(feature);
Expand All @@ -130,7 +130,7 @@ class LineBucket implements Bucket {
undefined;

const bucketFeature: BucketFeature = {
id: feature.id,
id,
properties: feature.properties,
type: feature.type,
sourceLayerIndex,
Expand Down Expand Up @@ -231,6 +231,7 @@ class LineBucket implements Bucket {
for (let i = 0; i < vertices.length - 1; i++) {
this.totalDistance += vertices[i].dist(vertices[i + 1]);
}
this.updateScaledDistance();
}

const isPolygon = vectorTileFeatureTypes[feature.type] === 'Polygon';
Expand Down Expand Up @@ -273,8 +274,8 @@ class LineBucket implements Bucket {

for (let i = first; i < len; i++) {

nextVertex = isPolygon && i === len - 1 ?
vertices[first + 1] : // if the line is closed, we treat the last vertex like the first
nextVertex = i === len - 1 ?
(isPolygon ? vertices[first + 1] : (undefined: any)) : // if it's a polygon, treat the last vertex like the first
vertices[i + 1]; // just the next vertex

// if two consecutive vertices exist, skip the current one
Expand Down Expand Up @@ -526,9 +527,7 @@ class LineBucket implements Bucket {
}
}

updateDistance(prev: Point, next: Point) {
this.distance += prev.dist(next);

updateScaledDistance() {
// Knowing the ratio of the full linestring covered by this tiled feature, as well
// as the total distance (in tile units) of this tiled feature, and the distance
// (in tile units) of the current vertex, we can determine the relative distance
Expand All @@ -537,6 +536,11 @@ class LineBucket implements Bucket {
(this.clipStart + (this.clipEnd - this.clipStart) * this.distance / this.totalDistance) * (MAX_LINE_DISTANCE - 1) :
this.distance;
}

updateDistance(prev: Point, next: Point) {
this.distance += prev.dist(next);
this.updateScaledDistance();
}
}

register('LineBucket', LineBucket, {omit: ['layers', 'patternFeatures']});
Expand Down
28 changes: 28 additions & 0 deletions src/geo/lng_lat.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
import {wrap} from '../util/util';
import LngLatBounds from './lng_lat_bounds';

/*
* Approximate radius of the earth in meters.
* Uses the WGS-84 approximation. The radius at the equator is ~6378137 and at the poles is ~6356752. https://en.wikipedia.org/wiki/World_Geodetic_System#WGS84
* 6371008.8 is one published "average radius" see https://en.wikipedia.org/wiki/Earth_radius#Mean_radius, or ftp://athena.fsv.cvut.cz/ZFG/grs80-Moritz.pdf p.4
*/
export const earthRadius = 6371008.8;

/**
* A `LngLat` object represents a given longitude and latitude coordinate, measured in degrees.
*
Expand Down Expand Up @@ -73,6 +80,27 @@ class LngLat {
return `LngLat(${this.lng}, ${this.lat})`;
}

/**
* Returns the approximate distance between a pair of coordinates in meters
* Uses the Haversine Formula (from R.W. Sinnott, "Virtues of the Haversine", Sky and Telescope, vol. 68, no. 2, 1984, p. 159)
*
* @param {LngLat} lngLat coordinates to compute the distance to
* @returns {number} Distance in meters between the two coordinates.
* @example
* var new_york = new mapboxgl.LngLat(-74.0060, 40.7128);
* var los_angeles = new mapboxgl.LngLat(-118.2437, 34.0522);
* new_york.distanceTo(los_angeles); // = 3935751.690893987, "true distance" using a non-spherical approximation is ~3966km
*/
distanceTo(lngLat: LngLat) {
const rad = Math.PI / 180;
const lat1 = this.lat * rad;
const lat2 = lngLat.lat * rad;
const a = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos((lngLat.lng - this.lng) * rad);

const maxMeters = earthRadius * Math.acos(Math.min(a, 1));
return maxMeters;
}

/**
* Returns a `LngLatBounds` from the coordinates extended by a given `radius`. The returned `LngLatBounds` completely contains the `radius`.
*
Expand Down
12 changes: 6 additions & 6 deletions src/geo/mercator_coordinate.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// @flow

import LngLat from '../geo/lng_lat';
import LngLat, {earthRadius} from '../geo/lng_lat';
import type {LngLatLike} from '../geo/lng_lat';

/*
* The circumference of the world in meters at the equator.
* The average circumference of the world in meters.
*/
const circumferenceAtEquator = 2 * Math.PI * 6378137;
const earthCircumfrence = 2 * Math.PI * earthRadius; // meters

/*
* The circumference of the world in meters at the given latitude.
* The circumference at a line of latitude in meters.
*/
function circumferenceAtLatitude(latitude: number) {
return circumferenceAtEquator * Math.cos(latitude * Math.PI / 180);
return earthCircumfrence * Math.cos(latitude * Math.PI / 180);
}

export function mercatorXfromLng(lng: number) {
Expand Down Expand Up @@ -142,7 +142,7 @@ class MercatorCoordinate {
*/
meterInMercatorCoordinateUnits() {
// 1 meter / circumference at equator in meters * Mercator projection scale factor at this latitude
return 1 / circumferenceAtEquator * mercatorScale(latFromMercatorY(this.y));
return 1 / earthCircumfrence * mercatorScale(latFromMercatorY(this.y));
}

}
Expand Down
9 changes: 4 additions & 5 deletions src/render/line_atlas.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class LineAtlas {
this.height = height;
this.nextRow = 0;

this.bytes = 4;
this.data = new Uint8Array(this.width * this.height * this.bytes);
this.data = new Uint8Array(this.width * this.height);

this.positions = {};
}
Expand Down Expand Up @@ -114,7 +113,7 @@ class LineAtlas {
signedDistance = (inside ? 1 : -1) * dist;
}

this.data[3 + (index + x) * 4] = Math.max(0, Math.min(255, signedDistance + offset));
this.data[index + x] = Math.max(0, Math.min(255, signedDistance + offset));
}
}

Expand All @@ -139,14 +138,14 @@ class LineAtlas {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.data);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, this.width, this.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, this.data);

} else {
gl.bindTexture(gl.TEXTURE_2D, this.texture);

if (this.dirty) {
this.dirty = false;
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, this.data);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, gl.ALPHA, gl.UNSIGNED_BYTE, this.data);
}
}
}
Expand Down
18 changes: 13 additions & 5 deletions src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@
"type": "string",
"doc": "Contains an attribution to be displayed when the map is shown to a user."
},
"promoteId": {
"type": "promoteId",
"doc": "A property to use as a feature id (for feature state). Either a property name, or an object of the form `{<sourceLayer>: <propertyName>}`. If specified as a string for a vector tile source, the same property is used across all its source layers."
},
"*": {
"type": "*",
"doc": "Other keys to configure the data source."
Expand Down Expand Up @@ -317,10 +321,6 @@
"default": "mapbox",
"doc": "The encoding used by this source. Mapbox Terrain RGB is used by default"
},
"promoteId": {
"type": "promoteId",
"doc": "A property to use as a feature id (for feature state). Either a property name, or an object of the form `{<sourceLayer>: <propertyName>}`."
},
"*": {
"type": "*",
"doc": "Other keys to configure the data source."
Expand Down Expand Up @@ -2821,7 +2821,9 @@
"group": "Types",
"sdk-support": {
"basic functionality": {
"js": "1.4.0"
"js": "1.4.0",
"android": "8.6.0",
"ios": "5.6.0"
}
}
},
Expand Down Expand Up @@ -5786,5 +5788,11 @@
"type": "property-type",
"doc": "Property is constant across all zoom levels and property values."
}
},
"promoteId": {
"*": {
"type": "string",
"doc": "A name of a feature property to use as ID for feature state."
}
}
}
6 changes: 3 additions & 3 deletions src/style-spec/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ export type VectorSourceSpecification = {
"scheme"?: "xyz" | "tms",
"minzoom"?: number,
"maxzoom"?: number,
"attribution"?: string
"attribution"?: string,
"promoteId"?: PromoteIdSpecification
}

export type RasterSourceSpecification = {
Expand All @@ -112,8 +113,7 @@ export type RasterDEMSourceSpecification = {
"maxzoom"?: number,
"tileSize"?: number,
"attribution"?: string,
"encoding"?: "terrarium" | "mapbox",
"promoteId"?: PromoteIdSpecification
"encoding"?: "terrarium" | "mapbox"
}

export type GeoJSONSourceSpecification = {|
Expand Down
32 changes: 18 additions & 14 deletions src/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,20 +250,7 @@ class Style extends Evented {
}

if (json.sprite) {
this._spriteRequest = loadSprite(json.sprite, this.map._requestManager, (err, images) => {
this._spriteRequest = null;
if (err) {
this.fire(new ErrorEvent(err));
} else if (images) {
for (const id in images) {
this.imageManager.addImage(id, images[id]);
}
}

this.imageManager.setLoaded(true);
this.dispatcher.broadcast('setImages', this.imageManager.listImages());
this.fire(new Event('data', {dataType: 'style'}));
});
this._loadSprite(json.sprite);
} else {
this.imageManager.setLoaded(true);
}
Expand All @@ -288,6 +275,23 @@ class Style extends Evented {
this.fire(new Event('style.load'));
}

_loadSprite(url: string) {
this._spriteRequest = loadSprite(url, this.map._requestManager, (err, images) => {
this._spriteRequest = null;
if (err) {
this.fire(new ErrorEvent(err));
} else if (images) {
for (const id in images) {
this.imageManager.addImage(id, images[id]);
}
}

this.imageManager.setLoaded(true);
this.dispatcher.broadcast('setImages', this.imageManager.listImages());
this.fire(new Event('data', {dataType: 'style'}));
});
}

_validateLayer(layer: StyleLayer) {
const sourceCache = this.sourceCaches[layer.source];
if (!sourceCache) {
Expand Down
19 changes: 3 additions & 16 deletions src/ui/control/scale_control.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ function updateScale(map, container, options) {
const maxWidth = options && options.maxWidth || 100;

const y = map._container.clientHeight / 2;
const maxMeters = getDistance(map.unproject([0, y]), map.unproject([maxWidth, y]));
const left = map.unproject([0, y]);
const right = map.unproject([maxWidth, y]);
const maxMeters = left.distanceTo(right);
// The real distance corresponding to 100px scale length is rounded off to
// near pretty number and the scale length for the same is found out.
// Default unit of the scale is based on User's locale.
Expand Down Expand Up @@ -121,21 +123,6 @@ function setScale(container, maxWidth, maxDistance, unit) {
container.innerHTML = distance + unit;
}

function getDistance(latlng1, latlng2) {
// Uses spherical law of cosines approximation.
const R = 6371000;

const rad = Math.PI / 180,
lat1 = latlng1.lat * rad,
lat2 = latlng2.lat * rad,
a = Math.sin(lat1) * Math.sin(lat2) +
Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad);

const maxMeters = R * Math.acos(Math.min(a, 1));
return maxMeters;

}

function getDecimalRoundNum(d) {
const multiplier = Math.pow(10, Math.ceil(-Math.log(d) / Math.LN10));
return Math.round(d * multiplier) / multiplier;
Expand Down
3 changes: 2 additions & 1 deletion test/ignores.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
"render-tests/icon-image/icon-sdf-non-sdf-one-layer": "skip - render sdf icon and normal icon in one layer",
"render-tests/text-variable-anchor/all-anchors-tile-map-mode": "skip - mapbox-gl-js does not need to render tiles",
"render-tests/fill-pattern/update-feature-state": "https://github.com/mapbox/mapbox-gl-js/issues/7207",
"render-tests/text-size/zero": "https://github.com/mapbox/mapbox-gl-js/issues/9161"
"render-tests/text-size/zero": "https://github.com/mapbox/mapbox-gl-js/issues/9161",
"render-tests/text-variable-anchor/left-top-right-buttom-offset-tile-map-mode": "skip - mapbox-gl-js does not need to render tiles"
}
Binary file modified test/integration/render-tests/extent/1024-symbol/expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading