Started adding Flow annotations to functions in the geo submodule

(re: #3744)
This commit is contained in:
Bryan Housel
2018-03-17 01:18:05 -04:00
parent 61c7f64077
commit 3e47ca005c
5 changed files with 71 additions and 54 deletions

View File

@@ -7,5 +7,6 @@
[lints]
[options]
include_warnings=true
[strict]

View File

@@ -1,3 +1,7 @@
// @flow
type Vec2 = [number, number];
type Mat2 = [Vec2, Vec2];
import _extend from 'lodash-es/extend';
import {
@@ -6,9 +10,10 @@ import {
} from './index';
export function geoExtent(min, max) {
if (!(this instanceof geoExtent)) return new geoExtent(min, max);
if (min instanceof geoExtent) {
export function geoExtent(min?: Vec2 | Mat2, max?: Vec2) {
if (!(this instanceof geoExtent)) {
return new geoExtent(min, max);
} else if (min instanceof geoExtent) {
return min;
} else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
this[0] = min[0];
@@ -19,6 +24,7 @@ export function geoExtent(min, max) {
}
}
// $FlowFixMe
geoExtent.prototype = new Array(2);
_extend(geoExtent.prototype, {
@@ -34,8 +40,8 @@ _extend(geoExtent.prototype, {
extend: function(obj) {
if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
return geoExtent(
[Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
[Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
[(Math.min(obj[0][0], this[0][0]): number), (Math.min(obj[0][1], this[0][1]): number)],
[(Math.max(obj[1][0], this[1][0]): number), (Math.max(obj[1][1], this[1][1]): number)]
);
},
@@ -101,16 +107,16 @@ _extend(geoExtent.prototype, {
intersection: function(obj) {
if (!this.intersects(obj)) return new geoExtent();
return new geoExtent(
[Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
[Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
[(Math.max(obj[0][0], this[0][0]): number), (Math.max(obj[0][1], this[0][1]): number)],
[(Math.min(obj[1][0], this[1][0]): number), (Math.min(obj[1][1], this[1][1]): number)]
);
},
percentContainedIn: function(obj) {
if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
var a1 = this.intersection(obj).area(),
a2 = this.area();
var a1 = this.intersection(obj).area();
var a2 = this.area();
if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
return 0;
@@ -120,9 +126,9 @@ _extend(geoExtent.prototype, {
},
padByMeters: function(meters) {
var dLat = geoMetersToLat(meters),
dLon = geoMetersToLon(meters, this.center()[1]);
padByMeters: function(meters: number) {
var dLat: number = geoMetersToLat(meters);
var dLon: number = geoMetersToLon(meters, this.center()[1]);
return geoExtent(
[this[0][0] - dLon, this[0][1] - dLat],
[this[1][0] + dLon, this[1][1] + dLat]

View File

@@ -1,32 +1,35 @@
// @flow
type Vec2 = [number, number];
// constants
var TAU = 2 * Math.PI;
var EQUATORIAL_RADIUS = 6356752.314245179;
var POLAR_RADIUS = 6378137.0;
export function geoLatToMeters(dLat) {
export function geoLatToMeters(dLat: number) {
return dLat * (TAU * POLAR_RADIUS / 360);
}
export function geoLonToMeters(dLon, atLat) {
export function geoLonToMeters(dLon: number, atLat: number) {
return Math.abs(atLat) >= 90 ? 0 :
dLon * (TAU * EQUATORIAL_RADIUS / 360) * Math.abs(Math.cos(atLat * (Math.PI / 180)));
}
export function geoMetersToLat(m) {
export function geoMetersToLat(m: number) {
return m / (TAU * POLAR_RADIUS / 360);
}
export function geoMetersToLon(m, atLat) {
export function geoMetersToLon(m: number, atLat: number) {
return Math.abs(atLat) >= 90 ? 0 :
m / (TAU * EQUATORIAL_RADIUS / 360) / Math.abs(Math.cos(atLat * (Math.PI / 180)));
}
export function geoMetersToOffset(meters, tileSize) {
export function geoMetersToOffset(meters: Vec2, tileSize?: number) {
tileSize = tileSize || 256;
return [
meters[0] * tileSize / (TAU * EQUATORIAL_RADIUS),
@@ -35,7 +38,7 @@ export function geoMetersToOffset(meters, tileSize) {
}
export function geoOffsetToMeters(offset, tileSize) {
export function geoOffsetToMeters(offset: Vec2, tileSize?: number) {
tileSize = tileSize || 256;
return [
offset[0] * TAU * EQUATORIAL_RADIUS / tileSize,
@@ -45,26 +48,24 @@ export function geoOffsetToMeters(offset, tileSize) {
// Equirectangular approximation of spherical distances on Earth
export function geoSphericalDistance(a, b) {
var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2);
var y = geoLatToMeters(a[1] - b[1]);
export function geoSphericalDistance(a: Vec2, b: Vec2) {
var x: number = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2);
var y: number = geoLatToMeters(a[1] - b[1]);
return Math.sqrt((x * x) + (y * y));
}
// scale to zoom
export function geoScaleToZoom(k, tileSize) {
export function geoScaleToZoom(k: number, tileSize?: number) {
tileSize = tileSize || 256;
var log2ts = Math.log(tileSize) * Math.LOG2E;
var log2ts: number = Math.log(tileSize) * Math.LOG2E;
return Math.log(k * TAU) / Math.LN2 - log2ts;
}
// zoom to scale
export function geoZoomToScale(z, tileSize) {
export function geoZoomToScale(z: number, tileSize?: number) {
tileSize = tileSize || 256;
return tileSize * Math.pow(2, z) / TAU;
}

View File

@@ -1,3 +1,8 @@
// @flow
type Vec2 = [number, number];
type Mat2 = [Vec2, Vec2];
type Transform = { x: number, y: number, k: number };
import {
geoMercatorRaw as d3_geoMercatorRaw,
geoTransform as d3_geoTransform
@@ -15,32 +20,33 @@ import {
* Resampling
*/
export function geoRawMercator() {
var project = d3_geoMercatorRaw,
k = 512 / Math.PI, // scale
x = 0, y = 0, // translate
clipExtent = [[0, 0], [0, 0]];
var project = d3_geoMercatorRaw;
var k: number = 512 / Math.PI; // scale
var x: number = 0;
var y: number = 0; // translate
var clipExtent: Mat2 = [[0, 0], [0, 0]];
function projection(point) {
function projection(point: Vec2) {
point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
return [point[0] * k + x, y - point[1] * k];
}
projection.invert = function(point) {
projection.invert = function(point: Vec2) {
point = project.invert((point[0] - x) / k, (y - point[1]) / k);
return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
};
projection.scale = function(_) {
projection.scale = function(_: number) {
if (!arguments.length) return k;
k = +_;
return projection;
};
projection.translate = function(_) {
projection.translate = function(_: Vec2) {
if (!arguments.length) return [x, y];
x = +_[0];
y = +_[1];
@@ -48,26 +54,26 @@ export function geoRawMercator() {
};
projection.clipExtent = function(_) {
projection.clipExtent = function(_: Mat2) {
if (!arguments.length) return clipExtent;
clipExtent = _;
return projection;
};
projection.transform = function(_) {
projection.transform = function(obj: Transform) {
if (!arguments.length) return d3_zoomIdentity.translate(x, y).scale(k);
x = +_.x;
y = +_.y;
k = +_.k;
x = +obj.x;
y = +obj.y;
k = +obj.k;
return projection;
};
projection.stream = d3_geoTransform({
point: function(x, y) {
x = projection([x, y]);
this.stream.point(x[0], x[1]);
point: function(x: number, y: number) {
var vec: Vec2 = projection([x, y]);
this.stream.point(vec[0], vec[1]);
}
}).stream;

View File

@@ -1,5 +1,8 @@
// @flow
type Vec2 = [number, number];
// vector equals
export function geoVecEqual(a, b, epsilon) {
export function geoVecEqual(a: Vec2, b: Vec2, epsilon?: number) {
if (epsilon) {
return (Math.abs(a[0] - b[0]) <= epsilon) && (Math.abs(a[1] - b[1]) <= epsilon);
} else {
@@ -8,27 +11,27 @@ export function geoVecEqual(a, b, epsilon) {
}
// vector addition
export function geoVecAdd(a, b) {
export function geoVecAdd(a: Vec2, b: Vec2) {
return [ a[0] + b[0], a[1] + b[1] ];
}
// vector subtraction
export function geoVecSubtract(a, b) {
export function geoVecSubtract(a: Vec2, b: Vec2) {
return [ a[0] - b[0], a[1] - b[1] ];
}
// vector scaling
export function geoVecScale(a, mag) {
export function geoVecScale(a: Vec2, mag: number) {
return [ a[0] * mag, a[1] * mag ];
}
// vector rounding (was: geoRoundCoordinates)
export function geoVecFloor(a) {
export function geoVecFloor(a: Vec2) {
return [ Math.floor(a[0]), Math.floor(a[1]) ];
}
// linear interpolation
export function geoVecInterp(a, b, t) {
export function geoVecInterp(a: Vec2, b: Vec2, t: number) {
return [
a[0] + (b[0] - a[0]) * t,
a[1] + (b[1] - a[1]) * t
@@ -36,20 +39,20 @@ export function geoVecInterp(a, b, t) {
}
// http://jsperf.com/id-dist-optimization
export function geoVecLength(a, b) {
var x = a[0] - b[0];
var y = a[1] - b[1];
export function geoVecLength(a: Vec2, b: Vec2) {
var x: number = a[0] - b[0];
var y: number = a[1] - b[1];
return Math.sqrt((x * x) + (y * y));
}
// Return the counterclockwise angle in the range (-pi, pi)
// between the positive X axis and the line intersecting a and b.
export function geoVecAngle(a, b) {
export function geoVecAngle(a: Vec2, b: Vec2) {
return Math.atan2(b[1] - a[1], b[0] - a[0]);
}
// dot product
export function geoVecDot(a, b, origin) {
export function geoVecDot(a: Vec2, b: Vec2, origin?: Vec2) {
origin = origin || [0, 0];
return (a[0] - origin[0]) * (b[0] - origin[0]) +
(a[1] - origin[1]) * (b[1] - origin[1]);
@@ -58,7 +61,7 @@ export function geoVecDot(a, b, origin) {
// 2D cross product of OA and OB vectors, returns magnitude of Z vector
// Returns a positive value, if OAB makes a counter-clockwise turn,
// negative for clockwise turn, and zero if the points are collinear.
export function geoVecCross(a, b, origin) {
export function geoVecCross(a: Vec2, b: Vec2, origin?: Vec2) {
origin = origin || [0, 0];
return (a[0] - origin[0]) * (b[1] - origin[1]) -
(a[1] - origin[1]) * (b[0] - origin[0]);