diff --git a/packages/turf-along/README.md b/packages/turf-along/README.md index 1c2ad30c2c..b032aa597d 100644 --- a/packages/turf-along/README.md +++ b/packages/turf-along/README.md @@ -6,13 +6,17 @@ Takes a [LineString][1] and returns a [Point][2] at a specified distance along the line. +If [distance][3] is longer than the length of [line][4], the last coordinate of the line is returned +If [distance][3] is negative, it will count distance along the line from end to start of the line. And if +a negative distance overshoots the length of the line, it will return the first coordinate of the line. + ### Parameters -* `line` **[Feature][3]<[LineString][4]>** input line -* `distance` **[number][5]** distance along the line -* `options` **[Object][6]?** Optional parameters +* `line` **[Feature][5]<[LineString][6]>** input line +* `distance` **[number][7]** distance along the line +* `options` **[Object][8]?** Optional parameters - * `options.units` **[string][7]** can be degrees, radians, miles, or kilometers (optional, default `"kilometers"`) + * `options.units` **[string][9]** can be degrees, radians, miles, or kilometers (optional, default `"kilometers"`) ### Examples @@ -26,23 +30,27 @@ var along = turf.along(line, 200, options); var addToMap = [along, line] ``` -Returns **[Feature][3]<[Point][8]>** Point `distance` `units` along the line +Returns **[Feature][5]<[Point][10]>** Point `distance` `units` along the line [1]: https://tools.ietf.org/html/rfc7946#section-3.1.4 [2]: https://tools.ietf.org/html/rfc7946#section-3.1.2 -[3]: https://tools.ietf.org/html/rfc7946#section-3.2 +[3]: distance + +[4]: line + +[5]: https://tools.ietf.org/html/rfc7946#section-3.2 -[4]: https://tools.ietf.org/html/rfc7946#section-3.1.4 +[6]: https://tools.ietf.org/html/rfc7946#section-3.1.4 -[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[8]: https://tools.ietf.org/html/rfc7946#section-3.1.2 +[10]: https://tools.ietf.org/html/rfc7946#section-3.1.2 diff --git a/packages/turf-along/index.ts b/packages/turf-along/index.ts index f881729b61..c6ed34d93e 100644 --- a/packages/turf-along/index.ts +++ b/packages/turf-along/index.ts @@ -2,12 +2,17 @@ import { Feature, LineString, Point } from "geojson"; import { bearing } from "@turf/bearing"; import { destination } from "@turf/destination"; import { distance as measureDistance } from "@turf/distance"; -import { point, Units } from "@turf/helpers"; +import { feature, point, Units } from "@turf/helpers"; import { getGeom } from "@turf/invariant"; +import { length } from "@turf/length"; /** * Takes a {@link LineString} and returns a {@link Point} at a specified distance along the line. * + * If {@link distance} is longer than the length of {@link line}, the last coordinate of the line is returned + * If {@link distance} is negative, it will count distance along the line from end to start of the line. And if + * a negative distance overshoots the length of the line, it will return the first coordinate of the line. + * * @name along * @param {Feature} line input line * @param {number} distance distance along the line @@ -28,6 +33,10 @@ function along( distance: number, options: { units?: Units } = {} ): Feature { + if (distance < 0) { + const lineFeature = line.type === "Feature" ? line : feature(line); + distance = Math.max(0, length(lineFeature, options) + distance); + } // Get Coords const geom = getGeom(line); const coords = geom.coordinates; diff --git a/packages/turf-along/package.json b/packages/turf-along/package.json index df48d1dedd..47e79b5768 100644 --- a/packages/turf-along/package.json +++ b/packages/turf-along/package.json @@ -68,6 +68,7 @@ "@turf/distance": "workspace:^", "@turf/helpers": "workspace:^", "@turf/invariant": "workspace:^", + "@turf/length": "workspace:^", "tslib": "^2.6.2" } } diff --git a/packages/turf-along/test.ts b/packages/turf-along/test.ts index 2fa6e5c184..f0981cf8f8 100644 --- a/packages/turf-along/test.ts +++ b/packages/turf-along/test.ts @@ -19,14 +19,27 @@ test("turf-along", (t) => { const pt6 = along(line.geometry, 2, options); const pt7 = along(line, 100, options); const pt8 = along(line.geometry, 0, options); - const fc = featureCollection([pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8]); + const pt9 = along(line, -1, options); + const pt10 = along(line.geometry, -1, options); + const fc = featureCollection([ + pt1, + pt2, + pt3, + pt4, + pt5, + pt6, + pt7, + pt8, + pt9, + pt10, + ]); fc.features.forEach((f) => { t.ok(f); t.equal(f.type, "Feature"); t.equal(f.geometry.type, "Point"); }); - t.equal(fc.features.length, 8); + t.equal(fc.features.length, 10); t.equal(fc.features[7].geometry.coordinates[0], pt8.geometry.coordinates[0]); t.equal(fc.features[7].geometry.coordinates[1], pt8.geometry.coordinates[1]); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb2b3ff97f..209e145dd9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -519,6 +519,9 @@ importers: '@turf/invariant': specifier: workspace:^ version: link:../turf-invariant + '@turf/length': + specifier: workspace:^ + version: link:../turf-length tslib: specifier: ^2.6.2 version: 2.6.2