[geos-commits] r3230 - in trunk: include/geos/operation/linemerge src/operation/linemerge tests/unit tests/unit/operation/linemerge

svn_geos at osgeo.org svn_geos at osgeo.org
Mon Feb 21 12:30:45 EST 2011


Author: strk
Date: 2011-02-21 09:30:45 -0800 (Mon, 21 Feb 2011)
New Revision: 3230

Added:
   trunk/tests/unit/operation/linemerge/LineSequencerTest.cpp
Modified:
   trunk/include/geos/operation/linemerge/LineSequencer.h
   trunk/src/operation/linemerge/LineSequencer.cpp
   trunk/tests/unit/Makefile.am
Log:
Add LineSequencer unit test, fix memory leaks in the class.

Modified: trunk/include/geos/operation/linemerge/LineSequencer.h
===================================================================
--- trunk/include/geos/operation/linemerge/LineSequencer.h	2011-02-21 17:30:28 UTC (rev 3229)
+++ trunk/include/geos/operation/linemerge/LineSequencer.h	2011-02-21 17:30:45 UTC (rev 3230)
@@ -4,6 +4,7 @@
  * GEOS - Geometry Engine Open Source
  * http://geos.refractions.net
  *
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
  * Copyright (C) 2006 Refractions Research Inc.
  *
  * This is free software; you can redistribute and/or modify it under
@@ -102,6 +103,8 @@
 	Sequences* findSequences();
 	DirEdgeList* findSequence(planargraph::Subgraph& graph);
 
+	void delAll( Sequences& );
+
 	/// return a newly allocated LineString
 	static geom::LineString* reverse(const geom::LineString *line);
 
@@ -109,8 +112,11 @@
 	 * Builds a geometry ({@link LineString} or {@link MultiLineString} )
 	 * representing the sequence.
 	 *
-	 * @param sequences a vector of vectors of const planarDirectedEdges
-	 *                  with LineMergeEdges as their parent edges.
+	 * @param sequences
+	 *    a vector of vectors of const planarDirectedEdges
+	 *    with LineMergeEdges as their parent edges.
+	 *    Ownership of container _and_ contents retained by caller.
+	 *
 	 * @return the sequenced geometry, possibly NULL
 	 *         if no sequence exists
 	 */

Modified: trunk/src/operation/linemerge/LineSequencer.cpp
===================================================================
--- trunk/src/operation/linemerge/LineSequencer.cpp	2011-02-21 17:30:28 UTC (rev 3229)
+++ trunk/src/operation/linemerge/LineSequencer.cpp	2011-02-21 17:30:45 UTC (rev 3230)
@@ -4,6 +4,7 @@
  * GEOS - Geometry Engine Open Source
  * http://geos.refractions.net
  *
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
  * Copyright (C) 2006 Refractions Research Inc.
  *
  * This is free software; you can redistribute and/or modify it under
@@ -123,6 +124,14 @@
 	return oddDegreeCount <= 2;
 }
 
+void
+LineSequencer::delAll( LineSequencer::Sequences& s)
+{
+  for ( Sequences::iterator i=s.begin(), e=s.end(); i!=e; ++i )
+  {
+    delete *i;
+  }
+}
 
 /*private*/
 LineSequencer::Sequences*
@@ -130,7 +139,7 @@
 {
 	Sequences *sequences = new Sequences();
 	planargraph::algorithm::ConnectedSubgraphFinder csFinder(graph);
-	vector<planargraph::Subgraph*>subgraphs;
+	vector<planargraph::Subgraph*> subgraphs;
 	csFinder.getConnectedSubgraphs(subgraphs);
 	for (vector<planargraph::Subgraph*>::const_iterator
 		it=subgraphs.begin(), endIt=subgraphs.end();
@@ -144,8 +153,12 @@
 		}
 		else {
 			// if any subgraph cannot be sequenced, abort
+			delete subgraph;
+			delAll(*sequences);
+			delete sequences;
 			return NULL;
 		}
+		delete subgraph;
 	}
 	return sequences;
 }
@@ -168,12 +181,15 @@
 	if (isRun) return;
 	isRun = true;
 
-	Sequences* sequences(findSequences());
+	Sequences* sequences = findSequences();
 	if (sequences == NULL) return;
 
 	sequencedGeometry = auto_ptr<Geometry>(buildSequencedGeometry(*sequences));
 	isSequenceableVar = true;
 
+	delAll(*sequences);
+	delete sequences;
+
 	// Lines were missing from result
 	assert(lineCount == sequencedGeometry->getNumGeometries());
 

Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am	2011-02-21 17:30:28 UTC (rev 3229)
+++ trunk/tests/unit/Makefile.am	2011-02-21 17:30:45 UTC (rev 3230)
@@ -75,6 +75,7 @@
 	operation/distance/DistanceOpTest.cpp \
 	operation/IsSimpleOpTest.cpp \
 	operation/linemerge/LineMergerTest.cpp \
+	operation/linemerge/LineSequencerTest.cpp \
 	operation/overlay/validate/FuzzyPointLocatorTest.cpp \
 	operation/overlay/validate/OffsetPointGeneratorTest.cpp \
 	operation/overlay/validate/OverlayResultValidatorTest.cpp \

Added: trunk/tests/unit/operation/linemerge/LineSequencerTest.cpp
===================================================================
--- trunk/tests/unit/operation/linemerge/LineSequencerTest.cpp	                        (rev 0)
+++ trunk/tests/unit/operation/linemerge/LineSequencerTest.cpp	2011-02-21 17:30:45 UTC (rev 3230)
@@ -0,0 +1,289 @@
+// 
+// Test Suite for geos::operation::linemerge::LineSequencer class.
+
+// tut
+#include <tut.hpp>
+// geos
+#include <geos/operation/linemerge/LineSequencer.h>
+#include <geos/platform.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/LineString.h>
+#include <geos/io/WKTReader.h>
+#include <geos/io/WKTWriter.h>
+#include <geos/util/IllegalArgumentException.h>
+// std
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace tut
+{
+  //
+  // Test Group
+  //
+
+  // Common data used by tests
+  struct test_linesequencer_data
+  {
+    typedef geos::operation::linemerge::LineSequencer LineSequencer;
+    typedef std::vector<geos::geom::Geometry*> GeomVect;
+    typedef std::vector<geos::geom::LineString*> LineVect;
+
+    geos::geom::GeometryFactory gf;
+    geos::io::WKTReader wktreader;
+    geos::io::WKTWriter wktwriter;
+
+    typedef geos::geom::Geometry Geom;
+    typedef geos::geom::Geometry::AutoPtr GeomPtr;
+
+    GeomVect inpGeoms;
+
+    test_linesequencer_data()
+      : gf(), wktreader(&gf), wktwriter()
+    {
+      wktwriter.setTrim(true);
+    }
+
+    ~test_linesequencer_data()
+    {
+      delAll(inpGeoms);
+    }
+
+    GeomPtr readWKT(const std::string& inputWKT)
+    {
+        return GeomPtr(wktreader.read(inputWKT));
+    }
+
+    void readWKT(const char* const* inputWKT, std::vector<Geom*>& geoms)
+    {
+      for (const char* const* ptr=inputWKT; *ptr; ++ptr) {
+        geoms.push_back(readWKT(*ptr).release());
+      }
+    }
+
+    void runLineSequencer(const char * const * inputWKT,
+                const std::string& expectedWKT)
+    {
+      readWKT(inputWKT, inpGeoms);
+
+      LineSequencer sequencer;
+      sequencer.add(inpGeoms);
+
+      if ( ! sequencer.isSequenceable() ) {
+      	ensure( expectedWKT.empty() );
+      } else {  
+        GeomPtr expected = readWKT(expectedWKT);
+        GeomPtr result ( sequencer.getSequencedLineStrings() );
+        ensure( expected->equalsExact( result.get() ) );
+
+        bool isSequenced = LineSequencer::isSequenced(result.get());
+        ensure( isSequenced );
+      }
+    }
+
+    void runIsSequenced(const std::string& inputWKT, bool exp)
+    {
+      GeomPtr g = readWKT(inputWKT);
+      bool isSequenced = LineSequencer::isSequenced(g.get());
+      ensure_equals( isSequenced, exp );
+    }
+
+    template <class TargetContainer>
+    void delAll(TargetContainer& geoms)
+    {
+      for (typename TargetContainer::const_iterator i = geoms.begin(),
+           e = geoms.end(); i != e; ++i)
+      {
+        Geom* g = dynamic_cast<Geom*>(*i);
+        delete g;
+      }
+    }
+
+
+  private:
+    // noncopyable
+    test_linesequencer_data(test_linesequencer_data const& other);
+    test_linesequencer_data& operator=(test_linesequencer_data const& rhs);
+  };
+
+  typedef test_group<test_linesequencer_data> group;
+  typedef group::object object;
+
+  group test_linesequencer_group("geos::operation::linemerge::LineSequencer");
+
+  //
+  // Test Cases
+  //
+
+  // testSimple
+  template<> template<>
+  void object::test<1>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 20, 0 30 )",
+      "LINESTRING ( 0 10, 0 20 )",
+      NULL };
+    const char* expWKT = 
+      "MULTILINESTRING ((0 0, 0 10), (0 10, 0 20), (0 20, 0 30))";
+
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testSimpleLoop
+  template<> template<>
+  void object::test<2>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 10, 0 0 )",
+      NULL };
+    const char* expWKT = 
+      "MULTILINESTRING ((0 0, 0 10), (0 10, 0 0))";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testSimpleBigLoop
+  template<> template<>
+  void object::test<3>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 20, 0 30 )",
+      "LINESTRING ( 0 30, 0 00 )",
+      "LINESTRING ( 0 10, 0 20 )",
+      NULL };
+    const char* expWKT = 
+      "MULTILINESTRING ((0 0, 0 10), (0 10, 0 20), (0 20, 0 30), (0 30, 0 0))";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // test2SimpleLoops
+  template<> template<>
+  void object::test<4>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 10, 0 0 )",
+      "LINESTRING ( 0 0, 0 20 )",
+      "LINESTRING ( 0 20, 0 0 )",
+      NULL };
+    const char* expWKT = 
+      "MULTILINESTRING ((0 10, 0 0), (0 0, 0 20), (0 20, 0 0), (0 0, 0 10))";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testWide8WithTail
+  template<> template<>
+  void object::test<5>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 10 0, 10 10 )",
+      "LINESTRING ( 0 0, 10 0 )",
+      "LINESTRING ( 0 10, 10 10 )",
+      "LINESTRING ( 0 10, 0 20 )",
+      "LINESTRING ( 10 10, 10 20 )",
+      "LINESTRING ( 0 20, 10 20 )",
+ 
+      "LINESTRING ( 10 20, 30 30 )",
+      NULL };
+    const char* expWKT = "";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testSimpleLoopWithTail
+  template<> template<>
+  void object::test<6>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 10, 10 10 )",
+      "LINESTRING ( 10 10, 10 20, 0 10 )",
+      NULL };
+    const char* expWKT = 
+"MULTILINESTRING ((0 0, 0 10), (0 10, 10 10), (10 10, 10 20, 0 10))";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testLineWithRing
+  template<> template<>
+  void object::test<7>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 10, 10 10, 10 20, 0 10 )",
+      "LINESTRING ( 0 30, 0 20 )",
+      "LINESTRING ( 0 20, 0 10 )",
+      NULL };
+    const char* expWKT = 
+        "MULTILINESTRING ((0 0, 0 10), (0 10, 10 10, 10 20, 0 10), (0 10, 0 20), (0 20, 0 30))";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testMultipleGraphsWithRing
+  template<> template<>
+  void object::test<8>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 10, 10 10, 10 20, 0 10 )",
+      "LINESTRING ( 0 30, 0 20 )",
+      "LINESTRING ( 0 20, 0 10 )",
+      "LINESTRING ( 0 60, 0 50 )",
+      "LINESTRING ( 0 40, 0 50 )",
+      NULL };
+    const char* expWKT = 
+"MULTILINESTRING ((0 0, 0 10), (0 10, 10 10, 10 20, 0 10), (0 10, 0 20), (0 20, 0 30), (0 40, 0 50), (0 50, 0 60))";
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testMultipleGraphsWithMultipeRings
+  template<> template<>
+  void object::test<9>()
+  {
+    const char* inpWKT[] = {
+      "LINESTRING ( 0 0, 0 10 )",
+      "LINESTRING ( 0 10, 10 10, 10 20, 0 10 )",
+      "LINESTRING ( 0 10, 40 40, 40 20, 0 10 )",
+      "LINESTRING ( 0 30, 0 20 )",
+      "LINESTRING ( 0 20, 0 10 )",
+      "LINESTRING ( 0 60, 0 50 )",
+      "LINESTRING ( 0 40, 0 50 )",
+      NULL };
+    const char* expWKT = 
+        "MULTILINESTRING ((0 0, 0 10), (0 10, 40 40, 40 20, 0 10), (0 10, 10 10, 10 20, 0 10), (0 10, 0 20), (0 20, 0 30), (0 40, 0 50), (0 50, 0 60))";
+
+    runLineSequencer(inpWKT, expWKT);
+  }
+
+  // testLineSequence
+  template<> template<>
+  void object::test<10>()
+  {
+    const char* expWKT = "LINESTRING ( 0 0, 0 10 )";
+    runIsSequenced(expWKT, true);
+  }
+
+  // testSplitLineSequence
+  template<> template<>
+  void object::test<11>()
+  {
+    const char* expWKT =
+      "MULTILINESTRING ((0 0, 0 1), (0 2, 0 3), (0 3, 0 4) )";
+    runIsSequenced(expWKT, true);
+  }
+
+  // testBadLineSequence
+  template<> template<>
+  void object::test<12>()
+  {
+    const char* expWKT =
+      "MULTILINESTRING ((0 0, 0 1), (0 2, 0 3), (0 1, 0 4) )";
+    runIsSequenced(expWKT, false);
+  }
+
+
+} // namespace tut
+



More information about the geos-commits mailing list