mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 17:23:02 +00:00
More flow coverage of geo submodule
(re: #3744) also: - Move types to index and export/import them - add return types
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
// @flow
|
||||
type Vec2 = [number, number];
|
||||
type Mat2 = [Vec2, Vec2];
|
||||
import type { Vec2, Mat2 } from '.';
|
||||
|
||||
import _extend from 'lodash-es/extend';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
type Vec2 = [number, number];
|
||||
import type { Vec2 } from '.';
|
||||
|
||||
// constants
|
||||
var TAU = 2 * Math.PI;
|
||||
@@ -7,29 +7,29 @@ var EQUATORIAL_RADIUS = 6356752.314245179;
|
||||
var POLAR_RADIUS = 6378137.0;
|
||||
|
||||
|
||||
export function geoLatToMeters(dLat: number) {
|
||||
export function geoLatToMeters(dLat: number): number {
|
||||
return dLat * (TAU * POLAR_RADIUS / 360);
|
||||
}
|
||||
|
||||
|
||||
export function geoLonToMeters(dLon: number, atLat: number) {
|
||||
export function geoLonToMeters(dLon: number, atLat: number): number {
|
||||
return Math.abs(atLat) >= 90 ? 0 :
|
||||
dLon * (TAU * EQUATORIAL_RADIUS / 360) * Math.abs(Math.cos(atLat * (Math.PI / 180)));
|
||||
}
|
||||
|
||||
|
||||
export function geoMetersToLat(m: number) {
|
||||
export function geoMetersToLat(m: number): number {
|
||||
return m / (TAU * POLAR_RADIUS / 360);
|
||||
}
|
||||
|
||||
|
||||
export function geoMetersToLon(m: number, atLat: number) {
|
||||
export function geoMetersToLon(m: number, atLat: number): number {
|
||||
return Math.abs(atLat) >= 90 ? 0 :
|
||||
m / (TAU * EQUATORIAL_RADIUS / 360) / Math.abs(Math.cos(atLat * (Math.PI / 180)));
|
||||
}
|
||||
|
||||
|
||||
export function geoMetersToOffset(meters: Vec2, tileSize?: number) {
|
||||
export function geoMetersToOffset(meters: Vec2, tileSize?: number): Vec2 {
|
||||
tileSize = tileSize || 256;
|
||||
return [
|
||||
meters[0] * tileSize / (TAU * EQUATORIAL_RADIUS),
|
||||
@@ -38,7 +38,7 @@ export function geoMetersToOffset(meters: Vec2, tileSize?: number) {
|
||||
}
|
||||
|
||||
|
||||
export function geoOffsetToMeters(offset: Vec2, tileSize?: number) {
|
||||
export function geoOffsetToMeters(offset: Vec2, tileSize?: number): Vec2 {
|
||||
tileSize = tileSize || 256;
|
||||
return [
|
||||
offset[0] * TAU * EQUATORIAL_RADIUS / tileSize,
|
||||
@@ -48,7 +48,7 @@ export function geoOffsetToMeters(offset: Vec2, tileSize?: number) {
|
||||
|
||||
|
||||
// Equirectangular approximation of spherical distances on Earth
|
||||
export function geoSphericalDistance(a: Vec2, b: Vec2) {
|
||||
export function geoSphericalDistance(a: Vec2, b: Vec2): number {
|
||||
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));
|
||||
@@ -56,7 +56,7 @@ export function geoSphericalDistance(a: Vec2, b: Vec2) {
|
||||
|
||||
|
||||
// scale to zoom
|
||||
export function geoScaleToZoom(k: number, tileSize?: number) {
|
||||
export function geoScaleToZoom(k: number, tileSize?: number): number {
|
||||
tileSize = tileSize || 256;
|
||||
var log2ts: number = Math.log(tileSize) * Math.LOG2E;
|
||||
return Math.log(k * TAU) / Math.LN2 - log2ts;
|
||||
@@ -64,7 +64,7 @@ export function geoScaleToZoom(k: number, tileSize?: number) {
|
||||
|
||||
|
||||
// zoom to scale
|
||||
export function geoZoomToScale(z: number, tileSize?: number) {
|
||||
export function geoZoomToScale(z: number, tileSize?: number): number {
|
||||
tileSize = tileSize || 256;
|
||||
return tileSize * Math.pow(2, z) / TAU;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// @flow
|
||||
import type { Vec2 } from '.';
|
||||
type Node = { id: string, loc: Vec2 };
|
||||
type Edge = { index: number, distance: number, loc: ?Vec2 };
|
||||
|
||||
import _every from 'lodash-es/every';
|
||||
import _some from 'lodash-es/some';
|
||||
|
||||
@@ -14,18 +19,18 @@ import {
|
||||
|
||||
// Return the counterclockwise angle in the range (-pi, pi)
|
||||
// between the positive X axis and the line intersecting a and b.
|
||||
export function geoAngle(a, b, projection) {
|
||||
export function geoAngle(a: Node, b: Node, projection: (Vec2) => Vec2): number {
|
||||
return geoVecAngle(projection(a.loc), projection(b.loc));
|
||||
}
|
||||
|
||||
export function geoEdgeEqual(a, b) {
|
||||
export function geoEdgeEqual(a: Vec2, b: Vec2): boolean {
|
||||
return (a[0] === b[0] && a[1] === b[1]) ||
|
||||
(a[0] === b[1] && a[1] === b[0]);
|
||||
}
|
||||
|
||||
// Rotate all points counterclockwise around a pivot point by given angle
|
||||
export function geoRotate(points, angle, around) {
|
||||
return points.map(function(point) {
|
||||
export function geoRotate(points: Array<Vec2>, angle: number, around: Vec2): Array<Vec2> {
|
||||
return points.map(function(point: Vec2) {
|
||||
var radial = geoVecSubtract(point, around);
|
||||
return [
|
||||
radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0],
|
||||
@@ -39,7 +44,7 @@ export function geoRotate(points, angle, around) {
|
||||
// projection onto that edge, if such a projection exists, or the distance to
|
||||
// the closest vertex on that edge. Returns an object with the `index` of the
|
||||
// chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
|
||||
export function geoChooseEdge(nodes, point, projection, activeID) {
|
||||
export function geoChooseEdge(nodes: Array<Node>, point: Vec2, projection: (loc: Vec2) => Vec2, activeID?: string): ?Edge {
|
||||
var dist = geoVecLength;
|
||||
var points = nodes.map(function(n) { return projection(n.loc); });
|
||||
var ids = nodes.map(function(n) { return n.id; });
|
||||
@@ -84,7 +89,7 @@ export function geoChooseEdge(nodes, point, projection, activeID) {
|
||||
// This is used to test e.g. multipolygon rings that cross
|
||||
// `activeNodes` is the ring containing the activeID being dragged.
|
||||
// `inactiveNodes` is the other ring to test against
|
||||
export function geoHasLineIntersections(activeNodes, inactiveNodes, activeID) {
|
||||
export function geoHasLineIntersections(activeNodes: Array<Node>, inactiveNodes: Array<Node>, activeID?: string): boolean {
|
||||
var actives = [];
|
||||
var inactives = [];
|
||||
var j, k, n1, n2, segment;
|
||||
@@ -125,7 +130,7 @@ export function geoHasLineIntersections(activeNodes, inactiveNodes, activeID) {
|
||||
|
||||
// Test active (dragged or drawing) segments against inactive segments
|
||||
// This is used to test whether a way intersects with itself.
|
||||
export function geoHasSelfIntersections(nodes, activeID) {
|
||||
export function geoHasSelfIntersections(nodes: Array<Node>, activeID?: string): boolean {
|
||||
var actives = [];
|
||||
var inactives = [];
|
||||
var j, k;
|
||||
@@ -175,7 +180,7 @@ export function geoHasSelfIntersections(nodes, activeID) {
|
||||
// From https://github.com/pgkelley4/line-segments-intersect
|
||||
// This uses the vector cross product approach described below:
|
||||
// http://stackoverflow.com/a/565282/786339
|
||||
export function geoLineIntersection(a, b) {
|
||||
export function geoLineIntersection(a: Array<Vec2>, b: Array<Vec2>): ?Vec2 {
|
||||
var p = [a[0][0], a[0][1]];
|
||||
var p2 = [a[1][0], a[1][1]];
|
||||
var q = [b[0][0], b[0][1]];
|
||||
@@ -198,7 +203,7 @@ export function geoLineIntersection(a, b) {
|
||||
}
|
||||
|
||||
|
||||
export function geoPathIntersections(path1, path2) {
|
||||
export function geoPathIntersections(path1: Array<Vec2>, path2: Array<Vec2>): Array<Vec2> {
|
||||
var intersections = [];
|
||||
for (var i = 0; i < path1.length - 1; i++) {
|
||||
for (var j = 0; j < path2.length - 1; j++) {
|
||||
@@ -213,7 +218,7 @@ export function geoPathIntersections(path1, path2) {
|
||||
return intersections;
|
||||
}
|
||||
|
||||
export function geoPathHasIntersections(path1, path2) {
|
||||
export function geoPathHasIntersections(path1: Array<Vec2>, path2: Array<Vec2>): boolean {
|
||||
for (var i = 0; i < path1.length - 1; i++) {
|
||||
for (var j = 0; j < path2.length - 1; j++) {
|
||||
var a = [ path1[i], path1[i+1] ];
|
||||
@@ -237,7 +242,7 @@ export function geoPathHasIntersections(path1, path2) {
|
||||
// ray-casting algorithm based on
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
//
|
||||
export function geoPointInPolygon(point, polygon) {
|
||||
export function geoPointInPolygon(point: Vec2, polygon: Array<Vec2>): boolean {
|
||||
var x = point[0];
|
||||
var y = point[1];
|
||||
var inside = false;
|
||||
@@ -257,14 +262,14 @@ export function geoPointInPolygon(point, polygon) {
|
||||
}
|
||||
|
||||
|
||||
export function geoPolygonContainsPolygon(outer, inner) {
|
||||
export function geoPolygonContainsPolygon(outer: Array<Vec2>, inner: Array<Vec2>): boolean {
|
||||
return _every(inner, function(point) {
|
||||
return geoPointInPolygon(point, outer);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
|
||||
export function geoPolygonIntersectsPolygon(outer: Array<Vec2>, inner: Array<Vec2>, checkSegments: boolean): boolean {
|
||||
function testPoints(outer, inner) {
|
||||
return _some(inner, function(point) {
|
||||
return geoPointInPolygon(point, outer);
|
||||
@@ -275,7 +280,7 @@ export function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
|
||||
}
|
||||
|
||||
|
||||
export function geoPathLength(path) {
|
||||
export function geoPathLength(path: Array<Vec2>): number {
|
||||
var length = 0;
|
||||
for (var i = 0; i < path.length - 1; i++) {
|
||||
length += geoVecLength(path[i], path[i + 1]);
|
||||
@@ -286,7 +291,7 @@ export function geoPathLength(path) {
|
||||
|
||||
// If the given point is at the edge of the padded viewport,
|
||||
// return a vector that will nudge the viewport in that direction
|
||||
export function geoViewportEdge(point, dimensions) {
|
||||
export function geoViewportEdge(point: Vec2, dimensions: Vec2): ?Vec2 {
|
||||
var pad = [80, 20, 50, 20]; // top, right, bottom, left
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// @flow
|
||||
export type Vec2 = [number, number];
|
||||
export type Mat2 = [Vec2, Vec2];
|
||||
export type Transform = { x: number, y: number, k: number };
|
||||
|
||||
export { geoExtent } from './extent.js';
|
||||
|
||||
export { geoLatToMeters } from './geo.js';
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// @flow
|
||||
type Vec2 = [number, number];
|
||||
type Mat2 = [Vec2, Vec2];
|
||||
type Transform = { x: number, y: number, k: number };
|
||||
import type { Mat2, Vec2, Transform } from '.';
|
||||
|
||||
import {
|
||||
geoMercatorRaw as d3_geoMercatorRaw,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @flow
|
||||
type Vec2 = [number, number];
|
||||
import type { Vec2 } from '.';
|
||||
|
||||
// vector equals
|
||||
export function geoVecEqual(a: Vec2, b: Vec2, epsilon?: number) {
|
||||
export function geoVecEqual(a: Vec2, b: Vec2, epsilon?: number): boolean {
|
||||
if (epsilon) {
|
||||
return (Math.abs(a[0] - b[0]) <= epsilon) && (Math.abs(a[1] - b[1]) <= epsilon);
|
||||
} else {
|
||||
@@ -11,27 +11,27 @@ export function geoVecEqual(a: Vec2, b: Vec2, epsilon?: number) {
|
||||
}
|
||||
|
||||
// vector addition
|
||||
export function geoVecAdd(a: Vec2, b: Vec2) {
|
||||
export function geoVecAdd(a: Vec2, b: Vec2): Vec2 {
|
||||
return [ a[0] + b[0], a[1] + b[1] ];
|
||||
}
|
||||
|
||||
// vector subtraction
|
||||
export function geoVecSubtract(a: Vec2, b: Vec2) {
|
||||
export function geoVecSubtract(a: Vec2, b: Vec2): Vec2 {
|
||||
return [ a[0] - b[0], a[1] - b[1] ];
|
||||
}
|
||||
|
||||
// vector scaling
|
||||
export function geoVecScale(a: Vec2, mag: number) {
|
||||
export function geoVecScale(a: Vec2, mag: number): Vec2 {
|
||||
return [ a[0] * mag, a[1] * mag ];
|
||||
}
|
||||
|
||||
// vector rounding (was: geoRoundCoordinates)
|
||||
export function geoVecFloor(a: Vec2) {
|
||||
export function geoVecFloor(a: Vec2): Vec2 {
|
||||
return [ Math.floor(a[0]), Math.floor(a[1]) ];
|
||||
}
|
||||
|
||||
// linear interpolation
|
||||
export function geoVecInterp(a: Vec2, b: Vec2, t: number) {
|
||||
export function geoVecInterp(a: Vec2, b: Vec2, t: number): Vec2 {
|
||||
return [
|
||||
a[0] + (b[0] - a[0]) * t,
|
||||
a[1] + (b[1] - a[1]) * t
|
||||
@@ -39,7 +39,7 @@ export function geoVecInterp(a: Vec2, b: Vec2, t: number) {
|
||||
}
|
||||
|
||||
// http://jsperf.com/id-dist-optimization
|
||||
export function geoVecLength(a: Vec2, b: Vec2) {
|
||||
export function geoVecLength(a: Vec2, b: Vec2): number {
|
||||
var x: number = a[0] - b[0];
|
||||
var y: number = a[1] - b[1];
|
||||
return Math.sqrt((x * x) + (y * y));
|
||||
@@ -47,12 +47,12 @@ export function geoVecLength(a: Vec2, b: Vec2) {
|
||||
|
||||
// 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: Vec2, b: Vec2) {
|
||||
export function geoVecAngle(a: Vec2, b: Vec2): number {
|
||||
return Math.atan2(b[1] - a[1], b[0] - a[0]);
|
||||
}
|
||||
|
||||
// dot product
|
||||
export function geoVecDot(a: Vec2, b: Vec2, origin?: Vec2) {
|
||||
export function geoVecDot(a: Vec2, b: Vec2, origin?: Vec2): number {
|
||||
origin = origin || [0, 0];
|
||||
return (a[0] - origin[0]) * (b[0] - origin[0]) +
|
||||
(a[1] - origin[1]) * (b[1] - origin[1]);
|
||||
@@ -61,7 +61,7 @@ export function geoVecDot(a: Vec2, b: Vec2, origin?: Vec2) {
|
||||
// 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: Vec2, b: Vec2, origin?: Vec2) {
|
||||
export function geoVecCross(a: Vec2, b: Vec2, origin?: Vec2): number {
|
||||
origin = origin || [0, 0];
|
||||
return (a[0] - origin[0]) * (b[1] - origin[1]) -
|
||||
(a[1] - origin[1]) * (b[0] - origin[0]);
|
||||
|
||||
Reference in New Issue
Block a user