/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-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.resources.coverage; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; import java.util.ArrayList; import java.util.List; import org.geotools.util.Utilities; /** * Performs some naive intersections on GeometryCollections, because JTS is not * supporting them. * * @author Emanuele Tajariol (GeoSolutions) * * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/build/maven/javadoc/../../../modules/library/coverage/src/main/java/org/geotools/resources/coverage/IntersectUtils.java $ */ public class IntersectUtils { /** * Tests whether the two geometries intersect. * * <P>This method relies completely on {@link Geometry#intersects(Geometry)} * but also tries to unroll <TT>GeometryCollection</TT>s. * * @param g1 * @param g2 * @return true if the two geometries intersect. */ public static boolean intersects(Geometry g1, Geometry g2) { Utilities.ensureNonNull("g1", g1); Utilities.ensureNonNull("g2", g2); if(g1 instanceof GeometryCollection) { if(g2 instanceof GeometryCollection) { return intersects((GeometryCollection)g1, (GeometryCollection)g2); } else { return intersects((GeometryCollection)g1, g2); } } else { if(g2 instanceof GeometryCollection) { return intersects((GeometryCollection)g2, g1); } else { return g1.intersects(g2); } } } /** * Helper method for {@link #intersects(Geometry, Geometry) intersects(Geometry, Geometry)} */ private static boolean intersects(GeometryCollection gc, Geometry g) { final int size=gc.getNumGeometries(); for (int i = 0; i < size; i++) { Geometry g1 = (Geometry)gc.getGeometryN(i); if( g1.intersects(g) ) return true; } return false; } /** * Helper method for {@link #intersects(Geometry, Geometry) intersects(Geometry, Geometry)} */ private static boolean intersects(GeometryCollection gc1, GeometryCollection gc2) { final int size=gc1.getNumGeometries(); for (int i = 0; i < size; i++) { Geometry g1 = (Geometry)gc1.getGeometryN(i); if( intersects(gc2, g1) ) return true; } return false; } /** * Return the intersection of two Geometries. * <BR>This method relies completely on {@link Geometry#intersection(Geometry)} * but also tries to unroll <TT>GeometryCollection</TT>s. * * @param g1 * @param g2 * @return true if the two geometries intersect. */ public static Geometry intersection(Geometry g1, Geometry g2) { if(g1 instanceof GeometryCollection) { if(g2 instanceof GeometryCollection) { return intersection((GeometryCollection)g1, (GeometryCollection)g2); } else { List<Geometry> ret = intersection((GeometryCollection)g1, g2); return g1.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(ret)); } } else { if(g2 instanceof GeometryCollection) { List<Geometry> ret = intersection((GeometryCollection)g2, g1); return g1.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(ret)); } else { return g1.intersection(g2); } } } /** * Helper method for {@link #intersection(Geometry, Geometry) intersection(Geometry, Geometry)} */ private static List<Geometry> intersection(GeometryCollection gc, Geometry g) { List<Geometry> ret = new ArrayList<Geometry>(); final int size=gc.getNumGeometries(); for (int i = 0; i < size; i++) { Geometry g1 = (Geometry)gc.getGeometryN(i); collect(g1.intersection(g), ret); } return ret; } /** * Helper method for {@link #intersection(Geometry, Geometry) intersection(Geometry, Geometry)} */ private static GeometryCollection intersection(GeometryCollection gc1, GeometryCollection gc2) { List<Geometry> ret = new ArrayList<Geometry>(); final int size=gc1.getNumGeometries(); for (int i = 0; i < size; i++) { Geometry g1 = (Geometry)gc1.getGeometryN(i); List<Geometry> partial = intersection(gc2, g1); ret.addAll(partial); } return gc1.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(ret)); } /** * Adds into the <TT>collector</TT> the Geometry <TT>g</TT>, or, if * <TT>g</TT> is a GeometryCollection, every geometry in it. * * @param g the Geometry (or GeometryCollection to unroll) * @param collector the Collection where the Geometries will be added into */ private static void collect(Geometry g, List<Geometry> collector) { if(g instanceof GeometryCollection) { GeometryCollection gc = (GeometryCollection)g; for (int i = 0; i < gc.getNumGeometries(); i++) { Geometry loop = gc.getGeometryN(i); if(! loop.isEmpty()) collector.add(loop); } } else { if(! g.isEmpty()) collector.add(g); } } /** * Flatten all first-level (i.e. non recursively) bundles * (GeometryCollections and MultiPolygons) into a GeometryCollection. * <BR>Valid structures:<UL> * <LI>null -> null</LI> * <LI>Polygon -> Polygon</LI> * <LI>MultiPolygon -> GeometryCollection of Polygons</LI> * <LI>GeometryCollection holding Polygons and MultiPolygons -> GeometryCollection of Polygons</LI> * </UL> * @throws IllegalArgumentException when encountering illegal Geometries; message is the Geometry class name. * @param geometry * @return */ public static Geometry unrollGeometries(Geometry geometry) throws IllegalArgumentException { if(geometry == null) return null; if(geometry instanceof com.vividsolutions.jts.geom.Polygon) { return geometry; } else if(geometry instanceof MultiPolygon) { MultiPolygon mp = (MultiPolygon)geometry; return geometry.getFactory().createGeometryCollection(unrollGeometries(mp).toArray(new Geometry[0])); } else if(geometry instanceof GeometryCollection) { List<com.vividsolutions.jts.geom.Polygon> ret = new ArrayList<Polygon>(); GeometryCollection gc = (GeometryCollection)geometry; for (int i = 0; i < gc.getNumGeometries(); i++) { Geometry g = gc.getGeometryN(i); if(g instanceof com.vividsolutions.jts.geom.Polygon) { ret.add((com.vividsolutions.jts.geom.Polygon) g ); } else if(g instanceof MultiPolygon) { ret.addAll(unrollGeometries((MultiPolygon)g)); } else { throw new IllegalArgumentException(g.getClass().toString()); } } return geometry.getFactory().createGeometryCollection(ret.toArray(new Geometry[0])); } else { throw new IllegalArgumentException(geometry.getClass().toString()); } } private static List<com.vividsolutions.jts.geom.Polygon> unrollGeometries(MultiPolygon mp) { List<com.vividsolutions.jts.geom.Polygon> ret = new ArrayList<Polygon>(); for (int i = 0; i < mp.getNumGeometries(); i++) { com.vividsolutions.jts.geom.Polygon g = (com.vividsolutions.jts.geom.Polygon)mp.getGeometryN(i); ret.add(g); } return ret; } }