/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2001-2006 Vivid Solutions
* (C) 2001-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.geometry.iso.util.algorithm2D;
import java.util.Iterator;
import java.util.List;
import org.geotools.geometry.iso.primitive.RingImpl;
import org.geotools.geometry.iso.primitive.RingImplUnsafe;
import org.geotools.geometry.iso.primitive.SurfaceImpl;
import org.geotools.geometry.iso.root.GeometryImpl;
import org.geotools.geometry.iso.topograph2D.Coordinate;
import org.geotools.geometry.iso.topograph2D.Location;
import org.geotools.geometry.iso.topograph2D.util.CoordinateArrays;
import org.opengis.geometry.Geometry;
import org.opengis.geometry.aggregate.MultiPrimitive;
import org.opengis.geometry.primitive.Ring;
/**
* Computes whether a point lies in the interior of an area {@link Geometry}.
* The algorithm used is only guaranteed to return correct results for points
* which are <b>not</b> on the boundary of the Geometry.
*
*
*
* @source $URL$
*/
public class SimplePointInAreaLocator {
/**
* locate is the main location function. It handles both single-element and
* multi-element Geometries. The algorithm for multi-element Geometries is
* more complex, since it has to take into account the boundaryDetermination
* rule
*
* @param p
* @param geom
* @return
*/
public static int locate(Coordinate p, GeometryImpl geom) {
// TODO auskommentiert; checken!
// if (geom.isEmpty())
// return Location.EXTERIOR;
if (containsPoint(p, geom))
return Location.INTERIOR;
return Location.EXTERIOR;
}
private static boolean containsPoint(Coordinate p, GeometryImpl geom) {
if (geom instanceof SurfaceImpl) {
return containsPointInPolygon(p, (SurfaceImpl) geom);
}
else if (geom instanceof MultiPrimitive) {
Iterator geomi = ((MultiPrimitive) geom).getElements().iterator();
while (geomi.hasNext()) {
GeometryImpl g2 = (GeometryImpl) geomi.next();
if (g2 != geom)
if (containsPoint(p, g2))
return true;
}
}
return false;
// OLD CODE:
// if (geom instanceof Polygon) {
// return containsPointInPolygon(p, (Polygon) geom);
// } else if (geom instanceof GeometryCollection) {
// Iterator geomi = new GeometryCollectionIterator(
// (GeometryCollection) geom);
// while (geomi.hasNext()) {
// Geometry g2 = (Geometry) geomi.next();
// if (g2 != geom)
// if (containsPoint(p, g2))
// return true;
// }
// }
// return false;
}
public static boolean containsPointInPolygon(Coordinate p,
SurfaceImpl aSurface) {
// TODO auskommentiert; checken!
// if (poly.isEmpty())
// return false;
List<Ring> rings = aSurface.getBoundaryRings();
Ring shell = rings.get(0);
// The point lies in the ring defined by the coordinatearray
// representation of the exterior ring?
// if not, return false
if (!CGAlgorithms.isPointInRing(p, CoordinateArrays
.toCoordinateArray(((RingImplUnsafe)shell).asDirectPositions()))) {
return false;
}
// The point lies in the ring defined by the coordinatearray
// representation of the exterior ring?
for (int i = 1; i < rings.size(); i++) {
RingImplUnsafe hole = (RingImplUnsafe) rings.get(i);
// if so, return false
if (CGAlgorithms.isPointInRing(p, CoordinateArrays
.toCoordinateArray(hole.asDirectPositions()))) {
return false;
}
}
// the point lies inside the exterior ring, and outside the holes, so
// its on the polygon
return true;
// OLD CODE:
// if (poly.isEmpty())
// return false;
// LinearRing shell = (LinearRing) poly.getExteriorRing();
// if (!CGAlgorithms.isPointInRing(p, shell.getCoordinates()))
// return false;
// // now test if the point lies in or on the holes
// for (int i = 0; i < poly.getNumInteriorRing(); i++) {
// LinearRing hole = (LinearRing) poly.getInteriorRingN(i);
// if (CGAlgorithms.isPointInRing(p, hole.getCoordinates()))
// return false;
// }
// return true;
}
}