turf icon indicating copy to clipboard operation
turf copied to clipboard

LineSliceAlong fails when start and end are 0

Open stevage opened this issue 7 years ago • 9 comments

const turf = require('@turf/turf');
const line = turf.lineString([[145,-37], [150, -37]]);
turf.lineSliceAlong(line, 0, 0);

Throws error Error: coordinates must be an array of two or more positions

https://runkit.com/stevebennett/turf-lineslicealong-line-0-0-fails

Maybe it's trivial, but my use case was progressively extending a line from 0% to 100% of an existing line feature. It blew up on the 0%.

stevage avatar Feb 03 '19 10:02 stevage

@stevage Thanks for reporting. This is a tricky case, but I believe it is working as intended. A zero length linestring is not a valid simple feature geometry.

morganherlocker avatar Feb 04 '19 17:02 morganherlocker

Hmm, I don't see anything in the GeoJSON spec prohibiting LineStrings consisting of the same position twice. Or maybe I misunderstood your meaning.

stevage avatar Feb 05 '19 04:02 stevage

I think our lineSliceAlong implementation is only passing in a single coord in to turf.lineString() rather than a duplicate set of coords which is where the problem is. @stevage is correct in that I think a linestring with 2 duplicate points is valid, although the reality is that such a geometry is probably likely to cause issues in subsequent operations on it...

rowanwins avatar Feb 05 '19 08:02 rowanwins

Turf additionally requires geometry to be simple feature compliant, which is more than the GeoJSON spec currently requires. This is due to limitations in some of the downstream geometry engines (JSTS), which do not support self intersections or overlapping ring vertices.

morganherlocker avatar Feb 05 '19 17:02 morganherlocker

I did look at the OGC simple feature spec and was surprised when I didn't see anything about duplicate coords on a linestring. But yep take that a line with 0 length is likely to cause issues in a range of places.

rowanwins avatar Feb 05 '19 22:02 rowanwins

I'm not sure that's a strong argument against ever returning a zero-length linestring. It's just up to the user to not pass that result to other places where it might cause problems. Just like any function that sometimes returns undefined, you could run into problems if you passed that undefined to some other function.

stevage avatar Feb 05 '19 22:02 stevage

note: Reopening issue for debate.

We should look into how JSTS will handle this data. My original argument was:

which do not support self intersections or overlapping ring vertices.

... which I have given some more thought and realized that this would not apply to this case, since:

  1. LineStrings do allow self intersections.
  2. This is not about linear rings, and overlapping vertices are needed in cases, such as representing a traffic circle or a winding GPS path.

Throws error Error: coordinates must be an array of two or more positions

The error message is correct, however, this points to abnormal behavior under the hood. This function should return a linestring with two duplicate coordinates.

morganherlocker avatar Feb 05 '19 23:02 morganherlocker

Related reading:

https://github.com/locationtech/jts/pull/346

morganherlocker avatar Feb 05 '19 23:02 morganherlocker

Here is a use case that I was debugging for quite a while today: I query some data from PostgreSQL into a NextJS app where I use turf. I added some simplification to the query to reduce the data. This simplification created a linestring with start and end being the same value, which is basically a point. According to LLMs that is valid behavior when using simplification in PostGIS(?)

My code is looking for the point in the center of the line which return the second 0 (because the line is 0 m long).

Test case

const l = turf.lineString([[-122.3116, 47.6623], [-122.3116, 47.6623]]);

const wayToHalf = turf.lineSliceAlong(l.geometry, 0, 0, { units: 'meters' })

console.log(wayToHalf)

// Error: coordinates must be an array of two or more positions

tordans avatar Feb 09 '25 19:02 tordans