object)
throws IOException {
if (object == null) {
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
index 5cd842b28..25972599b 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
@@ -90,7 +90,7 @@ public double[] getFlattenLatLngArray() {
/**
* @return an array of all the altitudes (or null if no altitudes are present at all). If a
- * coordinate does not contain altitude it's represented as {@link Double#NaN}
+ * coordinate does not contain altitude it's represented as {@link Double#NaN}
*/
@Nullable
public double[] getAltitudes() {
@@ -100,7 +100,8 @@ public double[] getAltitudes() {
/**
* Creates a list of {@link Point}s and returns it.
*
- * If possible consider using {@link #getFlattenLatLngArray()} and {@link #getAltitudes()} instead.
+ * If possible consider using {@link #getFlattenLatLngArray()} and {@link #getAltitudes()}
+ * instead.
*
* @return a list of {@link Point}s
*/
@@ -113,7 +114,11 @@ public List points() {
for (int i = 0; i < flattenLatLngPoints.length / 2; i++) {
double[] coordinates;
if (altitudes != null && !Double.isNaN(altitudes[i])) {
- coordinates = new double[]{flattenLatLngPoints[i * 2], flattenLatLngPoints[(i * 2) + 1], altitudes[i]};
+ coordinates = new double[]{
+ flattenLatLngPoints[i * 2],
+ flattenLatLngPoints[(i * 2) + 1],
+ altitudes[i]
+ };
} else {
coordinates = new double[]{flattenLatLngPoints[i * 2], flattenLatLngPoints[(i * 2) + 1]};
}
@@ -131,13 +136,21 @@ public List points() {
@Override
public boolean equals(Object o) {
- if (!(o instanceof FlattenListOfPoints)) return false;
+ if (!(o instanceof FlattenListOfPoints)) {
+ return false;
+ }
FlattenListOfPoints that = (FlattenListOfPoints) o;
- return Objects.deepEquals(flattenLatLngPoints, that.flattenLatLngPoints) && Objects.deepEquals(altitudes, that.altitudes) && Objects.deepEquals(boundingBoxes, that.boundingBoxes);
+ return Objects.deepEquals(flattenLatLngPoints, that.flattenLatLngPoints)
+ && Objects.deepEquals(altitudes, that.altitudes)
+ && Objects.deepEquals(boundingBoxes, that.boundingBoxes);
}
@Override
public int hashCode() {
- return Objects.hash(Arrays.hashCode(flattenLatLngPoints), Arrays.hashCode(altitudes), Arrays.hashCode(boundingBoxes));
+ return Objects.hash(
+ Arrays.hashCode(flattenLatLngPoints),
+ Arrays.hashCode(altitudes),
+ Arrays.hashCode(boundingBoxes)
+ );
}
}
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java
index e22d898ed..6a7a5cb12 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java
@@ -34,9 +34,16 @@ public void write(JsonWriter out, FlattenListOfPoints flattenListOfPoints) throw
for (int i = 0; i < flattenLatLngCoordinates.length / 2; i++) {
double[] value;
if (altitudes != null && !Double.isNaN(altitudes[i])) {
- value = new double[]{flattenLatLngCoordinates[i * 2], flattenLatLngCoordinates[(i * 2) + 1], altitudes[i]};
+ value = new double[]{
+ flattenLatLngCoordinates[i * 2],
+ flattenLatLngCoordinates[(i * 2) + 1],
+ altitudes[i]
+ };
} else {
- value = new double[]{flattenLatLngCoordinates[i * 2], flattenLatLngCoordinates[(i * 2) + 1]};
+ value = new double[]{
+ flattenLatLngCoordinates[i * 2],
+ flattenLatLngCoordinates[(i * 2) + 1]
+ };
}
writePointList(out, value);
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
index 57d278ed7..c6415e3cc 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
@@ -50,7 +50,8 @@
* @since 1.0.0
*/
@Keep
-public final class LineString implements FlattenedCoordinateContainer, FlattenListOfPoints> {
+public final class LineString implements
+ FlattenedCoordinateContainer, FlattenListOfPoints> {
private static final String TYPE = "LineString";
@@ -278,9 +279,13 @@ public String toString() {
@Override
public boolean equals(Object o) {
- if (!(o instanceof LineString)) return false;
+ if (!(o instanceof LineString)) {
+ return false;
+ }
LineString that = (LineString) o;
- return Objects.equals(type, that.type) && Objects.equals(bbox, that.bbox) && Objects.equals(flattenListOfPoints, that.flattenListOfPoints);
+ return Objects.equals(type, that.type)
+ && Objects.equals(bbox, that.bbox)
+ && Objects.equals(flattenListOfPoints, that.flattenListOfPoints);
}
@Override
@@ -298,7 +303,8 @@ public FlattenListOfPoints flattenCoordinates() {
*
* @since 4.6.0
*/
- static final class GsonTypeAdapter extends BaseGeometryTypeAdapter, FlattenListOfPoints> {
+ static final class GsonTypeAdapter extends
+ BaseGeometryTypeAdapter, FlattenListOfPoints> {
GsonTypeAdapter(Gson gson) {
super(gson, new FlattenListOfPointsTypeAdapter());
@@ -315,9 +321,10 @@ public LineString read(JsonReader jsonReader) throws IOException {
}
@Override
- CoordinateContainer> createCoordinateContainer(String type,
- BoundingBox bbox,
- FlattenListOfPoints flattenListOfPoints) {
+ CoordinateContainer> createCoordinateContainer(
+ String type,
+ BoundingBox bbox,
+ FlattenListOfPoints flattenListOfPoints) {
return new LineString(type == null ? "LineString" : type, bbox, flattenListOfPoints);
}
}
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/MultiPoint.java b/services-geojson/src/main/java/com/mapbox/geojson/MultiPoint.java
index c71b9310e..bfa3a7caa 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/MultiPoint.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/MultiPoint.java
@@ -36,7 +36,8 @@
* @since 1.0.0
*/
@Keep
-public final class MultiPoint implements FlattenedCoordinateContainer, FlattenListOfPoints> {
+public final class MultiPoint implements
+ FlattenedCoordinateContainer, FlattenListOfPoints> {
private static final String TYPE = "MultiPoint";
@@ -107,7 +108,8 @@ static MultiPoint fromLngLats(@NonNull double[][] coordinates) {
MultiPoint(String type, @Nullable BoundingBox bbox, List coordinates) {
this(type, bbox, new FlattenListOfPoints(coordinates));
}
- MultiPoint(String type, @Nullable BoundingBox bbox, FlattenListOfPoints flattenListOfPoints) {
+
+ MultiPoint(String type, @Nullable BoundingBox bbox, FlattenListOfPoints flattenListOfPoints) {
if (type == null) {
throw new NullPointerException("Null type");
}
@@ -197,9 +199,13 @@ public String toString() {
@Override
public boolean equals(Object o) {
- if (!(o instanceof MultiPoint)) return false;
+ if (!(o instanceof MultiPoint)) {
+ return false;
+ }
MultiPoint that = (MultiPoint) o;
- return Objects.equals(type, that.type) && Objects.equals(bbox, that.bbox) && Objects.equals(flattenListOfPoints, that.flattenListOfPoints);
+ return Objects.equals(type, that.type)
+ && Objects.equals(bbox, that.bbox)
+ && Objects.equals(flattenListOfPoints, that.flattenListOfPoints);
}
@Override
@@ -217,7 +223,8 @@ public FlattenListOfPoints flattenCoordinates() {
*
* @since 4.6.0
*/
- static final class GsonTypeAdapter extends BaseGeometryTypeAdapter, FlattenListOfPoints> {
+ static final class GsonTypeAdapter extends
+ BaseGeometryTypeAdapter, FlattenListOfPoints> {
GsonTypeAdapter(Gson gson) {
super(gson, new FlattenListOfPointsTypeAdapter());
@@ -234,9 +241,10 @@ public MultiPoint read(JsonReader jsonReader) throws IOException {
}
@Override
- CoordinateContainer> createCoordinateContainer(String type,
- BoundingBox bbox,
- FlattenListOfPoints flattenListOfPoints) {
+ CoordinateContainer> createCoordinateContainer(
+ String type,
+ BoundingBox bbox,
+ FlattenListOfPoints flattenListOfPoints) {
return new MultiPoint(type == null ? "MultiPoint" : type, bbox, flattenListOfPoints);
}
}
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/MultiPolygon.java b/services-geojson/src/main/java/com/mapbox/geojson/MultiPolygon.java
index e9f6ef053..0688a7be1 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/MultiPolygon.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/MultiPolygon.java
@@ -344,8 +344,8 @@ public int hashCode() {
*
* @since 4.6.0
*/
- static final class GsonTypeAdapter
- extends BaseGeometryTypeAdapter>>, List>>> {
+ static final class GsonTypeAdapter extends
+ BaseGeometryTypeAdapter>>, List>>> {
GsonTypeAdapter(Gson gson) {
super(gson, new ListofListofListOfPointCoordinatesTypeAdapter());
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/Point.java b/services-geojson/src/main/java/com/mapbox/geojson/Point.java
index 38a7f890f..24a57c78f 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/Point.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/Point.java
@@ -331,10 +331,15 @@ public static TypeAdapter typeAdapter(Gson gson) {
@Override
public String toString() {
String coordinatesStr;
- if (coordinates.length > 2)
- coordinatesStr = "[" + this.coordinates[0] + ", " + this.coordinates[1] + ", " + this.coordinates[2] + "]";
- else
+ if (coordinates.length > 2) {
+ coordinatesStr = "["
+ + this.coordinates[0] + ", "
+ + this.coordinates[1] + ", "
+ + this.coordinates[2]
+ + "]";
+ } else {
coordinatesStr = "[" + this.coordinates[0] + ", " + this.coordinates[1] + "]";
+ }
return "Point{"
+ "type=" + type + ", "
+ "bbox=" + bbox + ", "
@@ -344,9 +349,13 @@ public String toString() {
@Override
public boolean equals(Object o) {
- if (!(o instanceof Point)) return false;
+ if (!(o instanceof Point)) {
+ return false;
+ }
Point point = (Point) o;
- return Objects.equals(type, point.type) && Objects.equals(bbox, point.bbox) && Objects.deepEquals(coordinates, point.coordinates);
+ return Objects.equals(type, point.type)
+ && Objects.equals(bbox, point.bbox)
+ && Objects.deepEquals(coordinates, point.coordinates);
}
@Override
@@ -366,7 +375,8 @@ public int hashCode() {
*
* @since 4.6.0
*/
- static final class GsonTypeAdapter extends BaseGeometryTypeAdapter, double[]> {
+ static final class GsonTypeAdapter extends
+ BaseGeometryTypeAdapter, double[]> {
GsonTypeAdapter(Gson gson) {
super(gson, new ListOfDoublesCoordinatesTypeAdapter());
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/Polygon.java b/services-geojson/src/main/java/com/mapbox/geojson/Polygon.java
index df9d02974..e8970c064 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/Polygon.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/Polygon.java
@@ -432,7 +432,8 @@ public int hashCode() {
*
* @since 4.6.0
*/
- static final class GsonTypeAdapter extends BaseGeometryTypeAdapter>, List>> {
+ static final class GsonTypeAdapter extends
+ BaseGeometryTypeAdapter>, List>> {
GsonTypeAdapter(Gson gson) {
super(gson, new ListOfListOfPointCoordinatesTypeAdapter());
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifter.java b/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifter.java
index 75d7541bf..fc3571d84 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifter.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifter.java
@@ -55,7 +55,30 @@ public interface CoordinateShifter {
*/
List unshiftPoint(List shiftedCoordinates);
+ /**
+ * Shifted coordinate values according to its algorithm.
+ *
+ * @param lon unshifted longitude
+ * @param lat unshifted latitude
+ * @param altitude unshifted altitude
+ * @return shifted longitude, shifted latitude, shifted altitude
+ */
double[] shift(double lon, double lat, double altitude);
+
+ /**
+ * Shifted coordinate values according to its algorithm.
+ *
+ * @param lon unshifted longitude
+ * @param lat unshifted latitude
+ * @return shifted longitude, shifted latitude
+ */
double[] shift(double lon, double lat);
+
+ /**
+ * Unshifted coordinate values according to its algorithm.
+ *
+ * @param shiftedCoordinates shifted point
+ * @return unshifted longitude, shifted latitude, and altitude (if present)
+ */
double[] unshiftPointArray(double[] shiftedCoordinates);
}
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifterManager.java b/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifterManager.java
index 40ac56e0d..b5cc12d44 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifterManager.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/shifter/CoordinateShifterManager.java
@@ -42,7 +42,7 @@ public double[] shift(double lon, double lat) {
@Override
public double[] shift(double lon, double lat, double altitude) {
- if (Double.isNaN(altitude)){
+ if (Double.isNaN(altitude)) {
return shift(lon, lat);
} else {
return new double[]{lon, lat, altitude};
From cfa95b9731e6f420da241c9986c1567348ff3de2 Mon Sep 17 00:00:00 2001
From: Ramon
Date: Mon, 26 Jan 2026 15:10:21 +0200
Subject: [PATCH 12/17] Better names when reading point from JSON
---
.../geojson/BaseCoordinatesTypeAdapter.java | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/BaseCoordinatesTypeAdapter.java b/services-geojson/src/main/java/com/mapbox/geojson/BaseCoordinatesTypeAdapter.java
index fc9c9ecb6..38c165f2e 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/BaseCoordinatesTypeAdapter.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/BaseCoordinatesTypeAdapter.java
@@ -63,33 +63,31 @@ protected double[] readPointList(JsonReader in) throws IOException {
throw new NullPointerException();
}
- double coordinate0;
- double coordinate1;
- double coordinate2;
+ double lon;
+ double lat;
+ double altitude;
in.beginArray();
if (in.hasNext()) {
- coordinate0 = in.nextDouble();
+ lon = in.nextDouble();
} else {
throw new IndexOutOfBoundsException("Point coordinates should contain at least two values");
}
if (in.hasNext()) {
- coordinate1 = in.nextDouble();
+ lat = in.nextDouble();
} else {
throw new IndexOutOfBoundsException("Point coordinates should contain at least two values");
}
if (in.hasNext()) {
- coordinate2 = in.nextDouble();
+ altitude = in.nextDouble();
// Consume any extra value but don't store it
while (in.hasNext()) {
in.skipValue();
}
in.endArray();
- return CoordinateShifterManager.getCoordinateShifter()
- .shift(coordinate0, coordinate1, coordinate2);
+ return CoordinateShifterManager.getCoordinateShifter().shift(lon, lat, altitude);
} else {
in.endArray();
- return CoordinateShifterManager.getCoordinateShifter()
- .shift(coordinate0, coordinate1);
+ return CoordinateShifterManager.getCoordinateShifter().shift(lon, lat);
}
}
From 8db98e82ced842b2f032c56572081eb9779050db Mon Sep 17 00:00:00 2001
From: Ramon
Date: Mon, 26 Jan 2026 15:11:21 +0200
Subject: [PATCH 13/17] Fix order of lng,lat in various names and improved
tests
---
.../mapbox/geojson/FlattenListOfPoints.java | 46 +++++++++++--------
.../main/java/com/mapbox/geojson/Point.java | 4 +-
.../com/mapbox/geojson/LineStringTest.java | 4 +-
.../com/mapbox/geojson/MultiPointTest.java | 16 ++++---
.../java/com/mapbox/geojson/PointTest.java | 25 ++++++++++
5 files changed, 64 insertions(+), 31 deletions(-)
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
index 25972599b..2a27d9fe9 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
@@ -16,14 +16,14 @@
@Keep
public class FlattenListOfPoints implements Serializable {
/**
- * A one-dimensional array to store the flattened coordinates: [lat1, lng1, lat2, lng2, ...].
+ * A one-dimensional array to store the flattened coordinates: [lng1, lat1, lng2, lat2, ...].
*
* Note: we use one-dimensional array for performance reasons related to JNI access (
* Android JNI Tips
* - Primitive arrays)
*/
@NonNull
- private final double[] flattenLatLngPoints;
+ private final double[] flattenLngLatPoints;
/**
* An array to store the altitudes of each coordinate or {@link Double#NaN} if the coordinate
* does not have altitude.
@@ -37,19 +37,24 @@ public class FlattenListOfPoints implements Serializable {
@Nullable
private BoundingBox[] boundingBoxes;
- FlattenListOfPoints(List points) {
+ FlattenListOfPoints(@NonNull double[] flattenLngLatPoints, @Nullable double[] altitudes) {
+ this.flattenLngLatPoints = flattenLngLatPoints;
+ this.altitudes = altitudes;
+ }
+
+ FlattenListOfPoints(@NonNull List points) {
if (points.isEmpty()) {
- this.flattenLatLngPoints = new double[0];
+ this.flattenLngLatPoints = new double[0];
this.altitudes = null;
this.boundingBoxes = null;
return;
}
- double[] flattenLatLngCoordinates = new double[points.size() * 2];
+ double[] flattenLngLatCoordinates = new double[points.size() * 2];
double[] altitudes = null;
for (int i = 0; i < points.size(); i++) {
Point point = points.get(i);
- flattenLatLngCoordinates[i * 2] = point.longitude();
- flattenLatLngCoordinates[(i * 2) + 1] = point.latitude();
+ flattenLngLatCoordinates[i * 2] = point.longitude();
+ flattenLngLatCoordinates[(i * 2) + 1] = point.latitude();
// It is quite common to not have altitude in Point. Therefore only if we have points
// with altitude then we create an array to store those.
@@ -76,16 +81,17 @@ public class FlattenListOfPoints implements Serializable {
boundingBoxes[i] = point.bbox();
}
}
- this.flattenLatLngPoints = flattenLatLngCoordinates;
+ this.flattenLngLatPoints = flattenLngLatCoordinates;
this.altitudes = altitudes;
}
/**
- * @return a flatten array of all the coordinates (lat, lng): [lat1, lng1, lat2, lng2, ...].
+ * @return a flatten array of all the coordinates (longitude, latitude):
+ * [lng1, lat1, lng2, lat2, ...].
*/
@NonNull
- public double[] getFlattenLatLngArray() {
- return flattenLatLngPoints;
+ public double[] getFlattenLngLatArray() {
+ return flattenLngLatPoints;
}
/**
@@ -100,27 +106,27 @@ public double[] getAltitudes() {
/**
* Creates a list of {@link Point}s and returns it.
*
- * If possible consider using {@link #getFlattenLatLngArray()} and {@link #getAltitudes()}
+ * If possible consider using {@link #getFlattenLngLatArray()} and {@link #getAltitudes()}
* instead.
*
* @return a list of {@link Point}s
*/
@NonNull
public List points() {
- if (flattenLatLngPoints.length == 0) {
+ if (flattenLngLatPoints.length == 0) {
return new ArrayList<>();
}
- ArrayList points = new ArrayList<>(flattenLatLngPoints.length / 2);
- for (int i = 0; i < flattenLatLngPoints.length / 2; i++) {
+ ArrayList points = new ArrayList<>(flattenLngLatPoints.length / 2);
+ for (int i = 0; i < flattenLngLatPoints.length / 2; i++) {
double[] coordinates;
if (altitudes != null && !Double.isNaN(altitudes[i])) {
coordinates = new double[]{
- flattenLatLngPoints[i * 2],
- flattenLatLngPoints[(i * 2) + 1],
+ flattenLngLatPoints[i * 2],
+ flattenLngLatPoints[(i * 2) + 1],
altitudes[i]
};
} else {
- coordinates = new double[]{flattenLatLngPoints[i * 2], flattenLatLngPoints[(i * 2) + 1]};
+ coordinates = new double[]{flattenLngLatPoints[i * 2], flattenLngLatPoints[(i * 2) + 1]};
}
BoundingBox pointBbox = null;
if (boundingBoxes != null) {
@@ -140,7 +146,7 @@ public boolean equals(Object o) {
return false;
}
FlattenListOfPoints that = (FlattenListOfPoints) o;
- return Objects.deepEquals(flattenLatLngPoints, that.flattenLatLngPoints)
+ return Objects.deepEquals(flattenLngLatPoints, that.flattenLngLatPoints)
&& Objects.deepEquals(altitudes, that.altitudes)
&& Objects.deepEquals(boundingBoxes, that.boundingBoxes);
}
@@ -148,7 +154,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
return Objects.hash(
- Arrays.hashCode(flattenLatLngPoints),
+ Arrays.hashCode(flattenLngLatPoints),
Arrays.hashCode(altitudes),
Arrays.hashCode(boundingBoxes)
);
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/Point.java b/services-geojson/src/main/java/com/mapbox/geojson/Point.java
index 24a57c78f..1ee3b9a18 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/Point.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/Point.java
@@ -271,7 +271,7 @@ public BoundingBox bbox() {
}
/**
- * Provide a single double array containing the longitude, latitude, and optionally an
+ * Provide a list of Doubles containing the longitude, latitude, and optionally an
* altitude/elevation. {@link #longitude()}, {@link #latitude()}, and {@link #altitude()} are all
* available which make getting specific coordinates more direct.
*
@@ -292,7 +292,7 @@ public List coordinates() {
/**
* Provide a single double array containing the longitude, latitude, and optionally an
- * altitude/elevation. {@link #longitude()}, {@link #latitude()}, and {@link #altitude()} are all
+ * altitude. {@link #longitude()}, {@link #latitude()}, and {@link #altitude()} are all
* available which make getting specific coordinates more direct.
*
* @return a double array which holds this points coordinates
diff --git a/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java b/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java
index dad5aa4d3..efbc0298f 100644
--- a/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java
+++ b/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java
@@ -114,7 +114,7 @@ public void bbox_doesDeserializeWhenPresent() throws Exception {
assertEquals(3, coordinates.get(2).longitude(), DELTA);
assertEquals(4, coordinates.get(2).latitude(), DELTA);
- double[] coordinatesPrimitive = lineString.flattenCoordinates().getFlattenLatLngArray();
+ double[] coordinatesPrimitive = lineString.flattenCoordinates().getFlattenLngLatArray();
assertEquals(1, coordinatesPrimitive[0], DELTA);
assertEquals(2, coordinatesPrimitive[1], DELTA);
assertEquals(2, coordinatesPrimitive[2], DELTA);
@@ -154,7 +154,7 @@ public void fromJson() throws IOException {
assertEquals(1.0, secondPoint.latitude(), 0.0);
assertFalse(secondPoint.hasAltitude());
- double[] coordinates = geo.flattenCoordinates().getFlattenLatLngArray();
+ double[] coordinates = geo.flattenCoordinates().getFlattenLngLatArray();
double[] altitudes = geo.flattenCoordinates().getAltitudes();
assertEquals(100.0, coordinates[0], 0.0);
assertEquals(0.0, coordinates[1], 0.0);
diff --git a/services-geojson/src/test/java/com/mapbox/geojson/MultiPointTest.java b/services-geojson/src/test/java/com/mapbox/geojson/MultiPointTest.java
index 75318cae9..dee5add5b 100644
--- a/services-geojson/src/test/java/com/mapbox/geojson/MultiPointTest.java
+++ b/services-geojson/src/test/java/com/mapbox/geojson/MultiPointTest.java
@@ -94,19 +94,21 @@ public void testSerializable() throws Exception {
@Test
public void fromJson() throws IOException {
final String json = "{ \"type\": \"MultiPoint\"," +
- "\"coordinates\": [ [100, 0, 1000], [101, 1] ] } ";
+ "\"coordinates\": [ [100, 90, 1000], [101, 1] ] } ";
MultiPoint geo = MultiPoint.fromJson(json);
assertEquals("MultiPoint", geo.type());
List coordinates = geo.coordinates();
Point firstPoint = coordinates.get(0);
assertEquals(100.0, firstPoint.longitude(), DELTA);
- assertEquals(0.0, firstPoint.latitude(), DELTA);
+ assertEquals(90.0, firstPoint.latitude(), DELTA);
assertTrue(firstPoint.hasAltitude());
assertEquals(1000.0, firstPoint.altitude(), DELTA);
- double[] flattenLatLngArray = geo.flattenCoordinates().getFlattenLatLngArray();
- assertEquals(100.0, flattenLatLngArray[0], DELTA);
- assertEquals(0.0, flattenLatLngArray[1], DELTA);
+ double[] flattenLngLatArray = geo.flattenCoordinates().getFlattenLngLatArray();
+ assertEquals(100.0, flattenLngLatArray[0], DELTA);
+ assertEquals(firstPoint.longitude(), flattenLngLatArray[0], DELTA);
+ assertEquals(90.0, flattenLngLatArray[1], DELTA);
+ assertEquals(firstPoint.latitude(), flattenLngLatArray[1], DELTA);
Point secondPoint = coordinates.get(1);
@@ -115,8 +117,8 @@ public void fromJson() throws IOException {
assertFalse(secondPoint.hasAltitude());
assertEquals(Double.NaN, secondPoint.altitude(), DELTA);
- assertEquals(101.0, flattenLatLngArray[2], DELTA);
- assertEquals(1.0, flattenLatLngArray[3], DELTA);
+ assertEquals(101.0, flattenLngLatArray[2], DELTA);
+ assertEquals(1.0, flattenLngLatArray[3], DELTA);
}
@Test
diff --git a/services-geojson/src/test/java/com/mapbox/geojson/PointTest.java b/services-geojson/src/test/java/com/mapbox/geojson/PointTest.java
index 1b9335fe7..66de019b1 100644
--- a/services-geojson/src/test/java/com/mapbox/geojson/PointTest.java
+++ b/services-geojson/src/test/java/com/mapbox/geojson/PointTest.java
@@ -25,6 +25,18 @@ public class PointTest extends TestUtils {
public void sanity() throws Exception {
Point point = Point.fromLngLat(1.0, 2.0);
assertNotNull(point);
+ assertEquals("Point", point.type());
+ assertEquals(1.0, point.longitude(), DELTA);
+ assertEquals(2.0, point.latitude(), DELTA);
+ assertEquals(Double.NaN, point.altitude(), DELTA);
+ List coordinates = point.coordinates();
+ assertEquals(2, coordinates.size());
+ assertEquals(1.0, coordinates.get(0), DELTA);
+ assertEquals(2.0, coordinates.get(1), DELTA);
+ double[] doubles = point.flattenCoordinates();
+ assertEquals(2, doubles.length);
+ assertEquals(1.0, doubles[0], DELTA);
+ assertEquals(2.0, doubles[1], DELTA);
}
@Test
@@ -37,6 +49,19 @@ public void hasAltitude_returnsFalseWhenAltitudeNotPresent() throws Exception {
public void hasAltitude_returnsTrueWhenAltitudeIsPresent() throws Exception {
Point point = Point.fromLngLat(1.0, 2.0, 5.0);
assertTrue(point.hasAltitude());
+ assertEquals(1.0, point.longitude(), DELTA);
+ assertEquals(2.0, point.latitude(), DELTA);
+ assertEquals(5.0, point.altitude(), DELTA);
+ List coordinates = point.coordinates();
+ assertEquals(3, coordinates.size());
+ assertEquals(1.0, coordinates.get(0), DELTA);
+ assertEquals(2.0, coordinates.get(1), DELTA);
+ assertEquals(5.0, coordinates.get(2), DELTA);
+ double[] doubles = point.flattenCoordinates();
+ assertEquals(3, doubles.length);
+ assertEquals(1.0, doubles[0], DELTA);
+ assertEquals(2.0, doubles[1], DELTA);
+ assertEquals(5.0, doubles[2], DELTA);
}
@Test
From eb9672100121436982cd8fb56dbb6f692a992fbd Mon Sep 17 00:00:00 2001
From: Ramon
Date: Mon, 26 Jan 2026 15:11:38 +0200
Subject: [PATCH 14/17] Improve reading list of points from JSON
---
.../FlattenListOfPointsTypeAdapter.java | 86 ++++++++++++++++---
1 file changed, 74 insertions(+), 12 deletions(-)
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java
index 6a7a5cb12..e12333789 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPointsTypeAdapter.java
@@ -8,8 +8,6 @@
import com.mapbox.geojson.exception.GeoJsonException;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
/**
* Type Adapter to serialize/deserialize List<Point> into/from two dimentional double array.
@@ -19,6 +17,8 @@
@Keep
class FlattenListOfPointsTypeAdapter extends BaseCoordinatesTypeAdapter {
+ private static final int INITIAL_CAPACITY = 100;
+
@Override
public void write(JsonWriter out, FlattenListOfPoints flattenListOfPoints) throws IOException {
@@ -28,21 +28,21 @@ public void write(JsonWriter out, FlattenListOfPoints flattenListOfPoints) throw
}
out.beginArray();
- double[] flattenLatLngCoordinates = flattenListOfPoints.getFlattenLatLngArray();
+ double[] flattenLngLatCoordinates = flattenListOfPoints.getFlattenLngLatArray();
double[] altitudes = flattenListOfPoints.getAltitudes();
- for (int i = 0; i < flattenLatLngCoordinates.length / 2; i++) {
+ for (int i = 0; i < flattenLngLatCoordinates.length / 2; i++) {
double[] value;
if (altitudes != null && !Double.isNaN(altitudes[i])) {
value = new double[]{
- flattenLatLngCoordinates[i * 2],
- flattenLatLngCoordinates[(i * 2) + 1],
+ flattenLngLatCoordinates[i * 2],
+ flattenLngLatCoordinates[(i * 2) + 1],
altitudes[i]
};
} else {
value = new double[]{
- flattenLatLngCoordinates[i * 2],
- flattenLatLngCoordinates[(i * 2) + 1]
+ flattenLngLatCoordinates[i * 2],
+ flattenLngLatCoordinates[(i * 2) + 1]
};
}
@@ -54,21 +54,83 @@ public void write(JsonWriter out, FlattenListOfPoints flattenListOfPoints) throw
@Override
public FlattenListOfPoints read(JsonReader in) throws IOException {
-
if (in.peek() == JsonToken.NULL) {
throw new NullPointerException();
}
if (in.peek() == JsonToken.BEGIN_ARRAY) {
- List points = new ArrayList<>();
in.beginArray();
+ double[] flattenLngLats = new double[INITIAL_CAPACITY * 2];
+ double[] altitudes = null;
+ int currentIdx = 0;
while (in.peek() == JsonToken.BEGIN_ARRAY) {
- points.add(readPoint(in));
+ in.beginArray();
+ // Read longitude
+ if (in.hasNext()) {
+ flattenLngLats[currentIdx * 2] = in.nextDouble();
+ } else {
+ throw new IndexOutOfBoundsException(
+ "Point coordinates should contain at least two values"
+ );
+ }
+
+ // Read latitude
+ if (in.hasNext()) {
+ flattenLngLats[currentIdx * 2 + 1] = in.nextDouble();
+ } else {
+ throw new IndexOutOfBoundsException(
+ "Point coordinates should contain at least two values"
+ );
+ }
+
+ // Finally altitude if present
+ if (in.hasNext()) {
+ if (altitudes == null) {
+ altitudes = new double[flattenLngLats.length / 2];
+ // Fill in any previous altitude as NaN
+ for (int j = 0; j < currentIdx; j++) {
+ altitudes[j] = Double.NaN;
+ }
+ }
+ altitudes[currentIdx] = in.nextDouble();
+ // Consume any extra value but don't store it
+ while (in.hasNext()) {
+ in.skipValue();
+ }
+ in.endArray();
+ } else {
+ in.endArray();
+ if (altitudes != null) {
+ // If we are storing altitudes but this point doesn't have it then set it to NaN
+ altitudes[currentIdx] = Double.NaN;
+ }
+ }
+ currentIdx++;
+ // If we run out of space we grow the the arrays
+ if (currentIdx * 2 >= flattenLngLats.length) {
+ double[] newFlattenLngLats = new double[flattenLngLats.length * 2];
+ System.arraycopy(flattenLngLats, 0, newFlattenLngLats, 0, flattenLngLats.length);
+ flattenLngLats = newFlattenLngLats;
+ if (altitudes != null) {
+ double[] newAltitudes = new double[altitudes.length * 2];
+ System.arraycopy(altitudes, 0, newAltitudes, 0, altitudes.length);
+ altitudes = newAltitudes;
+ }
+ }
}
in.endArray();
- return new FlattenListOfPoints(points);
+ int totalPoints = currentIdx;
+ double[] trimmedFlattenLngLats = new double[totalPoints * 2];
+ System.arraycopy(flattenLngLats, 0, trimmedFlattenLngLats, 0, totalPoints * 2);
+ double[] trimmedAltitudes = null;
+ if (altitudes != null) {
+ trimmedAltitudes = new double[totalPoints];
+ System.arraycopy(altitudes, 0, trimmedAltitudes, 0, totalPoints);
+ }
+
+ return new FlattenListOfPoints(trimmedFlattenLngLats, trimmedAltitudes);
}
throw new GeoJsonException("coordinates should be non-null array of array of double");
From 63fc1577dbe69c1a321c293228515502e4f926b7 Mon Sep 17 00:00:00 2001
From: Ramon
Date: Mon, 26 Jan 2026 15:42:37 +0200
Subject: [PATCH 15/17] Expose LineString constructor with FlattenListOfPoints
---
.../mapbox/geojson/FlattenListOfPoints.java | 10 ++++-
.../java/com/mapbox/geojson/LineString.java | 38 +++++++++++++++++++
.../com/mapbox/geojson/LineStringTest.java | 8 ++++
.../mapbox/geojson/shifter/ShifterTest.java | 9 +++++
4 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
index 2a27d9fe9..aafcb4c98 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
@@ -37,7 +37,15 @@ public class FlattenListOfPoints implements Serializable {
@Nullable
private BoundingBox[] boundingBoxes;
- FlattenListOfPoints(@NonNull double[] flattenLngLatPoints, @Nullable double[] altitudes) {
+ /**
+ *
+ * @param flattenLngLatPoints A one-dimensional array coordinates: [lng1, lat1, lng2, lat2, ...].
+ * It is stored as is, no copy or shifting is done.
+ * @param altitudes An array of altitudes of each coordinate or {@link Double#NaN} if the
+ * coordinate does not have altitude. It is stored as is, no copy or shifting is
+ * done.
+ */
+ public FlattenListOfPoints(@NonNull double[] flattenLngLatPoints, @Nullable double[] altitudes) {
this.flattenLngLatPoints = flattenLngLatPoints;
this.altitudes = altitudes;
}
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
index c6415e3cc..be480c598 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
@@ -9,6 +9,8 @@
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.mapbox.geojson.gson.GeoJsonAdapterFactory;
+import com.mapbox.geojson.shifter.CoordinateShifter;
+import com.mapbox.geojson.shifter.CoordinateShifterManager;
import com.mapbox.geojson.utils.PolylineUtils;
import java.io.IOException;
@@ -144,6 +146,42 @@ public static LineString fromLngLats(@NonNull MultiPoint multiPoint, @Nullable B
return new LineString(TYPE, bbox, multiPoint.coordinates());
}
+ /**
+ * Create a new instance of this class by defining a {@link FlattenListOfPoints} object.
+ * The multipoint object should comply with the GeoJson specifications described in the
+ * documentation.
+ *
+ * @param flattenListOfPoints which will make up the LineString geometry. The points will be
+ * shifted according to the current
+ * {@link CoordinateShifterManager#getCoordinateShifter()}
+ * @param bbox optionally include a bbox definition
+ * @return a new instance of this class defined by the values passed inside this static factory
+ * method
+ */
+ public static LineString fromFlattenListOfPoints(
+ FlattenListOfPoints flattenListOfPoints,
+ @Nullable BoundingBox bbox
+ ) {
+ double[] flattenLngLatArray = flattenListOfPoints.getFlattenLngLatArray();
+ double[] altitudes = flattenListOfPoints.getAltitudes();
+ CoordinateShifter coordinateShifter = CoordinateShifterManager.getCoordinateShifter();
+ // Iterate all the points and shift them
+ for (int i = 0; i < flattenLngLatArray.length / 2; i++) {
+ if (altitudes != null && !Double.isNaN(altitudes[i])) {
+ double[] shifted = coordinateShifter.shift(flattenLngLatArray[i * 2], flattenLngLatArray[(i * 2) + 1], altitudes[i]);
+ flattenLngLatArray[i * 2] = shifted[0];
+ flattenLngLatArray[(i * 2) + 1] = shifted[1];
+ altitudes[i] = shifted[2];
+ } else {
+ double[] shifted = coordinateShifter.shift(flattenLngLatArray[i * 2], flattenLngLatArray[(i * 2) + 1]);
+ flattenLngLatArray[i * 2] = shifted[0];
+ flattenLngLatArray[(i * 2) + 1] = shifted[1];
+ }
+ }
+
+ return new LineString(TYPE, bbox, flattenListOfPoints);
+ }
+
LineString(String type, @Nullable BoundingBox bbox, List coordinates) {
this(type, bbox, new FlattenListOfPoints(coordinates));
}
diff --git a/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java b/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java
index efbc0298f..8717509c0 100644
--- a/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java
+++ b/services-geojson/src/test/java/com/mapbox/geojson/LineStringTest.java
@@ -44,6 +44,14 @@ public void fromLngLats_generatedFromMultipoint() throws Exception {
assertEquals("_gayB_c`|@_wemJ_kbvD", lineString.toPolyline(PRECISION_6));
}
+ @Test
+ public void fromFlattenListOfPoints() throws Exception {
+ double[] flattenLngLatPoints= new double[]{1.0, 2.0, 4.0, 8.0};
+ FlattenListOfPoints flattenListOfPoints = new FlattenListOfPoints(flattenLngLatPoints, null);
+ LineString lineString = LineString.fromFlattenListOfPoints(flattenListOfPoints, null);
+ assertEquals("_gayB_c`|@_wemJ_kbvD", lineString.toPolyline(PRECISION_6));
+ }
+
@Test
public void bbox_nullWhenNotSet() throws Exception {
List points = new ArrayList<>();
diff --git a/services-geojson/src/test/java/com/mapbox/geojson/shifter/ShifterTest.java b/services-geojson/src/test/java/com/mapbox/geojson/shifter/ShifterTest.java
index 6475e592f..67353d3cd 100644
--- a/services-geojson/src/test/java/com/mapbox/geojson/shifter/ShifterTest.java
+++ b/services-geojson/src/test/java/com/mapbox/geojson/shifter/ShifterTest.java
@@ -2,6 +2,7 @@
import com.google.gson.JsonParser;
import com.mapbox.geojson.BoundingBox;
+import com.mapbox.geojson.FlattenListOfPoints;
import com.mapbox.geojson.LineString;
import com.mapbox.geojson.Point;
@@ -222,6 +223,14 @@ public void linestring_basic_shift_with_bbox() {
+ "\"type\":\"LineString\",\"bbox\":[1.0,2.0,3.0,4.0]}",
jsonString);
+ double[] flattenLngLatPoints= new double[]{1.0, 1.0, 2.0, 2.0, 3.0, 3.0};
+ FlattenListOfPoints flattenListOfPoints = new FlattenListOfPoints(flattenLngLatPoints, null);
+ LineString lineString2 = LineString.fromFlattenListOfPoints(flattenListOfPoints, bbox);
+ String jsonString2 = lineString2.toJson();
+ compareJson("{\"coordinates\":[[1,1],[2,2],[3,3]],"
+ + "\"type\":\"LineString\",\"bbox\":[1.0,2.0,3.0,4.0]}",
+ jsonString2);
+
CoordinateShifterManager.setCoordinateShifter(null);
}
From 6d564fbe0fc30d092b8fed7a7b63d4316f05edfe Mon Sep 17 00:00:00 2001
From: Ramon
Date: Mon, 26 Jan 2026 16:29:15 +0200
Subject: [PATCH 16/17] Added encode/decode to PolylineUtils
---
.../java/com/mapbox/geojson/LineString.java | 6 +-
.../mapbox/geojson/utils/PolylineUtils.java | 99 +++++++++++++++++++
2 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
index be480c598..b7e19e4dd 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
@@ -221,7 +221,8 @@ static LineString fromLngLats(double[][] coordinates) {
* @since 1.0.0
*/
public static LineString fromPolyline(@NonNull String polyline, int precision) {
- return LineString.fromLngLats(PolylineUtils.decode(polyline, precision), null);
+ FlattenListOfPoints points = PolylineUtils.decodeToFlattenListOfPoints(polyline, precision);
+ return LineString.fromFlattenListOfPoints(points, null);
}
/**
@@ -264,6 +265,7 @@ public BoundingBox bbox() {
*/
@NonNull
@Override
+ @Deprecated
public List coordinates() {
return flattenListOfPoints.points();
}
@@ -292,7 +294,7 @@ public String toJson() {
* @since 1.0.0
*/
public String toPolyline(int precision) {
- return PolylineUtils.encode(coordinates(), precision);
+ return PolylineUtils.encode(flattenListOfPoints, precision);
}
/**
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/utils/PolylineUtils.java b/services-geojson/src/main/java/com/mapbox/geojson/utils/PolylineUtils.java
index 90a9b3b3a..f811453cb 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/utils/PolylineUtils.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/utils/PolylineUtils.java
@@ -1,6 +1,8 @@
package com.mapbox.geojson.utils;
import androidx.annotation.NonNull;
+
+import com.mapbox.geojson.FlattenListOfPoints;
import com.mapbox.geojson.Point;
import java.util.ArrayList;
@@ -79,6 +81,67 @@ public static List decode(@NonNull final String encodedPath, int precisio
return path.subList(0, itemsCount);
}
+ /**
+ * Decodes an encoded path string into a {@link FlattenListOfPoints}.
+ *
+ * @param encodedPath a String representing an encoded path string
+ * @param precision OSRMv4 uses 6, OSRMv5 and Google uses 5
+ * @return a {@link FlattenListOfPoints} making up the line
+ * @see Part of algorithm came from this source
+ * @see Part of algorithm came from this source.
+ */
+ @NonNull
+ public static FlattenListOfPoints decodeToFlattenListOfPoints(
+ @NonNull
+ final String encodedPath,
+ int precision
+ ) {
+ int len = encodedPath.length();
+
+ // OSRM uses precision=6, the default Polyline spec divides by 1E5, capping at precision=5
+ double factor = Math.pow(10, precision);
+
+ // For speed we preallocate to an upper bound on the final length, then
+ // truncate the array before returning.
+ double[] flattenLngLatCoordinates = new double[len];
+ int index = 0;
+ int lat = 0;
+ int lng = 0;
+ int itemsCount = 0;
+
+ while (index < len) {
+ int result = 1;
+ int shift = 0;
+ int temp;
+ do {
+ temp = encodedPath.charAt(index++) - 63 - 1;
+ result += temp << shift;
+ shift += 5;
+ }
+ while (temp >= 0x1f);
+ lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
+
+ result = 1;
+ shift = 0;
+ do {
+ temp = encodedPath.charAt(index++) - 63 - 1;
+ result += temp << shift;
+ shift += 5;
+ }
+ while (temp >= 0x1f);
+ lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
+
+ flattenLngLatCoordinates[itemsCount*2] = lng / factor;
+ flattenLngLatCoordinates[itemsCount*2+1] = lat / factor;
+
+ itemsCount++;
+ }
+
+ double[] trimmedFlattenLngLatCoordinates = new double[itemsCount * 2];
+ System.arraycopy(flattenLngLatCoordinates, 0, trimmedFlattenLngLatCoordinates, 0, itemsCount * 2);
+ return new FlattenListOfPoints(trimmedFlattenLngLatCoordinates, null);
+ }
+
/**
* Encodes a sequence of Points into an encoded path string.
*
@@ -113,6 +176,42 @@ public static String encode(@NonNull final List path, int precision) {
return result.toString();
}
+ /**
+ * Encodes a {@link FlattenListOfPoints} into an encoded path string.
+ *
+ * @param flattenListOfPoints a {@link FlattenListOfPoints} making up the line
+ * @param precision OSRMv4 uses 6, OSRMv5 and Google uses 5
+ * @return a String representing a path string
+ */
+ @NonNull
+ public static String encode(@NonNull final FlattenListOfPoints flattenListOfPoints, int precision) {
+ long lastLat = 0;
+ long lastLng = 0;
+
+ final StringBuilder result = new StringBuilder();
+
+ // OSRM uses precision=6, the default Polyline spec divides by 1E5, capping at precision=5
+ double factor = Math.pow(10, precision);
+
+ double[] flattenLngLatArray = flattenListOfPoints.getFlattenLngLatArray();
+ for (int i = 0; i < flattenLngLatArray.length / 2; i++) {
+ double longitude = flattenLngLatArray[i * 2];
+ double latitude = flattenLngLatArray[i * 2 + 1];
+ long lat = Math.round(latitude * factor);
+ long lng = Math.round(longitude * factor);
+
+ long varLat = lat - lastLat;
+ long varLng = lng - lastLng;
+
+ encode(varLat, result);
+ encode(varLng, result);
+
+ lastLat = lat;
+ lastLng = lng;
+ }
+ return result.toString();
+ }
+
private static void encode(long variable, StringBuilder result) {
variable = variable < 0 ? ~(variable << 1) : variable << 1;
while (variable >= 0x20) {
From b0fb8f77377a3f2517f34ed1d7e153ff5a2878d7 Mon Sep 17 00:00:00 2001
From: Ramon
Date: Mon, 26 Jan 2026 16:56:14 +0200
Subject: [PATCH 17/17] Build LineString.toString using the FlattenListOfPoints
---
.../mapbox/geojson/FlattenListOfPoints.java | 40 +++++++++++++++++++
.../java/com/mapbox/geojson/LineString.java | 2 +-
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
index aafcb4c98..34b4e267b 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/FlattenListOfPoints.java
@@ -33,6 +33,7 @@ public class FlattenListOfPoints implements Serializable {
/**
* An array to store the {@link BoundingBox} of each coordinate or null if the coordinate does
* not have bounding box.
+ * In practice is very unlikely that the points have bounding box when inside a list of points.
*/
@Nullable
private BoundingBox[] boundingBoxes;
@@ -167,4 +168,43 @@ public int hashCode() {
Arrays.hashCode(boundingBoxes)
);
}
+
+ @Override
+ public String toString() {
+ int totalPoints = flattenLngLatPoints.length / 2;
+
+ int iMax = totalPoints - 1;
+ if (iMax == -1) {
+ return "[]";
+ }
+
+ StringBuilder b = new StringBuilder();
+ b.append("[");
+
+ for (int i = 0; ; i++) {
+ b.append("Point{type=Point, bbox=");
+ if (boundingBoxes != null) {
+ BoundingBox boundingBox = boundingBoxes[i];
+ b.append(boundingBox);
+ } else {
+ b.append("null");
+ }
+ b.append(", coordinates=[");
+ b.append(flattenLngLatPoints[i * 2]);
+ b.append(", ");
+ b.append(flattenLngLatPoints[i * 2 + 1]);
+ if (altitudes != null && !Double.isNaN(altitudes[i])) {
+ b.append(", ");
+ b.append(altitudes[i]);
+ }
+ b.append("]}");
+ if (i == iMax) {
+ b.append("]");
+ break;
+ }
+ b.append(", ");
+ }
+
+ return b.toString();
+ }
}
diff --git a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
index b7e19e4dd..80901f1b9 100644
--- a/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
+++ b/services-geojson/src/main/java/com/mapbox/geojson/LineString.java
@@ -313,7 +313,7 @@ public String toString() {
return "LineString{"
+ "type=" + type + ", "
+ "bbox=" + bbox + ", "
- + "coordinates=" + coordinates()
+ + "coordinates=" + flattenCoordinates()
+ "}";
}