/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
* (C) 2010, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.data.shapefile.shp;
import java.nio.ByteBuffer;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
import java.nio.DoubleBuffer;
import org.geotoolkit.geometry.jts.JTS;
import org.apache.sis.storage.DataStoreException;
/**
*
* @author aaime
* @author Ian Schneider
* @author Johann Sorel (Geomatys)
* @module
*/
public class MultiPointHandler extends AbstractShapeHandler {
/** Creates new MultiPointHandler */
public MultiPointHandler(final boolean read3D) {
super(ShapeType.POINT,read3D);
}
public MultiPointHandler(final ShapeType type, final boolean read3D) throws DataStoreException {
super(type,read3D);
if ((type != ShapeType.MULTIPOINT) && (type != ShapeType.MULTIPOINTM)
&& (type != ShapeType.MULTIPOINTZ)) {
throw new DataStoreException(
"Multipointhandler constructor - expected type to be 8, 18, or 28");
}
}
/**
* Returns the shapefile shape type value for a point
*
* @return int Shapefile.POINT
*/
@Override
public ShapeType getShapeType() {
return shapeType;
}
/**
* Calcuates the record length of this object.
*
* @return int The length of the record that this shapepoint will take up in
* a shapefile
*/
@Override
public int getLength(final Object geometry) {
final MultiPoint mp = (MultiPoint) geometry;
final int numGeom = mp.getNumGeometries();
final int length;
if (shapeType == ShapeType.MULTIPOINT) {
// two doubles per coord (16 * numgeoms) + 40 for header
length = (numGeom * 16) + 40;
} else if (shapeType == ShapeType.MULTIPOINTM) {
// add the additional MMin, MMax for 16, then 8 per measure
length = (numGeom * 16) + 40 + 16
+ (8 * numGeom);
} else if (shapeType == ShapeType.MULTIPOINTZ) {
// add the additional ZMin,ZMax, plus 8 per Z
length = (numGeom * 16) + 40 + 16
+ (8 * numGeom) + 16
+ (8 * numGeom);
} else {
throw new IllegalStateException("Expected ShapeType of Arc, got "
+ shapeType);
}
return length;
}
protected Object createNull() {
return GEOMETRY_FACTORY.createMultiPoint(new Point[0]);
}
@Override
public Object estimated(final double minX, final double maxX, final double minY, final double maxY) {
final Coordinate coord = new Coordinate((minX + maxX) / 2, (minY + maxY) / 2);
return GEOMETRY_FACTORY.createMultiPoint(new Coordinate[] {coord});
}
@Override
public Object read(final ByteBuffer buffer, final ShapeType type) {
if (type == ShapeType.NULL) {
return createNull();
}
final int dimensions = (read3D && shapeType == ShapeType.MULTIPOINTZ)? 3 : 2;
// read bounding box (not needed)
buffer.position(buffer.position() + 32);
final int numpoints = buffer.getInt();
final DoubleBuffer dbuffer = buffer.asDoubleBuffer();
final double[] coords = new double[numpoints*dimensions];
final int xySize = numpoints*2;
dbuffer.get(coords,0,xySize);
if(dimensions==2){
return GEOMETRY_FACTORY.createMultiPoint(new ShapeCoordinateSequence2D(coords));
} else {
// z min, max
dbuffer.position(dbuffer.position() + 2);
dbuffer.get(coords,xySize,numpoints);
return GEOMETRY_FACTORY.createMultiPoint(new ShapeCoordinateSequence3D(coords));
}
}
// @Override
// public Object read(ByteBuffer buffer, ShapeType type) {
// if (type == ShapeType.NULL) {
// return createNull();
// }
//
// // read bounding box (not needed)
// buffer.position(buffer.position() + 4 * 8);
//
// final int numpoints = buffer.getInt();
// final Coordinate[] coords = new Coordinate[numpoints];
//
// for (int t = 0; t < numpoints; t++) {
// final double x = buffer.getDouble();
// final double y = buffer.getDouble();
// coords[t] = new Coordinate(x, y);
// }
//
// if (shapeType == ShapeType.MULTIPOINTZ) {
// //skip zmin zmax
// buffer.position(buffer.position() + 2 * 8);
//
// for (int t = 0; t < numpoints; t++) {
// coords[t].z = buffer.getDouble(); // z
// }
// }
//
// return GEOMETRY_FACTORY.createMultiPoint(coords);
// }
@Override
public void write(final ByteBuffer buffer, final Object geometry) {
MultiPoint mp = (MultiPoint) geometry;
Envelope box = mp.getEnvelopeInternal();
buffer.putDouble(box.getMinX());
buffer.putDouble(box.getMinY());
buffer.putDouble(box.getMaxX());
buffer.putDouble(box.getMaxY());
buffer.putInt(mp.getNumGeometries());
for (int t = 0, tt = mp.getNumGeometries(); t < tt; t++) {
Coordinate c = (mp.getGeometryN(t)).getCoordinate();
buffer.putDouble(c.x);
buffer.putDouble(c.y);
}
if (shapeType == ShapeType.MULTIPOINTZ) {
double[] zExtreame = {Double.NaN, Double.NaN};
JTS.zMinMax(new CoordinateArraySequence(mp.getCoordinates()), zExtreame);
if (Double.isNaN(zExtreame[0])) {
buffer.putDouble(0.0);
buffer.putDouble(0.0);
} else {
buffer.putDouble(zExtreame[0]);
buffer.putDouble(zExtreame[1]);
}
for (int t = 0; t < mp.getNumGeometries(); t++) {
Coordinate c = (mp.getGeometryN(t)).getCoordinate();
double z = c.z;
if (Double.isNaN(z)) {
buffer.putDouble(0.0);
} else {
buffer.putDouble(z);
}
}
}
if (shapeType == ShapeType.MULTIPOINTM
|| shapeType == ShapeType.MULTIPOINTZ) {
buffer.putDouble(-10E40);
buffer.putDouble(-10E40);
for (int t = 0; t < mp.getNumGeometries(); t++) {
buffer.putDouble(-10E40);
}
}
}
}