org.geolatte.geom.codec.WkbDialect Maven / Gradle / Ivy
Show all versions of geolatte-geom Show documentation
package org.geolatte.geom.codec;
import org.geolatte.geom.*;
import java.util.HashMap;
import java.util.Map;
import static org.geolatte.geom.GeometryType.*;
class WkbDialect {
final private Map typemap = new HashMap<>();
final public static Long WKB_POINT = 1L;
final public static Long WKB_LINESTRING = 2L;
final public static Long WKB_POLYGON = 3L;
final public static Long WKB_MULTIPOINT = 4L;
final public static Long WKB_MULTILINESTRING = 5L;
final public static Long WKB_MULTIPOLYGON = 6L;
final public static Long WKB_GEOMETRYCOLLECTION = 7L;
protected WkbDialect() {
typemap.put(WKB_POINT, POINT);
typemap.put(WKB_LINESTRING, LINESTRING);
typemap.put(WKB_POLYGON, POLYGON);
typemap.put(WKB_MULTIPOINT, MULTIPOINT);
typemap.put(WKB_MULTILINESTRING, MULTILINESTRING);
typemap.put(WKB_MULTIPOLYGON, MULTIPOLYGON);
typemap.put(WKB_GEOMETRYCOLLECTION, GEOMETRYCOLLECTION);
}
GeometryType parseType(long tpe) {
GeometryType gt = typemap.get(tpe);
if (gt == null) throw new WkbDecodeException("Unsupported WKB type code: " + tpe);
return gt;
}
boolean hasZ(long tpe) {
return false;
}
boolean hasM(long tpe) {
return false;
}
BaseWkbVisitor
mkVisitor(Geometry
geom, ByteOrder bo) {
ByteBuffer buffer = mkByteBuffer(geom, bo);
return new BaseWkbVisitor<>(buffer, this);
}
protected
ByteBuffer mkByteBuffer(Geometry
geom, ByteOrder bo) {
ByteBuffer buffer = ByteBuffer.allocate(calculateSize(geom, true));
if (bo != null) {
buffer.setByteOrder(bo);
}
return buffer;
}
protected
int calculateSize(Geometry
geom, boolean topLevel) {
int size = 1 + ByteBuffer.UINT_SIZE; //size for order byte + type field
if (topLevel) {
size += extraHeaderSize(geom);
}
//empty geoms have same representation as an empty GeometryCollection
if (geom.isEmpty()) return size + sizeEmptyGeometry(geom);
if (geom instanceof AbstractGeometryCollection) {
size += sizeOfGeometryCollection((AbstractGeometryCollection
) geom);
} else if (geom instanceof Polygon) {
size += getPolygonSize((Polygon
) geom);
} else if (geom instanceof Point) {
size += getPositionSize(geom);
} else {
size += ByteBuffer.UINT_SIZE; //to hold number of points
size += getPositionSize(geom) * geom.getNumPositions();
}
return size;
}
protected
int extraHeaderSize(Geometry
geom) {
return 0;
}
protected
int sizeEmptyGeometry(Geometry
geometry) {
if (geometry.getGeometryType() == GeometryType.POINT) {
//Empty Point encoded with NaN coordinates? then same size as one position,
// else number of elements (0 elements)
return emptyPointAsNaN() ? getPositionSize(geometry) : ByteBuffer.UINT_SIZE;
} else {
// indicate no positions follow
return ByteBuffer.UINT_SIZE;
}
}
protected
int getPositionSize(Geometry
geom) {
return geom.getCoordinateDimension() * ByteBuffer.DOUBLE_SIZE;
}
protected
int getPolygonSize(Polygon
geom) {
//to hold the number of linear rings
int size = ByteBuffer.UINT_SIZE;
//for each linear ring, a UINT holds the number of points
size += geom.isEmpty() ? 0 : ByteBuffer.UINT_SIZE * (geom.getNumInteriorRing() + 1);
size += getPositionSize(geom) * geom.getNumPositions();
return size;
}
protected
> int sizeOfGeometryCollection(AbstractGeometryCollection
collection) {
int size = ByteBuffer.UINT_SIZE;
for (G g : collection) {
size += calculateSize(g, false);
}
return size;
}
boolean emptyPointAsNaN() {
return true;
}
protected
Long geometryTypeCode(Geometry
geometry) {
for (Map.Entry tpe : typemap.entrySet()) {
if (tpe.getValue() == geometry.getGeometryType()) {
return tpe.getKey();
}
}
throw new UnsupportedConversionException(
String.format(
"Can't convert geometries of type %s",
geometry.getClass().getCanonicalName()
)
);
}
}