diff --git a/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequence.java b/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequence.java
index 4486734d63..dbd4a40bee 100644
--- a/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequence.java
+++ b/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequence.java
@@ -420,6 +420,185 @@ public Envelope expandEnvelope(Envelope env)
}
}
+ public static class Double2 extends PackedCoordinateSequence {
+ private static final long serialVersionUID = 5777450686367912720L;
+
+ double[] xy;
+ double[] z;
+ double[] m;
+
+ /**
+ * Builds a new packed coordinate sequence
+ *
+ * @param coords an array of double values that contains the ordinate values of the sequence
+ * @param dimension the total number of ordinates that make up a {@link Coordinate} in this sequence.
+ * @param measures the number of measure-ordinates each {@link Coordinate} in this sequence has.
+ */
+ public Double2(double[] xy, double[] z, double[] m) {
+ super(z != null ? 3 : 2, m != null ? 1 : 0);
+ this.xy = xy;
+ this.z = z;
+ this.m = m;
+ }
+
+ /**
+ * Builds a new packed coordinate sequence out of a coordinate array
+ *
+ * @param coordinates an array of {@link Coordinate}s
+ * @param dimension the total number of ordinates that make up a {@link Coordinate} in this sequence.
+ */
+ public Double2(Coordinate[] coordinates, int dimension) {
+ this( coordinates, dimension, Math.max(0,dimension-3));
+ }
+ /**
+ * Builds a new packed coordinate sequence out of a coordinate array
+ *
+ * @param coordinates an array of {@link Coordinate}s
+ * @param dimension the total number of ordinates that make up a {@link Coordinate} in this sequence.
+ * @param measures the number of measure-ordinates each {@link Coordinate} in this sequence has.
+ */
+ public Double2(Coordinate[] coordinates, int dimension, int measures) {
+ super(dimension,measures);
+ if (coordinates == null)
+ coordinates = new Coordinate[0];
+
+ xy = new double[coordinates.length];
+ for (int i = 0; i < coordinates.length; i++) {
+ xy[i * 2] = coordinates[i].x;
+ xy[i * 2 + 1] = coordinates[i].y;
+ if (dimension == 3)
+ z[i] = coordinates[i].getOrdinate(2);
+ if (measures == 1)
+ m[i] = coordinates[i].getOrdinate(3);
+ }
+ }
+ /**
+ * Builds a new packed coordinate sequence out of a coordinate array
+ *
+ * @param coordinates an array of {@link Coordinate}s
+ */
+ public Double2(Coordinate[] coordinates) {
+ this(coordinates, 3, 0);
+ }
+
+ /**
+ * Builds a new empty packed coordinate sequence of a given size and dimension
+ *
+ * @param size the number of coordinates in this sequence
+ * @param dimension the total number of ordinates that make up a {@link Coordinate} in this sequence.
+ * @param measures the number of measure-ordinates each {@link Coordinate} in this sequence has.
+ */
+ public Double2(int size, int dimension, int measures) {
+ super(dimension,measures);
+ xy = new double[size * 2];
+ if (dimension == 3)
+ z = new double[size];
+ if (measures == 1)
+ m = new double[size];
+ }
+
+ /**
+ * @see PackedCoordinateSequence#getCoordinate(int)
+ */
+ public Coordinate getCoordinateInternal(int i) {
+ double x = xy[i * 2];
+ double y = xy[i * 2 + 1];
+ if( dimension == 2 && measures == 0 ) {
+ return new CoordinateXY(x,y);
+ }
+ else if (dimension == 3 && measures == 0) {
+ double z = this.z[i];
+ return new Coordinate(x,y,z);
+ }
+ else if (dimension == 3 && measures == 1) {
+ double m = this.m[i];
+ return new CoordinateXYM(x,y,m);
+ }
+ else if (dimension == 4) {
+ double z = this.z[i];
+ double m = this.m[i];
+ return new CoordinateXYZM(x,y,z,m);
+ }
+ return new Coordinate(x, y);
+ }
+
+ /**
+ * Gets the underlying array containing the coordinate values.
+ *
+ * @return the array of coordinate values
+ */
+ public double[] getRawXYCoordinates()
+ {
+ return xy;
+ }
+
+ /**
+ * @see CoordinateSequence#size()
+ */
+ public int size() {
+ return xy.length / 2;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ * @see PackedCoordinateSequence#clone()
+ * @deprecated
+ */
+ public Object clone() {
+ return copy();
+ }
+
+ /**
+ * @see PackedCoordinateSequence#size()
+ */
+ public Double2 copy() {
+ double[] cloneXy = Arrays.copyOf(xy, xy.length);
+ double[] cloneZ = z != null ? Arrays.copyOf(z, z.length) : null;
+ double[] cloneM = m != null ? Arrays.copyOf(m, m.length) : null;
+ return new Double2(cloneXy, cloneZ, cloneM);
+ }
+
+ /**
+ * @see PackedCoordinateSequence#getOrdinate(int, int)
+ * Beware, for performance reasons the ordinate index is not checked, if
+ * it's over dimensions you may not get an exception but a meaningless
+ * value.
+ */
+ public double getOrdinate(int index, int ordinate) {
+ if (ordinate <= 1)
+ return xy[index * 2 + ordinate];
+ if (ordinate == 2)
+ return z[index];
+ if (ordinate == 3)
+ return m[index];
+ throw new RuntimeException("Ordinate must be <= 3");
+ }
+
+ /**
+ * @see PackedCoordinateSequence#setOrdinate(int, int, double)
+ */
+ public void setOrdinate(int index, int ordinate, double value) {
+ coordRef = null;
+ if (ordinate <= 1)
+ xy[index * 2 + ordinate] = value;
+ if (ordinate == 2)
+ z[index] = value;
+ if (ordinate == 3)
+ m[index] = value;
+ }
+
+ /**
+ * @see CoordinateSequence#expandEnvelope(Envelope)
+ */
+ public Envelope expandEnvelope(Envelope env)
+ {
+ for (int i = 0; i < xy.length; i += 2 ) {
+ env.expandToInclude(xy[i], xy[i + 1]);
+ }
+ return env;
+ }
+ }
+
/**
* Packed coordinate sequence implementation based on floats
*/
diff --git a/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceFactory.java b/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceFactory.java
index 35ed9e333a..70863ccb75 100644
--- a/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceFactory.java
+++ b/modules/core/src/main/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceFactory.java
@@ -39,6 +39,11 @@ public class PackedCoordinateSequenceFactory implements
*/
public static final int FLOAT = 1;
+ /**
+ * Type code for dim/measure separated arrays of type double
.
+ */
+ public static final int DOUBLE2 = 1;
+
/**
* A factory using array type {@link #DOUBLE}
*/
@@ -51,6 +56,12 @@ public class PackedCoordinateSequenceFactory implements
public static final PackedCoordinateSequenceFactory FLOAT_FACTORY =
new PackedCoordinateSequenceFactory(FLOAT);
+ /**
+ * A factory using array type {@link #DOUBLE2}
+ */
+ public static final PackedCoordinateSequenceFactory DOUBLE2_FACTORY =
+ new PackedCoordinateSequenceFactory(DOUBLE2);
+
private static final int DEFAULT_MEASURES = 0;
private static final int DEFAULT_DIMENSION = 3;
@@ -100,8 +111,10 @@ public CoordinateSequence create(Coordinate[] coordinates) {
}
if (type == DOUBLE) {
return new PackedCoordinateSequence.Double(coordinates, dimension, measures);
- } else {
+ } else if (type == FLOAT) {
return new PackedCoordinateSequence.Float(coordinates, dimension, measures);
+ } else {
+ return new PackedCoordinateSequence.Double2(coordinates, dimension, measures);
}
}
@@ -113,8 +126,10 @@ public CoordinateSequence create(CoordinateSequence coordSeq) {
int measures = coordSeq.getMeasures();
if (type == DOUBLE) {
return new PackedCoordinateSequence.Double(coordSeq.toCoordinateArray(), dimension, measures);
- } else {
+ } else if (type == FLOAT) {
return new PackedCoordinateSequence.Float(coordSeq.toCoordinateArray(), dimension, measures);
+ } else {
+ return new PackedCoordinateSequence.Double2(coordSeq.toCoordinateArray(), dimension, measures);
}
}
@@ -148,6 +163,11 @@ public CoordinateSequence create(double[] packedCoordinates, int dimension, int
return new PackedCoordinateSequence.Float(packedCoordinates, dimension, measures);
}
}
+
+ public CoordinateSequence create(double[] xy, double[] z, double[] m) {
+ return new PackedCoordinateSequence.Double2(xy, z, m);
+ }
+
/**
* Creates a packed coordinate sequence of type {@link #FLOAT}
* from the provided array.
@@ -184,9 +204,12 @@ public CoordinateSequence create(int size, int dimension) {
if (type == DOUBLE) {
return new PackedCoordinateSequence.Double(
size, dimension, Math.max(DEFAULT_MEASURES, dimension-3));
- } else {
+ } else if (type == FLOAT) {
return new PackedCoordinateSequence.Float(
size, dimension, Math.max(DEFAULT_MEASURES, dimension-3));
+ } else {
+ return new PackedCoordinateSequence.Double2(
+ size, dimension, Math.max(DEFAULT_MEASURES, dimension-3));
}
}
@@ -196,8 +219,10 @@ public CoordinateSequence create(int size, int dimension) {
public CoordinateSequence create(int size, int dimension, int measures) {
if (type == DOUBLE) {
return new PackedCoordinateSequence.Double(size, dimension, measures);
- } else {
+ } else if (type == FLOAT) {
return new PackedCoordinateSequence.Float(size, dimension, measures);
+ } else {
+ return new PackedCoordinateSequence.Double2(size, dimension, measures);
}
}
}
diff --git a/modules/core/src/test/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceTest.java b/modules/core/src/test/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceTest.java
index b2df619017..836f224d58 100644
--- a/modules/core/src/test/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceTest.java
+++ b/modules/core/src/test/java/org/locationtech/jts/geom/impl/PackedCoordinateSequenceTest.java
@@ -51,6 +51,10 @@ public void testDouble() {
public void testFloat() {
checkAll( PackedCoordinateSequenceFactory.FLOAT_FACTORY) ;
}
+
+ public void testDouble2() {
+ checkAll( PackedCoordinateSequenceFactory.DOUBLE2_FACTORY) ;
+ }
public void checkAll(CoordinateSequenceFactory factory)
{