/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009, 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.display2d.primitive.iso;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.sis.geometry.DirectPosition2D;
import org.geotoolkit.geometry.isoonjts.spatialschema.geometry.geometry.JTSGeometryFactory;
import org.geotoolkit.geometry.isoonjts.spatialschema.geometry.primitive.JTSPrimitiveFactory;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.Geometry;
import org.opengis.geometry.aggregate.MultiPrimitive;
import org.opengis.geometry.coordinate.GeometryFactory;
import org.opengis.geometry.coordinate.PolyhedralSurface;
import org.opengis.geometry.coordinate.Position;
import org.opengis.geometry.primitive.Curve;
import org.opengis.geometry.primitive.CurveSegment;
import org.opengis.geometry.primitive.OrientableCurve;
import org.opengis.geometry.primitive.Point;
import org.opengis.geometry.primitive.PrimitiveFactory;
import org.opengis.geometry.primitive.Ring;
import org.opengis.geometry.primitive.SurfaceBoundary;
/**
* A thin wrapper that adapts a ISO geometry to the Shape interface so that the geometry can be used
* by java2d without coordinate cloning.
*
* @author Johann Sorel (Geomatys)
* @version 2.9
* @module
*/
public class ISOGeometryJ2D implements Shape, Cloneable {
private ISOGeometryIterator<? extends Geometry> iterator = null;
/** The wrapped ISO geometry */
private Geometry geometry;
/**
* Creates a new GeometryJ2D object.
*
* @param geom - the wrapped geometry
*/
public ISOGeometryJ2D(final Geometry geom) {
this.geometry = geom;
}
/**
* Sets the geometry contained in this lite shape. Convenient to reuse this
* object instead of creating it again and again during rendering
*
* @param g
*/
public void setGeometry(final Geometry g) {
this.geometry = g;
this.iterator = null;
}
/**
* @return the current wrapped geometry
*/
public Geometry getGeometry() {
return geometry;
}
/**
* {@inheritDoc }
*/
@Override
public boolean contains(final Rectangle2D r) {
Geometry rect = createRectangle(
r.getMinX(),
r.getMinY(),
r.getWidth(),
r.getHeight());
return geometry.contains(rect);
}
/**
* {@inheritDoc }
*/
@Override
public boolean contains(final Point2D p) {
return geometry.contains(new DirectPosition2D(p.getX(), p.getY()));
}
/**
* {@inheritDoc }
*/
@Override
public boolean contains(final double x, final double y) {
return geometry.contains(new DirectPosition2D(x,y));
}
/**
* {@inheritDoc }
*/
@Override
public boolean contains(final double x, final double y, final double w, final double h) {
Geometry rect = createRectangle(x, y, w, h);
return geometry.contains(rect);
}
/**
* {@inheritDoc }
*/
@Override
public Rectangle getBounds() {
Envelope env = geometry.getEnvelope();
return new Rectangle(
(int)(env.getMinimum(0)+0.5),
(int)(env.getMinimum(1)+0.5),
(int)(env.getSpan(0)+0.5),
(int)(env.getSpan(1)+0.5));
}
/**
* {@inheritDoc }
*/
@Override
public Rectangle2D getBounds2D() {
Envelope env = geometry.getEnvelope();
return new Rectangle2D.Double(
env.getMinimum(0),
env.getMinimum(1),
env.getSpan(0),
env.getSpan(1));
}
/**
* {@inheritDoc }
*/
@Override
public PathIterator getPathIterator(final AffineTransform at) {
if(iterator == null){
// if (this.geometry.isEmpty()) {
// iterator = new ISOEmptyIterator();
// }else
if (this.geometry instanceof Point) {
iterator = new ISOPointIterator((Point) geometry, at);
} else if (this.geometry instanceof PolyhedralSurface) {
iterator = new ISOPolyhedralSurfaceIterator((PolyhedralSurface) geometry, at);
} else if (this.geometry instanceof Curve) {
iterator = new ISOCurveIterator((Curve)geometry, at);
} else if (this.geometry instanceof MultiPrimitive) {
iterator = new ISOMultiPrimitiveIterator((MultiPrimitive)geometry,at);
}
}else{
iterator.setTransform(at);
}
return iterator;
}
/**
* {@inheritDoc }
*/
@Override
public PathIterator getPathIterator(final AffineTransform at, final double flatness) {
return getPathIterator(at);
}
/**
* {@inheritDoc }
*/
@Override
public boolean intersects(final Rectangle2D r) {
Geometry rect = createRectangle(
r.getMinX(),
r.getMinY(),
r.getWidth(),
r.getHeight());
return geometry.intersects(rect);
}
/**
* {@inheritDoc }
*/
@Override
public boolean intersects(final double x, final double y, final double w, final double h) {
Geometry rect = createRectangle(x, y, w, h);
return geometry.intersects(rect);
}
/**
* Creates a jts Geometry object representing a rectangle with the given
* parameters
*
* @param x left coordinate
* @param y bottom coordinate
* @param w width
* @param h height
* @return a rectangle with the specified position and size
*/
private Geometry createRectangle(final double x, final double y, final double w, final double h) {
final GeometryFactory gf = new JTSGeometryFactory(geometry.getCoordinateReferenceSystem());
final PrimitiveFactory pf = new JTSPrimitiveFactory(geometry.getCoordinateReferenceSystem());
final List<Position> points = new ArrayList<Position>();
points.add(new DirectPosition2D(x, y));
points.add(new DirectPosition2D(x+w, y));
points.add(new DirectPosition2D(x+w, y+h));
points.add(new DirectPosition2D(x, y+h));
points.add(new DirectPosition2D(x, y));
CurveSegment segment = gf.createLineString(points);
OrientableCurve curve = pf.createCurve(Collections.singletonList(segment));
Ring exterior = pf.createRing(Collections.singletonList(curve));
SurfaceBoundary boundary = pf.createSurfaceBoundary(exterior, null);
return boundary;
}
}