diff --git a/CHANGELOG.md b/CHANGELOG.md index c58e93be2..c43103c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Mapbox welcomes participation and contributions from everyone. ### main +- Fixed `TurfMisc#lineSliceAlong` dropping the altitude of the line's vertices, a regression introduced in v7.10.0. ### v7.10.0 - February 05, 2026 - Added `DirectionsRefreshResponse#fromJson(Reader)`, a static factory method that deserializes a `DirectionsRefreshResponse` from a `java.io.Reader`. diff --git a/scripts/coverage.sh b/scripts/coverage.sh index 00b52cbc1..0a9593c4e 100644 --- a/scripts/coverage.sh +++ b/scripts/coverage.sh @@ -3,7 +3,7 @@ set -eoux # control sum of the key is const: echo | shasum -a 256 pgp_keys.asc shaSumAscKey="d56942c32a1bb70af75bf972302b6114049fb59cb76193fac349bb9b587b60c2" -curl https://keybase.io/codecovsecurity/pgp_keys.asc -o pgp_keys.asc +curl https://uploader.codecov.io/verification.gpg -o pgp_keys.asc # check sum echo "$shaSumAscKey pgp_keys.asc" | shasum -a 256 -c @@ -21,4 +21,4 @@ gpgv codecov.SHA256SUM.sig codecov.SHA256SUM shasum -a 256 -c codecov.SHA256SUM chmod +x codecov -./codecov \ No newline at end of file +./codecov diff --git a/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java b/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java index 3209cb68b..c1705f103 100644 --- a/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java +++ b/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java @@ -5,6 +5,7 @@ import androidx.annotation.Nullable; import com.mapbox.geojson.Feature; +import com.mapbox.geojson.FlattenListOfPoints; import com.mapbox.geojson.LineString; import com.mapbox.geojson.Point; import com.mapbox.turf.models.LineIntersectsResult; @@ -188,9 +189,11 @@ public static LineString lineSliceAlong(@NonNull LineString line, @FloatRange(from = 0) double stopDist, @NonNull @TurfConstants.TurfUnitCriteria String units) { - double[] coords = line.flattenCoordinates().getFlattenLngLatArray(); + FlattenListOfPoints flattenCoordinates = line.flattenCoordinates(); + double[] coords = flattenCoordinates.getFlattenLngLatArray(); + double[] altitudes = flattenCoordinates.getAltitudes(); - int size = line.flattenCoordinates().size(); + int size = flattenCoordinates.size(); if (size < 2) { throw new TurfException("Turf lineSlice requires a LineString Geometry made up of " + "at least 2 coordinates. The LineString passed in only contains " + size + "."); @@ -203,7 +206,9 @@ public static LineString lineSliceAlong(@NonNull LineString line, double travelled = 0; for (int i = 0; i < size; i++) { - Point pointAtI = Point.fromLngLat(coords[i * 2], coords[i * 2 + 1]); + // Altitude is kept only for the original vertices: the interpolated start and stop points + // are computed with 2D math (see TurfMeasurement#destination) and have no altitude. + Point pointAtI = pointAt(coords, altitudes, i); if (startDist >= travelled && i == size - 1) { break; @@ -247,6 +252,16 @@ public static LineString lineSliceAlong(@NonNull LineString line, return LineString.fromLngLats(slice); } + @NonNull + private static Point pointAt(@NonNull double[] coords, @Nullable double[] altitudes, int index) { + double longitude = coords[index * 2]; + double latitude = coords[(index * 2) + 1]; + if (altitudes != null && !Double.isNaN(altitudes[index])) { + return Point.fromLngLat(longitude, latitude, altitudes[index]); + } + return Point.fromLngLat(longitude, latitude); + } + /** * Takes a {@link Point} and a {@link LineString} and calculates the closest Point on the * LineString. diff --git a/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java b/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java index d277d244a..a01b4b870 100644 --- a/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java +++ b/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java @@ -583,6 +583,27 @@ public void testLineAlongStopLongerThanLength() throws IOException, TurfExceptio lineCoordinates.get(lineCoordinates.size() - 1).flattenCoordinates(), DELTA); } + @Test + public void testLineSliceAlongPreservesAltitude() throws TurfException { + List input = Arrays.asList( + Point.fromLngLat(113.99414062499999, 22.350075806124867, 10.0), + Point.fromLngLat(115.0, 22.8, 20.0), + Point.fromLngLat(116.76269531249999, 23.241346102386135, 30.0)); + LineString line = LineString.fromLngLats(input); + + // Slicing the whole line means every returned point is an original vertex. + double stop = TurfMeasurement.length(line, TurfConstants.UNIT_MILES); + LineString sliced = TurfMisc.lineSliceAlong(line, 0, stop, TurfConstants.UNIT_MILES); + + List slicedCoordinates = sliced.coordinates(); + assertEquals(input.size(), slicedCoordinates.size()); + for (int i = 0; i < input.size(); i++) { + assertTrue("point " + i + " lost altitude", slicedCoordinates.get(i).hasAltitude()); + assertArrayEquals(input.get(i).flattenCoordinates(), + slicedCoordinates.get(i).flattenCoordinates(), DELTA); + } + } + @Test public void testShortLine() throws IOException, TurfException {