GeoPackageWriter.java
package org.cugos.wkg;
import java.nio.ByteBuffer;
/**
* Write GeoPackage encoded Geometry
* @author Jared Erickson
*/
public class GeoPackageWriter implements Writer<byte[]> {
/**
* The GeoPackage version
*/
private int version = 0;
/**
* The GeoPackage binary type
*/
private GeoPackage.BinaryType binaryType = GeoPackage.BinaryType.Standard;
/**
* The GeoPackage Envelope Type
*/
private GeoPackage.EnvelopeType envelopType = GeoPackage.EnvelopeType.NoEnvelope;
/**
* The Endian flag
*/
private WKB.Endian endian = WKB.Endian.Big;
/**
* The WKBWriter
*/
private WKBWriter wkbWriter;
/**
* Create a new GeoPackageWriter that uses Big Endian and encodes the Envelope without MZ values
*/
public GeoPackageWriter() {
this(WKB.Endian.Big, GeoPackage.EnvelopeType.Envelope);
}
/**
* Create a new GeopackageWriter
* @param endian The Endian flag
* @param envelopeType The EnvelopeType
*/
public GeoPackageWriter(WKB.Endian endian, GeoPackage.EnvelopeType envelopeType) {
this.endian = endian;
this.envelopType = envelopeType;
this.wkbWriter = new WKBWriter(WKB.Type.EWKB, endian);
}
/**
* Write the Geometry to a hex String
* @param geometry The Geometry
* @return A WKB hex String
*/
public String writeToHex(Geometry geometry) {
return toHex(write(geometry));
}
/**
* Write a Geometry to an array of bytes
* @param g The Geometry
* @return An array of bytes
*/
@Override
public byte[] write(Geometry g) {
//System.out.println(calculateNumberOfBytes(g));
ByteBuffer buffer = ByteBuffer.allocate(calculateNumberOfBytes(g));
// Magic (2)
buffer.put((byte)'G');
buffer.put((byte)'P');
// Version (1)
buffer.put((byte)version);
// Flags (1)
byte flag = 0;
flag |= ((((byte) envelopType.getValue() << 1) & GeoPackage.Flag.EnvelopeIndicator.getValue()));
flag |= ((byte) binaryType.getValue()) & GeoPackage.Flag.BinaryType.getValue();
flag |= ((byte) (g.isEmpty() ? GeoPackage.GeometryEmptyType.Empty.getValue() : GeoPackage.GeometryEmptyType.NotEmpty.getValue())) & GeoPackage.Flag.GeometryEmpty.getValue();
flag |= ((byte) endian.getValue()) & GeoPackage.Flag.Endianess.getValue();
buffer.put(flag);
// SRS ID (4)
buffer.putInt(g.getSrid() != null ? Integer.parseInt(g.getSrid()) : -1);
// Envelope (8 * 4)
if (envelopType != GeoPackage.EnvelopeType.NoEnvelope) {
Envelope envelope = g.getEnvelope();
buffer.putDouble(envelope.getMinX());
buffer.putDouble(envelope.getMaxX());
buffer.putDouble(envelope.getMinY());
buffer.putDouble(envelope.getMaxY());
if (envelopType == GeoPackage.EnvelopeType.EnvelopeZ || envelopType == GeoPackage.EnvelopeType.EnvelopeZM) {
buffer.putDouble(envelope.getMinZ());
buffer.putDouble(envelope.getMaxZ());
}
if (envelopType == GeoPackage.EnvelopeType.EnvelopeM || envelopType == GeoPackage.EnvelopeType.EnvelopeZM) {
buffer.putDouble(envelope.getMinM());
buffer.putDouble(envelope.getMaxM());
}
}
// WKBGeometry
wkbWriter.putGeometry(buffer, g);
return buffer.array();
}
@Override
public String getName() {
return "GeoPackage";
}
protected int calculateNumberOfBytes(Geometry g) {
return wkbWriter.calculateNumberOfBytes(g)
+ 2 // magic
+ 1 // version
+ 1 // flags
+ 4 // srid
+ calculateNumberOfBytes(envelopType);
}
private int calculateNumberOfBytes(GeoPackage.EnvelopeType envelopeType) {
if (envelopeType == GeoPackage.EnvelopeType.NoEnvelope) {
return 0;
} else if (envelopeType == GeoPackage.EnvelopeType.Envelope) {
return 8 * 4;
} else if (envelopeType == GeoPackage.EnvelopeType.EnvelopeZ) {
return 8 * 6;
} else if (envelopeType == GeoPackage.EnvelopeType.EnvelopeM) {
return 8 * 6;
} else if (envelopeType == GeoPackage.EnvelopeType.EnvelopeZM) {
return 8 * 8;
} else {
return 0;
}
}
/**
* The hex array
*/
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
/**
* Convert an array of bytes to a hex String.
* @param bytes The array of bytes
* @return The hex String
*/
private static String toHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}