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

added test cases for issue #852 #892

Merged
merged 6 commits into from
Aug 11, 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
47 changes: 31 additions & 16 deletions packages/turf-line-split/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ module.exports = function (line, splitter) {

// remove excessive decimals from splitter
// to avoid possible approximation issues in rbush
truncate(splitter, 6, 3, true);
var truncatedSplitter = truncate(splitter, 7);

switch (splitterType) {
case 'Point':
return splitLineWithPoint(line, splitter);
return splitLineWithPoint(line, truncatedSplitter);
case 'MultiPoint':
return splitLineWithPoints(line, flatten(splitter));
return splitLineWithPoints(line, flatten(truncatedSplitter));
case 'LineString':
case 'MultiLineString':
case 'Polygon':
case 'MultiPolygon':
return splitLineWithPoints(line, lineIntersect(line, splitter));
return splitLineWithPoints(line, lineIntersect(line, truncatedSplitter));
default:
throw new Error('<splitter> geometry type is not supported');
}
Expand Down Expand Up @@ -99,7 +99,7 @@ function splitLineWithPoints(line, splitter) {
}

/**
* Split LineString with MultiPoint
* Split LineString with Point
*
* @private
* @param {Feature<LineString>} line LineString
Expand All @@ -109,6 +109,12 @@ function splitLineWithPoints(line, splitter) {
function splitLineWithPoint(line, splitter) {
var results = [];

// handle endpoints
var startPoint = getCoords(line)[0];
var endPoint = getCoords(line)[line.geometry.coordinates.length - 1];
if (pointsEquals(startPoint, getCoords(splitter)) ||
pointsEquals(endPoint, getCoords(splitter))) return featureCollection([line]);

// Create spatial index
var tree = rbush();
var segments = lineSegment(line);
Expand All @@ -123,8 +129,8 @@ function splitLineWithPoint(line, splitter) {
// RBush might return multiple lines - only process the closest line to splitter
var closestSegment = findClosestFeature(splitter, search);

// Initial value is the first point of the first segments (begining of line)
var initialValue = [getCoords(segments.features[0])[0]];
// Initial value is the first point of the first segments (beginning of line)
var initialValue = [startPoint];
var lastCoords = featureReduce(segments, function (previous, current, index) {
var currentCoords = getCoords(current)[1];
var splitterCoords = getCoords(splitter);
Expand All @@ -134,8 +140,7 @@ function splitLineWithPoint(line, splitter) {
previous.push(splitterCoords);
results.push(lineString(previous));
// Don't duplicate splitter coordinate (Issue #688)
if (splitterCoords[0] === currentCoords[0] &&
splitterCoords[1] === currentCoords[1]) return [splitterCoords];
if (pointsEquals(splitterCoords, currentCoords)) return [splitterCoords];
return [splitterCoords, currentCoords];

// Keep iterating over coords until finished or intersection is found
Expand All @@ -151,6 +156,7 @@ function splitLineWithPoint(line, splitter) {
return featureCollection(results);
}


/**
* Find Closest Feature
*
Expand All @@ -160,22 +166,31 @@ function splitLineWithPoint(line, splitter) {
* @returns {Feature<LineString>} closest LineString
*/
function findClosestFeature(point, lines) {
// Filter to one segment that is the closest to the line
var closestDistance;
var closestFeature;
if (!lines.features) throw new Error('<lines> must contain features');
// Filter to one segment that is the closest to the line
if (lines.features.length === 1) return lines.features[0];

var closestFeature;
var closestDistance = Infinity;
featureEach(lines, function (segment) {
var pt = pointOnLine(segment, point);
var dist = pt.properties.dist;
if (closestDistance === undefined) {
closestFeature = segment;
closestDistance = dist;
} else if (dist < closestDistance) {
if (dist < closestDistance) {
closestFeature = segment;
closestDistance = dist;
}
});
return closestFeature;
}

/**
* Compares two points and returns if they are equals
*
* @private
* @param {Array<number>} pt1 point
* @param {Array<number>} pt2 point
* @returns {boolean} true if they are equals
*/
function pointsEquals(pt1, pt2) {
return pt1[0] === pt2[0] && pt1[1] === pt2[1];
}
49 changes: 36 additions & 13 deletions packages/turf-line-split/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ test('turf-line-split', t => {
t.end();
});

test('turf-line-split - lines should only contain 2 vertices #688', t => {
const pt = point([8, 50]);
test('turf-line-split -- throws', t => {
const pt = point([9, 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.throws(() => lineSplit(null, pt), '<geojson> is required');
t.throws(() => lineSplit(line, null), '<geojson> is required');
t.throws(() => lineSplit(pt, pt), '<line> must be LineString');
t.throws(() => lineSplit(line, featureCollection([pt, line])), '<splitter> cannot be a FeatureCollection');
t.end();
});

test('turf-line-split - splitter exactly on end of line', t => {
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;
Expand All @@ -52,18 +53,40 @@ test('turf-line-split - splitter exactly on end of line', t => {
t.end();
});

test('turf-line-split -- throws', t => {
const pt = point([9, 50]);

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

t.throws(() => lineSplit(null, pt), '<geojson> is required');
t.throws(() => lineSplit(line, null), '<geojson> is required');
t.throws(() => lineSplit(pt, pt), '<line> must be LineString');
t.throws(() => lineSplit(line, featureCollection([pt, line])), '<splitter> cannot be a FeatureCollection');
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 -- precision issue #852", t => {
const line = lineString([[9.2202022, 49.1438226], [9.2199531, 49.1439048], [9.2196177, 49.1440264]]);
const startPoint = point([9.2202022, 49.1438226]);
const middlePoint = point([9.2199531, 49.1439048]);
const endPoint = point([9.2196177, 49.1440264]);
const [line1, line2] = lineSplit(line, middlePoint).features;

t.deepEqual(line1, lineString([[9.2202022, 49.1438226], [9.2199531, 49.1439048]]), 'middlePoint: line1 should have 2 vertices');
t.deepEqual(line2, lineString([[9.2199531, 49.1439048], [9.2196177, 49.1440264]]), 'middlePoint: line2 should have 2 vertices');
t.deepEqual(lineSplit(line, startPoint).features, [line], 'startPoint: should only contain 1 line of 3 vertices');
t.deepEqual(lineSplit(line, endPoint).features, [line], 'endPoint: should only contain 1 line of 3 vertices');
t.end();
});

test('turf-line-split -- prevent input mutation', t => {
const line = lineString([[9.2202022, 49.1438226], [9.2199531, 49.1439048], [9.2196177, 49.1440264]]);
const lineBefore = JSON.parse(JSON.stringify(line));
lineSplit(line, point([9.2196177, 49.1440264]));

t.deepEqual(line, lineBefore, 'line should be the same');
t.end();
})


/**
* Colorize FeatureCollection
Expand All @@ -75,7 +98,7 @@ function colorize(geojson) {
const results = [];
featureEach(geojson, (feature, index) => {
const r = (index % 2 === 0) ? 'F' : '0';
const g = (index % 2 === 0) ? '0' : '0';
const g = '0';
const b = (index % 2 === 0) ? '0' : 'F';
feature.properties = Object.assign({
stroke: '#' + r + g + b,
Expand Down
18 changes: 9 additions & 9 deletions packages/turf-line-split/test/out/issue-#852.geojson
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
49.1438226
],
[
9.2199531,
9.2199532,
49.1439048
],
[
9.219953,
49.143905
]
]
}
Expand All @@ -35,8 +31,12 @@
"type": "LineString",
"coordinates": [
[
9.219953,
49.143905
9.2199532,
49.1439048
],
[
9.2199531,
49.1439048
],
[
9.2196177,
Expand Down Expand Up @@ -72,8 +72,8 @@
"geometry": {
"type": "Point",
"coordinates": [
9.219953,
49.143905
9.219953175634146,
49.14390480825327
]
}
}
Expand Down
Loading