Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geodesic Convolution Buffers #33

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
2e8d9d4
point buffer implemented
morganherlocker Dec 5, 2014
33b4c02
add fixtures
morganherlocker Dec 5, 2014
dff0c3d
multipoint buffers
morganherlocker Dec 5, 2014
08b5023
line buffer test
morganherlocker Dec 5, 2014
685a2e9
segment offset and caps implemented
morganherlocker Dec 6, 2014
4ddb2d5
geodesic linestring buffer FC
morganherlocker Dec 6, 2014
0f72899
multiline string support
morganherlocker Dec 6, 2014
41833ff
linestring buffer line made
mclaeysb Jun 1, 2016
2b8d30c
cleanup
mclaeysb Jun 3, 2016
076506a
arc at fixed bearings
mclaeysb Jun 3, 2016
bd4d459
polygon offset implemented
mclaeysb Jun 9, 2016
d258dfe
line buffer return polygon, polygon buffer with or without rings retu…
mclaeysb Jun 9, 2016
e45a8aa
removed old turf featurecollection
mclaeysb Jun 9, 2016
b13b9c8
lineBuffer for closed line fix
mclaeysb Jun 10, 2016
6cf9427
all offsets are now polygon coordinates
mclaeysb Jun 10, 2016
b0dc332
brackets fix and lineOffset fix fix
mclaeysb Jun 10, 2016
78432fe
commented winding function
mclaeysb Jun 10, 2016
a5bacab
added rewind function
mclaeysb Jun 10, 2016
3a0199f
automatically rewind polygons
mclaeysb Jun 10, 2016
8a506c9
re-randomize arc points, remove duplicate vertices first
mclaeysb Jun 12, 2016
99a1f35
added test
mclaeysb Jun 12, 2016
723b692
strip simplepolygon features
mclaeysb Jun 12, 2016
a07f2e7
add package
mclaeysb Jun 12, 2016
72fb68a
removed old fixtures
mclaeysb Jun 12, 2016
8eb2573
moved test.js and fixtures to tests dir
mclaeysb Jun 13, 2016
5b5d4f8
renamed tests to test
mclaeysb Jul 21, 2016
f68be48
basic benchmarks comparing this branch to master which uses jsts
mclaeysb Jul 21, 2016
095be64
updated package with correct test ref and bench devDep
mclaeysb Jul 21, 2016
77f4f96
renamed test fixtures
mclaeysb Jul 21, 2016
f426516
fixed equal arrays and modulo function: no longer extending built-in …
mclaeysb Jul 30, 2016
20f0eb8
single simplepolygon call in offsetToBuffer
mclaeysb Aug 2, 2016
f75aee9
allow FeatureCollection input
mclaeysb Aug 7, 2016
5c5ac1b
small tweaks
mclaeysb Aug 9, 2016
92ef49b
added test that buffers circle with buffer radius equal to circle radius
mclaeysb Aug 9, 2016
bbdb86f
removed test/fixtures/out/*
mclaeysb Aug 9, 2016
a147571
Fix neglecting of holes caused by f75aee9dd5d70f310ee8289147a43747d71…
mclaeysb Aug 9, 2016
6eebbf3
fix winding function
mclaeysb Aug 15, 2016
60f5ad1
ignore extra fixtures and their test
mclaeysb Aug 15, 2016
3350d07
entab
mclaeysb Aug 17, 2016
173433a
Always measure bearings from point where arc is made
mclaeysb Aug 20, 2016
81756a3
fix to make shortcut arc for reflex angles pass through point, fully …
mclaeysb Aug 21, 2016
e0b23e9
simplify linestrings and polygons before buffering > speedup
mclaeysb Aug 26, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
linestring buffer line made
mclaeysb committed Jun 1, 2016
commit 41833ff137c48baabb943b4ad4f57b1d1f81b469
108 changes: 100 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
var featurecollection = require('turf-featurecollection');
var destination = require('turf-destination');
var bearing = require('turf-bearing');
var point = require('turf-point');
var polygon = require('turf-polygon');
var helpers = require('turf-helpers');

module.exports = function(feature, radius, units, resolution){
if(!resolution) resolution = 36;
if(!resolution) resolution = 32;
var geom = feature.geometry
if(geom.type === 'Point') {
return pointBuffer(feature, radius, units, resolution);
} else if(geom.type === 'MultiPoint') {
var buffers = [];
geom.coordinates.forEach(function(coords) {
buffers.push(pointBuffer(point(coords[0], coords[1]), radius, units, resolution));
buffers.push(pointBuffer(helpers.point(coords[0], coords[1]), radius, units, resolution));
});
return featurecollection(buffers)
} else if(geom.type === 'LineString') {
@@ -22,7 +21,7 @@ module.exports = function(feature, radius, units, resolution){
geom.coordinates.forEach(function(line){
buffers.push(lineBuffer(feature, radius, units, resolution));
});
} else if(geom.type === 'Polygon') {
} else if(geom.type === 'Polygon') {

} else if(geom.type === 'MultiPolygon') {

@@ -39,25 +38,42 @@ function pointBuffer (pt, radius, units, resolution) {
if((ring[0][0] !== ring[ring.length-1][0]) && (ring[0][1] != ring[ring.length-1][1])) {
ring.push([ring[0][0], ring[0][1]]);
}
return polygon([ring])
return helpers.polygon([ring])
}

function lineBuffer (line, radius, units, resolution) {

var lineBuffer = [];
var firstLinePoint = helpers.point(line.geometry.coordinates[0]);
var firstLineBearing = bearing(helpers.point(line.geometry.coordinates[0]), helpers.point(line.geometry.coordinates[1]));
var firstBufferPoint = destination(firstLinePoint, radius, firstLineBearing + 90, units);
var lastLinePoint = helpers.point(line.geometry.coordinates[line.geometry.coordinates.length-1]);
var lastLineBearing = bearing(helpers.point(line.geometry.coordinates[line.geometry.coordinates.length-2]), helpers.point(line.geometry.coordinates[line.geometry.coordinates.length-1]));
lineBuffer.push.apply(lineBuffer,[firstBufferPoint.geometry.coordinates]);
lineBuffer.push.apply(lineBuffer,lineBufferOneSide(line, radius, units, resolution, true, false).geometry.coordinates);
lineBuffer.push.apply(lineBuffer,arc(lastLinePoint, radius, lastLineBearing + 90, lastLineBearing - 90, units, resolution, true).geometry.coordinates);
lineBuffer.push.apply(lineBuffer,lineBufferOneSide(line, radius, units, resolution, true, true).geometry.coordinates);
lineBuffer.push.apply(lineBuffer,arc(firstLinePoint, radius, firstLineBearing - 90, firstLineBearing + 90, units, resolution, true).geometry.coordinates);

return helpers.polygon([lineBuffer]);
/*
var lineBuffers = featurecollection([])
//break line into segments
var segments = [];
for(var i = 0; i < line.geometry.coordinates.length-1; i++) {
segments.push([line.geometry.coordinates[i], line.geometry.coordinates[i+1]]);
}
*/
/*create a set of boxes parallel to the segments

---------

((|¯¯¯¯¯¯¯¯¯|))
(((|---------|)))
((|_________|))

*/
/*
for(var i = 0; i < segments.length; i++) {
var bottom = point(segments[i][0][0], segments[i][0][1])
var top = point(segments[i][1][0], segments[i][1][1])
@@ -95,4 +111,80 @@ function lineBuffer (line, radius, units, resolution) {
}
console.log(JSON.stringify(lineBuffers))
return lineBuffers;
}
*/
}

function lineBufferOneSide (line, radius, units, resolution, right, reverse) {
if(right === undefined) var right = true;
if(reverse === undefined) var reverse = false;
var coords = line.geometry.coordinates;
if(reverse) coords = coords.reverse();
var lineBuffer = [];
if (coords.length == 2) return lineBuffer;
var currentLinePoint = helpers.point(coords[1]);
var currentLineBearing = bearing(helpers.point(coords[0]), helpers.point(coords[1]));
for (var i = 1; i < coords.length-1; i++) {
var nextLinePoint = helpers.point(coords[i+1]);
var nextLineBearing = bearing(currentLinePoint, nextLinePoint);
lineBuffer.push.apply(lineBuffer,arc(currentLinePoint, radius, currentLineBearing + Math.pow(-1, right + 1) * 90, nextLineBearing + Math.pow(-1, right + 1) * 90, units, resolution, right).geometry.coordinates);
var currentLinePoint = nextLinePoint;
var currentLineBearing = nextLineBearing;
}
return helpers.lineString(lineBuffer)
}

function arc (pt, radius, bearing1, bearing2, units, resolution, right) {
if(right === undefined) var right = true;
var arc = [];
var resMultiple = 360/resolution;
var steps = Math.floor((Math.pow(-1, right + 1) * (bearing1 - bearing2)).mod(360)/resMultiple);
for(var i = 0; i < steps; i++) {
var spoke = destination(pt, radius, bearing1 + Math.pow(-1, !right + 1) * i * resMultiple, units);
arc.push(spoke.geometry.coordinates);

}
if(bearing1 - i * resMultiple != bearing2) {
var spoke = destination(pt, radius, bearing2, units);
arc.push(spoke.geometry.coordinates);
}
return helpers.lineString(arc)
}




// Function to compare Arrays of numbers. From http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript
// Warn if overriding existing method
if(Array.prototype.equals)
console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the JavaScript norms currently, extending built-in objects can be dangerous, since the extensions may break other code or native behavior. Could this be implemented instead as a function that takes two arrays, and the same with the mod extension?

// if the other array is a falsy value, return
if (!array)
return false;

// compare lengths - can save a lot of time
if (this.length != array.length)
return false;

for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

// Fix Javascript modulo for negative number. From http://stackoverflow.com/questions/4467539/javascript-modulo-not-behaving
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
}