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

cheap-ruler

Package Overview
Dependencies
Maintainers
1
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 2.1.0 to 2.2.0

53

cheap-ruler.js

@@ -19,7 +19,13 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cheapRuler = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

// units per degree on equator
this.d = (units === 'miles' ? 24901.55 : 40075.16) / 360;
var f = lat * Math.PI / 180;
// longitude correction based on latitude
this.e = Math.cos(lat * Math.PI / 180);
// multiplier for unit conversion
var m = units === 'miles' ? 1.609344 :
units === 'meters' ? 1000 : 1;
// longitude correction
this.kx = m * (111.41513 * Math.cos(f) - 0.09455 * Math.cos(3 * f) + 0.00012 * Math.cos(5 * f));
// latitude correction
this.ky = m * (111.13209 - 0.56605 * Math.cos(2 * f) + 0.0012 * Math.cos(4 * f));
}

@@ -29,10 +35,10 @@

distance: function (a, b) {
var dx = (a[0] - b[0]) * this.e;
var dy = a[1] - b[1];
return Math.sqrt(dx * dx + dy * dy) * this.d;
var dx = (a[0] - b[0]) * this.kx;
var dy = (a[1] - b[1]) * this.ky;
return Math.sqrt(dx * dx + dy * dy);
},
bearing: function (a, b) {
var dx = (b[0] - a[0]) * this.e;
var dy = b[1] - a[1];
var dx = (b[0] - a[0]) * this.kx;
var dy = (b[1] - a[1]) * this.ky;
if (!dx && !dy) return 0;

@@ -46,6 +52,5 @@ var bearing = Math.atan2(-dy, dx) * 180 / Math.PI + 90;

var a = (90 - bearing) * Math.PI / 180;
var d = dist / this.d;
return [
p[0] + d * Math.cos(a) / this.e,
p[1] + d * Math.sin(a)
p[0] + Math.cos(a) * dist / this.kx,
p[1] + Math.sin(a) * dist / this.ky
];

@@ -73,3 +78,3 @@ },

return (Math.abs(sum) / 2) * this.e * this.d * this.d;
return (Math.abs(sum) / 2) * this.kx * this.ky;
},

@@ -101,8 +106,8 @@

var y = line[i][1];
var dx = (line[i + 1][0] - x) * this.e;
var dy = line[i + 1][1] - y;
var dx = (line[i + 1][0] - x) * this.kx;
var dy = (line[i + 1][1] - y) * this.ky;
if (dx !== 0 || dy !== 0) {
var t = ((p[0] - x) * this.e * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
var t = ((p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);

@@ -114,9 +119,9 @@ if (t > 1) {

} else if (t > 0) {
x += dx * t / this.e;
y += dy * t;
x += (dx / this.kx) * t;
y += (dy / this.ky) * t;
}
}
dx = (p[0] - x) * this.e;
dy = p[1] - y;
dx = (p[0] - x) * this.kx;
dy = (p[1] - y) * this.ky;

@@ -195,4 +200,4 @@ var sqDist = dx * dx + dy * dy;

bufferPoint: function (p, buffer) {
var v = buffer / this.d;
var h = v / this.e;
var v = buffer / this.ky;
var h = buffer / this.kx;
return [

@@ -207,4 +212,4 @@ p[0] - h,

bufferBBox: function (bbox, buffer) {
var v = buffer / this.d;
var h = v / this.e;
var v = buffer / this.ky;
var h = buffer / this.kx;
return [

@@ -211,0 +216,0 @@ bbox[0] - h,

@@ -17,3 +17,3 @@ 'use strict';

var distances = [1, 100, 1000, 5000];
var distances = [1, 100, 500, 1000, 5000];

@@ -27,7 +27,8 @@ for (var i = 0; i < distances.length; i++) {

var p1 = ruler.destination([0, lat], dist / 2, 90);
var p2 = ruler.destination([0, lat], dist / 2, 90 - 180);
var p1 = ruler.destination([0, lat], dist / 2, 45);
var p2 = ruler.destination([0, lat], dist / 2, 45 - 180);
var d = ruler.distance(p1, p2);
var d2 = turf.distance(turf.point(p1), turf.point(p2));
// var d2 = vincenty.distVincenty(p1[1], p1[0], p2[1], p2[0]).distance / 1000;
// var d = turf.distance(turf.point(p1), turf.point(p2));
// var d = fccDist(p1, p2, lat);
var d2 = vincenty.distVincenty(p1[1], p1[0], p2[1], p2[0]).distance / 1000;
var err = Math.abs((d - d2) / d2);

@@ -42,1 +43,11 @@ var errStr = (Math.round(100 * 1e2 * err) / 1e2) + '%';

}
function fccDist(a, b, lat) {
var f = lat * Math.PI / 180;
var k1 = 111.13209 - 0.56605 * Math.cos(2 * f) + 0.0012 * Math.cos(4 * f);
var k2 = 111.41513 * Math.cos(f) - 0.09455 * Math.cos(3 * f) + 0.00012 * Math.cos(5 * f);
var dy = k1 * (a[1] - b[1]);
var dx = k2 * (a[0] - b[0]);
return Math.sqrt(dx * dx + dy * dy);
}

@@ -18,7 +18,13 @@ 'use strict';

// units per degree on equator
this.d = (units === 'miles' ? 24901.55 : 40075.16) / 360;
var f = lat * Math.PI / 180;
// longitude correction based on latitude
this.e = Math.cos(lat * Math.PI / 180);
// multiplier for unit conversion
var m = units === 'miles' ? 1.609344 :
units === 'meters' ? 1000 : 1;
// longitude correction
this.kx = m * (111.41513 * Math.cos(f) - 0.09455 * Math.cos(3 * f) + 0.00012 * Math.cos(5 * f));
// latitude correction
this.ky = m * (111.13209 - 0.56605 * Math.cos(2 * f) + 0.0012 * Math.cos(4 * f));
}

@@ -28,10 +34,10 @@

distance: function (a, b) {
var dx = (a[0] - b[0]) * this.e;
var dy = a[1] - b[1];
return Math.sqrt(dx * dx + dy * dy) * this.d;
var dx = (a[0] - b[0]) * this.kx;
var dy = (a[1] - b[1]) * this.ky;
return Math.sqrt(dx * dx + dy * dy);
},
bearing: function (a, b) {
var dx = (b[0] - a[0]) * this.e;
var dy = b[1] - a[1];
var dx = (b[0] - a[0]) * this.kx;
var dy = (b[1] - a[1]) * this.ky;
if (!dx && !dy) return 0;

@@ -45,6 +51,5 @@ var bearing = Math.atan2(-dy, dx) * 180 / Math.PI + 90;

var a = (90 - bearing) * Math.PI / 180;
var d = dist / this.d;
return [
p[0] + d * Math.cos(a) / this.e,
p[1] + d * Math.sin(a)
p[0] + Math.cos(a) * dist / this.kx,
p[1] + Math.sin(a) * dist / this.ky
];

@@ -72,3 +77,3 @@ },

return (Math.abs(sum) / 2) * this.e * this.d * this.d;
return (Math.abs(sum) / 2) * this.kx * this.ky;
},

@@ -100,8 +105,8 @@

var y = line[i][1];
var dx = (line[i + 1][0] - x) * this.e;
var dy = line[i + 1][1] - y;
var dx = (line[i + 1][0] - x) * this.kx;
var dy = (line[i + 1][1] - y) * this.ky;
if (dx !== 0 || dy !== 0) {
var t = ((p[0] - x) * this.e * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
var t = ((p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);

@@ -113,9 +118,9 @@ if (t > 1) {

} else if (t > 0) {
x += dx * t / this.e;
y += dy * t;
x += (dx / this.kx) * t;
y += (dy / this.ky) * t;
}
}
dx = (p[0] - x) * this.e;
dy = p[1] - y;
dx = (p[0] - x) * this.kx;
dy = (p[1] - y) * this.ky;

@@ -194,4 +199,4 @@ var sqDist = dx * dx + dy * dy;

bufferPoint: function (p, buffer) {
var v = buffer / this.d;
var h = v / this.e;
var v = buffer / this.ky;
var h = buffer / this.kx;
return [

@@ -206,4 +211,4 @@ p[0] - h,

bufferBBox: function (bbox, buffer) {
var v = buffer / this.d;
var h = v / this.e;
var v = buffer / this.ky;
var h = buffer / this.kx;
return [

@@ -210,0 +215,0 @@ bbox[0] - h,

{
"name": "cheap-ruler",
"version": "2.1.0",
"version": "2.2.0",
"description": "A collection of fast approximations to common geographic measurements.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -7,4 +7,7 @@ # cheap-ruler [![Build Status](https://travis-ci.org/mapbox/cheap-ruler.svg?branch=master)](https://travis-ci.org/mapbox/cheap-ruler)

For distances under a hundred miles and not on the poles,
the results are [typically within 0.1%](#precision) of corresponding Turf functions.
The approximations are based on an [FCC-approved formula of ellipsoidal Earth projection](https://www.gpo.gov/fdsys/pkg/CFR-2005-title47-vol4/pdf/CFR-2005-title47-vol4-sec73-208.pdf).
For distances under 500 kilometers and not on the poles,
the results are very precise — within [0.1% margin of error](#precision)
compared to [Vincenti formulas](https://en.wikipedia.org/wiki/Vincenty%27s_formulae),
and usually much less for shorter distances.

@@ -172,18 +175,12 @@ ## Performance

A table that shows the margin of error for `ruler.distance` compared to `turf.distance`:
A table that shows the margin of error for `ruler.distance` compared to `node-vincenty`
(a state of the art distance formula):
| lat | 0&deg; | 10&deg; | 20&deg; | 30&deg; | 40&deg; | 50&deg; | 60&deg; | 70&deg; | 80&deg; |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 1km | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% |
| 100km | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.08% | 0.09% | 0.11% |
| 1000km | 0.11% | 0.11% | 0.12% | 0.14% | 0.18% | 0.25% | 0.42% | 0.89% | 3.48% |
| 1km | 0% | 0% | 0% | 0% | 0% | 0% | 0% | 0% | 0% |
| 100km | 0% | 0% | 0% | 0% | 0% | 0% | 0.01% | 0.01% | 0.04% |
| 500km | 0% | 0% | 0% | 0.01% | 0.02% | 0.04% | 0.08% | 0.2% | 0.83% |
| 1000km | 0% | 0% | 0.02% | 0.04% | 0.07% | 0.15% | 0.31% | 0.78% | 3.36% |
The same table for a much more precise Vincenty distance formula (using `node-vincenty` module):
| lat | 0&deg; | 10&deg; | 20&deg; | 30&deg; | 40&deg; | 50&deg; | 60&deg; | 70&deg; | 80&deg; |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 1km | 0.34% | 0.32% | 0.26% | 0.17% | 0.06% | 0.06% | 0.17% | 0.26% | 0.31% |
| 100km | 0.34% | 0.32% | 0.26% | 0.17% | 0.06% | 0.06% | 0.16% | 0.25% | 0.28% |
| 1000km | 0.36% | 0.34% | 0.3% | 0.23% | 0.16% | 0.11% | 0.17% | 0.55% | 3.08% |
Errors for all other methods are similar.

@@ -29,5 +29,5 @@ 'use strict';

var actual = ruler.distance(points[i], points[i + 1]);
assertErr(t, expected, actual, 0.001, 'distance');
assertErr(t, expected, actual, 0.003, 'distance');
}
t.pass('distance within 0.1%');
t.pass('distance within 0.3%');
t.end();

@@ -40,5 +40,5 @@ });

var actual = ruler.bearing(points[i], points[i + 1]);
assertErr(t, expected, actual, 0.0001, 'bearing');
assertErr(t, expected, actual, 0.005, 'bearing');
}
t.pass('bearing within 0.01%');
t.pass('bearing within 0.05%');
t.end();

@@ -52,6 +52,6 @@ });

var actual = ruler.destination(points[i], 1.0, bearing);
assertErr(t, expected[0], actual[0], 3e-7, 'destination longitude');
assertErr(t, expected[1], actual[1], 3e-7, 'destination latitude');
assertErr(t, expected[0], actual[0], 1e-6, 'destination longitude');
assertErr(t, expected[1], actual[1], 1e-6, 'destination latitude');
}
t.pass('destination within 3e-7');
t.pass('destination within 1e-6');
t.end();

@@ -64,5 +64,5 @@ });

var actual = ruler.lineDistance(lines[i]);
assertErr(t, expected, actual, 0.001, 'lineDistance');
assertErr(t, expected, actual, 0.003, 'lineDistance');
}
t.pass('lineDistance within 0.1%');
t.pass('lineDistance within 0.3%');
t.end();

@@ -77,5 +77,5 @@ });

var actual = ruler.area([lines[i]]);
assertErr(t, expected, actual, 0.0002, 'area');
assertErr(t, expected, actual, 0.003, 'area');
}
t.pass('area within 0.02%');
t.pass('area within 0.3%');
t.end();

@@ -90,6 +90,6 @@ });

var actual = ruler.along(lines[i], dist);
assertErr(t, expected[0], actual[0], 2e-7, 'along longitude');
assertErr(t, expected[1], actual[1], 2e-7, 'along latitude');
assertErr(t, expected[0], actual[0], 1e-6, 'along longitude');
assertErr(t, expected[1], actual[1], 1e-6, 'along latitude');
}
t.pass('lineDistance within 0.1%');
t.pass('along point within 1e-6');
t.end();

@@ -112,3 +112,3 @@ });

var p = ruler.pointOnLine(line, [-77.034076, 38.882017]).point;
t.same(p, [-77.03051972665213, 38.88046894284234], 'pointOnLine');
t.same(p, [-77.03052697027461, 38.880457194811896], 'pointOnLine');
t.end();

@@ -128,7 +128,8 @@ });

turf.point(start), turf.point(stop), turf.linestring(line)).geometry.coordinates);
var actual = ruler.lineDistance(ruler.lineSlice(start, stop, line));
assertErr(t, expected, actual, 0.001, 'lineSlice length');
assertErr(t, expected, actual, 0, 'lineSlice length');
}
t.pass('lineSlice length within 0.1%');
t.pass('lineSlice length the same');
t.end();

@@ -150,5 +151,5 @@ });

assertErr(t, expected, actual, 0.001, 'lineSliceAlong length');
assertErr(t, expected, actual, 1e-10, 'lineSliceAlong length');
}
t.pass('lineSliceAlong length within 0.1%');
t.pass('lineSliceAlong length within 1e-10');
t.end();

@@ -163,3 +164,3 @@ });

var actual = ruler.lineDistance(ruler.lineSlice(start, stop, line));
t.equal(actual, 0.018665535420681036, 'lineSlice reversed length');
t.equal(actual, 0.018676802802910702, 'lineSlice reversed length');
t.end();

@@ -170,10 +171,10 @@ });

for (var i = 0; i < points.length; i++) {
var expected = turfPointBuffer(points[i], 0.01);
var actual = milesRuler.bufferPoint(points[i], 0.01);
assertErr(t, expected[0], actual[0], 1e-8, 'bufferPoint west');
assertErr(t, expected[1], actual[1], 1e-8, 'bufferPoint east');
assertErr(t, expected[2], actual[2], 1e-8, 'bufferPoint south');
assertErr(t, expected[3], actual[3], 1e-8, 'bufferPoint north');
var expected = turfPointBuffer(points[i], 0.1);
var actual = milesRuler.bufferPoint(points[i], 0.1);
assertErr(t, expected[0], actual[0], 3e-5, 'bufferPoint west');
assertErr(t, expected[1], actual[1], 3e-5, 'bufferPoint east');
assertErr(t, expected[2], actual[2], 3e-5, 'bufferPoint south');
assertErr(t, expected[3], actual[3], 3e-5, 'bufferPoint north');
}
t.pass('point buffer error within 1e-8');
t.pass('point buffer error within 3e-5');
t.end();

@@ -185,3 +186,3 @@ });

var bbox2 = ruler.bufferBBox(bbox, 1);
t.same(bbox2, [29.989308794440007, 37.991016879283826, 40.01069120555999, 39.008983120716174], 'bufferBBox');
t.same(bbox2, [29.989319515875376, 37.99098271225711, 40.01068048412462, 39.00901728774289], 'bufferBBox');
t.end();

@@ -188,0 +189,0 @@ });

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