| | |
| | | * |
| | | * @author Markus Schaber, markus.schaber@logix-tt.com |
| | | */ |
| | | public class JtsBinaryParser |
| | | { |
| | | public class JtsBinaryParser { |
| | | |
| | | /** |
| | | * Get the appropriate ValueGetter for my endianness |
| | |
| | | * @param bytes The appropriate Byte Getter |
| | | * @return the ValueGetter |
| | | */ |
| | | public static ValueGetter valueGetterForEndian(ByteGetter bytes) |
| | | { |
| | | if (bytes.get(0) == ValueGetter.XDR.NUMBER) |
| | | { // XDR |
| | | public static ValueGetter valueGetterForEndian(ByteGetter bytes) { |
| | | if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR |
| | | return new ValueGetter.XDR(bytes); |
| | | } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) |
| | | { |
| | | } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) { |
| | | return new ValueGetter.NDR(bytes); |
| | | } else |
| | | { |
| | | } else { |
| | | throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0)); |
| | | } |
| | | } |
| | |
| | | /** |
| | | * Parse a hex encoded geometry |
| | | */ |
| | | public Geometry parse(String value) |
| | | { |
| | | public Geometry parse(String value) { |
| | | StringByteGetter bytes = new ByteGetter.StringByteGetter(value); |
| | | return parseGeometry(valueGetterForEndian(bytes)); |
| | | } |
| | |
| | | /** |
| | | * Parse a binary encoded geometry. |
| | | */ |
| | | public Geometry parse(byte[] value) |
| | | { |
| | | public Geometry parse(byte[] value) { |
| | | BinaryByteGetter bytes = new ByteGetter.BinaryByteGetter(value); |
| | | return parseGeometry(valueGetterForEndian(bytes)); |
| | | } |
| | |
| | | /** |
| | | * Parse a geometry starting at offset. |
| | | */ |
| | | protected Geometry parseGeometry(ValueGetter data) |
| | | { |
| | | protected Geometry parseGeometry(ValueGetter data) { |
| | | return parseGeometry(data, 0, false); |
| | | } |
| | | |
| | | /** |
| | | * Parse with a known geometry factory |
| | | */ |
| | | protected Geometry parseGeometry(ValueGetter data, int srid, boolean inheritSrid) |
| | | { |
| | | protected Geometry parseGeometry(ValueGetter data, int srid, boolean inheritSrid) { |
| | | byte endian = data.getByte(); // skip and test endian flag |
| | | if (endian != data.endian) |
| | | { |
| | | if (endian != data.endian) { |
| | | throw new IllegalArgumentException("Endian inconsistency!"); |
| | | } |
| | | int typeword = data.getInt(); |
| | |
| | | boolean haveM = (typeword & 0x40000000) != 0; |
| | | boolean haveS = (typeword & 0x20000000) != 0; |
| | | |
| | | if (haveS) |
| | | { |
| | | if (haveS) { |
| | | int newsrid = data.getInt(); |
| | | if (inheritSrid && newsrid != srid) |
| | | { |
| | | if (inheritSrid && newsrid != srid) { |
| | | throw new IllegalArgumentException("Inconsistent srids in complex geometry: " + srid + ", " + newsrid); |
| | | } else |
| | | { |
| | | } else { |
| | | srid = newsrid; |
| | | } |
| | | } else if (!inheritSrid) |
| | | { |
| | | } else if (!inheritSrid) { |
| | | srid = -1; |
| | | } |
| | | |
| | | Geometry result; |
| | | switch (realtype) |
| | | { |
| | | switch (realtype) { |
| | | case org.postgis.Geometry.POINT: |
| | | result = parsePoint(data, haveZ, haveM); |
| | | break; |
| | |
| | | return result; |
| | | } |
| | | |
| | | private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) |
| | | { |
| | | private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) { |
| | | double X = data.getDouble(); |
| | | double Y = data.getDouble(); |
| | | Point result; |
| | | if (haveZ) |
| | | { |
| | | if (haveZ) { |
| | | double Z = data.getDouble(); |
| | | result = JtsGeometry.geofac.createPoint(new Coordinate(X, Y, Z)); |
| | | } else |
| | | { |
| | | } else { |
| | | result = JtsGeometry.geofac.createPoint(new Coordinate(X, Y)); |
| | | } |
| | | |
| | | if (haveM) |
| | | { // skip M value |
| | | if (haveM) { // skip M value |
| | | data.getDouble(); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Parse an Array of "full" Geometries |
| | | */ |
| | | private void parseGeometryArray(ValueGetter data, Geometry[] container, int srid) |
| | | { |
| | | for (int i = 0; i < container.length; i++) |
| | | { |
| | | private void parseGeometryArray(ValueGetter data, Geometry[] container, int srid) { |
| | | for (int i = 0; i < container.length; i++) { |
| | | container[i] = parseGeometry(data, srid, true); |
| | | } |
| | | } |
| | |
| | | * @param haveZ |
| | | * @param haveM |
| | | */ |
| | | private CoordinateSequence parseCS(ValueGetter data, boolean haveZ, boolean haveM) |
| | | { |
| | | private CoordinateSequence parseCS(ValueGetter data, boolean haveZ, boolean haveM) { |
| | | int count = data.getInt(); |
| | | int dims = haveZ ? 3 : 2; |
| | | CoordinateSequence cs = new PackedCoordinateSequence.Double(count, dims); |
| | | |
| | | for (int i = 0; i < count; i++) |
| | | { |
| | | for (int d = 0; d < dims; d++) |
| | | { |
| | | for (int i = 0; i < count; i++) { |
| | | for (int d = 0; d < dims; d++) { |
| | | cs.setOrdinate(i, d, data.getDouble()); |
| | | } |
| | | if (haveM) |
| | | { // skip M value |
| | | if (haveM) { // skip M value |
| | | data.getDouble(); |
| | | } |
| | | } |
| | | return cs; |
| | | } |
| | | |
| | | private MultiPoint parseMultiPoint(ValueGetter data, int srid) |
| | | { |
| | | private MultiPoint parseMultiPoint(ValueGetter data, int srid) { |
| | | Point[] points = new Point[data.getInt()]; |
| | | parseGeometryArray(data, points, srid); |
| | | return JtsGeometry.geofac.createMultiPoint(points); |
| | | } |
| | | |
| | | private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) |
| | | { |
| | | private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) { |
| | | return JtsGeometry.geofac.createLineString(parseCS(data, haveZ, haveM)); |
| | | } |
| | | |
| | | private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) |
| | | { |
| | | private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) { |
| | | return JtsGeometry.geofac.createLinearRing(parseCS(data, haveZ, haveM)); |
| | | } |
| | | |
| | | private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM, int srid) |
| | | { |
| | | private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM, int srid) { |
| | | int holecount = data.getInt() - 1; |
| | | LinearRing[] rings = new LinearRing[holecount]; |
| | | LinearRing shell = parseLinearRing(data, haveZ, haveM); |
| | | shell.setSRID(srid); |
| | | for (int i = 0; i < holecount; i++) |
| | | { |
| | | for (int i = 0; i < holecount; i++) { |
| | | rings[i] = parseLinearRing(data, haveZ, haveM); |
| | | rings[i].setSRID(srid); |
| | | } |
| | | return JtsGeometry.geofac.createPolygon(shell, rings); |
| | | } |
| | | |
| | | private MultiLineString parseMultiLineString(ValueGetter data, int srid) |
| | | { |
| | | private MultiLineString parseMultiLineString(ValueGetter data, int srid) { |
| | | int count = data.getInt(); |
| | | LineString[] strings = new LineString[count]; |
| | | parseGeometryArray(data, strings, srid); |
| | | return JtsGeometry.geofac.createMultiLineString(strings); |
| | | } |
| | | |
| | | private MultiPolygon parseMultiPolygon(ValueGetter data, int srid) |
| | | { |
| | | private MultiPolygon parseMultiPolygon(ValueGetter data, int srid) { |
| | | int count = data.getInt(); |
| | | Polygon[] polys = new Polygon[count]; |
| | | parseGeometryArray(data, polys, srid); |
| | | return JtsGeometry.geofac.createMultiPolygon(polys); |
| | | } |
| | | |
| | | private GeometryCollection parseCollection(ValueGetter data, int srid) |
| | | { |
| | | private GeometryCollection parseCollection(ValueGetter data, int srid) { |
| | | int count = data.getInt(); |
| | | Geometry[] geoms = new Geometry[count]; |
| | | parseGeometryArray(data, geoms, srid); |