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

Fix duplicate nodes from line-intersect & line-split #688 #696

Merged
merged 1 commit into from
Apr 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 10 additions & 9 deletions packages/turf-line-intersect/bench.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Benchmark = require('benchmark');
const path = require('path');
const fs = require('fs');
const path = require('path');
const load = require('load-json-file');
const Benchmark = require('benchmark');
const lineIntersect = require('./');

const directory = path.join(__dirname, 'test', 'in') + path.sep;
Expand All @@ -16,18 +16,19 @@ const fixtures = fs.readdirSync(directory).map(filename => {
/**
* Benchmark Results
*
* 2-vertex-segment x 7,177,957 ops/sec ±0.83% (92 runs sampled)
* double-intersect x 88,165 ops/sec ±3.02% (78 runs sampled)
* multi-linestring x 19,554 ops/sec ±2.09% (77 runs sampled)
* multi-polygon x 11,149 ops/sec ±2.05% (74 runs sampled)
* same-coordinates x 67,439 ops/sec ±2.01% (73 runs sampled)
* 2-vertex-segment x 4,123,821 ops/sec ±12.92% (74 runs sampled)
* double-intersect x 53,118 ops/sec ±4.22% (72 runs sampled)
* multi-linestring x 16,417 ops/sec ±2.31% (77 runs sampled)
* polygons-with-holes x 9,739 ops/sec ±2.55% (85 runs sampled)
* same-coordinates x 51,303 ops/sec ±4.23% (71 runs sampled)
*/
const suite = new Benchmark.Suite('turf-line-intersect');
for (const {name, geojson} of fixtures) {
suite.add(name, () => lineIntersect(geojson.features[0], geojson.features[1]));
const [line1, line2] = geojson.features;
suite.add(name, () => lineIntersect(line1, line2));
}

suite
.on('cycle', e => { console.log(String(e.target)); })
.on('cycle', e => console.log(String(e.target)))
.on('complete', () => {})
.run();
19 changes: 14 additions & 5 deletions packages/turf-line-intersect/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
var helpers = require('@turf/helpers');
var meta = require('@turf/meta');
var lineSegment = require('@turf/line-segment');
var getCoords = require('@turf/invariant').getCoords;
var rbush = require('geojson-rbush');
var helpers = require('@turf/helpers');
var getCoords = require('@turf/invariant').getCoords;
var lineSegment = require('@turf/line-segment');
var point = helpers.point;
var featureCollection = helpers.featureCollection;
var featureEach = meta.featureEach;
var featureCollection = helpers.featureCollection;

/**
* Takes any LineString or Polygon GeoJSON and returns the intersecting point(s).
Expand Down Expand Up @@ -37,7 +37,9 @@ var featureEach = meta.featureEach;
* var addToMap = [line, line2, intersects]
*/
module.exports = function (line1, line2) {
var unique = {};
var results = [];

// Handles simple 2-vertex segments
if (line1.geometry.type === 'LineString' &&
line2.geometry.type === 'LineString' &&
Expand All @@ -47,13 +49,20 @@ module.exports = function (line1, line2) {
if (intersect) results.push(intersect);
return featureCollection(results);
}

// Handles complex GeoJSON Geometries
var tree = rbush();
tree.load(lineSegment(line2));
featureEach(lineSegment(line1), function (segment) {
featureEach(tree.search(segment), function (match) {
var intersect = intersects(segment, match);
if (intersect) results.push(intersect);
if (intersect) {
var key = getCoords(intersect).join(',');
if (!unique[key]) {
unique[key] = true;
results.push(intersect);
}
}
});
});
return featureCollection(results);
Expand Down
18 changes: 13 additions & 5 deletions packages/turf-line-intersect/test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const test = require('tape');
const fs = require('fs');
const test = require('tape');
const path = require('path');
const load = require('load-json-file');
const write = require('write-json-file');
const featureEach = require('@turf/meta').featureEach;
const featureCollection = require('@turf/helpers').featureCollection;
const truncate = require('@turf/truncate');
const {featureEach} = require('@turf/meta');
const {featureCollection, lineString} = require('@turf/helpers');
const lineIntersect = require('./');

const directories = {
Expand All @@ -23,8 +23,7 @@ const fixtures = fs.readdirSync(directories.in).map(filename => {

test('turf-line-intersect', t => {
for (const {filename, name, geojson} of fixtures) {
const line1 = geojson.features[0];
const line2 = geojson.features[1];
const [line1, line2] = geojson.features;
const points = truncate(lineIntersect(line1, line2));
const results = featureCollection([line1, line2]);
featureEach(points, point => results.features.push(point));
Expand All @@ -34,3 +33,12 @@ test('turf-line-intersect', t => {
}
t.end();
});

test('turf-line-intersect - same point #688', t => {
const line1 = lineString([[7, 50], [8, 50], [9, 50]]);
const line2 = lineString([[8, 49], [8, 50], [8, 51]]);

var results = lineIntersect(line1, line2);
t.equal(results.features.length, 1, 'should return single point');
t.end();
});
16 changes: 11 additions & 5 deletions packages/turf-line-split/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,28 @@ function splitLineWithPoint(line, splitter) {
// Initial value is the first point of the first segments (begining of line)
var initialValue = [getCoords(segments.features[0])[0]];
var lastCoords = featureReduce(segments, function (previous, current, index) {
var currentCoords = getCoords(current)[1];
var splitterCoords = getCoords(splitter);

// Location where segment intersects with line
if (index === closestSegment.id) {
var coords = getCoords(splitter);
previous.push(coords);
previous.push(splitterCoords);
results.push(lineString(previous));
return [coords, getCoords(current)[1]];
// Don't duplicate splitter coordinate (Issue #688)
if (splitterCoords[0] === currentCoords[0] &&
splitterCoords[1] === currentCoords[1]) return [splitterCoords];
return [splitterCoords, currentCoords];

// Keep iterating over coords until finished or intersection is found
} else {
previous.push(getCoords(current)[1]);
previous.push(currentCoords);
return previous;
}
}, initialValue);
// Append last line to final split results
results.push(lineString(lastCoords));
if (lastCoords.length > 1) {
results.push(lineString(lastCoords));
}
return featureCollection(results);
}

Expand Down
25 changes: 22 additions & 3 deletions packages/turf-line-split/test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const test = require('tape');
const fs = require('fs');
const test = require('tape');
const path = require('path');
const load = require('load-json-file');
const write = require('write-json-file');
const featureEach = require('@turf/meta').featureEach;
const featureCollection = require('@turf/helpers').featureCollection;
const {featureEach} = require('@turf/meta');
const {point, lineString, featureCollection} = require('@turf/helpers');
const lineSplit = require('./');

const directories = {
Expand Down Expand Up @@ -33,6 +33,25 @@ test('turf-line-split', t => {
t.end();
});

test('turf-line-split - lines should only contain 2 vertices #688', t => {
const pt = point([8, 50]);
const line = lineString([[7, 50], [8, 50], [9, 50]]);
const [line1, line2] = lineSplit(line, pt).features;

t.deepEqual(line1, lineString([[7, 50], [8, 50]]), 'line1 should have 2 vertices');
t.deepEqual(line2, lineString([[8, 50], [9, 50]]), 'line2 should have 2 vertices');
t.end();
});

test('turf-line-split - splitter exactly on end of line', t => {
const pt = point([9, 50]);
const line = lineString([[7, 50], [8, 50], [9, 50]]);
const features = lineSplit(line, pt).features;

t.deepEqual(features, [line], 'should only contain 1 line of 3 vertices');
t.end();
});

/**
* Colorize FeatureCollection
*
Expand Down