GeoPackageReader.java
package org.cugos.wkg;
import java.nio.ByteBuffer;
/**
* Read GeoPackage encoded Geometry
* @author Jared Erickson
*/
public class GeoPackageReader implements Reader<byte[]> {
/**
* The WKBReader
*/
private final WKBReader wkbReader = new WKBReader();
/**
* Read a Geometry from an array of bytes.
* @param bytes The array of bytes
* @return A Geometry or null
*/
@Override
public Geometry read(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.wrap(bytes);
return read(buffer, true).getGeometry();
}
@Override
public String getName() {
return "GeoPackage";
}
/**
* Read a Geometry from a hex String
* @param hex The hex String
* @return A Geometry or null
*/
public Geometry read(String hex) {
return read(toBytes(hex));
}
/**
* Read a Geometry from a ByteBuffer
* @param buffer The ByteBuffer
* @return A Geometry or null
*/
private GeoPackageGeometry read(ByteBuffer buffer, boolean shouldReadGeometry) {
GeoPackageGeometry geoPackageGeometry = new GeoPackageGeometry();
// Magic
byte[] magic = new byte[2];
buffer.get(magic);
// Version
int version = buffer.get();
geoPackageGeometry.setVersion(version);
// Flags
byte flags = buffer.get();
int geoPackageBinaryType = flags & GeoPackage.Flag.BinaryType.getValue();
GeoPackage.BinaryType binaryType = GeoPackage.BinaryType.get(geoPackageBinaryType);
geoPackageGeometry.setBinaryType(binaryType);
int emptyGeometryFlag = flags & GeoPackage.Flag.GeometryEmpty.getValue();
GeoPackage.GeometryEmptyType geometryEmptyType = GeoPackage.GeometryEmptyType.get(emptyGeometryFlag);
geoPackageGeometry.setGeometryEmptyType(geometryEmptyType);
int envelopeTypeFlag = (flags & GeoPackage.Flag.EnvelopeIndicator.getValue()) >> 1;
GeoPackage.EnvelopeType envelopeType = GeoPackage.EnvelopeType.get(envelopeTypeFlag);
geoPackageGeometry.setEnvelopeType(envelopeType);
int byteOrder = flags & GeoPackage.Flag.Endianess.getValue();
WKB.Endian endian = WKB.Endian.get(byteOrder);
geoPackageGeometry.setEndian(endian);
// SRS ID
int srsId = buffer.getInt();
geoPackageGeometry.setSrsId(srsId);
//Envelope
Envelope envelope = null;
if (envelopeType != GeoPackage.EnvelopeType.NoEnvelope) {
double minX = buffer.getDouble();
double maxX = buffer.getDouble();
double minY = buffer.getDouble();
double maxY = buffer.getDouble();
double minZ = Double.NaN;
double maxZ = Double.NaN;
double minM = Double.NaN;
double maxM = Double.NaN;
if (envelopeType == GeoPackage.EnvelopeType.EnvelopeZ || envelopeType == GeoPackage.EnvelopeType.EnvelopeZM) {
minZ = buffer.getDouble();
maxZ = buffer.getDouble();
}
if (envelopeType == GeoPackage.EnvelopeType.EnvelopeM || envelopeType == GeoPackage.EnvelopeType.EnvelopeZM) {
minM = buffer.getDouble();
maxM = buffer.getDouble();
}
envelope = Envelope.create3DM(minX, minY, minZ, minM, maxX, maxY, maxZ, maxM);
}
geoPackageGeometry.setEnvelope(envelope);
// WKBGeometry
if (shouldReadGeometry) {
Geometry geometry = wkbReader.read(buffer);
geometry.setSrid(String.valueOf(srsId));
geoPackageGeometry.setGeometry(geometry);
}
return geoPackageGeometry;
}
/**
* Convert a hex String into a byte Array
* @param hexString The hex String
* @return An array of bytes
*/
private static byte[] toBytes(String hexString) {
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i+1), 16));
}
return data;
}
/**
* A GeoPackageGeometry holds the GeoPackage header information plus a Geometry
*/
private static class GeoPackageGeometry {
private int version;
private GeoPackage.BinaryType binaryType;
private GeoPackage.GeometryEmptyType geometryEmptyType;
private GeoPackage.EnvelopeType envelopeType;
private WKB.Endian endian;
private int srsId;
private Envelope envelope;
private Geometry geometry;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public GeoPackage.BinaryType getBinaryType() {
return binaryType;
}
public void setBinaryType(GeoPackage.BinaryType binaryType) {
this.binaryType = binaryType;
}
public GeoPackage.GeometryEmptyType getGeometryEmptyType() {
return geometryEmptyType;
}
public void setGeometryEmptyType(GeoPackage.GeometryEmptyType geometryEmptyType) {
this.geometryEmptyType = geometryEmptyType;
}
public GeoPackage.EnvelopeType getEnvelopeType() {
return envelopeType;
}
public void setEnvelopeType(GeoPackage.EnvelopeType envelopeType) {
this.envelopeType = envelopeType;
}
public WKB.Endian getEndian() {
return endian;
}
public void setEndian(WKB.Endian endian) {
this.endian = endian;
}
public int getSrsId() {
return srsId;
}
public void setSrsId(int srsId) {
this.srsId = srsId;
}
public Envelope getEnvelope() {
return envelope;
}
public void setEnvelope(Envelope envelope) {
this.envelope = envelope;
}
public Geometry getGeometry() {
return geometry;
}
public void setGeometry(Geometry geometry) {
this.geometry = geometry;
}
}
}