提交 fd0020e0 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Create a factory with proper SRID in ValueGeometry.getGeometryNoCopy() instead…

Create a factory with proper SRID in ValueGeometry.getGeometryNoCopy() instead of a trick in getGeometry()
上级 940de591
...@@ -10,6 +10,7 @@ import java.sql.SQLException; ...@@ -10,6 +10,7 @@ import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.Bits;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.CoordinateSequence;
...@@ -143,24 +144,38 @@ public class ValueGeometry extends Value { ...@@ -143,24 +144,38 @@ public class ValueGeometry extends Value {
public Geometry getGeometry() { public Geometry getGeometry() {
Geometry geometry = getGeometryNoCopy(); Geometry geometry = getGeometryNoCopy();
Geometry copy = geometry.copy(); Geometry copy = geometry.copy();
/*
* Geometry factory is not preserved in WKB format, but SRID is preserved.
*
* We use a new factory to read geometries from WKB with default SRID value of
* 0.
*
* Geometry.copy() copies the geometry factory and copied value has SRID form
* the factory instead of original SRID value. So we need to copy SRID here with
* non-recommended (but not deprecated) setSRID() method.
*/
copy.setSRID(geometry.getSRID());
return copy; return copy;
} }
public Geometry getGeometryNoCopy() { public Geometry getGeometryNoCopy() {
if (geometry == null) { if (geometry == null) {
try { try {
geometry = new WKBReader().read(bytes); int srid = 0;
getSRID: if (bytes.length >= 5) {
boolean bigEndian;
switch (bytes[0]) {
case 0:
bigEndian = true;
break;
case 1:
bigEndian = false;
break;
default:
break getSRID;
}
int type = Bits.readInt(bytes, 1);
if ((type & (bigEndian ? 0x2000_0000 : 0x20)) != 0 && bytes.length >= 9) {
srid = Bits.readInt(bytes, 5);
if (!bigEndian) {
srid = Integer.reverseBytes(srid);
}
}
}
/*
* No-arg WKBReader() constructor instantiates a new GeometryFactory and a new
* PrecisionModel anyway, so special case for srid == 0 is not needed.
*/
geometry = new WKBReader(new GeometryFactory(new PrecisionModel(), srid)).read(bytes);
} catch (ParseException ex) { } catch (ParseException ex) {
throw DbException.convert(ex); throw DbException.convert(ex);
} }
......
...@@ -26,7 +26,9 @@ import org.locationtech.jts.geom.GeometryFactory; ...@@ -26,7 +26,9 @@ import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.util.AffineTransformation; import org.locationtech.jts.geom.util.AffineTransformation;
import org.locationtech.jts.io.ByteOrderValues;
import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBWriter;
import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.io.WKTReader;
/** /**
...@@ -604,6 +606,26 @@ public class TestSpatial extends TestBase { ...@@ -604,6 +606,26 @@ public class TestSpatial extends TestBase {
// Test SRID // Test SRID
copy = ValueGeometry.get(geom3d.getBytes()); copy = ValueGeometry.get(geom3d.getBytes());
assertEquals(27572, copy.getGeometry().getSRID()); assertEquals(27572, copy.getGeometry().getSRID());
Point point = new GeometryFactory().createPoint((new Coordinate(1.1d, 1.2d)));
// SRID 0
checkSRID(ValueGeometry.getFromGeometry(point).getBytes(), 0);
checkSRID(new WKBWriter(2, ByteOrderValues.BIG_ENDIAN, false).write(point), 0);
checkSRID(new WKBWriter(2, ByteOrderValues.BIG_ENDIAN, true).write(point), 0);
checkSRID(new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN, false).write(point), 0);
checkSRID(new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN, true).write(point), 0);
// SRID 1,000,000,000
point.setSRID(1_000_000_000);
checkSRID(ValueGeometry.getFromGeometry(point).getBytes(), 1_000_000_000);
checkSRID(new WKBWriter(2, ByteOrderValues.BIG_ENDIAN, true).write(point), 1_000_000_000);
checkSRID(new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN, true).write(point), 1_000_000_000);
}
private void checkSRID(byte[] bytes, int srid) {
Point point = (Point) ValueGeometry.get(bytes).getGeometry();
assertEquals(1.1, point.getX());
assertEquals(1.2, point.getY());
assertEquals(srid, point.getSRID());
assertEquals(srid, point.getFactory().getSRID());
} }
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论