This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 1a9bd95d3b feat(Geometry): handle the case where an EWKT/EWKN geometry
define a 2d crs with a Z value, ellipsoid height is added
1a9bd95d3b is described below
commit 1a9bd95d3bc32e45692619eb35873e236752ffb7
Author: jsorel <[email protected]>
AuthorDate: Wed Sep 16 16:07:25 2026 +0200
feat(Geometry): handle the case where an EWKT/EWKN geometry define a 2d crs
with a Z value, ellipsoid height is added
---
.../org/apache/sis/geometries/adapter/Srid.java | 120 +++++++++++++++++----
.../sis/geometries/adapter/WellKnownBinary.java | 6 ++
.../geometries/adapter/WellKnownBinaryParser.java | 39 ++++---
.../sis/geometries/adapter/WellKnownText.java | 7 ++
.../geometries/adapter/WellKnownTextParser.java | 40 ++++---
.../geometries/adapter/WellKnownBinaryTest.java | 39 ++++++-
.../sis/geometries/adapter/WellKnownTextTest.java | 36 ++++++-
7 files changed, 227 insertions(+), 60 deletions(-)
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Srid.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Srid.java
index e121324b3e..714357fde4 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Srid.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/Srid.java
@@ -16,11 +16,15 @@
*/
package org.apache.sis.geometries.adapter;
+import java.util.logging.Logger;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.util.logging.Logging;
import org.opengis.metadata.Identifier;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.SingleCRS;
import org.opengis.util.FactoryException;
@@ -29,16 +33,34 @@ import org.opengis.util.FactoryException;
* {@link CoordinateReferenceSystem}. A <abbr>SRID</abbr> is the numeric part
of an <abbr>EPSG</abbr>
* code, and is what {@code EWKT} and {@code EWKB} carry in place of a full
system definition.
*
- * <p>The mapping is the one of the identifier the system already carries,
never a search for an
- * equivalent definition: {@link #of(CoordinateReferenceSystem)} reads the
identifier and
- * {@link #forCode(int)} builds the system the authority defines for that
code. Neither method
- * changes the axis order, so a system read back from a code is the one the
<abbr>EPSG</abbr>
- * authority defines, which for a geographic system is (<var>latitude</var>,
<var>longitude</var>)
- * and not the (<var>longitude</var>, <var>latitude</var>) order that some
databases assume.</p>
+ * <p>Neither method changes the axis order, so a system read back from a code
is the one the
+ * <abbr>EPSG</abbr> authority defines, which for a geographic system is
(<var>latitude</var>,
+ * <var>longitude</var>) and not the (<var>longitude</var>,
<var>latitude</var>) order that some
+ * databases assume.</p>
+ *
+ * <h2>Heights</h2>
+ * A spatial reference identifier usually names a two-dimensional system,
while the geometry it
+ * describes may have a <var>z</var> ordinate: {@code SRID=4326} on a {@code
POINT Z} is the usual
+ * way of writing a position above the ellipsoid of <abbr>EPSG</abbr>:4326.
The two directions
+ * therefore do not map one system onto one code:
+ *
+ * <ul>
+ * <li>{@link #forCode(int, int)} adds an {@linkplain
CommonCRS.Vertical#ELLIPSOIDAL ellipsoidal
+ * height} to a two-dimensional system when the geometry needs three
dimensions.</li>
+ * <li>{@link #of(CoordinateReferenceSystem)} looks at the
+ * {@linkplain CRS#getHorizontalComponent horizontal component} of a
three-dimensional system
+ * when the system itself has no code, which is the converse
operation.</li>
+ * </ul>
*
* @author Johann Sorel (Geomatys)
*/
final class Srid {
+ /**
+ * The logger where to report the absence of the <abbr>EPSG</abbr>
definitions, which keeps a
+ * geometry from being written with its identifier but does not keep it
from being written.
+ */
+ private static final Logger LOGGER =
Logger.getLogger("org.apache.sis.geometries");
+
/**
* Value meaning that the coordinate reference system has no spatial
reference identifier,
* which is how the extended formats say that they carry no system.
@@ -53,40 +75,94 @@ final class Srid {
/**
* Returns the spatial reference identifier of the given coordinate
reference system, or
- * {@link #UNDEFINED} if it has none. Only the identifiers the system
already carries are
- * examined; the <abbr>EPSG</abbr> geodetic dataset is not searched for an
equivalent
- * definition, so a system built from axes and a datum has no identifier
whatever it describes.
+ * {@link #UNDEFINED} if none can be determined.
+ *
+ * <p>Three sources are tried in turn, from the cheapest and most certain
to the most costly:
+ * the identifier the system itself carries, then the identifier of its
+ * {@linkplain CRS#getHorizontalComponent horizontal component}, then a
search of the
+ * <abbr>EPSG</abbr> definitions for a system equivalent to that
horizontal component. The
+ * last one is needed because a three-dimensional system built by adding
an ellipsoidal height
+ * to a two-dimensional one keeps no identifier — neither the combined
system nor the
+ * horizontal component extracted back from it carries the code the height
was added to.</p>
*
* @param crs the system whose identifier to return, or {@code null}.
* @return the spatial reference identifier, or {@link #UNDEFINED} if none.
*/
static int of(final CoordinateReferenceSystem crs) {
- if (crs != null) {
- final Identifier id = IdentifiedObjects.getIdentifier(crs,
Citations.EPSG);
- if (id != null) try {
- return Integer.parseInt(id.getCode());
- } catch (NumberFormatException e) {
- // An EPSG code which is not a number cannot be written as a
SRID. Fall through.
+ if (crs == null) {
+ return UNDEFINED;
+ }
+ int srid = declaredCode(crs);
+ if (srid == UNDEFINED) {
+ final SingleCRS horizontal = CRS.getHorizontalComponent(crs);
+ if (horizontal != null && horizontal != crs) {
+ srid = declaredCode(horizontal);
+ if (srid == UNDEFINED) try {
+ final Integer code =
IdentifiedObjects.lookupEPSG(horizontal);
+ if (code != null) {
+ srid = code;
+ }
+ } catch (FactoryException e) {
+ // The definitions are not available. The geometry is
written without a SRID.
+ Logging.ignorableException(LOGGER, Srid.class, "of", e);
+ }
}
}
+ return srid;
+ }
+
+ /**
+ * Returns the <abbr>EPSG</abbr> code which the given system already
carries, or
+ * {@link #UNDEFINED} if it carries none. The <abbr>EPSG</abbr> geodetic
dataset is not
+ * searched, so this method is cheap and never fails.
+ */
+ private static int declaredCode(final CoordinateReferenceSystem crs) {
+ final Identifier id = IdentifiedObjects.getIdentifier(crs,
Citations.EPSG);
+ if (id != null) try {
+ return Integer.parseInt(id.getCode());
+ } catch (NumberFormatException e) {
+ // An EPSG code which is not a number cannot be written as a SRID.
+ }
return UNDEFINED;
}
/**
* Returns the coordinate reference system which the <abbr>EPSG</abbr>
authority defines for
- * the given spatial reference identifier.
+ * the given spatial reference identifier, in the given number of
dimensions.
*
- * @param srid the spatial reference identifier to resolve.
- * @return the coordinate reference system of that identifier.
- * @throws IllegalArgumentException if the identifier is unknown, or if
the definitions
- * are not available.
+ * <p>A two-dimensional system asked for three dimensions is completed
with an
+ * {@linkplain CommonCRS.Vertical#ELLIPSOIDAL ellipsoidal height}, which
is what the
+ * <var>z</var> ordinate of a geometry carrying such an identifier means.
Any other
+ * disagreement between the two is an error: dropping a dimension would
silently discard
+ * ordinates.</p>
+ *
+ * @param srid the spatial reference identifier to resolve.
+ * @param dimension number of ordinates the positions have, 2 or 3.
+ * @return the coordinate reference system of that identifier, of exactly
{@code dimension}
+ * dimensions.
+ * @throws IllegalArgumentException if the identifier is unknown, if the
definitions are not
+ * available, or if the system cannot describe positions of that
many ordinates.
*/
- static CoordinateReferenceSystem forCode(final int srid) {
+ static CoordinateReferenceSystem forCode(final int srid, final int
dimension) {
+ final CoordinateReferenceSystem crs;
try {
- return CRS.forCode("EPSG:" + srid);
+ crs = CRS.forCode("EPSG:" + srid);
} catch (FactoryException e) {
throw new IllegalArgumentException("Cannot resolve the spatial
reference identifier "
+ srid + " to a coordinate reference system: " +
e.getMessage(), e);
}
+ final int actual = crs.getCoordinateSystem().getDimension();
+ if (actual == dimension) {
+ return crs;
+ }
+ if (actual == 2 && dimension == 3) try {
+ return CRS.compound(crs, CommonCRS.Vertical.ELLIPSOIDAL.crs());
+ } catch (FactoryException e) {
+ throw new IllegalArgumentException("Cannot add an ellipsoidal
height to the coordinate"
+ + " reference system of the spatial reference identifier "
+ srid + ": " + e.getMessage(), e);
+ }
+ throw new IllegalArgumentException("The coordinate reference system of
the spatial reference"
+ + " identifier " + srid + " has " + actual + " dimensions,
which cannot describe"
+ + " positions of " + dimension + " ordinates.");
}
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinary.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinary.java
index ffe64a5365..c07baf3adb 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinary.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinary.java
@@ -154,6 +154,12 @@ public final class WellKnownBinary {
* system it names is used unless the caller passed one of their own to
* {@link #decode(byte[], CoordinateReferenceSystem)}.</p>
*
+ * <p>An identifier usually names a two-dimensional system while the
type code may have the
+ * {@code Z} flag. Such a geometry is read as positions above the
ellipsoid of that system:
+ * an ellipsoidal height is added to it. The converse holds on
writing, where the identifier
+ * of the {@linkplain
org.apache.sis.referencing.CRS#getHorizontalComponent horizontal
+ * component} is written when the three-dimensional system has none of
its own.</p>
+ *
* <p>This dialect is a superset of {@link #OGC} on reading: the
thousands of a type code
* are still understood, so a plain Well-Known Binary decodes
unchanged. The converse does
* not hold — the {@code OGC} dialect rejects the high order bits.</p>
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinaryParser.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinaryParser.java
index 49cc8d46ed..d5034e87d6 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinaryParser.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownBinaryParser.java
@@ -119,6 +119,12 @@ final class WellKnownBinaryParser {
*/
private CoordinateReferenceSystem sridCRS;
+ /**
+ * Number of dimensions {@link #sridCRS} was resolved for, since a
two-dimensional identifier
+ * gives a different system depending on whether the positions carry a
<var>z</var> ordinate.
+ */
+ private int sridDimension;
+
/**
* Index in {@link #data} of the next byte to read.
*/
@@ -515,26 +521,27 @@ final class WellKnownBinaryParser {
*/
private CoordinateReferenceSystem crs() {
final int dimension = positionDimension();
- final CoordinateReferenceSystem declared;
- final String source;
if (userCRS != null) {
- declared = userCRS;
- source = "The given coordinate reference system";
- } else if (srid != Srid.UNDEFINED) {
- if (sridCRS == null) {
- sridCRS = Srid.forCode(srid);
+ final int actual = userCRS.getCoordinateSystem().getDimension();
+ if (actual != dimension) {
+ throw error("The given coordinate reference system has " +
actual + " dimensions,"
+ + " but the bytes have " + dimension + " ordinates per
position");
}
- declared = sridCRS;
- source = "The coordinate reference system of SRID " + srid;
- } else {
- return Geometries.getUndefinedCRS(dimension);
+ return userCRS;
}
- final int actual = declared.getCoordinateSystem().getDimension();
- if (actual != dimension) {
- throw error(source + " has " + actual + " dimensions,"
- + " but the bytes have " + dimension + " ordinates per
position");
+ if (srid != Srid.UNDEFINED) {
+ /*
+ * Srid.forCode(…) returns a system of exactly the requested
number of dimensions,
+ * adding an ellipsoidal height to a two-dimensional one when the
type code has the
+ * Z flag. The dimension is therefore part of the cache key.
+ */
+ if (sridCRS == null || sridDimension != dimension) {
+ sridCRS = Srid.forCode(srid, dimension);
+ sridDimension = dimension;
+ }
+ return sridCRS;
}
- return declared;
+ return Geometries.getUndefinedCRS(dimension);
}
/**
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownText.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownText.java
index fedd8c6b5b..d143f17f6a 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownText.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownText.java
@@ -146,6 +146,13 @@ public final class WellKnownText {
* the prefix is an ordinary Well-Known Text. On reading, the prefix
is optional, and the
* system it names is used unless the caller passed one of their own to
* {@link #decode(String, CoordinateReferenceSystem)}.</p>
+ *
+ * <p>An identifier usually names a two-dimensional system while the
text may carry a
+ * <var>z</var> ordinate, as in {@code SRID=4326;POINT Z (1 2 3)}.
Such a text is read as a
+ * position above the ellipsoid of that system: an ellipsoidal height
is added to it. The
+ * converse holds on writing, where the identifier of the
+ * {@linkplain org.apache.sis.referencing.CRS#getHorizontalComponent
horizontal component}
+ * is written when the three-dimensional system has none of its
own.</p>
*/
EWKT
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownTextParser.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownTextParser.java
index f3b1e9e96f..0635c2e9ff 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownTextParser.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/WellKnownTextParser.java
@@ -121,6 +121,12 @@ final class WellKnownTextParser {
*/
private CoordinateReferenceSystem sridCRS;
+ /**
+ * Number of dimensions {@link #sridCRS} was resolved for, since a
two-dimensional identifier
+ * gives a different system depending on whether the positions carry a
<var>z</var> ordinate.
+ */
+ private int sridDimension;
+
/**
* Index in {@link #text} of the next character to read.
*/
@@ -542,26 +548,28 @@ final class WellKnownTextParser {
*/
private CoordinateReferenceSystem crs() {
final int dimension = positionDimension();
- final CoordinateReferenceSystem declared;
- final String source;
if (userCRS != null) {
- declared = userCRS;
- source = "The given coordinate reference system";
- } else if (srid != Srid.UNDEFINED) {
- if (sridCRS == null) {
- sridCRS = Srid.forCode(srid);
+ final int actual = userCRS.getCoordinateSystem().getDimension();
+ if (actual != dimension) {
+ throw error("The given coordinate reference system has " +
actual + " dimensions,"
+ + " but the text has " + dimension + " ordinates per
position");
}
- declared = sridCRS;
- source = "The coordinate reference system of SRID " + srid;
- } else {
- return Geometries.getUndefinedCRS(dimension);
+ return userCRS;
}
- final int actual = declared.getCoordinateSystem().getDimension();
- if (actual != dimension) {
- throw error(source + " has " + actual + " dimensions,"
- + " but the text has " + dimension + " ordinates per
position");
+ if (srid != Srid.UNDEFINED) {
+ /*
+ * Srid.forCode(…) returns a system of exactly the requested
number of dimensions,
+ * adding an ellipsoidal height to a two-dimensional one if the
text has a Z ordinate.
+ * The dimension is therefore part of the cache key: an EMPTY
element may ask for one
+ * before a later element establishes the flags.
+ */
+ if (sridCRS == null || sridDimension != dimension) {
+ sridCRS = Srid.forCode(srid, dimension);
+ sridDimension = dimension;
+ }
+ return sridCRS;
}
- return declared;
+ return Geometries.getUndefinedCRS(dimension);
}
/**
diff --git
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownBinaryTest.java
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownBinaryTest.java
index 99c75693d9..b1d865ef13 100644
---
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownBinaryTest.java
+++
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownBinaryTest.java
@@ -42,6 +42,7 @@ import org.apache.sis.geometries.surface.Triangle;
import org.apache.sis.maths.NDArrays;
import org.apache.sis.maths.SampleSystem;
import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.IdentifiedObjects;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -474,10 +475,10 @@ public final class WellKnownBinaryTest {
final CoordinateReferenceSystem crs = Geometries.getUndefinedCRS(2);
assertSame(crs, ewkb.decode(bytes,
crs).getCoordinateReferenceSystem());
/*
- * EPSG:4326 is two dimensional, so a Z geometry carrying it
contradicts it.
- * 0xA0000001 is the point type with the Z bit and the identifier bit.
+ * A three dimensional identifier cannot describe a two dimensional
geometry.
+ * EPSG:4979 is the three dimensional WGS 84, and is 0x1373.
*/
- assertExtendedMalformed("00" + "A0000001" + "000010E6" + ONE + TWO +
THREE);
+ assertExtendedMalformed("00" + "20000001" + "00001373" + ONE + TWO);
/*
* An identifier which no authority defines. 999999 is 0xF423F.
*/
@@ -489,6 +490,38 @@ public final class WellKnownBinaryTest {
+ "00" + "20000001" + "00000F11" + ONE + TWO);
}
+ /**
+ * Verifies that a two dimensional identifier on a geometry which has the
{@code Z} flag gives
+ * a three dimensional system, by adding an ellipsoidal height to the one
the identifier names,
+ * and that writing such a geometry gives the identifier back.
+ */
+ @Test
+ public void testExtendedEllipsoidalHeight() {
+ final WellKnownBinary ewkb = new
WellKnownBinary(WellKnownBinary.Flavor.EWKB);
+ /*
+ * 0xA0000001 is the point type with the Z bit and the identifier bit,
and EPSG:4326 is
+ * two dimensional, so the height is the one that identifier implies.
+ */
+ final byte[] bytes = bytes("00" + "A0000001" + "000010E6" + ONE + TWO
+ THREE);
+ final Geometry geometry = ewkb.decode(bytes);
+ final CoordinateReferenceSystem crs =
geometry.getCoordinateReferenceSystem();
+ assertEquals(3, crs.getCoordinateSystem().getDimension(), "Promoted to
three dimensions");
+ assertNotNull(CRS.getVerticalComponent(crs, true), "Has a height");
+ assertEquals("POINT Z (1 2 3)", wkt.encode(geometry));
+ /*
+ * Writing gives the identifier back even though the three dimensional
system carries
+ * none of its own, so the bytes round-trip unchanged.
+ */
+ assertArrayEquals(bytes, ewkb.encode(geometry));
+ /*
+ * An identifier which is already three dimensional is used as it is.
EPSG:4979 is 0x1373.
+ */
+ final Geometry direct = ewkb.decode(bytes("00" + "A0000001" +
"00001373" + ONE + TWO + THREE));
+ assertEquals("4979", IdentifiedObjects.getIdentifier(
+ direct.getCoordinateReferenceSystem(),
Citations.EPSG).getCode());
+ assertEquals("00" + "A0000001" + "00001373" + ONE + TWO + THREE,
hex(ewkb.encode(direct)));
+ }
+
/**
* Verifies that the given hexadecimal bytes are rejected by the extended
dialect.
*/
diff --git
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownTextTest.java
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownTextTest.java
index 0a3def45dc..7159e53944 100644
---
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownTextTest.java
+++
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/adapter/WellKnownTextTest.java
@@ -40,6 +40,7 @@ import org.apache.sis.geometries.surface.Triangle;
import org.apache.sis.maths.NDArrays;
import org.apache.sis.maths.SampleSystem;
import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.IdentifiedObjects;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -353,10 +354,39 @@ public final class WellKnownTextTest {
final CoordinateReferenceSystem crs = Geometries.getUndefinedCRS(2);
assertSame(crs, ewkt.decode("SRID=4326;POINT (1 2)",
crs).getCoordinateReferenceSystem());
/*
- * The system the prefix names must have as many dimensions as the
text has ordinates.
- * EPSG:4326 is two dimensional, so a Z geometry contradicts it.
+ * A three dimensional identifier cannot describe a two dimensional
geometry: dropping the
+ * height would discard nothing here, but the converse of adding one
is not defined.
+ * EPSG:4979 is the three dimensional WGS 84.
*/
- assertThrows(IllegalArgumentException.class, () ->
ewkt.decode("SRID=4326;POINT Z (1 2 3)"));
+ assertThrows(IllegalArgumentException.class, () ->
ewkt.decode("SRID=4979;POINT (1 2)"));
+ }
+
+ /**
+ * Verifies that a two dimensional identifier on a geometry which has a
<var>z</var> ordinate
+ * gives a three dimensional system, by adding an ellipsoidal height to
the one the identifier
+ * names, and that writing such a geometry gives the identifier back.
+ */
+ @Test
+ public void testExtendedEllipsoidalHeight() {
+ final WellKnownText ewkt = new
WellKnownText(WellKnownText.Flavor.EWKT);
+ final Geometry geometry = ewkt.decode("SRID=4326;POINT Z (1 2 3)");
+ final CoordinateReferenceSystem crs =
geometry.getCoordinateReferenceSystem();
+ assertEquals(3, crs.getCoordinateSystem().getDimension(), "Promoted to
three dimensions");
+ assertNotNull(CRS.getVerticalComponent(crs, true), "Has a height");
+ /*
+ * The height is the one the identifier implies, so writing the
geometry gives the
+ * identifier back even though the three dimensional system carries
none of its own.
+ */
+ assertEquals("SRID=4326;POINT Z (1 2 3)", ewkt.encode(geometry));
+ assertEquals("SRID=4326;LINESTRING Z (0 0 0, 1 1 1)",
+ ewkt.encode(ewkt.decode("SRID=4326;LINESTRING Z (0 0 0, 1
1 1)")));
+ /*
+ * An identifier which is already three dimensional is used as it is.
+ */
+ final Geometry direct = ewkt.decode("SRID=4979;POINT Z (1 2 3)");
+ assertEquals("4979", IdentifiedObjects.getIdentifier(
+ direct.getCoordinateReferenceSystem(),
Citations.EPSG).getCode());
+ assertEquals("SRID=4979;POINT Z (1 2 3)", ewkt.encode(direct));
}
/**