From b29efcffaaf08afbed8b24045796c935659d4c26 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:58:21 +0200 Subject: [PATCH 1/9] Compute multiFeatureLocation in addition to location property in @turf/nearest-point-on-line Fix unit tests --- packages/turf-nearest-point-on-line/index.ts | 27 +++++++++++--- packages/turf-nearest-point-on-line/test.ts | 35 +++++++++++++++++++ .../out/line-northern-latitude-#344.geojson | 1 + .../test/out/line1.geojson | 1 + .../test/out/multiLine1.geojson | 1 + .../test/out/multiLine2.geojson | 1 + .../test/out/multiLine3.geojson | 1 + .../test/out/route1.geojson | 1 + .../test/out/route2.geojson | 1 + 9 files changed, 65 insertions(+), 4 deletions(-) diff --git a/packages/turf-nearest-point-on-line/index.ts b/packages/turf-nearest-point-on-line/index.ts index 231517e71c..e391624da5 100644 --- a/packages/turf-nearest-point-on-line/index.ts +++ b/packages/turf-nearest-point-on-line/index.ts @@ -22,7 +22,7 @@ import { getCoord, getCoords } from "@turf/invariant"; * @param {Geometry|Feature|number[]} pt point to snap from * @param {Object} [options={}] Optional parameters * @param {Units} [options.units='kilometers'] Supports all valid Turf {@link https://turfjs.org/docs/api/types/Units Units} - * @returns {Feature} closest point on the `line` to `point`. The properties object will contain four values: `index`: closest point was found on nth line part, `multiFeatureIndex`: closest point was found on the nth line of the `MultiLineString`, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point. + * @returns {Feature} closest point on the `line` to `point`. The properties object will contain four values: `index`: closest point was found on nth line part, `multiFeatureIndex`: closest point was found on the nth line of the `MultiLineString`, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point, `multiFeatureLocation`: distance along the line between start of the `MultiLineString` where closest point was found and the closest point. * @example * var line = turf.lineString([ * [-77.031669, 38.878605], @@ -51,6 +51,7 @@ function nearestPointOnLine( index: number; multiFeatureIndex: number; location: number; + multiFeatureLocation: number; [key: string]: any; } > { @@ -62,18 +63,33 @@ function nearestPointOnLine( let closestPt: Feature< Point, - { dist: number; index: number; multiFeatureIndex: number; location: number } + { + dist: number; + index: number; + multiFeatureIndex: number; + location: number; + multiFeatureLocation: number; + } > = point([Infinity, Infinity], { dist: Infinity, index: -1, multiFeatureIndex: -1, location: -1, + multiFeatureLocation: -1, }); let length = 0.0; + let multiFeatureLength = 0.0; + let currentMultiFeatureIndex = -1; flattenEach( lines, function (line: any, _featureIndex: number, multiFeatureIndex: number) { + //reset multiFeatureLength at each changed multiFeatureIndex + if (currentMultiFeatureIndex !== multiFeatureIndex) { + currentMultiFeatureIndex = multiFeatureIndex; + multiFeatureLength = 0.0; + } + const coords: any = getCoords(line); for (let i = 0; i < coords.length - 1; i++) { @@ -106,10 +122,12 @@ function nearestPointOnLine( ); } + const lineLocationDist = distance(start, intersectPos, options); const intersectPt = point(intersectPos, { dist: distance(pt, intersectPos, options), multiFeatureIndex: multiFeatureIndex, - location: length + distance(start, intersectPos, options), + location: length + lineLocationDist, + multiFeatureLocation: multiFeatureLength + lineLocationDist, }); if (intersectPt.properties.dist < closestPt.properties.dist) { @@ -124,8 +142,9 @@ function nearestPointOnLine( }; } - // update length + // update length and multiFeatureLength length += sectionLength; + multiFeatureLength += sectionLength; } } ); diff --git a/packages/turf-nearest-point-on-line/test.ts b/packages/turf-nearest-point-on-line/test.ts index 9dec50f98b..d1d61f176a 100644 --- a/packages/turf-nearest-point-on-line/test.ts +++ b/packages/turf-nearest-point-on-line/test.ts @@ -40,6 +40,10 @@ test("turf-nearest-point-on-line", (t) => { onLine.properties["marker-color"] = "#F0F"; onLine.properties.dist = round(onLine.properties.dist, 6); onLine.properties.location = round(onLine.properties.location, 6); + onLine.properties.multiFeatureLocation = round( + onLine.properties.multiFeatureLocation, + 6 + ); const between = lineString( [onLine.geometry.coordinates, point.geometry.coordinates], { stroke: "#F00", "stroke-width": 6 } @@ -399,6 +403,37 @@ test("turf-nearest-point-on-line -- multifeature index", (t) => { t.end(); }); +test("turf-nearest-point-on-line -- issue 2753 multifeature location", (t) => { + const multiLine = multiLineString([ + [ + [-122.3125, 47.6632], + [-122.3102, 47.6646], + ], + [ + [-122.3116, 47.6623], + [-122.3091, 47.6636], + ], + ]); + + const ptA = point([-122.3106, 47.6638], { name: "A" }); + const ptB = point([-122.3102, 47.6634], { name: "B" }); + + const nearestToA = nearestPointOnLine(multiLine, ptA, { units: "meters" }); + const nearestToB = nearestPointOnLine(multiLine, ptB, { units: "meters" }); + + t.equal( + Number(nearestToA.properties.multiFeatureLocation.toFixed(6)), + 150.296465, + "nearestToA multiFeatureLocation" + ); + t.equal( + Number(nearestToB.properties.multiFeatureLocation.toFixed(6)), + 157.738215, + "nearestToB multiFeatureLocation" + ); + t.end(); +}); + test("turf-nearest-point-on-line -- issue 1514", (t) => { const pt = point([-40.01, 56]); const line = lineString([ diff --git a/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson b/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson index 4c16f72487..a2c63eb1ba 100644 --- a/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson +++ b/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson @@ -42,6 +42,7 @@ "dist": 5.959562, "multiFeatureIndex": 0, "location": 19.748879, + "multiFeatureLocation": 19.748879, "index": 1, "marker-color": "#F0F" }, diff --git a/packages/turf-nearest-point-on-line/test/out/line1.geojson b/packages/turf-nearest-point-on-line/test/out/line1.geojson index d896f49105..b16f86d055 100644 --- a/packages/turf-nearest-point-on-line/test/out/line1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/line1.geojson @@ -42,6 +42,7 @@ "dist": 2.556271, "multiFeatureIndex": 0, "location": 22.137494, + "multiFeatureLocation": 22.137494, "index": 1, "marker-color": "#F0F" }, diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson index b6765f1fe4..fbd6b87bc8 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson @@ -71,6 +71,7 @@ "index": 21, "multiFeatureIndex": 1, "location": 9479.011715, + "multiFeatureLocation": 4800.716022, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson index 6c55987cc8..cfd5ce7482 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson @@ -52,6 +52,7 @@ "index": 0, "multiFeatureIndex": 1, "location": 1656.139708, + "multiFeatureLocation": 0, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson index d858ad925f..cbee7754fd 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson @@ -60,6 +60,7 @@ "dist": 121.937841, "multiFeatureIndex": 0, "location": 214.735285, + "multiFeatureLocation": 214.735285, "index": 0, "marker-color": "#F0F" }, diff --git a/packages/turf-nearest-point-on-line/test/out/route1.geojson b/packages/turf-nearest-point-on-line/test/out/route1.geojson index 71003b12d5..d38a116b52 100644 --- a/packages/turf-nearest-point-on-line/test/out/route1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/route1.geojson @@ -4795,6 +4795,7 @@ "dist": 7.876557, "multiFeatureIndex": 0, "location": 183.46844, + "multiFeatureLocation": 183.46844, "index": 3104, "marker-color": "#F0F" }, diff --git a/packages/turf-nearest-point-on-line/test/out/route2.geojson b/packages/turf-nearest-point-on-line/test/out/route2.geojson index 59b51f99d4..518f884ded 100644 --- a/packages/turf-nearest-point-on-line/test/out/route2.geojson +++ b/packages/turf-nearest-point-on-line/test/out/route2.geojson @@ -3799,6 +3799,7 @@ "dist": 19.22738, "multiFeatureIndex": 0, "location": 303.639629, + "multiFeatureLocation": 303.639629, "index": 1185, "marker-color": "#F0F" }, From 5d16fe8f6049804758e06c4175c986260b4c7e99 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:22:33 +0100 Subject: [PATCH 2/9] Add contributor for @turf/nearest-point-on-line --- packages/turf-nearest-point-on-line/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/turf-nearest-point-on-line/package.json b/packages/turf-nearest-point-on-line/package.json index 846c7630cc..7856d1b416 100644 --- a/packages/turf-nearest-point-on-line/package.json +++ b/packages/turf-nearest-point-on-line/package.json @@ -5,6 +5,7 @@ "author": "Turf Authors", "contributors": [ "Angel Lacret <@alacret>", + "Emil Junker <@EmilJunker>", "Jon Miles <@jonmiles>", "John Ziebro <@Insighttful>" ], From 2cf5f710143043895d82f49efedb6b0f27c7c6b6 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Tue, 2 Dec 2025 10:49:09 +0100 Subject: [PATCH 3/9] nearest-point-on-line Rename param pt to inputPoint --- packages/turf-nearest-point-on-line/index.ts | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/turf-nearest-point-on-line/index.ts b/packages/turf-nearest-point-on-line/index.ts index e391624da5..85d82268fc 100644 --- a/packages/turf-nearest-point-on-line/index.ts +++ b/packages/turf-nearest-point-on-line/index.ts @@ -18,8 +18,8 @@ import { getCoord, getCoords } from "@turf/invariant"; * on the line. * * @function - * @param {Geometry|Feature} lines lines to snap to - * @param {Geometry|Feature|number[]} pt point to snap from + * @param {Geometry|Feature} lines Lines to snap to + * @param {Geometry|Feature|number[]} inputPoint Point to snap from * @param {Object} [options={}] Optional parameters * @param {Units} [options.units='kilometers'] Supports all valid Turf {@link https://turfjs.org/docs/api/types/Units Units} * @returns {Feature} closest point on the `line` to `point`. The properties object will contain four values: `index`: closest point was found on nth line part, `multiFeatureIndex`: closest point was found on the nth line of the `MultiLineString`, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point, `multiFeatureLocation`: distance along the line between start of the `MultiLineString` where closest point was found and the closest point. @@ -32,17 +32,17 @@ import { getCoord, getCoords } from "@turf/invariant"; * [-77.021884, 38.889563], * [-77.019824, 38.892368] * ]); - * var pt = turf.point([-77.037076, 38.884017]); + * var inputPoint = turf.point([-77.037076, 38.884017]); * - * var snapped = turf.nearestPointOnLine(line, pt, {units: 'miles'}); + * var snapped = turf.nearestPointOnLine(line, inputPoint, {units: 'miles'}); * * //addToMap - * var addToMap = [line, pt, snapped]; + * var addToMap = [line, inputPoint, snapped]; * snapped.properties['marker-color'] = '#00f'; */ function nearestPointOnLine( lines: Feature | G, - pt: Coord, + inputPoint: Coord, options: { units?: Units } = {} ): Feature< Point, @@ -55,11 +55,11 @@ function nearestPointOnLine( [key: string]: any; } > { - if (!lines || !pt) { - throw new Error("lines and pt are required arguments"); + if (!lines || !inputPoint) { + throw new Error("lines and inputPoint are required arguments"); } - const ptPos = getCoord(pt); + const inputPos = getCoord(inputPoint); let closestPt: Feature< Point, @@ -109,22 +109,22 @@ function nearestPointOnLine( // Short circuit if snap point is start or end position of the line // Test the end position first for consistency in case they are // coincident - if (stopPos[0] === ptPos[0] && stopPos[1] === ptPos[1]) { + if (stopPos[0] === inputPos[0] && stopPos[1] === inputPos[1]) { [intersectPos, wasEnd] = [stopPos, true]; - } else if (startPos[0] === ptPos[0] && startPos[1] === ptPos[1]) { + } else if (startPos[0] === inputPos[0] && startPos[1] === inputPos[1]) { [intersectPos, wasEnd] = [startPos, false]; } else { // Otherwise, find the nearest point the hard way. [intersectPos, wasEnd] = nearestPointOnSegment( startPos, stopPos, - ptPos + inputPos ); } const lineLocationDist = distance(start, intersectPos, options); const intersectPt = point(intersectPos, { - dist: distance(pt, intersectPos, options), + dist: distance(inputPoint, intersectPos, options), multiFeatureIndex: multiFeatureIndex, location: length + lineLocationDist, multiFeatureLocation: multiFeatureLength + lineLocationDist, From cd34656269b07b77638b6402b88dbb6f47628019 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:33:38 +0100 Subject: [PATCH 4/9] nearest-point-on-line Rename point properties --- packages/turf-nearest-point-on-line/index.ts | 67 ++++++++----------- packages/turf-nearest-point-on-line/test.ts | 63 +++++++++-------- .../out/line-northern-latitude-#344.geojson | 11 +-- .../test/out/line1.geojson | 11 +-- .../test/out/multiLine1.geojson | 11 +-- .../test/out/multiLine2.geojson | 11 +-- .../test/out/multiLine3.geojson | 11 +-- .../test/out/route1.geojson | 11 +-- .../test/out/route2.geojson | 11 +-- 9 files changed, 104 insertions(+), 103 deletions(-) diff --git a/packages/turf-nearest-point-on-line/index.ts b/packages/turf-nearest-point-on-line/index.ts index 85d82268fc..0de3f34a01 100644 --- a/packages/turf-nearest-point-on-line/index.ts +++ b/packages/turf-nearest-point-on-line/index.ts @@ -22,7 +22,7 @@ import { getCoord, getCoords } from "@turf/invariant"; * @param {Geometry|Feature|number[]} inputPoint Point to snap from * @param {Object} [options={}] Optional parameters * @param {Units} [options.units='kilometers'] Supports all valid Turf {@link https://turfjs.org/docs/api/types/Units Units} - * @returns {Feature} closest point on the `line` to `point`. The properties object will contain four values: `index`: closest point was found on nth line part, `multiFeatureIndex`: closest point was found on the nth line of the `MultiLineString`, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point, `multiFeatureLocation`: distance along the line between start of the `MultiLineString` where closest point was found and the closest point. + * @returns {Feature} closest point on the `lines` to the `inputPoint`. The point will have the following properties: `lineStringIndex`: closest point was found on the nth LineString (only relevant if input is MultiLineString), `segmentIndex`: closest point was found on nth line segment of the LineString, `totalDistance`: distance along the line from the absolute start of the MultiLineString, `lineDistance`: distance along the line from the start of the LineString where the closest point was found, `segmentDistance`: distance along the line from the start of the line segment where the closest point was found, `pointDistance`: distance to the input point. * @example * var line = turf.lineString([ * [-77.031669, 38.878605], @@ -47,11 +47,12 @@ function nearestPointOnLine( ): Feature< Point, { - dist: number; - index: number; - multiFeatureIndex: number; - location: number; - multiFeatureLocation: number; + lineStringIndex: number; + segmentIndex: number; + totalDistance: number; + lineDistance: number; + segmentDistance: number; + pointDistance: number; [key: string]: any; } > { @@ -61,21 +62,13 @@ function nearestPointOnLine( const inputPos = getCoord(inputPoint); - let closestPt: Feature< - Point, - { - dist: number; - index: number; - multiFeatureIndex: number; - location: number; - multiFeatureLocation: number; - } - > = point([Infinity, Infinity], { - dist: Infinity, - index: -1, - multiFeatureIndex: -1, - location: -1, - multiFeatureLocation: -1, + let closestPt = point([Infinity, Infinity], { + lineStringIndex: -1, + segmentIndex: -1, + totalDistance: -1, + lineDistance: -1, + segmentDistance: -1, + pointDistance: Infinity, }); let length = 0.0; @@ -122,24 +115,20 @@ function nearestPointOnLine( ); } - const lineLocationDist = distance(start, intersectPos, options); - const intersectPt = point(intersectPos, { - dist: distance(inputPoint, intersectPos, options), - multiFeatureIndex: multiFeatureIndex, - location: length + lineLocationDist, - multiFeatureLocation: multiFeatureLength + lineLocationDist, - }); - - if (intersectPt.properties.dist < closestPt.properties.dist) { - closestPt = { - ...intersectPt, - properties: { - ...intersectPt.properties, - // Legacy behaviour where index progresses to next segment # if we - // went with the end point this iteration. - index: wasEnd ? i + 1 : i, - }, - }; + const pointDistance = distance(inputPoint, intersectPos, options); + + if (pointDistance < closestPt.properties.pointDistance) { + const lineLocationDist = distance(start, intersectPos, options); + closestPt = point(intersectPos, { + lineStringIndex: multiFeatureIndex, + // Legacy behaviour where index progresses to next segment + // if we went with the end point this iteration. + segmentIndex: wasEnd ? i + 1 : i, + totalDistance: length + lineLocationDist, + lineDistance: multiFeatureLength + lineLocationDist, + segmentDistance: lineLocationDist, + pointDistance: pointDistance, + }); } // update length and multiFeatureLength diff --git a/packages/turf-nearest-point-on-line/test.ts b/packages/turf-nearest-point-on-line/test.ts index d1d61f176a..38051365e5 100644 --- a/packages/turf-nearest-point-on-line/test.ts +++ b/packages/turf-nearest-point-on-line/test.ts @@ -37,13 +37,16 @@ test("turf-nearest-point-on-line", (t) => { for (const { name, filename, geojson } of fixtures) { const [line, point] = geojson.features; const onLine = nearestPointOnLine(line, point); - onLine.properties["marker-color"] = "#F0F"; - onLine.properties.dist = round(onLine.properties.dist, 6); - onLine.properties.location = round(onLine.properties.location, 6); - onLine.properties.multiFeatureLocation = round( - onLine.properties.multiFeatureLocation, + onLine.geometry.coordinates[0] = round(onLine.geometry.coordinates[0], 6); + onLine.geometry.coordinates[1] = round(onLine.geometry.coordinates[1], 6); + onLine.properties.totalDistance = round(onLine.properties.totalDistance, 6); + onLine.properties.lineDistance = round(onLine.properties.lineDistance, 6); + onLine.properties.segmentDistance = round( + onLine.properties.segmentDistance, 6 ); + onLine.properties.pointDistance = round(onLine.properties.pointDistance, 6); + onLine.properties["marker-color"] = "#F0F"; const between = lineString( [onLine.geometry.coordinates, point.geometry.coordinates], { stroke: "#F00", "stroke-width": 6 } @@ -79,9 +82,9 @@ test("turf-nearest-point-on-line - first point", (t) => { "pt on start does not move" ); t.equal( - Number(snapped.properties.location.toFixed(6)), + Number(snapped.properties.totalDistance.toFixed(6)), 0, - "properties.location" + "properties.totalDistance" ); t.end(); @@ -108,7 +111,7 @@ test("turf-nearest-point-on-line - points behind first point", (t) => { first.geometry.coordinates, "pt behind start moves to first vertex" ); - expectedLocation.push(Number(snapped.properties.location.toFixed(6))); + expectedLocation.push(Number(snapped.properties.totalDistance.toFixed(6))); }); const filepath = @@ -117,7 +120,7 @@ test("turf-nearest-point-on-line - points behind first point", (t) => { t.deepEqual( loadJsonFileSync(filepath), expectedLocation, - "properties.location" + "properties.totalDistance" ); t.end(); }); @@ -146,7 +149,7 @@ test("turf-nearest-point-on-line - points in front of last point", (t) => { last.geometry.coordinates, "pt behind start moves to last vertex" ); - expectedLocation.push(Number(snapped.properties.location.toFixed(6))); + expectedLocation.push(Number(snapped.properties.totalDistance.toFixed(6))); }); const filepath = @@ -155,7 +158,7 @@ test("turf-nearest-point-on-line - points in front of last point", (t) => { t.deepEqual( loadJsonFileSync(filepath), expectedLocation, - "properties.location" + "properties.totalDistance" ); t.end(); }); @@ -209,7 +212,9 @@ test("turf-nearest-point-on-line - points on joints", (t) => { "pt on joint stayed in place" ); if (!expectedLocation[i]) expectedLocation[i] = []; - expectedLocation[i][j] = Number(snapped.properties.location.toFixed(6)); + expectedLocation[i][j] = Number( + snapped.properties.totalDistance.toFixed(6) + ); }); }); @@ -218,7 +223,7 @@ test("turf-nearest-point-on-line - points on joints", (t) => { t.deepEqual( expectedLocation, loadJsonFileSync(filepath), - "properties.location" + "properties.totalDistance" ); t.end(); }); @@ -249,7 +254,7 @@ test("turf-nearest-point-on-line - points on top of line", (t) => { const snapped = nearestPointOnLine(line, pt, { units: "miles" }); const shift = distance(pt, snapped, { units: "miles" }); t.true(shift < 0.000001, "pt did not shift far"); - expectedLocation.push(Number(snapped.properties.location.toFixed(6))); + expectedLocation.push(Number(snapped.properties.totalDistance.toFixed(6))); } const filepath = @@ -258,7 +263,7 @@ test("turf-nearest-point-on-line - points on top of line", (t) => { t.deepEqual( expectedLocation, loadJsonFileSync(filepath), - "properties.location" + "properties.totalDistance" ); t.end(); }); @@ -324,11 +329,11 @@ test("turf-nearest-point-on-line - check dist and index", (t) => { const pt = point([-92.110576, 41.040649]); const snapped = truncate(nearestPointOnLine(line, pt)); - t.equal(snapped.properties.index, 8, "properties.index"); + t.equal(snapped.properties.segmentIndex, 8, "properties.segmentIndex"); t.equal( - Number(snapped.properties.dist.toFixed(6)), + Number(snapped.properties.pointDistance.toFixed(6)), 0.823802, - "properties.dist" + "properties.pointDistance" ); t.deepEqual( snapped.geometry.coordinates, @@ -346,9 +351,9 @@ test("turf-nearest-point-on-line -- Issue #691", (t) => { [9, 50], ]); const pointAlong = along(line1, 10); - const { location } = nearestPointOnLine(line1, pointAlong).properties; + const { totalDistance } = nearestPointOnLine(line1, pointAlong).properties; - t.false(isNaN(location)); + t.false(isNaN(totalDistance)); t.end(); }); @@ -396,9 +401,9 @@ test("turf-nearest-point-on-line -- multifeature index", (t) => { ], ]); t.equal( - nearestPointOnLine(multiLine.geometry, pt).properties.multiFeatureIndex, + nearestPointOnLine(multiLine.geometry, pt).properties.lineStringIndex, 1, - "multiFeatureIndex" + "properties.lineStringIndex" ); t.end(); }); @@ -422,14 +427,14 @@ test("turf-nearest-point-on-line -- issue 2753 multifeature location", (t) => { const nearestToB = nearestPointOnLine(multiLine, ptB, { units: "meters" }); t.equal( - Number(nearestToA.properties.multiFeatureLocation.toFixed(6)), + Number(nearestToA.properties.lineDistance.toFixed(6)), 150.296465, - "nearestToA multiFeatureLocation" + "nearestToA lineDistance" ); t.equal( - Number(nearestToB.properties.multiFeatureLocation.toFixed(6)), + Number(nearestToB.properties.lineDistance.toFixed(6)), 157.738215, - "nearestToB multiFeatureLocation" + "nearestToB lineDistance" ); t.end(); }); @@ -549,7 +554,7 @@ test("turf-nearest-point-on-line -- issue 2808 redundant point support", (t) => const thePoint = point([10.57846, 49.8468386]); const nearest = nearestPointOnLine(line1, thePoint); // should not throw - t.equal(nearest.properties.dist, 0, "redundant point should not throw"); + t.equal(nearest.properties.pointDistance, 0, "redundant point support"); t.end(); }); @@ -563,8 +568,8 @@ test("turf-nearest-point-on-line -- duplicate points on line string shouldn't br ]); const userPoint = point([-80.191762, 25.885587]); const nearest = nearestPointOnLine(line, userPoint, { units: "meters" }); - t.equal(nearest.properties.dist > 4, true, "dist should be greater than 4"); - t.equal(nearest.properties.location, 0, "location should be 0"); + t.equal(nearest.properties.pointDistance > 4, true, "pointDistance be > 4"); + t.equal(nearest.properties.totalDistance, 0, "totalDistance be 0"); t.end(); }); diff --git a/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson b/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson index a2c63eb1ba..6f9fda4842 100644 --- a/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson +++ b/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson @@ -39,11 +39,12 @@ { "type": "Feature", "properties": { - "dist": 5.959562, - "multiFeatureIndex": 0, - "location": 19.748879, - "multiFeatureLocation": 19.748879, - "index": 1, + "lineStringIndex": 0, + "segmentIndex": 1, + "totalDistance": 19.748879, + "lineDistance": 19.748879, + "segmentDistance": 1.771897, + "pointDistance": 5.959562, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/line1.geojson b/packages/turf-nearest-point-on-line/test/out/line1.geojson index b16f86d055..5cd2985313 100644 --- a/packages/turf-nearest-point-on-line/test/out/line1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/line1.geojson @@ -39,11 +39,12 @@ { "type": "Feature", "properties": { - "dist": 2.556271, - "multiFeatureIndex": 0, - "location": 22.137494, - "multiFeatureLocation": 22.137494, - "index": 1, + "lineStringIndex": 0, + "segmentIndex": 1, + "totalDistance": 22.137494, + "lineDistance": 22.137494, + "segmentDistance": 3.445915, + "pointDistance": 2.556271, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson index fbd6b87bc8..1509aa498b 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson @@ -67,11 +67,12 @@ { "type": "Feature", "properties": { - "dist": 114.725451, - "index": 21, - "multiFeatureIndex": 1, - "location": 9479.011715, - "multiFeatureLocation": 4800.716022, + "lineStringIndex": 1, + "segmentIndex": 21, + "totalDistance": 9479.011715, + "lineDistance": 4800.716022, + "segmentDistance": 173.221741, + "pointDistance": 114.725451, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson index cfd5ce7482..d6f1dab2cb 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson @@ -48,11 +48,12 @@ { "type": "Feature", "properties": { - "dist": 390.942725, - "index": 0, - "multiFeatureIndex": 1, - "location": 1656.139708, - "multiFeatureLocation": 0, + "lineStringIndex": 1, + "segmentIndex": 0, + "totalDistance": 1656.139708, + "lineDistance": 0, + "segmentDistance": 0, + "pointDistance": 390.942725, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson index cbee7754fd..e5e78b9281 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson @@ -57,11 +57,12 @@ { "type": "Feature", "properties": { - "dist": 121.937841, - "multiFeatureIndex": 0, - "location": 214.735285, - "multiFeatureLocation": 214.735285, - "index": 0, + "lineStringIndex": 0, + "segmentIndex": 0, + "totalDistance": 214.735285, + "lineDistance": 214.735285, + "segmentDistance": 214.735285, + "pointDistance": 121.937841, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/route1.geojson b/packages/turf-nearest-point-on-line/test/out/route1.geojson index d38a116b52..1095737315 100644 --- a/packages/turf-nearest-point-on-line/test/out/route1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/route1.geojson @@ -4792,11 +4792,12 @@ { "type": "Feature", "properties": { - "dist": 7.876557, - "multiFeatureIndex": 0, - "location": 183.46844, - "multiFeatureLocation": 183.46844, - "index": 3104, + "lineStringIndex": 0, + "segmentIndex": 3104, + "totalDistance": 183.46844, + "lineDistance": 183.46844, + "segmentDistance": 0.044741, + "pointDistance": 7.876557, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/route2.geojson b/packages/turf-nearest-point-on-line/test/out/route2.geojson index 518f884ded..7e627fd54e 100644 --- a/packages/turf-nearest-point-on-line/test/out/route2.geojson +++ b/packages/turf-nearest-point-on-line/test/out/route2.geojson @@ -3796,11 +3796,12 @@ { "type": "Feature", "properties": { - "dist": 19.22738, - "multiFeatureIndex": 0, - "location": 303.639629, - "multiFeatureLocation": 303.639629, - "index": 1185, + "lineStringIndex": 0, + "segmentIndex": 1185, + "totalDistance": 303.639629, + "lineDistance": 303.639629, + "segmentDistance": 0.867249, + "pointDistance": 19.22738, "marker-color": "#F0F" }, "geometry": { From 4994d889442cc22e90a4bb417c1002acf5afcd10 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:49:16 +0100 Subject: [PATCH 5/9] nearest-point-on-line Rename some internal variables --- packages/turf-nearest-point-on-line/index.ts | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/turf-nearest-point-on-line/index.ts b/packages/turf-nearest-point-on-line/index.ts index 0de3f34a01..1aeaf590c8 100644 --- a/packages/turf-nearest-point-on-line/index.ts +++ b/packages/turf-nearest-point-on-line/index.ts @@ -71,16 +71,16 @@ function nearestPointOnLine( pointDistance: Infinity, }); - let length = 0.0; - let multiFeatureLength = 0.0; - let currentMultiFeatureIndex = -1; + let totalDistance = 0.0; + let lineDistance = 0.0; + let currentLineStringIndex = -1; flattenEach( lines, - function (line: any, _featureIndex: number, multiFeatureIndex: number) { - //reset multiFeatureLength at each changed multiFeatureIndex - if (currentMultiFeatureIndex !== multiFeatureIndex) { - currentMultiFeatureIndex = multiFeatureIndex; - multiFeatureLength = 0.0; + function (line: any, _featureIndex: number, lineStringIndex: number) { + //reset lineDistance at each changed lineStringIndex + if (currentLineStringIndex !== lineStringIndex) { + currentLineStringIndex = lineStringIndex; + lineDistance = 0.0; } const coords: any = getCoords(line); @@ -94,8 +94,8 @@ function nearestPointOnLine( const stop: Feature = point(coords[i + 1]); const stopPos = getCoord(stop); - // sectionLength - const sectionLength = distance(start, stop, options); + // segmentLength + const segmentLength = distance(start, stop, options); let intersectPos: Position; let wasEnd: boolean; @@ -118,22 +118,22 @@ function nearestPointOnLine( const pointDistance = distance(inputPoint, intersectPos, options); if (pointDistance < closestPt.properties.pointDistance) { - const lineLocationDist = distance(start, intersectPos, options); + const segmentDistance = distance(start, intersectPos, options); closestPt = point(intersectPos, { - lineStringIndex: multiFeatureIndex, + lineStringIndex: lineStringIndex, // Legacy behaviour where index progresses to next segment // if we went with the end point this iteration. segmentIndex: wasEnd ? i + 1 : i, - totalDistance: length + lineLocationDist, - lineDistance: multiFeatureLength + lineLocationDist, - segmentDistance: lineLocationDist, + totalDistance: totalDistance + segmentDistance, + lineDistance: lineDistance + segmentDistance, + segmentDistance: segmentDistance, pointDistance: pointDistance, }); } - // update length and multiFeatureLength - length += sectionLength; - multiFeatureLength += sectionLength; + // update totalDistance and lineDistance + totalDistance += segmentLength; + lineDistance += segmentLength; } } ); From 7f36fea188e7ab9d29e8c56070f45382b13477ff Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:05:38 +0100 Subject: [PATCH 6/9] nearest-point-on-line Add back deprecated properties --- packages/turf-nearest-point-on-line/index.ts | 25 +++++++++++++++++++ packages/turf-nearest-point-on-line/test.ts | 4 +++ .../out/line-northern-latitude-#344.geojson | 4 +++ .../test/out/line1.geojson | 4 +++ .../test/out/multiLine1.geojson | 4 +++ .../test/out/multiLine2.geojson | 4 +++ .../test/out/multiLine3.geojson | 4 +++ .../test/out/route1.geojson | 4 +++ .../test/out/route2.geojson | 4 +++ 9 files changed, 57 insertions(+) diff --git a/packages/turf-nearest-point-on-line/index.ts b/packages/turf-nearest-point-on-line/index.ts index 1aeaf590c8..ce7875f6ca 100644 --- a/packages/turf-nearest-point-on-line/index.ts +++ b/packages/turf-nearest-point-on-line/index.ts @@ -53,6 +53,12 @@ function nearestPointOnLine( lineDistance: number; segmentDistance: number; pointDistance: number; + // deprecated properties START + multiFeatureIndex: number; // replaced by lineStringIndex + index: number; // replaced by segmentIndex + location: number; // replaced by totalDistance + dist: number; // replaced by pointDistance + // deprecated properties END [key: string]: any; } > { @@ -69,6 +75,12 @@ function nearestPointOnLine( lineDistance: -1, segmentDistance: -1, pointDistance: Infinity, + // deprecated properties START + multiFeatureIndex: -1, + index: -1, + location: -1, + dist: Infinity, + // deprecated properties END }); let totalDistance = 0.0; @@ -128,7 +140,20 @@ function nearestPointOnLine( lineDistance: lineDistance + segmentDistance, segmentDistance: segmentDistance, pointDistance: pointDistance, + // deprecated properties START + multiFeatureIndex: -1, + index: -1, + location: -1, + dist: Infinity, }); + closestPt.properties = { + ...closestPt.properties, + multiFeatureIndex: closestPt.properties.lineStringIndex, + index: closestPt.properties.segmentIndex, + location: closestPt.properties.totalDistance, + dist: closestPt.properties.pointDistance, + // deprecated properties END + }; } // update totalDistance and lineDistance diff --git a/packages/turf-nearest-point-on-line/test.ts b/packages/turf-nearest-point-on-line/test.ts index 38051365e5..8a0caccae5 100644 --- a/packages/turf-nearest-point-on-line/test.ts +++ b/packages/turf-nearest-point-on-line/test.ts @@ -46,6 +46,10 @@ test("turf-nearest-point-on-line", (t) => { 6 ); onLine.properties.pointDistance = round(onLine.properties.pointDistance, 6); + // deprecated properties START + onLine.properties.location = round(onLine.properties.location, 6); + onLine.properties.dist = round(onLine.properties.dist, 6); + // deprecated properties END onLine.properties["marker-color"] = "#F0F"; const between = lineString( [onLine.geometry.coordinates, point.geometry.coordinates], diff --git a/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson b/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson index 6f9fda4842..10518c5c43 100644 --- a/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson +++ b/packages/turf-nearest-point-on-line/test/out/line-northern-latitude-#344.geojson @@ -45,6 +45,10 @@ "lineDistance": 19.748879, "segmentDistance": 1.771897, "pointDistance": 5.959562, + "dist": 5.959562, + "multiFeatureIndex": 0, + "location": 19.748879, + "index": 1, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/line1.geojson b/packages/turf-nearest-point-on-line/test/out/line1.geojson index 5cd2985313..0d99764126 100644 --- a/packages/turf-nearest-point-on-line/test/out/line1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/line1.geojson @@ -45,6 +45,10 @@ "lineDistance": 22.137494, "segmentDistance": 3.445915, "pointDistance": 2.556271, + "dist": 2.556271, + "multiFeatureIndex": 0, + "location": 22.137494, + "index": 1, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson index 1509aa498b..ad4ceee464 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine1.geojson @@ -73,6 +73,10 @@ "lineDistance": 4800.716022, "segmentDistance": 173.221741, "pointDistance": 114.725451, + "dist": 114.725451, + "multiFeatureIndex": 1, + "location": 9479.011715, + "index": 21, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson index d6f1dab2cb..33d69b0377 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine2.geojson @@ -54,6 +54,10 @@ "lineDistance": 0, "segmentDistance": 0, "pointDistance": 390.942725, + "dist": 390.942725, + "multiFeatureIndex": 1, + "location": 1656.139708, + "index": 0, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson b/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson index e5e78b9281..60de5cb7b1 100644 --- a/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson +++ b/packages/turf-nearest-point-on-line/test/out/multiLine3.geojson @@ -63,6 +63,10 @@ "lineDistance": 214.735285, "segmentDistance": 214.735285, "pointDistance": 121.937841, + "dist": 121.937841, + "multiFeatureIndex": 0, + "location": 214.735285, + "index": 0, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/route1.geojson b/packages/turf-nearest-point-on-line/test/out/route1.geojson index 1095737315..cafeca72c1 100644 --- a/packages/turf-nearest-point-on-line/test/out/route1.geojson +++ b/packages/turf-nearest-point-on-line/test/out/route1.geojson @@ -4798,6 +4798,10 @@ "lineDistance": 183.46844, "segmentDistance": 0.044741, "pointDistance": 7.876557, + "dist": 7.876557, + "multiFeatureIndex": 0, + "location": 183.46844, + "index": 3104, "marker-color": "#F0F" }, "geometry": { diff --git a/packages/turf-nearest-point-on-line/test/out/route2.geojson b/packages/turf-nearest-point-on-line/test/out/route2.geojson index 7e627fd54e..c2cc1bb967 100644 --- a/packages/turf-nearest-point-on-line/test/out/route2.geojson +++ b/packages/turf-nearest-point-on-line/test/out/route2.geojson @@ -3802,6 +3802,10 @@ "lineDistance": 303.639629, "segmentDistance": 0.867249, "pointDistance": 19.22738, + "dist": 19.22738, + "multiFeatureIndex": 0, + "location": 303.639629, + "index": 1185, "marker-color": "#F0F" }, "geometry": { From 4f5dd3005f0bb7aa26e4d8d714891cda8036c51b Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:07:26 +0100 Subject: [PATCH 7/9] nearest-point-on-line Mark old properties as deprecated --- packages/turf-nearest-point-on-line/index.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/turf-nearest-point-on-line/index.ts b/packages/turf-nearest-point-on-line/index.ts index ce7875f6ca..45e8c24975 100644 --- a/packages/turf-nearest-point-on-line/index.ts +++ b/packages/turf-nearest-point-on-line/index.ts @@ -54,10 +54,14 @@ function nearestPointOnLine( segmentDistance: number; pointDistance: number; // deprecated properties START - multiFeatureIndex: number; // replaced by lineStringIndex - index: number; // replaced by segmentIndex - location: number; // replaced by totalDistance - dist: number; // replaced by pointDistance + /** @deprecated use `lineStringIndex` instead */ + multiFeatureIndex: number; + /** @deprecated use `segmentIndex` instead */ + index: number; + /** @deprecated use `totalDistance` instead */ + location: number; + /** @deprecated use `pointDistance` instead */ + dist: number; // deprecated properties END [key: string]: any; } From 1566b353f151d1b2ed54411791106af5e06db557 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:12:28 +0100 Subject: [PATCH 8/9] nearest-point-on-line Clean up tests --- packages/turf-nearest-point-on-line/test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/turf-nearest-point-on-line/test.ts b/packages/turf-nearest-point-on-line/test.ts index 8a0caccae5..4bd13e3bd4 100644 --- a/packages/turf-nearest-point-on-line/test.ts +++ b/packages/turf-nearest-point-on-line/test.ts @@ -47,8 +47,8 @@ test("turf-nearest-point-on-line", (t) => { ); onLine.properties.pointDistance = round(onLine.properties.pointDistance, 6); // deprecated properties START - onLine.properties.location = round(onLine.properties.location, 6); onLine.properties.dist = round(onLine.properties.dist, 6); + onLine.properties.location = round(onLine.properties.location, 6); // deprecated properties END onLine.properties["marker-color"] = "#F0F"; const between = lineString( @@ -318,7 +318,7 @@ test("turf-nearest-point-on-line - points on sides of lines", (t) => { t.end(); }); -test("turf-nearest-point-on-line - check dist and index", (t) => { +test("turf-nearest-point-on-line - segmentIndex and pointDistance", (t) => { const line = lineString([ [-92.090492, 41.102897], [-92.191085, 41.079868], @@ -390,7 +390,7 @@ test("turf-nearest-point-on-line -- Geometry Support", (t) => { t.end(); }); -test("turf-nearest-point-on-line -- multifeature index", (t) => { +test("turf-nearest-point-on-line -- lineStringIndex", (t) => { const pt = point([4, 30]); const multiLine = multiLineString([ [ @@ -412,7 +412,7 @@ test("turf-nearest-point-on-line -- multifeature index", (t) => { t.end(); }); -test("turf-nearest-point-on-line -- issue 2753 multifeature location", (t) => { +test("turf-nearest-point-on-line -- issue 2753", (t) => { const multiLine = multiLineString([ [ [-122.3125, 47.6632], From 5c89527ceb2c5d735350c171b444420dbc26fc28 Mon Sep 17 00:00:00 2001 From: Emil Junker <19289477+EmilJunker@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:36:19 +0100 Subject: [PATCH 9/9] nearest-point-on-line Update README --- packages/turf-nearest-point-on-line/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/turf-nearest-point-on-line/README.md b/packages/turf-nearest-point-on-line/README.md index 30a732d28d..c6aba3c0e8 100644 --- a/packages/turf-nearest-point-on-line/README.md +++ b/packages/turf-nearest-point-on-line/README.md @@ -12,8 +12,8 @@ on the line. ### Parameters -* `lines` **([Geometry][1] | [Feature][2]<([LineString][3] | [MultiLineString][4])>)** lines to snap to -* `pt` **([Geometry][1] | [Feature][2]<[Point][5]> | [Array][6]<[number][7]>)** point to snap from +* `lines` **([Geometry][1] | [Feature][2]<([LineString][3] | [MultiLineString][4])>)** Lines to snap to +* `inputPoint` **([Geometry][1] | [Feature][2]<[Point][5]> | [Array][6]<[number][7]>)** Point to snap from * `options` **[Object][8]** Optional parameters (optional, default `{}`) * `options.units` **Units** Supports all valid Turf [Units][9] (optional, default `'kilometers'`) @@ -29,16 +29,16 @@ var line = turf.lineString([ [-77.021884, 38.889563], [-77.019824, 38.892368] ]); -var pt = turf.point([-77.037076, 38.884017]); +var inputPoint = turf.point([-77.037076, 38.884017]); -var snapped = turf.nearestPointOnLine(line, pt, {units: 'miles'}); +var snapped = turf.nearestPointOnLine(line, inputPoint, {units: 'miles'}); //addToMap -var addToMap = [line, pt, snapped]; +var addToMap = [line, inputPoint, snapped]; snapped.properties['marker-color'] = '#00f'; ``` -Returns **[Feature][2]<[Point][5]>** closest point on the `line` to `point`. The properties object will contain four values: `index`: closest point was found on nth line part, `multiFeatureIndex`: closest point was found on the nth line of the `MultiLineString`, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point. +Returns **[Feature][2]<[Point][5]>** closest point on the `lines` to the `inputPoint`. The point will have the following properties: `lineStringIndex`: closest point was found on the nth LineString (only relevant if input is MultiLineString), `segmentIndex`: closest point was found on nth line segment of the LineString, `totalDistance`: distance along the line from the absolute start of the MultiLineString, `lineDistance`: distance along the line from the start of the LineString where the closest point was found, `segmentDistance`: distance along the line from the start of the line segment where the closest point was found, `pointDistance`: distance to the input point. [1]: https://tools.ietf.org/html/rfc7946#section-3.1