diff --git a/packages/turf-midpoint/index.ts b/packages/turf-midpoint/index.ts index 70ccef3f5..6bb791de0 100644 --- a/packages/turf-midpoint/index.ts +++ b/packages/turf-midpoint/index.ts @@ -3,6 +3,7 @@ import { bearing } from "@turf/bearing"; import { destination } from "@turf/destination"; import { distance } from "@turf/distance"; import { Coord } from "@turf/helpers"; +import { getCoord } from "@turf/invariant"; /** * Takes two points and returns a point midway between them. The midpoint is @@ -28,6 +29,14 @@ function midpoint(point1: Coord, point2: Coord): Feature { const heading = bearing(point1, point2); const midpoint = destination(point1, dist / 2, heading); + // Interpolate altitude (z-coordinate) when both input points carry one. + // destination() propagates only the origin's z unchanged; average them instead. + const coord1 = getCoord(point1); + const coord2 = getCoord(point2); + if (coord1[2] !== undefined && coord2[2] !== undefined) { + midpoint.geometry.coordinates[2] = (coord1[2] + coord2[2]) / 2; + } + return midpoint; } diff --git a/packages/turf-midpoint/package.json b/packages/turf-midpoint/package.json index f3f24b63a..9fb062f0f 100644 --- a/packages/turf-midpoint/package.json +++ b/packages/turf-midpoint/package.json @@ -64,6 +64,7 @@ "@turf/destination": "workspace:*", "@turf/distance": "workspace:*", "@turf/helpers": "workspace:*", + "@turf/invariant": "workspace:*", "@types/geojson": "catalog:", "tslib": "catalog:" } diff --git a/packages/turf-midpoint/test.ts b/packages/turf-midpoint/test.ts index a55881ec3..bc7019869 100644 --- a/packages/turf-midpoint/test.ts +++ b/packages/turf-midpoint/test.ts @@ -68,3 +68,34 @@ test("midpoint -- long distance", function (t) { t.end(); }); +test("midpoint -- interpolates altitude (z-coordinate) from 3D points", function (t) { + var pt1 = point([0, 0, 100]); + var pt2 = point([10, 0, 200]); + + var mid = midpoint(pt1, pt2); + var coords = mid.geometry.coordinates; + + // The midpoint of two 3D points must interpolate z as the average + t.equal( + coords[2], + 150, + "z should be the average of the two input altitudes (100+200)/2 = 150" + ); + + t.end(); +}); + +test("midpoint -- returns undefined z when inputs have no altitude", function (t) { + var pt1 = point([0, 0]); + var pt2 = point([10, 0]); + + var mid = midpoint(pt1, pt2); + + t.equal( + mid.geometry.coordinates[2], + undefined, + "z should be undefined when inputs have no altitude" + ); + + t.end(); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac1488206..7bb37ee1b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4173,6 +4173,9 @@ importers: '@turf/helpers': specifier: workspace:* version: link:../turf-helpers + '@turf/invariant': + specifier: workspace:* + version: link:../turf-invariant '@types/geojson': specifier: 'catalog:' version: 7946.0.14 @@ -7288,6 +7291,7 @@ packages: '@lerna/create@9.0.3': resolution: {integrity: sha512-hUTEWrR8zH+/Z3bp/R1aLm6DW8vB/BB7KH7Yeg4fMfrvSwxegiLVW9uJFAzWkK4mzEagmj/Dti85Yg9MN13t0g==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + deprecated: This package is an implementation detail of Lerna and is no longer published separately. '@ljharb/resumer@0.1.3': resolution: {integrity: sha512-d+tsDgfkj9X5QTriqM4lKesCkMMJC3IrbPKHvayP00ELx2axdXvDfWkqjxrLXIzGcQzmj7VAUT1wopqARTvafw==} @@ -8443,6 +8447,7 @@ packages: conventional-changelog-core@5.0.1: resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Please use conventional-changelog instead. conventional-changelog-preset-loader@3.0.0: resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} @@ -9158,6 +9163,7 @@ packages: git-raw-commits@3.0.0: resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. hasBin: true git-remote-origin-url@2.0.0: @@ -9167,6 +9173,7 @@ packages: git-semver-tags@5.0.1: resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. hasBin: true git-up@7.0.0: @@ -11361,10 +11368,12 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me temp-dir@1.0.0: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==}