var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); // index.ts import { distance } from "@turf/distance"; import { flattenEach } from "@turf/meta"; import { point, degreesToRadians, radiansToDegrees } from "@turf/helpers"; import { getCoord, getCoords } from "@turf/invariant"; function nearestPointOnLine(lines, pt, options = {}) { if (!lines || !pt) { throw new Error("lines and pt are required arguments"); } const ptPos = getCoord(pt); let closestPt = point([Infinity, Infinity], { dist: Infinity, index: -1, multiFeatureIndex: -1, location: -1 }); let length = 0; flattenEach( lines, function(line, _featureIndex, multiFeatureIndex) { const coords = getCoords(line); for (let i = 0; i < coords.length - 1; i++) { const start = point(coords[i]); start.properties.dist = distance(pt, start, options); const startPos = getCoord(start); const stop = point(coords[i + 1]); stop.properties.dist = distance(pt, stop, options); const stopPos = getCoord(stop); const sectionLength = distance(start, stop, options); let intersectPos; let wasEnd; if (startPos[0] === ptPos[0] && startPos[1] === ptPos[1]) { [intersectPos, , wasEnd] = [startPos, void 0, false]; } else if (stopPos[0] === ptPos[0] && stopPos[1] === ptPos[1]) { [intersectPos, , wasEnd] = [stopPos, void 0, true]; } else { [intersectPos, , wasEnd] = nearestPointOnSegment( start.geometry.coordinates, stop.geometry.coordinates, getCoord(pt) ); } let intersectPt; if (intersectPos) { intersectPt = point(intersectPos, { dist: distance(pt, intersectPos, options), multiFeatureIndex, location: length + distance(start, intersectPos, options) }); } if (intersectPt && intersectPt.properties.dist < closestPt.properties.dist) { closestPt = __spreadProps(__spreadValues({}, intersectPt), { properties: __spreadProps(__spreadValues({}, intersectPt.properties), { // Legacy behaviour where index progresses to next segment # if we // went with the end point this iteration. index: wasEnd ? i + 1 : i }) }); } length += sectionLength; } } ); return closestPt; } function dot(v1, v2) { const [v1x, v1y, v1z] = v1; const [v2x, v2y, v2z] = v2; return v1x * v2x + v1y * v2y + v1z * v2z; } function cross(v1, v2) { const [v1x, v1y, v1z] = v1; const [v2x, v2y, v2z] = v2; return [v1y * v2z - v1z * v2y, v1z * v2x - v1x * v2z, v1x * v2y - v1y * v2x]; } function magnitude(v) { return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2) + Math.pow(v[2], 2)); } function angle(v1, v2) { const theta = dot(v1, v2) / (magnitude(v1) * magnitude(v2)); return Math.acos(Math.min(Math.max(theta, -1), 1)); } function lngLatToVector(a) { const lat = degreesToRadians(a[1]); const lng = degreesToRadians(a[0]); return [ Math.cos(lat) * Math.cos(lng), Math.cos(lat) * Math.sin(lng), Math.sin(lat) ]; } function vectorToLngLat(v) { const [x, y, z] = v; const lat = radiansToDegrees(Math.asin(z)); const lng = radiansToDegrees(Math.atan2(y, x)); return [lng, lat]; } function nearestPointOnSegment(posA, posB, posC) { const A = lngLatToVector(posA); const B = lngLatToVector(posB); const C = lngLatToVector(posC); const [Cx, Cy, Cz] = C; const [D, E, F] = cross(A, B); const a = E * Cz - F * Cy; const b = F * Cx - D * Cz; const c = D * Cy - E * Cx; const f = c * E - b * F; const g = a * F - c * D; const h = b * D - a * E; const t = 1 / Math.sqrt(Math.pow(f, 2) + Math.pow(g, 2) + Math.pow(h, 2)); const I1 = [f * t, g * t, h * t]; const I2 = [-1 * f * t, -1 * g * t, -1 * h * t]; const angleAB = angle(A, B); const angleAI1 = angle(A, I1); const angleBI1 = angle(B, I1); const angleAI2 = angle(A, I2); const angleBI2 = angle(B, I2); let I; if (angleAI1 < angleAI2 && angleAI1 < angleBI2 || angleBI1 < angleAI2 && angleBI1 < angleBI2) { I = I1; } else { I = I2; } if (angle(A, I) > angleAB || angle(B, I) > angleAB) { if (distance(vectorToLngLat(I), vectorToLngLat(A)) <= distance(vectorToLngLat(I), vectorToLngLat(B))) { return [vectorToLngLat(A), true, false]; } else { return [vectorToLngLat(B), false, true]; } } return [vectorToLngLat(I), false, false]; } var turf_nearest_point_on_line_default = nearestPointOnLine; export { turf_nearest_point_on_line_default as default, nearestPointOnLine }; //# sourceMappingURL=index.js.map