forked from geodmms/xdgnjobs

Dennis Kao
2014-01-15 94ae08701bbd7585a0b7e5a92d1975965a503c03
xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/postjts/JtsBinaryWriter.java
@@ -50,8 +50,7 @@
 *
 * @author markus.schaber@logi-track.com
 */
public class JtsBinaryWriter
{
public class JtsBinaryWriter {
    /**
     * Get the appropriate ValueGetter for my endianness
@@ -59,16 +58,12 @@
     * @param bytes The appropriate Byte Getter
     * @return the ValueGetter
     */
    public static ValueSetter valueSetterForEndian(ByteSetter bytes, byte endian)
    {
        if (endian == ValueSetter.XDR.NUMBER)
        { // XDR
    public static ValueSetter valueSetterForEndian(ByteSetter bytes, byte endian) {
        if (endian == ValueSetter.XDR.NUMBER) { // XDR
            return new ValueSetter.XDR(bytes);
        } else if (endian == ValueSetter.NDR.NUMBER)
        {
        } else if (endian == ValueSetter.NDR.NUMBER) {
            return new ValueSetter.NDR(bytes);
        } else
        {
        } else {
            throw new IllegalArgumentException("Unknown Endian type:" + endian);
        }
    }
@@ -79,16 +74,14 @@
     * Currently, geometries with more than 2 dimensions and measures are not
     * cleanly supported, but SRID is honored.
     */
    public String writeHexed(Geometry geom, byte REP)
    {
    public String writeHexed(Geometry geom, byte REP) {
        int length = estimateBytes(geom);
        ByteSetter.StringByteSetter bytes = new ByteSetter.StringByteSetter(length);
        writeGeometry(geom, valueSetterForEndian(bytes, REP));
        return bytes.result();
    }
    public String writeHexed(Geometry geom)
    {
    public String writeHexed(Geometry geom) {
        return writeHexed(geom, ValueSetter.NDR.NUMBER);
    }
@@ -98,37 +91,30 @@
     * Currently, geometries with more than 2 dimensions and measures are not
     * cleanly supported, but SRID is honored.
     */
    public byte[] writeBinary(Geometry geom, byte REP)
    {
    public byte[] writeBinary(Geometry geom, byte REP) {
        int length = estimateBytes(geom);
        ByteSetter.BinaryByteSetter bytes = new ByteSetter.BinaryByteSetter(length);
        writeGeometry(geom, valueSetterForEndian(bytes, REP));
        return bytes.result();
    }
    public byte[] writeBinary(Geometry geom)
    {
    public byte[] writeBinary(Geometry geom) {
        return writeBinary(geom, ValueSetter.NDR.NUMBER);
    }
    /**
     * Parse a geometry starting at offset.
     */
    protected void writeGeometry(Geometry geom, ValueSetter dest)
    {
    protected void writeGeometry(Geometry geom, ValueSetter dest) {
        final int dimension;
        if (geom == null)
        {
        if (geom == null) {
            throw new NullPointerException();
        } else if (geom.isEmpty())
        {
        } else if (geom.isEmpty()) {
            // don't set any flag bits
            dimension = 0;
        } else
        {
        } else {
            dimension = getCoordDim(geom);
            if (dimension < 2 || dimension > 4)
            {
            if (dimension < 2 || dimension > 4) {
                throw new IllegalArgumentException("Unsupported geometry dimensionality: " + dimension);
            }
        }
@@ -138,30 +124,25 @@
        // write typeword
        final int plaintype = getWKBType(geom);
        int typeword = plaintype;
        if (dimension == 3 || dimension == 4)
        {
        if (dimension == 3 || dimension == 4) {
            typeword |= 0x80000000;
        }
        if (dimension == 4)
        {
        if (dimension == 4) {
            typeword |= 0x40000000;
        }
        final boolean haveSrid = checkSrid(geom);
        if (haveSrid)
        {
        if (haveSrid) {
            typeword |= 0x20000000;
        }
        dest.setInt(typeword);
        if (haveSrid)
        {
        if (haveSrid) {
            dest.setInt(geom.getSRID());
        }
        switch (plaintype)
        {
        switch (plaintype) {
        case org.postgis.Geometry.POINT:
            writePoint((Point) geom, dest);
            break;
@@ -188,37 +169,27 @@
        }
    }
    public static int getWKBType(Geometry geom)
    {
    public static int getWKBType(Geometry geom) {
        // We always write emtpy geometries as emtpy collections - for OpenGIS
        // conformance
        if (geom.isEmpty())
        {
        if (geom.isEmpty()) {
            return org.postgis.Geometry.GEOMETRYCOLLECTION;
        } else if (geom instanceof Point)
        {
        } else if (geom instanceof Point) {
            return org.postgis.Geometry.POINT;
        } else if (geom instanceof com.vividsolutions.jts.geom.LineString)
        {
        } else if (geom instanceof com.vividsolutions.jts.geom.LineString) {
            return org.postgis.Geometry.LINESTRING;
        } else if (geom instanceof com.vividsolutions.jts.geom.Polygon)
        {
        } else if (geom instanceof com.vividsolutions.jts.geom.Polygon) {
            return org.postgis.Geometry.POLYGON;
        } else if (geom instanceof MultiPoint)
        {
        } else if (geom instanceof MultiPoint) {
            return org.postgis.Geometry.MULTIPOINT;
        } else if (geom instanceof MultiLineString)
        {
        } else if (geom instanceof MultiLineString) {
            return org.postgis.Geometry.MULTILINESTRING;
        } else if (geom instanceof com.vividsolutions.jts.geom.MultiPolygon)
        {
        } else if (geom instanceof com.vividsolutions.jts.geom.MultiPolygon) {
            return org.postgis.Geometry.MULTIPOLYGON;
        }
        if (geom instanceof com.vividsolutions.jts.geom.GeometryCollection)
        {
        if (geom instanceof com.vividsolutions.jts.geom.GeometryCollection) {
            return org.postgis.Geometry.GEOMETRYCOLLECTION;
        } else
        {
        } else {
            throw new IllegalArgumentException("Unknown Geometry Type: " + geom.getClass().getName());
        }
    }
@@ -227,8 +198,7 @@
     * Writes a "slim" Point (without endiannes, srid ant type, only the
     * ordinates and measure. Used by writeGeometry.
     */
    private void writePoint(Point geom, ValueSetter dest)
    {
    private void writePoint(Point geom, ValueSetter dest) {
        writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
    }
@@ -236,62 +206,49 @@
     * Write a Coordinatesequence, part of LinearRing and Linestring, but not
     * MultiPoint!
     */
    private void writeCoordinates(CoordinateSequence seq, int dims, ValueSetter dest)
    {
        for (int i = 0; i < seq.size(); i++)
        {
            for (int d = 0; d < dims; d++)
            {
    private void writeCoordinates(CoordinateSequence seq, int dims, ValueSetter dest) {
        for (int i = 0; i < seq.size(); i++) {
            for (int d = 0; d < dims; d++) {
                dest.setDouble(seq.getOrdinate(i, d));
            }
        }
    }
    private void writeMultiPoint(MultiPoint geom, ValueSetter dest)
    {
    private void writeMultiPoint(MultiPoint geom, ValueSetter dest) {
        dest.setInt(geom.getNumPoints());
        for (int i = 0; i < geom.getNumPoints(); i++)
        {
        for (int i = 0; i < geom.getNumPoints(); i++) {
            writeGeometry(geom.getGeometryN(i), dest);
        }
    }
    private void writeLineString(LineString geom, ValueSetter dest)
    {
    private void writeLineString(LineString geom, ValueSetter dest) {
        dest.setInt(geom.getNumPoints());
        writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
    }
    private void writePolygon(Polygon geom, ValueSetter dest)
    {
    private void writePolygon(Polygon geom, ValueSetter dest) {
        dest.setInt(geom.getNumInteriorRing() + 1);
        writeLineString(geom.getExteriorRing(), dest);
        for (int i = 0; i < geom.getNumInteriorRing(); i++)
        {
        for (int i = 0; i < geom.getNumInteriorRing(); i++) {
            writeLineString(geom.getInteriorRingN(i), dest);
        }
    }
    private void writeMultiLineString(MultiLineString geom, ValueSetter dest)
    {
    private void writeMultiLineString(MultiLineString geom, ValueSetter dest) {
        writeGeometryArray(geom, dest);
    }
    private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest)
    {
    private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest) {
        writeGeometryArray(geom, dest);
    }
    private void writeCollection(GeometryCollection geom, ValueSetter dest)
    {
    private void writeCollection(GeometryCollection geom, ValueSetter dest) {
        writeGeometryArray(geom, dest);
    }
    private void writeGeometryArray(Geometry geom, ValueSetter dest)
    {
    private void writeGeometryArray(Geometry geom, ValueSetter dest) {
        dest.setInt(geom.getNumGeometries());
        for (int i = 0; i < geom.getNumGeometries(); i++)
        {
        for (int i = 0; i < geom.getNumGeometries(); i++) {
            writeGeometry(geom.getGeometryN(i), dest);
        }
    }
@@ -299,8 +256,7 @@
    /**
     * Estimate how much bytes a geometry will need in WKB.
     */
    protected int estimateBytes(Geometry geom)
    {
    protected int estimateBytes(Geometry geom) {
        int result = 0;
        // write endian flag
@@ -309,13 +265,11 @@
        // write typeword
        result += 4;
        if (checkSrid(geom))
        {
        if (checkSrid(geom)) {
            result += 4;
        }
        switch (getWKBType(geom))
        {
        switch (getWKBType(geom)) {
        case org.postgis.Geometry.POINT:
            result += estimatePoint((Point) geom);
            break;
@@ -343,26 +297,22 @@
        return result;
    }
    private boolean checkSrid(Geometry geom)
    {
    private boolean checkSrid(Geometry geom) {
        final int srid = geom.getSRID();
        // SRID is default 0 with jts geometries
        return (srid != -1) && (srid != 0);
    }
    private int estimatePoint(Point geom)
    {
    private int estimatePoint(Point geom) {
        return 8 * getCoordDim(geom);
    }
    /**
     * Write an Array of "full" Geometries
     */
    private int estimateGeometryArray(Geometry container)
    {
    private int estimateGeometryArray(Geometry container) {
        int result = 0;
        for (int i = 0; i < container.getNumGeometries(); i++)
        {
        for (int i = 0; i < container.getNumGeometries(); i++) {
            result += estimateBytes(container.getGeometryN(i));
        }
        return result;
@@ -371,12 +321,10 @@
    /**
     * Estimate an array of "fat" Points
     */
    private int estimateMultiPoint(MultiPoint geom)
    {
    private int estimateMultiPoint(MultiPoint geom) {
        // int size
        int result = 4;
        if (geom.getNumGeometries() > 0)
        {
        if (geom.getNumGeometries() > 0) {
            // We can shortcut here, compared to estimateGeometryArray, as all
            // subgeoms have the same fixed size
            result += geom.getNumGeometries() * estimateBytes(geom.getGeometryN(0));
@@ -384,85 +332,68 @@
        return result;
    }
    private int estimateLineString(LineString geom)
    {
        if (geom == null || geom.getNumGeometries() == 0)
        {
    private int estimateLineString(LineString geom) {
        if (geom == null || geom.getNumGeometries() == 0) {
            return 0;
        } else
        {
        } else {
            return 4 + 8 * getCoordSequenceDim(geom.getCoordinateSequence()) * geom.getCoordinateSequence().size();
        }
    }
    private int estimatePolygon(Polygon geom)
    {
    private int estimatePolygon(Polygon geom) {
        // int length
        int result = 4;
        result += estimateLineString(geom.getExteriorRing());
        for (int i = 0; i < geom.getNumInteriorRing(); i++)
        {
        for (int i = 0; i < geom.getNumInteriorRing(); i++) {
            result += estimateLineString(geom.getInteriorRingN(i));
        }
        return result;
    }
    private int estimateMultiLineString(MultiLineString geom)
    {
    private int estimateMultiLineString(MultiLineString geom) {
        // 4-byte count + subgeometries
        return 4 + estimateGeometryArray(geom);
    }
    private int estimateMultiPolygon(MultiPolygon geom)
    {
    private int estimateMultiPolygon(MultiPolygon geom) {
        // 4-byte count + subgeometries
        return 4 + estimateGeometryArray(geom);
    }
    private int estimateCollection(GeometryCollection geom)
    {
    private int estimateCollection(GeometryCollection geom) {
        // 4-byte count + subgeometries
        return 4 + estimateGeometryArray(geom);
    }
    public static final int getCoordDim(Geometry geom)
    {
        if (geom.isEmpty())
        {
    public static final int getCoordDim(Geometry geom) {
        if (geom.isEmpty()) {
            return 0;
        }
        if (geom instanceof Point)
        {
        if (geom instanceof Point) {
            return getCoordSequenceDim(((Point) geom).getCoordinateSequence());
        } else if (geom instanceof LineString)
        {
        } else if (geom instanceof LineString) {
            return getCoordSequenceDim(((LineString) geom).getCoordinateSequence());
        } else if (geom instanceof Polygon)
        {
        } else if (geom instanceof Polygon) {
            return getCoordSequenceDim(((Polygon) geom).getExteriorRing().getCoordinateSequence());
        } else
        {
        } else {
            return getCoordDim(geom.getGeometryN(0));
        }
    }
    public static final int getCoordSequenceDim(CoordinateSequence coords)
    {
    public static final int getCoordSequenceDim(CoordinateSequence coords) {
        if (coords == null || coords.size() == 0)
            return 0;
        // JTS has a really strange way to handle dimensions!
        // Just have a look at PackedCoordinateSequence and
        // CoordinateArraySequence
        int dimensions = coords.getDimension();
        if (dimensions == 3)
        {
        if (dimensions == 3) {
            // CoordinateArraySequence will always return 3, so we have to
            // check, if
            // the third ordinate contains NaN, then the geom is actually
            // 2-dimensional
            return Double.isNaN(coords.getOrdinate(0, CoordinateSequence.Z)) ? 2 : 3;
        } else
        {
        } else {
            return dimensions;
        }
    }