/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.common.instance.orient.internal;
import java.io.IOException;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.io.ByteOrderValues;
import com.vividsolutions.jts.io.OutStream;
import com.vividsolutions.jts.io.WKBConstants;
import com.vividsolutions.jts.io.WKBWriter;
/**
* WKB writer that differentiates between {@link LinearRing} and
* {@link LineString}.
*
* @author Simon Templer
*/
public class ExtendedWKBWriter extends WKBWriter {
/**
* Value for LinearRing geometry type
*/
public static final int wkbLinearRing = 8;
private final int byteOrder;
private final int outputDimension;
private final boolean includeSRID = false;
// holds output data values
private final byte[] buf = new byte[8];
/**
* @see WKBWriter#WKBWriter(int)
*/
public ExtendedWKBWriter(int outputDimension) {
super(outputDimension);
this.outputDimension = outputDimension;
this.byteOrder = ByteOrderValues.BIG_ENDIAN;
}
/**
* @see com.vividsolutions.jts.io.WKBWriter#write(com.vividsolutions.jts.geom.Geometry,
* com.vividsolutions.jts.io.OutStream)
*/
@Override
public void write(Geometry geom, OutStream os) throws IOException {
if (geom instanceof LinearRing) {
writeLinearRing((LinearRing) geom, os);
}
else {
super.write(geom, os);
}
}
private void writeLinearRing(LinearRing ring, OutStream os) throws IOException {
writeByteOrder(os);
writeGeometryType(wkbLinearRing, ring, os);
writeCoordinateSequence(ring.getCoordinateSequence(), true, os);
}
private void writeGeometryType(int geometryType, Geometry g, OutStream os) throws IOException {
int flag3D = (outputDimension == 3) ? 0x80000000 : 0;
int typeInt = geometryType | flag3D;
typeInt |= includeSRID ? 0x20000000 : 0;
writeInt(typeInt, os);
if (includeSRID) {
writeInt(g.getSRID(), os);
}
}
private void writeByteOrder(OutStream os) throws IOException {
if (byteOrder == ByteOrderValues.LITTLE_ENDIAN)
buf[0] = WKBConstants.wkbNDR;
else
buf[0] = WKBConstants.wkbXDR;
os.write(buf, 1);
}
private void writeCoordinateSequence(CoordinateSequence seq, boolean writeSize, OutStream os)
throws IOException {
if (writeSize)
writeInt(seq.size(), os);
for (int i = 0; i < seq.size(); i++) {
writeCoordinate(seq, i, os);
}
}
private void writeInt(int intValue, OutStream os) throws IOException {
ByteOrderValues.putInt(intValue, buf, byteOrder);
os.write(buf, 4);
}
private void writeCoordinate(CoordinateSequence seq, int index, OutStream os)
throws IOException {
ByteOrderValues.putDouble(seq.getX(index), buf, byteOrder);
os.write(buf, 8);
ByteOrderValues.putDouble(seq.getY(index), buf, byteOrder);
os.write(buf, 8);
// only write 3rd dim if caller has requested it for this writer
if (outputDimension >= 3) {
// if 3rd dim is requested, only write it if the CoordinateSequence
// provides it
double ordVal = Coordinate.NULL_ORDINATE;
if (seq.getDimension() >= 3)
ordVal = seq.getOrdinate(index, 2);
ByteOrderValues.putDouble(ordVal, buf, byteOrder);
os.write(buf, 8);
}
}
}