Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cheap-ruler

Package Overview
Dependencies
Maintainers
0
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cheap-ruler - npm Package Compare versions

Comparing version 3.0.2 to 4.0.0

index.d.ts

819

cheap-ruler.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.CheapRuler = factory());
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.CheapRuler = factory());
})(this, (function () { 'use strict';
var factors = {
kilometers: 1,
miles: 1000 / 1609.344,
nauticalmiles: 1000 / 1852,
meters: 1000,
metres: 1000,
yards: 1000 / 0.9144,
feet: 1000 / 0.3048,
inches: 1000 / 0.0254
};
const factors = {
kilometers: 1,
miles: 1000 / 1609.344,
nauticalmiles: 1000 / 1852,
meters: 1000,
metres: 1000,
yards: 1000 / 0.9144,
feet: 1000 / 0.3048,
inches: 1000 / 0.0254
};
// Values that define WGS84 ellipsoid model of the Earth
var RE = 6378.137; // equatorial radius
var FE = 1 / 298.257223563; // flattening
// Values that define WGS84 ellipsoid model of the Earth
const RE = 6378.137; // equatorial radius
const FE = 1 / 298.257223563; // flattening
var E2 = FE * (2 - FE);
var RAD = Math.PI / 180;
const E2 = FE * (2 - FE);
const RAD = Math.PI / 180;
/**
* A collection of very fast approximations to common geodesic measurements. Useful for performance-sensitive code that measures things on a city scale.
*
* @param {number} lat latitude
* @param {string} [units='kilometers']
* @returns {CheapRuler}
* @example
* const ruler = cheapRuler(35.05, 'miles');
* //=ruler
*/
var CheapRuler = function CheapRuler(lat, units) {
if (lat === undefined) { throw new Error('No latitude given.'); }
if (units && !factors[units]) { throw new Error(("Unknown unit " + units + ". Use one of: " + (Object.keys(factors).join(', ')))); }
/**
* A collection of very fast approximations to common geodesic measurements. Useful for performance-sensitive code that measures things on a city scale.
*/
class CheapRuler {
/**
* Creates a ruler object from tile coordinates (y and z).
*
* @param {number} y
* @param {number} z
* @param {keyof typeof factors} [units='kilometers']
* @returns {CheapRuler}
* @example
* const ruler = cheapRuler.fromTile(1567, 12);
* //=ruler
*/
static fromTile(y, z, units) {
const n = Math.PI * (1 - 2 * (y + 0.5) / Math.pow(2, z));
const lat = Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))) / RAD;
return new CheapRuler(lat, units);
}
// Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional
var m = RAD * RE * (units ? factors[units] : 1);
var coslat = Math.cos(lat * RAD);
var w2 = 1 / (1 - E2 * (1 - coslat * coslat));
var w = Math.sqrt(w2);
/**
* Multipliers for converting between units.
*
* @example
* // convert 50 meters to yards
* 50 * CheapRuler.units.yards / CheapRuler.units.meters;
*/
static get units() {
return factors;
}
// multipliers for converting longitude and latitude degrees into distance
this.kx = m * w * coslat; // based on normal radius of curvature
this.ky = m * w * w2 * (1 - E2); // based on meridonal radius of curvature
};
/**
* Creates a ruler instance for very fast approximations to common geodesic measurements around a certain latitude.
*
* @param {number} lat latitude
* @param {keyof typeof factors} [units='kilometers']
* @example
* const ruler = cheapRuler(35.05, 'miles');
* //=ruler
*/
constructor(lat, units) {
if (lat === undefined) throw new Error('No latitude given.');
if (units && !factors[units]) throw new Error(`Unknown unit ${ units }. Use one of: ${ Object.keys(factors).join(', ')}`);
var staticAccessors = { units: { configurable: true } };
// Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional
const m = RAD * RE * (units ? factors[units] : 1);
const coslat = Math.cos(lat * RAD);
const w2 = 1 / (1 - E2 * (1 - coslat * coslat));
const w = Math.sqrt(w2);
/**
* Given two points of the form [longitude, latitude], returns the distance.
*
* @param {Array<number>} a point [longitude, latitude]
* @param {Array<number>} b point [longitude, latitude]
* @returns {number} distance
* @example
* const distance = ruler.distance([30.5, 50.5], [30.51, 50.49]);
* //=distance
*/
CheapRuler.fromTile = function fromTile (y, z, units) {
var n = Math.PI * (1 - 2 * (y + 0.5) / Math.pow(2, z));
var lat = Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))) / RAD;
return new CheapRuler(lat, units);
};
// multipliers for converting longitude and latitude degrees into distance
this.kx = m * w * coslat; // based on normal radius of curvature
this.ky = m * w * w2 * (1 - E2); // based on meridonal radius of curvature
}
/**
* Multipliers for converting between units.
*
* @example
* // convert 50 meters to yards
* 50 * CheapRuler.units.yards / CheapRuler.units.meters;
*/
staticAccessors.units.get = function () {
return factors;
};
/**
* Given two points of the form [longitude, latitude], returns the distance.
*
* @param {[number, number]} a point [longitude, latitude]
* @param {[number, number]} b point [longitude, latitude]
* @returns {number} distance
* @example
* const distance = ruler.distance([30.5, 50.5], [30.51, 50.49]);
* //=distance
*/
distance(a, b) {
const dx = wrap(a[0] - b[0]) * this.kx;
const dy = (a[1] - b[1]) * this.ky;
return Math.sqrt(dx * dx + dy * dy);
}
CheapRuler.prototype.distance = function distance (a, b) {
var dx = wrap(a[0] - b[0]) * this.kx;
var dy = (a[1] - b[1]) * this.ky;
return Math.sqrt(dx * dx + dy * dy);
};
/**
* Returns the bearing between two points in angles.
*
* @param {[number, number]} a point [longitude, latitude]
* @param {[number, number]} b point [longitude, latitude]
* @returns {number} bearing
* @example
* const bearing = ruler.bearing([30.5, 50.5], [30.51, 50.49]);
* //=bearing
*/
bearing(a, b) {
const dx = wrap(b[0] - a[0]) * this.kx;
const dy = (b[1] - a[1]) * this.ky;
return Math.atan2(dx, dy) / RAD;
}
/**
* Returns the bearing between two points in angles.
*
* @param {Array<number>} a point [longitude, latitude]
* @param {Array<number>} b point [longitude, latitude]
* @returns {number} bearing
* @example
* const bearing = ruler.bearing([30.5, 50.5], [30.51, 50.49]);
* //=bearing
*/
CheapRuler.prototype.bearing = function bearing (a, b) {
var dx = wrap(b[0] - a[0]) * this.kx;
var dy = (b[1] - a[1]) * this.ky;
return Math.atan2(dx, dy) / RAD;
};
/**
* Returns a new point given distance and bearing from the starting point.
*
* @param {[number, number]} p point [longitude, latitude]
* @param {number} dist distance
* @param {number} bearing
* @returns {[number, number]} point [longitude, latitude]
* @example
* const point = ruler.destination([30.5, 50.5], 0.1, 90);
* //=point
*/
destination(p, dist, bearing) {
const a = bearing * RAD;
return this.offset(p,
Math.sin(a) * dist,
Math.cos(a) * dist);
}
/**
* Returns a new point given distance and bearing from the starting point.
*
* @param {Array<number>} p point [longitude, latitude]
* @param {number} dist distance
* @param {number} bearing
* @returns {Array<number>} point [longitude, latitude]
* @example
* const point = ruler.destination([30.5, 50.5], 0.1, 90);
* //=point
*/
CheapRuler.prototype.destination = function destination (p, dist, bearing) {
var a = bearing * RAD;
return this.offset(p,
Math.sin(a) * dist,
Math.cos(a) * dist);
};
/**
* Returns a new point given easting and northing offsets (in ruler units) from the starting point.
*
* @param {[number, number]} p point [longitude, latitude]
* @param {number} dx easting
* @param {number} dy northing
* @returns {[number, number]} point [longitude, latitude]
* @example
* const point = ruler.offset([30.5, 50.5], 10, 10);
* //=point
*/
offset(p, dx, dy) {
return [
p[0] + dx / this.kx,
p[1] + dy / this.ky
];
}
/**
* Returns a new point given easting and northing offsets (in ruler units) from the starting point.
*
* @param {Array<number>} p point [longitude, latitude]
* @param {number} dx easting
* @param {number} dy northing
* @returns {Array<number>} point [longitude, latitude]
* @example
* const point = ruler.offset([30.5, 50.5], 10, 10);
* //=point
*/
CheapRuler.prototype.offset = function offset (p, dx, dy) {
return [
p[0] + dx / this.kx,
p[1] + dy / this.ky
];
};
/**
* Given a line (an array of points), returns the total line distance.
*
* @param {[number, number][]} points [longitude, latitude]
* @returns {number} total line distance
* @example
* const length = ruler.lineDistance([
* [-67.031, 50.458], [-67.031, 50.534],
* [-66.929, 50.534], [-66.929, 50.458]
* ]);
* //=length
*/
lineDistance(points) {
let total = 0;
for (let i = 0; i < points.length - 1; i++) {
total += this.distance(points[i], points[i + 1]);
}
return total;
}
/**
* Given a line (an array of points), returns the total line distance.
*
* @param {Array<Array<number>>} points [longitude, latitude]
* @returns {number} total line distance
* @example
* const length = ruler.lineDistance([
* [-67.031, 50.458], [-67.031, 50.534],
* [-66.929, 50.534], [-66.929, 50.458]
* ]);
* //=length
*/
CheapRuler.prototype.lineDistance = function lineDistance (points) {
var total = 0;
for (var i = 0; i < points.length - 1; i++) {
total += this.distance(points[i], points[i + 1]);
}
return total;
};
/**
* Given a polygon (an array of rings, where each ring is an array of points), returns the area.
*
* @param {[number, number][][]} polygon
* @returns {number} area value in the specified units (square kilometers by default)
* @example
* const area = ruler.area([[
* [-67.031, 50.458], [-67.031, 50.534], [-66.929, 50.534],
* [-66.929, 50.458], [-67.031, 50.458]
* ]]);
* //=area
*/
area(polygon) {
let sum = 0;
/**
* Given a polygon (an array of rings, where each ring is an array of points), returns the area.
*
* @param {Array<Array<Array<number>>>} polygon
* @returns {number} area value in the specified units (square kilometers by default)
* @example
* const area = ruler.area([[
* [-67.031, 50.458], [-67.031, 50.534], [-66.929, 50.534],
* [-66.929, 50.458], [-67.031, 50.458]
* ]]);
* //=area
*/
CheapRuler.prototype.area = function area (polygon) {
var sum = 0;
for (let i = 0; i < polygon.length; i++) {
const ring = polygon[i];
for (var i = 0; i < polygon.length; i++) {
var ring = polygon[i];
for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
sum += wrap(ring[j][0] - ring[k][0]) * (ring[j][1] + ring[k][1]) * (i ? -1 : 1);
}
}
for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
sum += wrap(ring[j][0] - ring[k][0]) * (ring[j][1] + ring[k][1]) * (i ? -1 : 1);
return (Math.abs(sum) / 2) * this.kx * this.ky;
}
}
return (Math.abs(sum) / 2) * this.kx * this.ky;
};
/**
* Returns the point at a specified distance along the line.
*
* @param {[number, number][]} line
* @param {number} dist distance
* @returns {[number, number]} point [longitude, latitude]
* @example
* const point = ruler.along(line, 2.5);
* //=point
*/
along(line, dist) {
let sum = 0;
/**
* Returns the point at a specified distance along the line.
*
* @param {Array<Array<number>>} line
* @param {number} dist distance
* @returns {Array<number>} point [longitude, latitude]
* @example
* const point = ruler.along(line, 2.5);
* //=point
*/
CheapRuler.prototype.along = function along (line, dist) {
var sum = 0;
if (dist <= 0) return line[0];
if (dist <= 0) { return line[0]; }
for (let i = 0; i < line.length - 1; i++) {
const p0 = line[i];
const p1 = line[i + 1];
const d = this.distance(p0, p1);
sum += d;
if (sum > dist) return interpolate(p0, p1, (dist - (sum - d)) / d);
}
for (var i = 0; i < line.length - 1; i++) {
var p0 = line[i];
var p1 = line[i + 1];
var d = this.distance(p0, p1);
sum += d;
if (sum > dist) { return interpolate(p0, p1, (dist - (sum - d)) / d); }
}
return line[line.length - 1];
}
return line[line.length - 1];
};
/**
* Returns the distance from a point `p` to a line segment `a` to `b`.
*
* @pointToSegmentDistance
* @param {[number, number]} p point [longitude, latitude]
* @param {[number, number]} a segment point 1 [longitude, latitude]
* @param {[number, number]} b segment point 2 [longitude, latitude]
* @returns {number} distance
* @example
* const distance = ruler.pointToSegmentDistance([-67.04, 50.5], [-67.05, 50.57], [-67.03, 50.54]);
* //=distance
*/
pointToSegmentDistance(p, a, b) {
let [x, y] = a;
let dx = wrap(b[0] - x) * this.kx;
let dy = (b[1] - y) * this.ky;
/**
* Returns the distance from a point `p` to a line segment `a` to `b`.
*
* @pointToSegmentDistance
* @param {Array<number>} p point [longitude, latitude]
* @param {Array<number>} p1 segment point 1 [longitude, latitude]
* @param {Array<number>} p2 segment point 2 [longitude, latitude]
* @returns {number} distance
* @example
* const distance = ruler.pointToSegmentDistance([-67.04, 50.5], [-67.05, 50.57], [-67.03, 50.54]);
* //=distance
*/
CheapRuler.prototype.pointToSegmentDistance = function pointToSegmentDistance (p, a, b) {
var x = a[0];
var y = a[1];
var dx = wrap(b[0] - x) * this.kx;
var dy = (b[1] - y) * this.ky;
var t = 0;
if (dx !== 0 || dy !== 0) {
const t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
if (dx !== 0 || dy !== 0) {
t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = b[0];
y = b[1];
if (t > 1) {
x = b[0];
y = b[1];
} else if (t > 0) {
x += (dx / this.kx) * t;
y += (dy / this.ky) * t;
}
}
} else if (t > 0) {
x += (dx / this.kx) * t;
y += (dy / this.ky) * t;
dx = wrap(p[0] - x) * this.kx;
dy = (p[1] - y) * this.ky;
return Math.sqrt(dx * dx + dy * dy);
}
}
dx = wrap(p[0] - x) * this.kx;
dy = (p[1] - y) * this.ky;
/**
* Returns an object of the form {point, index, t}, where point is closest point on the line
* from the given point, index is the start index of the segment with the closest point,
* and t is a parameter from 0 to 1 that indicates where the closest point is on that segment.
*
* @param {[number, number][]} line
* @param {[number, number]} p point [longitude, latitude]
* @returns {{point: [number, number], index: number, t: number}} {point, index, t}
* @example
* const point = ruler.pointOnLine(line, [-67.04, 50.5]).point;
* //=point
*/
pointOnLine(line, p) {
let minDist = Infinity;
let minX = line[0][0];
let minY = line[0][1];
let minI = 0;
let minT = 0;
return Math.sqrt(dx * dx + dy * dy);
};
for (let i = 0; i < line.length - 1; i++) {
/**
* Returns an object of the form {point, index, t}, where point is closest point on the line
* from the given point, index is the start index of the segment with the closest point,
* and t is a parameter from 0 to 1 that indicates where the closest point is on that segment.
*
* @param {Array<Array<number>>} line
* @param {Array<number>} p point [longitude, latitude]
* @returns {Object} {point, index, t}
* @example
* const point = ruler.pointOnLine(line, [-67.04, 50.5]).point;
* //=point
*/
CheapRuler.prototype.pointOnLine = function pointOnLine (line, p) {
var minDist = Infinity;
var minX, minY, minI, minT;
let x = line[i][0];
let y = line[i][1];
let dx = wrap(line[i + 1][0] - x) * this.kx;
let dy = (line[i + 1][1] - y) * this.ky;
let t = 0;
for (var i = 0; i < line.length - 1; i++) {
if (dx !== 0 || dy !== 0) {
t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
var x = line[i][0];
var y = line[i][1];
var dx = wrap(line[i + 1][0] - x) * this.kx;
var dy = (line[i + 1][1] - y) * this.ky;
var t = 0;
if (t > 1) {
x = line[i + 1][0];
y = line[i + 1][1];
if (dx !== 0 || dy !== 0) {
t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
} else if (t > 0) {
x += (dx / this.kx) * t;
y += (dy / this.ky) * t;
}
}
if (t > 1) {
x = line[i + 1][0];
y = line[i + 1][1];
dx = wrap(p[0] - x) * this.kx;
dy = (p[1] - y) * this.ky;
} else if (t > 0) {
x += (dx / this.kx) * t;
y += (dy / this.ky) * t;
const sqDist = dx * dx + dy * dy;
if (sqDist < minDist) {
minDist = sqDist;
minX = x;
minY = y;
minI = i;
minT = t;
}
}
return {
point: [minX, minY],
index: minI,
t: Math.max(0, Math.min(1, minT))
};
}
dx = wrap(p[0] - x) * this.kx;
dy = (p[1] - y) * this.ky;
/**
* Returns a part of the given line between the start and the stop points (or their closest points on the line).
*
* @param {[number, number]} start point [longitude, latitude]
* @param {[number, number]} stop point [longitude, latitude]
* @param {[number, number][]} line
* @returns {[number, number][]} line part of a line
* @example
* const line2 = ruler.lineSlice([-67.04, 50.5], [-67.05, 50.56], line1);
* //=line2
*/
lineSlice(start, stop, line) {
let p1 = this.pointOnLine(line, start);
let p2 = this.pointOnLine(line, stop);
var sqDist = dx * dx + dy * dy;
if (sqDist < minDist) {
minDist = sqDist;
minX = x;
minY = y;
minI = i;
minT = t;
}
}
if (p1.index > p2.index || (p1.index === p2.index && p1.t > p2.t)) {
const tmp = p1;
p1 = p2;
p2 = tmp;
}
return {
point: [minX, minY],
index: minI,
t: Math.max(0, Math.min(1, minT))
};
};
const slice = [p1.point];
/**
* Returns a part of the given line between the start and the stop points (or their closest points on the line).
*
* @param {Array<number>} start point [longitude, latitude]
* @param {Array<number>} stop point [longitude, latitude]
* @param {Array<Array<number>>} line
* @returns {Array<Array<number>>} line part of a line
* @example
* const line2 = ruler.lineSlice([-67.04, 50.5], [-67.05, 50.56], line1);
* //=line2
*/
CheapRuler.prototype.lineSlice = function lineSlice (start, stop, line) {
var p1 = this.pointOnLine(line, start);
var p2 = this.pointOnLine(line, stop);
const l = p1.index + 1;
const r = p2.index;
if (p1.index > p2.index || (p1.index === p2.index && p1.t > p2.t)) {
var tmp = p1;
p1 = p2;
p2 = tmp;
}
if (!equals(line[l], slice[0]) && l <= r)
slice.push(line[l]);
var slice = [p1.point];
for (let i = l + 1; i <= r; i++) {
slice.push(line[i]);
}
var l = p1.index + 1;
var r = p2.index;
if (!equals(line[r], p2.point))
slice.push(p2.point);
if (!equals(line[l], slice[0]) && l <= r)
{ slice.push(line[l]); }
return slice;
}
for (var i = l + 1; i <= r; i++) {
slice.push(line[i]);
}
/**
* Returns a part of the given line between the start and the stop points indicated by distance along the line.
*
* @param {number} start start distance
* @param {number} stop stop distance
* @param {[number, number][]} line
* @returns {[number, number][]} part of a line
* @example
* const line2 = ruler.lineSliceAlong(10, 20, line1);
* //=line2
*/
lineSliceAlong(start, stop, line) {
let sum = 0;
const slice = [];
if (!equals(line[r], p2.point))
{ slice.push(p2.point); }
for (let i = 0; i < line.length - 1; i++) {
const p0 = line[i];
const p1 = line[i + 1];
const d = this.distance(p0, p1);
return slice;
};
sum += d;
/**
* Returns a part of the given line between the start and the stop points indicated by distance along the line.
*
* @param {number} start distance
* @param {number} stop distance
* @param {Array<Array<number>>} line
* @returns {Array<Array<number>>} line part of a line
* @example
* const line2 = ruler.lineSliceAlong(10, 20, line1);
* //=line2
*/
CheapRuler.prototype.lineSliceAlong = function lineSliceAlong (start, stop, line) {
var sum = 0;
var slice = [];
if (sum > start && slice.length === 0) {
slice.push(interpolate(p0, p1, (start - (sum - d)) / d));
}
for (var i = 0; i < line.length - 1; i++) {
var p0 = line[i];
var p1 = line[i + 1];
var d = this.distance(p0, p1);
if (sum >= stop) {
slice.push(interpolate(p0, p1, (stop - (sum - d)) / d));
return slice;
}
sum += d;
if (sum > start) slice.push(p1);
}
if (sum > start && slice.length === 0) {
slice.push(interpolate(p0, p1, (start - (sum - d)) / d));
return slice;
}
if (sum >= stop) {
slice.push(interpolate(p0, p1, (stop - (sum - d)) / d));
return slice;
/**
* Given a point, returns a bounding box object ([w, s, e, n]) created from the given point buffered by a given distance.
*
* @param {[number, number]} p point [longitude, latitude]
* @param {number} buffer
* @returns {[number, number, number, number]} bbox ([w, s, e, n])
* @example
* const bbox = ruler.bufferPoint([30.5, 50.5], 0.01);
* //=bbox
*/
bufferPoint(p, buffer) {
const v = buffer / this.ky;
const h = buffer / this.kx;
return [
p[0] - h,
p[1] - v,
p[0] + h,
p[1] + v
];
}
if (sum > start) { slice.push(p1); }
/**
* Given a bounding box, returns the box buffered by a given distance.
*
* @param {[number, number, number, number]} bbox ([w, s, e, n])
* @param {number} buffer
* @returns {[number, number, number, number]} bbox ([w, s, e, n])
* @example
* const bbox = ruler.bufferBBox([30.5, 50.5, 31, 51], 0.2);
* //=bbox
*/
bufferBBox(bbox, buffer) {
const v = buffer / this.ky;
const h = buffer / this.kx;
return [
bbox[0] - h,
bbox[1] - v,
bbox[2] + h,
bbox[3] + v
];
}
/**
* Returns true if the given point is inside in the given bounding box, otherwise false.
*
* @param {[number, number]} p point [longitude, latitude]
* @param {[number, number, number, number]} bbox ([w, s, e, n])
* @returns {boolean}
* @example
* const inside = ruler.insideBBox([30.5, 50.5], [30, 50, 31, 51]);
* //=inside
*/
insideBBox(p, bbox) { // eslint-disable-line
return wrap(p[0] - bbox[0]) >= 0 &&
wrap(p[0] - bbox[2]) <= 0 &&
p[1] >= bbox[1] &&
p[1] <= bbox[3];
}
}
return slice;
};
/**
* @param {[number, number]} a
* @param {[number, number]} b
*/
function equals(a, b) {
return a[0] === b[0] && a[1] === b[1];
}
/**
* Given a point, returns a bounding box object ([w, s, e, n]) created from the given point buffered by a given distance.
*
* @param {Array<number>} p point [longitude, latitude]
* @param {number} buffer
* @returns {Array<number>} box object ([w, s, e, n])
* @example
* const bbox = ruler.bufferPoint([30.5, 50.5], 0.01);
* //=bbox
*/
CheapRuler.prototype.bufferPoint = function bufferPoint (p, buffer) {
var v = buffer / this.ky;
var h = buffer / this.kx;
return [
p[0] - h,
p[1] - v,
p[0] + h,
p[1] + v
];
};
/**
* @param {[number, number]} a
* @param {[number, number]} b
* @param {number} t
* @returns {[number, number]}
*/
function interpolate(a, b, t) {
const dx = wrap(b[0] - a[0]);
const dy = b[1] - a[1];
return [
a[0] + dx * t,
a[1] + dy * t
];
}
/**
* Given a bounding box, returns the box buffered by a given distance.
*
* @param {Array<number>} box object ([w, s, e, n])
* @param {number} buffer
* @returns {Array<number>} box object ([w, s, e, n])
* @example
* const bbox = ruler.bufferBBox([30.5, 50.5, 31, 51], 0.2);
* //=bbox
*/
CheapRuler.prototype.bufferBBox = function bufferBBox (bbox, buffer) {
var v = buffer / this.ky;
var h = buffer / this.kx;
return [
bbox[0] - h,
bbox[1] - v,
bbox[2] + h,
bbox[3] + v
];
};
/**
* normalize a degree value into [-180..180] range
* @param {number} deg
*/
function wrap(deg) {
while (deg < -180) deg += 360;
while (deg > 180) deg -= 360;
return deg;
}
/**
* Returns true if the given point is inside in the given bounding box, otherwise false.
*
* @param {Array<number>} p point [longitude, latitude]
* @param {Array<number>} box object ([w, s, e, n])
* @returns {boolean}
* @example
* const inside = ruler.insideBBox([30.5, 50.5], [30, 50, 31, 51]);
* //=inside
*/
CheapRuler.prototype.insideBBox = function insideBBox (p, bbox) {
return wrap(p[0] - bbox[0]) >= 0 &&
wrap(p[0] - bbox[2]) <= 0 &&
p[1] >= bbox[1] &&
p[1] <= bbox[3];
};
return CheapRuler;
Object.defineProperties( CheapRuler, staticAccessors );
function equals(a, b) {
return a[0] === b[0] && a[1] === b[1];
}
function interpolate(a, b, t) {
var dx = wrap(b[0] - a[0]);
var dy = b[1] - a[1];
return [
a[0] + dx * t,
a[1] + dy * t
];
}
// normalize a degree value into [-180..180] range
function wrap(deg) {
while (deg < -180) { deg += 360; }
while (deg > 180) { deg -= 360; }
return deg;
}
return CheapRuler;
}));

@@ -1,2 +0,1 @@

'use strict'; /* @flow */

@@ -23,9 +22,2 @@ const factors = {

* A collection of very fast approximations to common geodesic measurements. Useful for performance-sensitive code that measures things on a city scale.
*
* @param {number} lat latitude
* @param {string} [units='kilometers']
* @returns {CheapRuler}
* @example
* const ruler = cheapRuler(35.05, 'miles');
* //=ruler
*/

@@ -38,3 +30,3 @@ export default class CheapRuler {

* @param {number} z
* @param {string} [units='kilometers']
* @param {keyof typeof factors} [units='kilometers']
* @returns {CheapRuler}

@@ -66,4 +58,3 @@ * @example

* @param {number} lat latitude
* @param {string} [units='kilometers']
* @returns {CheapRuler}
* @param {keyof typeof factors} [units='kilometers']
* @example

@@ -91,4 +82,4 @@ * const ruler = cheapRuler(35.05, 'miles');

*
* @param {Array<number>} a point [longitude, latitude]
* @param {Array<number>} b point [longitude, latitude]
* @param {[number, number]} a point [longitude, latitude]
* @param {[number, number]} b point [longitude, latitude]
* @returns {number} distance

@@ -108,4 +99,4 @@ * @example

*
* @param {Array<number>} a point [longitude, latitude]
* @param {Array<number>} b point [longitude, latitude]
* @param {[number, number]} a point [longitude, latitude]
* @param {[number, number]} b point [longitude, latitude]
* @returns {number} bearing

@@ -125,6 +116,6 @@ * @example

*
* @param {Array<number>} p point [longitude, latitude]
* @param {[number, number]} p point [longitude, latitude]
* @param {number} dist distance
* @param {number} bearing
* @returns {Array<number>} point [longitude, latitude]
* @returns {[number, number]} point [longitude, latitude]
* @example

@@ -144,6 +135,6 @@ * const point = ruler.destination([30.5, 50.5], 0.1, 90);

*
* @param {Array<number>} p point [longitude, latitude]
* @param {[number, number]} p point [longitude, latitude]
* @param {number} dx easting
* @param {number} dy northing
* @returns {Array<number>} point [longitude, latitude]
* @returns {[number, number]} point [longitude, latitude]
* @example

@@ -163,3 +154,3 @@ * const point = ruler.offset([30.5, 50.5], 10, 10);

*
* @param {Array<Array<number>>} points [longitude, latitude]
* @param {[number, number][]} points [longitude, latitude]
* @returns {number} total line distance

@@ -184,3 +175,3 @@ * @example

*
* @param {Array<Array<Array<number>>>} polygon
* @param {[number, number][][]} polygon
* @returns {number} area value in the specified units (square kilometers by default)

@@ -211,5 +202,5 @@ * @example

*
* @param {Array<Array<number>>} line
* @param {[number, number][]} line
* @param {number} dist distance
* @returns {Array<number>} point [longitude, latitude]
* @returns {[number, number]} point [longitude, latitude]
* @example

@@ -239,5 +230,5 @@ * const point = ruler.along(line, 2.5);

* @pointToSegmentDistance
* @param {Array<number>} p point [longitude, latitude]
* @param {Array<number>} p1 segment point 1 [longitude, latitude]
* @param {Array<number>} p2 segment point 2 [longitude, latitude]
* @param {[number, number]} p point [longitude, latitude]
* @param {[number, number]} a segment point 1 [longitude, latitude]
* @param {[number, number]} b segment point 2 [longitude, latitude]
* @returns {number} distance

@@ -252,6 +243,5 @@ * @example

let dy = (b[1] - y) * this.ky;
let t = 0;
if (dx !== 0 || dy !== 0) {
t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
const t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);

@@ -279,5 +269,5 @@ if (t > 1) {

*
* @param {Array<Array<number>>} line
* @param {Array<number>} p point [longitude, latitude]
* @returns {Object} {point, index, t}
* @param {[number, number][]} line
* @param {[number, number]} p point [longitude, latitude]
* @returns {{point: [number, number], index: number, t: number}} {point, index, t}
* @example

@@ -289,3 +279,6 @@ * const point = ruler.pointOnLine(line, [-67.04, 50.5]).point;

let minDist = Infinity;
let minX, minY, minI, minT;
let minX = line[0][0];
let minY = line[0][1];
let minI = 0;
let minT = 0;

@@ -336,6 +329,6 @@ for (let i = 0; i < line.length - 1; i++) {

*
* @param {Array<number>} start point [longitude, latitude]
* @param {Array<number>} stop point [longitude, latitude]
* @param {Array<Array<number>>} line
* @returns {Array<Array<number>>} line part of a line
* @param {[number, number]} start point [longitude, latitude]
* @param {[number, number]} stop point [longitude, latitude]
* @param {[number, number][]} line
* @returns {[number, number][]} line part of a line
* @example

@@ -376,6 +369,6 @@ * const line2 = ruler.lineSlice([-67.04, 50.5], [-67.05, 50.56], line1);

*
* @param {number} start distance
* @param {number} stop distance
* @param {Array<Array<number>>} line
* @returns {Array<Array<number>>} line part of a line
* @param {number} start start distance
* @param {number} stop stop distance
* @param {[number, number][]} line
* @returns {[number, number][]} part of a line
* @example

@@ -414,5 +407,5 @@ * const line2 = ruler.lineSliceAlong(10, 20, line1);

*
* @param {Array<number>} p point [longitude, latitude]
* @param {[number, number]} p point [longitude, latitude]
* @param {number} buffer
* @returns {Array<number>} box object ([w, s, e, n])
* @returns {[number, number, number, number]} bbox ([w, s, e, n])
* @example

@@ -436,5 +429,5 @@ * const bbox = ruler.bufferPoint([30.5, 50.5], 0.01);

*
* @param {Array<number>} box object ([w, s, e, n])
* @param {[number, number, number, number]} bbox ([w, s, e, n])
* @param {number} buffer
* @returns {Array<number>} box object ([w, s, e, n])
* @returns {[number, number, number, number]} bbox ([w, s, e, n])
* @example

@@ -458,4 +451,4 @@ * const bbox = ruler.bufferBBox([30.5, 50.5, 31, 51], 0.2);

*
* @param {Array<number>} p point [longitude, latitude]
* @param {Array<number>} box object ([w, s, e, n])
* @param {[number, number]} p point [longitude, latitude]
* @param {[number, number, number, number]} bbox ([w, s, e, n])
* @returns {boolean}

@@ -466,3 +459,3 @@ * @example

*/
insideBBox(p, bbox) {
insideBBox(p, bbox) { // eslint-disable-line
return wrap(p[0] - bbox[0]) >= 0 &&

@@ -475,2 +468,6 @@ wrap(p[0] - bbox[2]) <= 0 &&

/**
* @param {[number, number]} a
* @param {[number, number]} b
*/
function equals(a, b) {

@@ -480,2 +477,8 @@ return a[0] === b[0] && a[1] === b[1];

/**
* @param {[number, number]} a
* @param {[number, number]} b
* @param {number} t
* @returns {[number, number]}
*/
function interpolate(a, b, t) {

@@ -490,3 +493,6 @@ const dx = wrap(b[0] - a[0]);

// normalize a degree value into [-180..180] range
/**
* normalize a degree value into [-180..180] range
* @param {number} deg
*/
function wrap(deg) {

@@ -493,0 +499,0 @@ while (deg < -180) deg += 360;

{
"name": "cheap-ruler",
"version": "3.0.2",
"version": "4.0.0",
"description": "A collection of fast approximations to common geographic measurements.",
"author": "Vladimir Agafonkin",
"license": "ISC",
"type": "module",
"main": "cheap-ruler.js",
"exports": "./index.js",
"module": "index.js",
"jsdelivr": "cheap-ruler.min.js",
"unpkg": "cheap-ruler.min.js",
"types": "cheap-ruler.d.ts",
"dependencies": {},
"types": "index.d.ts",
"devDependencies": {
"@rollup/plugin-buble": "^0.21.3",
"@turf/turf": "^6.5.0",
"@turf/turf": "^7.0.0",
"benchmark": "^2.1.4",
"eslint": "^8.2.0",
"eslint-config-mourner": "^3.0.0",
"esm": "^3.2.25",
"eslint": "^9.5.0",
"eslint-config-mourner": "^4.0.0",
"node-vincenty": "0.0.6",
"nyc": "^15.1.0",
"rollup": "^2.60.0",
"rollup-plugin-terser": "^7.0.2",
"tape": "^5.3.2",
"ts-node": "^10.4.0",
"typescript": "^4.4.4"
"rollup": "^4.18.0",
"typescript": "^5.5.2"
},
"scripts": {
"pretest": "eslint index.js bench test/*.js",
"test": "tape -r esm test/test.js",
"posttest": "npm run build && npm run types",
"types": "ts-node test/types.ts",
"build": "rollup -c",
"prepublishOnly": "npm test",
"cov": "nyc tape test/test.js"
"test": "tsc && node --test test/test.js",
"build": "rollup index.js -o cheap-ruler.js -n CheapRuler -f umd",
"prepublishOnly": "npm test && npm run build",
"cov": "node --test --experimental-test-coverage test/test.js"
},
"files": [
"index.js",
"cheap-ruler.js",
"cheap-ruler.min.js",
"cheap-ruler.d.ts"
"index.d.ts",
"cheap-ruler.js"
],
"eslintConfig": {
"extends": "mourner"
},
"repository": {

@@ -53,9 +42,3 @@ "type": "git",

"distance"
],
"author": "Vladimir Agafonkin",
"license": "ISC",
"bugs": {
"url": "https://github.com/mapbox/cheap-ruler/issues"
},
"homepage": "https://github.com/mapbox/cheap-ruler#readme"
]
}

@@ -1,2 +0,2 @@

# cheap-ruler [![Build Status](https://travis-ci.org/mapbox/cheap-ruler.svg?branch=master)](https://travis-ci.org/mapbox/cheap-ruler) [![](https://img.shields.io/badge/simply-awesome-brightgreen.svg)](https://github.com/mourner/projects)
# cheap-ruler [![Node](https://github.com/mapbox/cheap-ruler/actions/workflows/node.yml/badge.svg)](https://github.com/mapbox/cheap-ruler/actions/workflows/node.yml) [![](https://img.shields.io/badge/simply-awesome-brightgreen.svg)](https://github.com/mourner/projects)

@@ -195,4 +195,4 @@ A collection of very fast approximations to common geodesic measurements.

- NPM: `npm install cheap-ruler`
- [Browser build on CDN](https://unpkg.com/cheap-ruler@3.0.1/cheap-ruler.js)
- [Browser build on CDN (minified)](https://unpkg.com/cheap-ruler@3.0.1/cheap-ruler.min.js)
- [Browser build on CDN (ESM)](https://esm.run/cheap-ruler)
- [Browser build on CDN (UMD)](https://cdn.jsdelivr.net/npm/cheap-ruler/cheap-ruler.js)

@@ -199,0 +199,0 @@ ## Precision

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc