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

arc

Package Overview
Dependencies
Maintainers
2
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

arc - npm Package Compare versions

Comparing version 0.0.3 to 0.1.0

.jshintrc

138

arc.js

@@ -0,1 +1,3 @@

'use strict';
var D2R = Math.PI / 180;

@@ -16,9 +18,4 @@ var R2D = 180 / Math.PI;

Coord.prototype.antipode = function() {
var anti_lat = -1 * this.lat;
if (this.lon < 0) {
var anti_lon = 180 + this.lon;
} else {
var anti_lon = (180 - this.lon) * -1;
}
var anti_lon = (this.lon < 0) ? 180 + this.lon : (180 - this.lon) * -1;
return new Coord(anti_lon, anti_lat);

@@ -39,3 +36,3 @@ };

this.properties = properties || {};
this.geometries = []
this.geometries = [];
};

@@ -53,4 +50,4 @@

} else {
var multiline = []
for (i = 0; i < this.geometries.length; i++) {
var multiline = [];
for (var i = 0; i < this.geometries.length; i++) {
multiline.push(this.geometries[i].coords);

@@ -67,10 +64,10 @@ }

var wkt_string = '';
for (i = 0; i < this.geometries.length; i++) {
var wkt = 'LINESTRING(';
var collect = function(c) { wkt += c[0] + ' ' + c[1] + ','; };
for (var i = 0; i < this.geometries.length; i++) {
if (this.geometries[i].coords.length === 0) {
return 'LINESTRING(empty)';
} else {
var wkt = 'LINESTRING(';
this.geometries[i].coords.forEach(function(c,idx) {
wkt += c[0] + ' ' + c[1] + ',';
});
var coords = this.geometries[i].coords;
coords.forEach(collect);
wkt_string += wkt.substring(0, wkt.length - 1) + ')';

@@ -87,5 +84,10 @@ }

var GreatCircle = function(start,end,properties) {
this.start = start;
this.end = end;
if (!start || start.x === undefined || start.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
if (!end || end.x === undefined || end.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
this.start = new Coord(start.x,start.y);
this.end = new Coord(end.x,end.y);
this.properties = properties || {};

@@ -129,4 +131,2 @@

var first_pass = [];
//var minx = 0;
//var maxx = 0;
if (!npoints || npoints <= 2) {

@@ -137,7 +137,5 @@ first_pass.push([this.start.lon, this.start.lat]);

var delta = 1.0 / (npoints - 1);
for (var i = 0; i < npoints; i++) {
for (var i = 0; i < npoints; ++i) {
var step = delta * i;
var pair = this.interpolate(step);
//minx = Math.min(minx,pair[0]);
//maxx = Math.max(maxx,pair[0]);
first_pass.push(pair);

@@ -153,10 +151,17 @@ }

var dfMaxSmallDiffLong = 0;
for (var i = 1; i < first_pass.length; i++) {
//if (minx > 170 && maxx > 180) {
// }
var dfPrevX = first_pass[i-1][0];
var dfX = first_pass[i][0];
// from http://www.gdal.org/ogr2ogr.html
// -datelineoffset:
// (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be splited)
var dfDateLineOffset = options && options.offset ? options.offset : 10;
var dfLeftBorderX = 180 - dfDateLineOffset;
var dfRightBorderX = -180 + dfDateLineOffset;
var dfDiffSpace = 360 - dfDateLineOffset;
// https://github.com/OSGeo/gdal/blob/7bfb9c452a59aac958bff0c8386b891edf8154ca/gdal/ogr/ogrgeometryfactory.cpp#L2342
for (var j = 1; j < first_pass.length; ++j) {
var dfPrevX = first_pass[j-1][0];
var dfX = first_pass[j][0];
var dfDiffLong = Math.abs(dfX - dfPrevX);
if (dfDiffLong > 350 &&
((dfX > 170 && dfPrevX < -170) || (dfPrevX > 170 && dfX < -170))) {
if (dfDiffLong > dfDiffSpace &&
((dfX > dfLeftBorderX && dfPrevX < dfRightBorderX) || (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX))) {
bHasBigDiff = true;

@@ -168,33 +173,32 @@ } else if (dfDiffLong > dfMaxSmallDiffLong) {

var poMulti = []
if (bHasBigDiff && dfMaxSmallDiffLong < 10) {
var poNewLS = []
var poMulti = [];
if (bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset) {
var poNewLS = [];
poMulti.push(poNewLS);
for (var i = 0; i < first_pass.length; i++) {
var dfX = parseFloat(first_pass[i][0]);
if (i > 0 && Math.abs(dfX - first_pass[i-1][0]) > 350) {
var dfX1 = parseFloat(first_pass[i-1][0]);
var dfY1 = parseFloat(first_pass[i-1][1]);
var dfX2 = parseFloat(first_pass[i][0]);
var dfY2 = parseFloat(first_pass[i][1]);
if (dfX1 > -180 && dfX1 < -170 && dfX2 == 180 &&
i+1 < first_pass.length &&
first_pass[i-1][0] > -180 && first_pass[i-1][0] < -170)
for (var k = 0; k < first_pass.length; ++k) {
var dfX0 = parseFloat(first_pass[k][0]);
if (k > 0 && Math.abs(dfX0 - first_pass[k-1][0]) > dfDiffSpace) {
var dfX1 = parseFloat(first_pass[k-1][0]);
var dfY1 = parseFloat(first_pass[k-1][1]);
var dfX2 = parseFloat(first_pass[k][0]);
var dfY2 = parseFloat(first_pass[k][1]);
if (dfX1 > -180 && dfX1 < dfRightBorderX && dfX2 == 180 &&
k+1 < first_pass.length &&
first_pass[k-1][0] > -180 && first_pass[k-1][0] < dfRightBorderX)
{
poNewLS.push([-180, first_pass[i][1]]);
i++;
poNewLS.push([first_pass[i][0], first_pass[i][1]]);
poNewLS.push([-180, first_pass[k][1]]);
k++;
poNewLS.push([first_pass[k][0], first_pass[k][1]]);
continue;
} else if (dfX1 > 170 && dfX1 < 180 && dfX2 == -180 &&
i+1 < first_pass.length &&
first_pass[i-1][0] > 170 && first_pass[i-1][0] < 180)
} else if (dfX1 > dfLeftBorderX && dfX1 < 180 && dfX2 == -180 &&
k+1 < first_pass.length &&
first_pass[k-1][0] > dfLeftBorderX && first_pass[k-1][0] < 180)
{
poNewLS.push([180, first_pass[i][1]]);
i++;
poNewLS.push([first_pass[i][0], first_pass[i][1]]);
poNewLS.push([180, first_pass[k][1]]);
k++;
poNewLS.push([first_pass[k][0], first_pass[k][1]]);
continue;
}
if (dfX1 < -170 && dfX2 > 170)
if (dfX1 < dfRightBorderX && dfX2 > dfLeftBorderX)
{

@@ -210,3 +214,3 @@ // swap dfX1, dfX2

}
if (dfX1 > 170 && dfX2 < -170) {
if (dfX1 > dfLeftBorderX && dfX2 < dfRightBorderX) {
dfX2 += 360;

@@ -219,5 +223,5 @@ }

var dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
poNewLS.push([first_pass[i-1][0] > 170 ? 180 : -180, dfY]);
poNewLS.push([first_pass[k-1][0] > dfLeftBorderX ? 180 : -180, dfY]);
poNewLS = [];
poNewLS.push([first_pass[i-1][0] > 170 ? -180 : 180, dfY]);
poNewLS.push([first_pass[k-1][0] > dfLeftBorderX ? -180 : 180, dfY]);
poMulti.push(poNewLS);

@@ -230,13 +234,13 @@ }

}
poNewLS.push([dfX, first_pass[i][1]]);
poNewLS.push([dfX0, first_pass[k][1]]);
} else {
poNewLS.push([first_pass[i][0], first_pass[i][1]]);
poNewLS.push([first_pass[k][0], first_pass[k][1]]);
}
}
} else {
// add normally
var poNewLS = []
poMulti.push(poNewLS);
for (var i = 0; i < first_pass.length; i++) {
poNewLS.push([first_pass[i][0],first_pass[i][1]]);
// add normally
var poNewLS0 = [];
poMulti.push(poNewLS0);
for (var l = 0; l < first_pass.length; ++l) {
poNewLS0.push([first_pass[l][0],first_pass[l][1]]);
}

@@ -246,8 +250,8 @@ }

var arc = new Arc(this.properties);
for (var i = 0; i < poMulti.length; i++) {
for (var m = 0; m < poMulti.length; ++m) {
var line = new LineString();
arc.geometries.push(line);
var points = poMulti[i];
for (var j = 0; j < points.length; j++) {
line.move_to(points[j]);
var points = poMulti[m];
for (var j0 = 0; j0 < points.length; ++j0) {
line.move_to(points[j0]);
}

@@ -254,0 +258,0 @@ }

{
"name": "arc",
"version": "0.0.3",
"version": "0.1.0",
"description": "draw great circle arcs",
"url": "https://github.com/springmeyer/arc.js",
"keywords": [
"maps",
"spherical",
"globe",
"rhumb line",
"crow flies",
"great circle"
"maps",
"spherical",
"globe",
"rhumb line",
"crow flies",
"great circle"
],
"contributors": [
"Dane Springmeyer <dane@dbsgeo.com>"
"Dane Springmeyer <dane@dbsgeo.com>"
],
"repository" : {
"type" : "git",
"url" : "git://github.com/springmeyer/arc.js.git"
"repository": {
"type": "git",
"url": "git://github.com/springmeyer/arc.js.git"
},
"licenses": [{
"licenses": [
{
"type": "BSD"
}],
}
],
"main": "./index",
"engines": {
"node": ">=0.4.0"
"node": ">=0.4.0"
},
"scripts" : {
"test" : "mocha -R spec"
"scripts": {
"test": "mocha -R spec"
},
"devDependencies": {
"mocha": "~1.17.1"
}
}
# arc.js
Calculate great circles routes.
Calculate great circles routes as lines in GeoJSON or WKT format.
Algorithms from http://williams.best.vwh.net/avform.htm#Intermediate
Includes basic support for splitting lines that cross the dateline, based on
a partial port of code from OGR.
# Installation
For NodeJS usage, install with npm:
npm install -g
# Usage

@@ -25,4 +21,5 @@

The API works like so:
# API
**1)** Create start and end coordinates

@@ -32,6 +29,6 @@

var start = new arc.Coord(-122, 48);
var end = new arc.Coord(-77, 39);
var start = { x: -122, y: 48 };
var end = { x: -77, y: 39 };
These are `[lon,lat]` pairs like GeoJSON. Be aware that Leaflet uses `[lat,lon]` order [currently](https://github.com/Leaflet/Leaflet/issues/1455).
Note that `x` here is longitude in degrees and `y` is latitude in degrees.

@@ -42,14 +39,11 @@ **2)** Create GreatCircle object

var gc = new arc.GreatCircle(start, end, {'name': 'Seattle to DC'});
var generator = new arc.GreatCircle(start, end, {'name': 'Seattle to DC'});
**3)** Generate a line
**3)** Generate a line arc
Then call the `Arc` function to generate a line:
Then call the `Arc` function on the `GreatCircle` object to generate a line:
var npoints = 6;
var line = gc.Arc(npoints);
var line = generator.Arc(100,{offset:10});
The `npoints` argument specifies the number of intermediate vertices you want in the resulting line. The higher the number the more dense and accurate the line will be.
Then `line` will be a raw sequence of the start and end coordinates plus an arc of
The `line` will be a raw sequence of the start and end coordinates plus an arc of
intermediate coordinate pairs.

@@ -68,4 +62,12 @@

You can then serialize to a GeoJSON geometry:
#### Arc options
The first argument to `Arc` specifies the number of intermediate vertices you want in the resulting line. The higher the number the more dense and accurate the line will be.
The second argument is an optional object to declare options. The `offset` option controls the likelyhood that lines will be split which cross the dateline. The higher the number the more likely. The default value is 10, which means lines within 10 degress of the dateline will be split. For lines that cross and dateline and are also near the poles you will likely need a higher value to trigger splitting. It is unclear to me (@springmeyer) what the drawbacks are of high offsets. I simply ported the code from OGR's `gdal/ogr/ogrgeometryfactory.cpp` and have not taken the time to fully comprehend how it works.
**4)** Convert line to GeoJSON geometry
To serialize to a GeoJSON geometry:
> line.json();

@@ -77,3 +79,2 @@ { geometry:

properties: { name: 'Seattle to DC' } }

@@ -84,4 +85,3 @@ Or to WKT (Well known text):

'LINESTRING(-122 48.00000000000001,-112.06161978373486 47.7241672604096,-102.38404317022653 46.60813199882492,-93.22718895342909 44.716217302635705,-84.74823988299501 42.14415510795357,-77 38.99999999999999)'
It is then up to you to add up these features to create fully fledged geodata. See the examples/ directory for sample code to create GeoJSON feature collection from multiple routes.

@@ -0,6 +1,8 @@

'use strict';
var arc = require('../');
var assert = require('assert');
describe('Arc.js', function() {
it('should be able to create an arc.Coord', function() {
describe('Coord', function() {
it('#constructor', function() {
var coord = new arc.Coord(0,0);

@@ -12,3 +14,82 @@ assert.equal(coord.lon,0);

});
it('#view', function() {
var coord = new arc.Coord(0,0);
assert.equal(coord.view(),'0,0');
});
it('#antipode', function() {
var coord = new arc.Coord(0,0);
assert.equal(coord.antipode().view(),'-180,0');
});
});
describe('Arc', function() {
it('#constructor', function() {
var a = new arc.Arc();
assert.deepEqual(a.properties, {});
});
it('#wkt', function() {
var a = new arc.Arc();
assert.equal(a.wkt(), '');
});
it('#json', function() {
var a = new arc.Arc();
assert.deepEqual(a.json(),{
'geometry': { 'type': 'LineString', 'coordinates': null },
'type': 'Feature', 'properties': {}
});
});
});
describe('GreatCircle', function() {
it('#constructor', function() {
var a = new arc.GreatCircle({
x: 0, y: 0
}, {
x: 10, y: 0
});
assert.ok(a);
});
it('#interpolate', function() {
var a = new arc.GreatCircle({
x: 0, y: 0
}, {
x: 10, y: 0
});
assert.deepEqual(a.interpolate(0), [0, 0]);
assert.deepEqual(a.interpolate(1), [10, 0]);
});
});
var routes = [
[{x: -122, y: 48}, {x: -77, y: 39}, {'name': 'Seattle to DC'}],
[{x: -122, y: 48}, {x: 0, y: 51}, {'name': 'Seattle to London'}],
[{x: -75.9375, y: 35.460669951495305}, {x: 146.25, y: -43.06888777416961}, {'name': 'crosses dateline 1'}],
[{x: 145.54687500000003, y: 48.45835188280866}, {x: -112.5, y: -37.71859032558814}, {'name': 'crosses dateline 2'}],
[{x: -74.564208984375, y: -0.17578097424708533}, {x: 137.779541015625, y: -22.75592068148639}, {'name':'south 1'}],
[{x: -66.829833984375, y: -18.81271785640776 }, {x: 118.795166015625, y: -20.797201434306984}, {'name':'south 2'}]
];
// trouble: needs work
//{ x: 114.576416015625, y:-44.21370990970204},{x: -65.423583984375, y:-43.19716728250127}
var arcs = [
{"properties":{"name":"Seattle to DC"},"geometries":[{"coords":[[-122,48.00000000000001],[-97.72808611752785,45.75368189927002],[-77,38.99999999999999]],"length":3}]},
{"properties":{"name":"Seattle to London"},"geometries":[{"coords":[[-122,48.00000000000001],[-64.16590091973099,67.47624207149578],[0,51]],"length":3}]},
{"properties":{"name":"crosses dateline 1"},"geometries":[{"coords":[[-75.9375,35.46066995149531],[-136.82303405489677,-10.367409282634164],[146.25,-43.06888777416961]],"length":3}]},
{"properties":{"name":"crosses dateline 2"},"geometries":[{"coords":[[145.54687500000003,48.45835188280866],[-157.28484118689477,8.44205355944752],[-112.5,-37.71859032558814]],"length":3}]},
{"properties":{"name":"south 1"},"geometries":[{"coords":[[-74.564208984375,-0.17578097424708533],[-140.44327137076033,-35.80108605508993],[137.779541015625,-22.755920681486387]],"length":3}]},
{"properties":{"name":"south 2"},"geometries":[{"coords":[[-66.829833984375,-18.812717856407765],[-146.78177837397814,-82.1795027896656],[118.795166015625,-20.79720143430698]],"length":3}]}
];
describe('Routes', function() {
routes.forEach(function(route,idx) {
it(route[2].name, function() {
var gc = new arc.GreatCircle(route[0], route[1], route[2]);
var line = gc.Arc(3);
//console.log(JSON.stringify(line))
assert.deepEqual(line,arcs[idx]);
});
});
});

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