/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.renderer.shape;
import com.vividsolutions.jts.geom.Envelope;
import org.geotools.data.shapefile.shp.ShapeType;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.nio.ByteBuffer;
import javax.measure.quantity.Torque;
/**
* Useful methods common to all geometry handlers
*
* @author jeichar
*
* @since 2.1.x
* @source $URL$
*/
public class GeometryHandlerUtilities {
/**
* DOCUMENT ME!
*
* @param buffer
*
* @return
*/
public static Envelope readBounds(ByteBuffer buffer) {
double[] tmpbbox = new double[4];
tmpbbox[0] = buffer.getDouble();
tmpbbox[1] = buffer.getDouble();
tmpbbox[2] = buffer.getDouble();
tmpbbox[3] = buffer.getDouble();
Envelope geomBBox = new Envelope(tmpbbox[0], tmpbbox[2], tmpbbox[1],
tmpbbox[3]);
return geomBBox;
}
/**
* Applies the specied transformation to the points in src, dropping
* the transformed points in dest. In case of transformation failure,
* it skips the points were the transformation failed.
* @param type
* @param mt
* @param src
* @param dest
* @throws TransformException
*/
public static void transform(ShapeType type, MathTransform mt,
double[] src, double[] dest, int numPoints) throws TransformException {
try {
mt.transform(src, 0, dest, 0, numPoints);
} catch(TransformException e) {
tolerantTransform(type, mt, src, dest);
}
}
static void tolerantTransform(ShapeType type, MathTransform mt,
double[] src, double[] dest) throws TransformException {
boolean startPointTransformed = true;
for (int i = 0; i < dest.length; i += 2) {
try {
mt.transform(src, i, dest, i, 1);
if (!startPointTransformed) {
startPointTransformed = true;
for (int j = 0; j < i; j += 2) {
dest[j] = src[i];
dest[j + 1] = src[i + 1];
}
}
} catch (TransformException e) {
if (i == 0) {
startPointTransformed = false;
} else if (startPointTransformed) {
if ((i == (dest.length - 2))
&& ((type == ShapeType.POLYGON)
|| (type == ShapeType.POLYGONZ)
|| (type == ShapeType.POLYGONM))) {
dest[i] = dest[0];
dest[i + 1] = dest[1];
} else {
dest[i] = dest[i - 2];
dest[i + 1] = dest[i - 1];
}
}
}
}
if (!startPointTransformed) {
throw new TransformException(
"Unable to transform any of the points in the shape");
}
}
/**
* calculates the distance between the centers of the two pixels at x,y
*
* @param mt the transform to use to calculate the centers.
* @param x the x coordinate at which to make the calculation
* @param y the y coordinate at which to make the calculation
* @return a point whose x coord it the distance in world coordinates between x-0.5 and x+0.5 and the y is the span
* around the y point.
* @throws NoninvertibleTransformException
* @throws TransformException
*/
public static Point2D calculateSpan(MathTransform mt, int x, int y)
throws NoninvertibleTransformException, TransformException {
MathTransform screenToWorld = mt.inverse();
double[] original = new double[] { x-0.5, y-0.5, x+0.5, y+0.5 };
double[] coords = new double[4];
screenToWorld.transform(original, 0, coords, 0, 2);
Point2D span = new Point2D.Double(Math.abs(coords[0] - coords[2]),
Math.abs(coords[1] - coords[3]));
return span;
}
public static ScreenMap calculateScreenSize(Rectangle screenSize,
boolean hasOpacity)
throws TransformException, NoninvertibleTransformException {
if (hasOpacity) {
// if opacity then this short optimization cannot be used
// so return a screenMap that always says to write there.
return new ScreenMap(0,0, 0, 0) {
public boolean get(int x, int y) {
return false;
}
public void set(int x, int y, boolean value) {
return;
}
};
}
return new ScreenMap(screenSize.x, screenSize.y, screenSize.width + 1, screenSize.height + 1);
}
}