Subversion Repositories hibernate-spatial

Rev

Blame | Last modification | View Log | RSS feed

package org.hibernatespatial.wkb;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import org.hibernatespatial.jts.geom.CoordinateDimension;
import org.hibernatespatial.mgeom.MCoordinate;

/**
 * @author Karel Maesen, Geovise BVBA
 *         creation-date: Nov 11, 2010
 */
public abstract class WKBEncoder<G extends Geometry> {


    public Bytes encode(G geom) {
        return encode(geom, null);
    }

    public Bytes encode(G geom, WKBByteOrder wbo) {
        CoordinateDimension dimension = CoordinateDimension.valueFor(hasZ(geom), hasM(geom));
        Bytes output = Bytes.allocate(calculateSize(geom, dimension));
        if (wbo != null) {
            output.setWKBByteOrder(wbo);
        }
        writeByteOrder(output);
        writeTypeCodeAndSRID(geom, dimension, output);
        writeNumComponents(geom, output);
        writeComponents(geom, dimension, output);
        output.rewind();
        return output;
    }

    protected void writeByteOrder(Bytes output){
        output.put(output.getWKBByteOrder().byteValue());
    }


    protected void writeCoordinate(Coordinate coordinate, CoordinateDimension dimension, Bytes output) {
        output.putDouble(coordinate.x);
        output.putDouble(coordinate.y);
        if(dimension.hasZ()){
            output.putDouble(coordinate.z);
        }
        if (dimension.hasM()){
            double m = 0.0;
            if (coordinate instanceof MCoordinate){
                m = ((MCoordinate)coordinate).m;
            }
            output.putDouble(m);
        }
    }

    protected boolean hasM(Geometry geom) {
        Coordinate co = geom.getCoordinate();
        if (co instanceof MCoordinate) {
            return ! Double.isNaN(((MCoordinate)co).m);
        }
        return false;
    }

    protected boolean hasZ(Geometry geom) {
        return !Double.isNaN(geom.getCoordinate().z);
    }

    protected void writeTypeCodeAndSRID(G geometry, CoordinateDimension dimension, Bytes output){
            long typeCode = getGeometryType();
            boolean hasSRID = (geometry.getSRID() > 0);
            if (hasSRID)
                typeCode |= WKB.SRID_FLAG;
            if (dimension.hasM())
                typeCode |= WKB.M_FLAG;
            if (dimension.hasZ())
                typeCode |= WKB.Z_FLAG;
            output.putUInt(typeCode);
            if(hasSRID){
                output.putInt(geometry.getSRID());
            }

    }

    protected abstract long getGeometryType();

    protected abstract void writeNumComponents(G geometry, Bytes output);

    protected abstract void writeComponents(G geometry, CoordinateDimension dimension, Bytes output);

    protected abstract int calculateSize(G geom, CoordinateDimension dimension);


}