[geos-commits] r3195 - in trunk: include/geos/operation/union src/operation/union

svn_geos at osgeo.org svn_geos at osgeo.org
Thu Feb 10 09:14:30 EST 2011


Author: strk
Date: 2011-02-10 06:14:30 -0800 (Thu, 10 Feb 2011)
New Revision: 3195

Added:
   trunk/include/geos/operation/union/UnaryUnionOp.h
   trunk/src/operation/union/UnaryUnionOp.cpp
Modified:
   trunk/include/geos/operation/union/Makefile.am
   trunk/src/operation/union/Makefile.am
Log:
UnaryUnionOp port from JTS-1.12

Modified: trunk/include/geos/operation/union/Makefile.am
===================================================================
--- trunk/include/geos/operation/union/Makefile.am	2011-02-10 14:10:17 UTC (rev 3194)
+++ trunk/include/geos/operation/union/Makefile.am	2011-02-10 14:14:30 UTC (rev 3195)
@@ -10,4 +10,5 @@
 
 geos_HEADERS = \
     CascadedPolygonUnion.h \
-    PointGeometryUnion.h
+    PointGeometryUnion.h \
+    UnaryUnionOp.h

Added: trunk/include/geos/operation/union/UnaryUnionOp.h
===================================================================
--- trunk/include/geos/operation/union/UnaryUnionOp.h	                        (rev 0)
+++ trunk/include/geos/operation/union/UnaryUnionOp.h	2011-02-10 14:14:30 UTC (rev 3195)
@@ -0,0 +1,215 @@
+/**********************************************************************
+ * $Id$
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation. 
+ * See the COPYING file for more information.
+ *
+ **********************************************************************
+ *
+ * Last port: operation/union/UnaryUnionOp.java r320 (JTS-1.12)
+ *
+ **********************************************************************/
+
+#ifndef GEOS_OP_UNION_UNARYUNION_H
+#define GEOS_OP_UNION_UNARYUNION_H
+
+#include <memory>
+#include <vector>
+
+#include <geos/export.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/Point.h>
+#include <geos/geom/LineString.h>
+#include <geos/geom/Polygon.h>
+#include <geos/geom/util/GeometryExtracter.h>
+#include <geos/operation/overlay/snap/SnapIfNeededOverlayOp.h>
+
+// Forward declarations
+namespace geos {
+    namespace geom {
+        class GeometryFactory;
+        class Geometry;
+    }
+}
+
+namespace geos {
+namespace operation { // geos::operation
+namespace geounion {  // geos::operation::geounion
+
+/**
+ * Unions a collection of Geometry or a single Geometry
+ * (which may be a collection) together.
+ * By using this special-purpose operation over a collection of
+ * geometries it is possible to take advantage of various optimizations
+ * to improve performance.
+ * Heterogeneous {@link GeometryCollection}s are fully supported.
+ * 
+ * The result obeys the following contract:
+ * 
+ * - Unioning a set of overlapping {@link Polygons}s has the effect of
+ *   merging the areas (i.e. the same effect as
+ *   iteratively unioning all individual polygons together).
+ * - Unioning a set of {@link LineString}s has the effect of
+ *   <b>fully noding</b> and <b>dissolving</b> the input linework.
+ *   In this context "fully noded" means that there will be a node or
+ *   endpoint in the output for every endpoint or line segment crossing
+ *   in the input.
+ *   "Dissolved" means that any duplicate (e.g. coincident) line segments
+ *   or portions of line segments will be reduced to a single line segment
+ *   in the output.  *   This is consistent with the semantics of the
+ *   {@link Geometry#union(Geometry)} operation.
+ *   If <b>merged</b> linework is required, the {@link LineMerger} class
+ *   can be used.
+ * - Unioning a set of {@link Points}s has the effect of merging
+ *   al identical points (producing a set with no duplicates).
+ *
+ * <tt>UnaryUnion</tt> always operates on the individual components of
+ * MultiGeometries.
+ * So it is possible to use it to "clean" invalid self-intersecting
+ * MultiPolygons (although the polygon components must all still be
+ * individually valid.)
+ */
+class GEOS_DLL UnaryUnionOp
+{
+public:
+
+  template <typename T>
+  static std::auto_ptr<geom::Geometry> Union(const T& geoms)
+  {
+    UnaryUnionOp op(geoms);
+    return op.Union();
+  }
+
+  template <class T>
+  static std::auto_ptr<geom::Geometry> Union(const T& geoms,
+      geom::GeometryFactory& geomFact)
+  {
+    UnaryUnionOp op(geoms, geomFact);
+    return op.Union();
+  }
+
+  static std::auto_ptr<geom::Geometry> Union(const geom::Geometry& geom)
+  {
+    UnaryUnionOp op(geom);
+    return op.Union();
+  }
+
+  template <class T>
+  UnaryUnionOp(const T& geoms, geom::GeometryFactory& geomFactIn)
+      :
+      geomFact(&geomFactIn)
+  {
+    extractAll(geoms);
+  }
+
+  template <class T>
+  UnaryUnionOp(const T& geoms)
+      :
+      geomFact(0)
+  {
+    extractAll(geoms);
+  }
+
+  UnaryUnionOp(const geom::Geometry& geom)
+      :
+      geomFact(geom.getFactory())
+  {
+    extract(geom);
+  }
+
+  /**
+   * \brief
+   * Gets the union of the input geometries.
+   *
+   * If no input geometries were provided, a POINT EMPTY is returned.
+   *
+   * @return a Geometry containing the union
+   * @return an empty GEOMETRYCOLLECTION if no geometries were provided
+   *         in the input
+   */
+  std::auto_ptr<geom::Geometry> Union();
+
+private:
+
+  template <typename T>
+  void extractGeoms(const T& geoms)
+  {
+      for (typename T::const_iterator
+              i=geoms.begin(),
+              e=geoms.end();
+              i!=e;
+              ++i)
+      {
+          const geom::Geometry* geom = *i;
+          extract(*geom);
+      }
+  }
+
+  void extract(const geom::Geometry& geom)
+  {
+      using namespace geom::util;
+
+      if ( ! geomFact ) geomFact = geom.getFactory();
+
+      GeometryExtracter::extract<geom::Polygon>(geom, polygons);
+      GeometryExtracter::extract<geom::LineString>(geom, lines);
+      GeometryExtracter::extract<geom::Point>(geom, points);
+  }
+
+  /**
+   * Computes a unary union with no extra optimization,
+   * and no short-circuiting.
+   * Due to the way the overlay operations
+   * are implemented, this is still efficient in the case of linear
+   * and puntal geometries.
+   * Uses robust version of overlay operation
+   * to ensure identical behaviour to the <tt>union(Geometry)</tt> operation.
+   *
+   * @param g0 a geometry
+   * @return the union of the input geometry
+   */
+  std::auto_ptr<geom::Geometry> unionNoOpt(const geom::Geometry& g0)
+  {
+    using geos::operation::overlay::OverlayOp;
+    using geos::operation::overlay::snap::SnapIfNeededOverlayOp;
+
+    if ( ! empty.get() ) {
+      empty.reset( geomFact->createEmptyGeometry() );
+    }
+    return SnapIfNeededOverlayOp::overlayOp(g0, *empty, OverlayOp::opUNION);
+  }
+
+  /**
+   * Computes the union of two geometries,
+   * either of both of which may be null.
+   *
+   * @param g0 a Geometry (ownership transferred)
+   * @param g1 a Geometry (ownership transferred)
+   * @return the union of the input(s)
+   * @return null if both inputs are null
+   */
+  std::auto_ptr<geom::Geometry> unionWithNull(std::auto_ptr<geom::Geometry> g0,
+                                              std::auto_ptr<geom::Geometry> g1);
+
+  std::vector<const geom::Polygon*> polygons;
+  std::vector<const geom::LineString*> lines;
+  std::vector<const geom::Point*> points;
+
+  const geom::GeometryFactory* geomFact;
+
+  std::auto_ptr<geom::Geometry> empty;
+};
+ 
+
+} // namespace geos::operation::union
+} // namespace geos::operation
+} // namespace geos
+
+#endif

Modified: trunk/src/operation/union/Makefile.am
===================================================================
--- trunk/src/operation/union/Makefile.am	2011-02-10 14:10:17 UTC (rev 3194)
+++ trunk/src/operation/union/Makefile.am	2011-02-10 14:14:30 UTC (rev 3195)
@@ -10,6 +10,7 @@
 
 libopunion_la_SOURCES = \
     CascadedPolygonUnion.cpp \
-    PointGeometryUnion.cpp 
+    PointGeometryUnion.cpp \
+    UnaryUnionOp.cpp 
 
 libopunion_la_LIBADD = 

Added: trunk/src/operation/union/UnaryUnionOp.cpp
===================================================================
--- trunk/src/operation/union/UnaryUnionOp.cpp	                        (rev 0)
+++ trunk/src/operation/union/UnaryUnionOp.cpp	2011-02-10 14:14:30 UTC (rev 3195)
@@ -0,0 +1,127 @@
+/**********************************************************************
+ * $Id$
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation. 
+ * See the COPYING file for more information.
+ *
+ **********************************************************************
+ *
+ * Last port: operation/union/UnaryUnionOp.java r320 (JTS-1.12)
+ *
+ **********************************************************************/
+
+#include <memory> // for auto_ptr
+#include <cassert> // for assert
+#include <algorithm> // for copy
+
+#include <geos/operation/union/UnaryUnionOp.h> 
+#include <geos/operation/union/CascadedPolygonUnion.h> 
+#include <geos/operation/union/PointGeometryUnion.h> 
+#include <geos/geom/Coordinate.h> 
+#include <geos/geom/Puntal.h> 
+#include <geos/geom/Point.h>
+#include <geos/geom/MultiPoint.h>
+#include <geos/geom/MultiLineString.h>
+#include <geos/geom/MultiPolygon.h>
+#include <geos/geom/GeometryCollection.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/Location.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/util/GeometryCombiner.h>
+#include <geos/algorithm/PointLocator.h>
+
+namespace geos {
+namespace operation { // geos::operation
+namespace geounion {  // geos::operation::geounion
+
+/*private*/
+std::auto_ptr<geom::Geometry>
+UnaryUnionOp::unionWithNull(std::auto_ptr<geom::Geometry> g0,
+                            std::auto_ptr<geom::Geometry> g1)
+{
+  std::auto_ptr<geom::Geometry> ret;
+  if ( ( ! g0.get() ) && ( ! g1.get() ) ) return ret;
+
+  if ( ! g0.get() ) return g1;
+  if ( ! g1.get() ) return g0;
+
+  ret.reset( g0->Union(g1.get()) );
+  return ret;
+}
+
+/*public*/
+std::auto_ptr<geom::Geometry>
+UnaryUnionOp::Union()
+{
+  using geom::Puntal;
+  typedef std::auto_ptr<geom::Geometry> GeomAutoPtr;
+
+  GeomAutoPtr ret;
+  if ( ! geomFact ) return ret;
+
+  /**
+   * For points and lines, only a single union operation is
+   * required, since the OGC model allowings self-intersecting
+   * MultiPoint and MultiLineStrings.
+   * This is not the case for polygons, so Cascaded Union is required.
+   */
+
+  GeomAutoPtr unionPoints;
+  if (!points.empty()) {
+      GeomAutoPtr ptGeom = geomFact->buildGeometry( points.begin(),
+                                                    points.end()    );
+      unionPoints = unionNoOpt(*ptGeom);
+  }
+
+  GeomAutoPtr unionLines;
+  if (!lines.empty()) {
+      GeomAutoPtr lineGeom = geomFact->buildGeometry( lines.begin(),
+                                                      lines.end()    );
+      unionLines = unionNoOpt(*lineGeom);
+  }
+
+  GeomAutoPtr unionPolygons;
+  if (!polygons.empty()) {
+      unionPolygons.reset( CascadedPolygonUnion::Union( polygons.begin(),
+                                                        polygons.end()   ) );
+  }
+
+  /**
+   * Performing two unions is somewhat inefficient,
+   * but is mitigated by unioning lines and points first
+   */
+
+  GeomAutoPtr unionLA = unionWithNull(unionLines, unionPolygons);
+  assert(!unionLines.get()); assert(!unionPolygons.get());
+
+  if ( ! unionPoints.get() ) {
+    ret = unionLA;
+    assert(!unionLA.get()); 
+  }
+  else if ( ! unionLA.get() ) {
+    ret = unionPoints;
+    assert(!unionPoints.get()); 
+  }
+  else {
+    Puntal& up = dynamic_cast<Puntal&>(*unionPoints);
+    ret = PointGeometryUnion::Union(up, *unionLA);
+  }
+
+  if ( ! ret.get() ) {
+          ret.reset( geomFact->createGeometryCollection() );
+  }
+
+  return ret;
+
+}
+
+} // namespace geos::operation::union
+} // namespace geos::operation
+} // namespace geos



More information about the geos-commits mailing list