Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61036 - in sandbox/geometry: boost/geometry/algorithms boost/geometry/multi/algorithms libs/geometry/test/algorithms libs/geometry/test/multi/algorithms
From: barend.gehrels_at_[hidden]
Date: 2010-04-04 07:10:28


Author: barendgehrels
Date: 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
New Revision: 61036
URL: http://svn.boost.org/trac/boost/changeset/61036

Log:
Fixed multi_dissolve using new dissolver
Dissolve now outputs, normally, to a vector of the original geometry, or, in case of a multi, to its single type. Like union and intersection
Implemented multi_dissolve for not-connected linestrings
Fixed some accidental tabs from testcases
Text files modified:
   sandbox/geometry/boost/geometry/algorithms/dissolve.hpp | 24 ++---
   sandbox/geometry/boost/geometry/algorithms/union.hpp | 13 ++
   sandbox/geometry/boost/geometry/multi/algorithms/dissolve.hpp | 165 +++++++++++++++++++++------------------
   sandbox/geometry/libs/geometry/test/algorithms/dissolve.cpp | 94 +++++++++++-----------
   sandbox/geometry/libs/geometry/test/algorithms/equals.cpp | 14 +-
   sandbox/geometry/libs/geometry/test/algorithms/reverse.cpp | 8
   sandbox/geometry/libs/geometry/test/algorithms/test_dissolve.hpp | 75 +++++++++++++----
   sandbox/geometry/libs/geometry/test/algorithms/unique.cpp | 9 +
   sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.cpp | 51 +++++++++++
   sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.vcproj | 2
   sandbox/geometry/libs/geometry/test/multi/algorithms/multi_reverse.cpp | 2
   sandbox/geometry/libs/geometry/test/multi/algorithms/multi_unique.cpp | 4
   12 files changed, 280 insertions(+), 181 deletions(-)

Modified: sandbox/geometry/boost/geometry/algorithms/dissolve.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/dissolve.hpp (original)
+++ sandbox/geometry/boost/geometry/algorithms/dissolve.hpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -170,29 +170,23 @@
 template
 <
     typename Geometry,
- typename GeometryOut
+ typename Collection
>
-inline void dissolve(Geometry const& geometry, GeometryOut& out)
+inline void dissolve(Geometry const& geometry, Collection& output_collection)
 {
     concept::check<Geometry const>();
- concept::check<GeometryOut>();
 
- std::vector<GeometryOut> v;
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ concept::check<geometry_out>();
+
     dispatch::dissolve
     <
         typename tag<Geometry>::type,
- typename tag<GeometryOut>::type,
+ typename tag<geometry_out>::type,
         Geometry,
- GeometryOut
- >::apply(geometry, std::back_inserter(v));
- if (boost::size(v) > 0)
- {
- out = v.front();
- }
- else
- {
- out = geometry;
- }
+ geometry_out
+ >::apply(geometry, std::back_inserter(output_collection));
 }
 
 

Modified: sandbox/geometry/boost/geometry/algorithms/union.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/union.hpp (original)
+++ sandbox/geometry/boost/geometry/algorithms/union.hpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -188,6 +188,18 @@
 }
 
 
+/*!
+ \brief Combines two geometries which each other
+ \ingroup union
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param output_collection, the output collection
+ \note Called union_ because union is a reserved word.
+*/
 template
 <
     typename Geometry1,
@@ -212,7 +224,6 @@
             typename geometry::point_type<geometry_out>::type
> strategy;
 
-
     union_inserter<geometry_out>(geometry1, geometry2,
                 std::back_inserter(output_collection),
                 strategy());

Modified: sandbox/geometry/boost/geometry/multi/algorithms/dissolve.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/multi/algorithms/dissolve.hpp (original)
+++ sandbox/geometry/boost/geometry/multi/algorithms/dissolve.hpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -15,7 +15,7 @@
 #include <boost/geometry/algorithms/dissolve.hpp>
 #include <boost/geometry/algorithms/union.hpp>
 
-#include <boost/geometry/multi/algorithms/union.hpp>
+#include <boost/geometry/algorithms/detail/overlay/dissolver.hpp>
 
 
 namespace boost { namespace geometry
@@ -26,18 +26,17 @@
 namespace detail { namespace dissolve
 {
 
-template <typename Multi, typename MultiOut>
+template <typename Multi, typename GeometryOut>
 struct dissolve_multi
 {
     template <typename OutputIterator>
     static inline OutputIterator apply(Multi const& multi, OutputIterator out)
     {
         typedef typename boost::range_value<Multi>::type polygon_type;
- typedef typename boost::range_value<MultiOut>::type output_polygon_type;
         typedef typename boost::range_iterator<Multi const>::type iterator_type;
 
         // Step 1: dissolve all polygons in the multi-polygon, independantly
- MultiOut step1;
+ std::vector<GeometryOut> step1;
         for (iterator_type it = boost::begin(multi);
             it != boost::end(multi);
             ++it)
@@ -45,41 +44,17 @@
             dissolve_ring_or_polygon
                 <
                     polygon_type,
- output_polygon_type
+ GeometryOut
>::apply(*it, std::back_inserter(step1));
         }
 
         // Step 2: remove mutual overlap
- // TODO: solve quadratic behaviour by alternating division in x/y axis
- // per division there are 3 cases: cases above the line, cases below the line, cases crossing the line
- // recursively handle those 3 cases and union them.
- MultiOut step2;
- for (iterator_type it = boost::begin(step1);
- it != boost::end(step1);
- ++it)
+ std::vector<GeometryOut> step2; // TODO avoid this, output to "out", if possible
+ detail::dissolver::dissolver_generic<detail::dissolver::plusmin_policy>::apply(step1, step2);
+ BOOST_FOREACH(GeometryOut const& g, step2)
         {
- if (step2.empty())
- {
- step2.push_back(*it);
- }
- else
- {
- MultiOut unioned;
- for (iterator_type it2 = boost::begin(step2);
- it2 != boost::end(step2);
- ++it2)
- {
- geometry::union_inserter
- <
- output_polygon_type
- >(*it2, *it, std::back_inserter(unioned));
- }
- step2.swap(unioned);
- }
+ *out++ = g;
         }
-
- // Step 3: output
- *out++ = step2;
         return out;
     }
 };
@@ -88,7 +63,7 @@
 // Dissolve on multi_linestring tries to create larger linestrings from input,
 // or closed rings.
 
-template <typename Multi, typename MultiOut>
+template <typename Multi, typename GeometryOut>
 struct dissolve_multi_linestring
 {
     typedef typename point_type<Multi>::type point_type;
@@ -104,18 +79,51 @@
         {}
     };
 
- // Have a map<point, <index,start/end> > such that we can find
- // the corresponding point on each end. Note that it uses the
+ // Have a map<point, <index,start/end> > such that we can find
+ // the corresponding point on each end. Note that it uses the
     // default "equals" for the point-type
     typedef std::multimap
         <
- point_type,
- mapped,
- boost::geometry::less<point_type>
+ point_type,
+ mapped,
+ boost::geometry::less<point_type>
> map_type;
 
     typedef typename map_type::const_iterator map_iterator_type;
 
+ static inline void copy(linestring_type const& ls,
+ GeometryOut& target,
+ bool copy_forward)
+ {
+ if (copy_forward)
+ {
+ std::copy(boost::begin(ls), boost::end(ls),
+ std::back_inserter(target));
+ }
+ else
+ {
+ std::reverse_copy(boost::begin(ls), boost::end(ls),
+ std::back_inserter(target));
+ }
+ }
+
+ static inline map_iterator_type find_start(map_type const& map,
+ std::map<int, bool>& included)
+ {
+ for (map_iterator_type it = map.begin();
+ it != map.end();
+ ++it)
+ {
+ int count = map.count(it->first);
+ if (count == 1 && ! included[it->second.index])
+ {
+ included[it->second.index] = true;
+ return it;
+ }
+ }
+ return map.end();
+ }
+
     template <typename OutputIterator>
     static inline OutputIterator apply(Multi const& multi, OutputIterator out)
     {
@@ -126,8 +134,7 @@
 
         map_type map;
 
-
- // 1: fill the map.
+ // 1: fill the map.
         int index = 0;
         for (iterator_type it = boost::begin(multi);
             it != boost::end(multi);
@@ -145,12 +152,18 @@
 
         // 2: merge (dissolve) the lines
 
- // 2a: start with the first one (by copying)
- int current_index = 0;
- included[current_index] = true;
- linestring_type current = *boost::begin(multi);
+ // 2a: start with one having a unique starting point
+ map_iterator_type first = find_start(map, included);
+ bool found = first != map.end();
+ if (! found)
+ {
+ return out;
+ }
+
+ int current_index = first->second.index;
+ GeometryOut current;
+ copy(multi[current_index], current, first->second.is_from);
 
- bool found = true;
         while(found)
         {
             // 2b: get all candidates, ask for range
@@ -161,27 +174,27 @@
             // 2c: for all candidates get closest one
             found = false;
             int closest_index = -1;
- bool closest_from = false;
+ bool from_is_closest = false;
             // TODO: make utility to initalize distance result with large value
- distance_result_type min_dist
- = make_distance_result<distance_result_type>(100);
- for (map_iterator_type it = range.first;
- ! found && it != range.second;
+ distance_result_type min_dist
+ = make_distance_result<distance_result_type>(100);
+ for (map_iterator_type it = range.first;
+ ! found && it != range.second;
                 ++it)
             {
                 if (it->second.index != current_index
                     && ! included[it->second.index])
                 {
                     linestring_type const& ls = multi[it->second.index];
- point_type const& p = it->second.is_from
- ? *boost::begin(ls)
+ point_type const& p = it->second.is_from
+ ? *boost::begin(ls)
                         : *(boost::end(ls) - 1);
 
                     distance_result_type d = geometry::distance(it->first, p);
                     if (! found || d < min_dist)
                     {
                         closest_index = it->second.index;
- closest_from = it->second.is_from;
+ from_is_closest = it->second.is_from;
                         min_dist = d;
 
                         //std::cout << "TO " << geometry::wkt(p) << std::endl;
@@ -194,28 +207,30 @@
             {
                 current_index = closest_index;
                 included[current_index] = true;
- linestring_type const& ls = multi[current_index];
- if (closest_from)
- {
- std::copy(boost::begin(ls), boost::end(ls),
- std::back_inserter(current));
- }
- else
- {
- std::reverse_copy(boost::begin(ls), boost::end(ls),
- std::back_inserter(current));
- }
+ copy(multi[current_index], current, from_is_closest);
             }
 
             if (! found && (included.size() != boost::size(multi)))
             {
                 // Get one which is NOT found and go again
- std::cout << "TODO" << std::endl;
+ map_iterator_type next = find_start(map, included);
+ found = next != map.end();
+
+ if (found)
+ {
+ current_index = next->second.index;
+
+ *out++ = current;
+ geometry::clear(current);
+
+ copy(multi[current_index], current, next->second.is_from);
+ }
             }
         }
- MultiOut mo;
- mo.push_back(current);
- *out++ = mo;
+ if (boost::size(current) > 0)
+ {
+ *out++ = current;
+ }
 
         return out;
     }
@@ -232,15 +247,15 @@
 {
 
 
-template<typename Multi, typename MultiOut>
-struct dissolve<multi_polygon_tag, multi_polygon_tag, Multi, MultiOut>
- : detail::dissolve::dissolve_multi<Multi, MultiOut>
+template<typename Multi, typename GeometryOut>
+struct dissolve<multi_polygon_tag, polygon_tag, Multi, GeometryOut>
+ : detail::dissolve::dissolve_multi<Multi, GeometryOut>
 {};
 
 
-template<typename Multi, typename MultiOut>
-struct dissolve<multi_linestring_tag, multi_linestring_tag, Multi, MultiOut>
- : detail::dissolve::dissolve_multi_linestring<Multi, MultiOut>
+template<typename Multi, typename GeometryOut>
+struct dissolve<multi_linestring_tag, linestring_tag, Multi, GeometryOut>
+ : detail::dissolve::dissolve_multi_linestring<Multi, GeometryOut>
 {};
 
 

Modified: sandbox/geometry/libs/geometry/test/algorithms/dissolve.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/dissolve.cpp (original)
+++ sandbox/geometry/libs/geometry/test/algorithms/dissolve.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -18,85 +18,85 @@
     typedef boost::geometry::polygon<P> polygon;
 
     // Simplex
- test_one<polygon>("1",
- "POLYGON((0 0,0 4,1.5 2.5,2.5 1.5,4 0,0 0))",
- 0, 6, 8);
+ test_one<polygon, polygon>("1",
+ "POLYGON((0 0,0 4,1.5 2.5,2.5 1.5,4 0,0 0))",
+ 0, 6, 8);
 
     // Self intersecting
- test_one<polygon>("2",
- "POLYGON((1 2,1 1,2 1,2 2.25,3 2.25,3 0,0 0,0 3,3 3,2.75 2,1 2))",
- 1, 12, 7.9296875);
+ test_one<polygon, polygon>("2",
+ "POLYGON((1 2,1 1,2 1,2 2.25,3 2.25,3 0,0 0,0 3,3 3,2.75 2,1 2))",
+ 1, 12, 7.9296875);
 
     // Self intersecting in last segment
- test_one<polygon>("3",
- "POLYGON((0 2,2 4,2 0,4 2,0 2))",
- 0, 4, 2.0);
+ test_one<polygon, polygon>("3",
+ "POLYGON((0 2,2 4,2 0,4 2,0 2))",
+ 0, 4, 2.0);
 
     // Self tangent
- test_one<polygon>("4",
- "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))",
- 0, 11, 12.0);
+ test_one<polygon, polygon>("4",
+ "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))",
+ 0, 11, 12.0);
 
 
     // Self tangent in corner
- test_one<polygon>("5",
- "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))",
- 0, 11, 16.0);
+ test_one<polygon, polygon>("5",
+ "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))",
+ 0, 11, 16.0);
 
 
     // With spike
- test_one<polygon>("6",
- "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))",
- 0, 6, 16);
+ test_one<polygon, polygon>("6",
+ "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))",
+ 0, 6, 16);
 
 
     // Non intersection, but with duplicate
- test_one<polygon>("d1",
- "POLYGON((0 0,0 4,4 0,4 0,0 0))",
- 0, 4, 8);
+ test_one<polygon, polygon>("d1",
+ "POLYGON((0 0,0 4,4 0,4 0,0 0))",
+ 0, 4, 8);
 
 
     // With many duplicates
- test_one<polygon>("d2",
- "POLYGON((0 0,0 1,0 1,0 1,0 2,0 2,0 3,0 3,0 3,0 3,0 4,2 4,2 4,4 4,4 0,4 0,3 0,3 0,3 0,3 0,3 0,0 0))",
- 0, 10, 16);
+ test_one<polygon, polygon>("d2",
+ "POLYGON((0 0,0 1,0 1,0 1,0 2,0 2,0 3,0 3,0 3,0 3,0 4,2 4,2 4,4 4,4 0,4 0,3 0,3 0,3 0,3 0,3 0,0 0))",
+ 0, 10, 16);
 
 
     // Hole: interior tangent to exterior
- test_one<polygon>("h1",
- "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,2 4,3 2,1 2))",
- 0, 6, 16);
+ test_one<polygon, polygon>("h1",
+ "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 2,2 4,3 2,1 2))",
+ 0, 6, 16);
 
     // Hole: interior intersecting exterior
- test_one<polygon>("h2",
- "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,5 4,1 1))",
- 0, 8, 16.25);
+ test_one<polygon, polygon>("h2",
+ "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,5 4,1 1))",
+ 0, 8, 16.25);
 
 
     // Hole: two intersecting holes
- test_one<polygon>("h3",
- "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,3 3,3 1,1 1),(2 2,2 3.5,3.5 3.5,3.5 2,2 2))",
- 0, 5, 16);
+ test_one<polygon, polygon>("h3",
+ "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 3,3 3,3 1,1 1),(2 2,2 3.5,3.5 3.5,3.5 2,2 2))",
+ 0, 5, 16);
 
     // Hole: self-intersecting hole
- test_one<polygon>("h4",
- "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 3,3 2.5,1 3.5,1.5 3.5,1 1))",
- 1, 9, 14.484848484848484);
-
- // See power point
- test_one<polygon>("case_1",
- "POLYGON((1 3,0 9,9 5,1 7,9 8,2 5,10 10,9 2,1 3))",
- 0, 7, 50.48056402439);
+ test_one<polygon, polygon>("h4",
+ "POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,3 3,3 2.5,1 3.5,1.5 3.5,1 1))",
+ 1, 9, 14.484848484848484);
+
+ // See power point
+ test_one<polygon, polygon>("case_1",
+ "POLYGON((1 3,0 9,9 5,1 7,9 8,2 5,10 10,9 2,1 3))",
+ 0, 7, 50.48056402439);
 
 
- // Real-life
- std::string const toolkit = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))";
- test_one<polygon>("toolkit", toolkit,
- 0, 25, 91756.916526794434);
+ // Real-life
+ std::string const toolkit = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))";
+ test_one<polygon, polygon>("toolkit", toolkit,
+ 0, 25, 91756.916526794434);
 
     std::string const ticket17 = "POLYGON ((-122.28139163 37.37319149,-122.28100699 37.37273669,-122.28002186 37.37303123,-122.27979681 37.37290072,-122.28007349 37.37240493,-122.27977334 37.37220360,-122.27819720 37.37288580,-122.27714184 37.37275161,-122.27678628 37.37253167,-122.27766437 37.37180973,-122.27804382 37.37121453,-122.27687664 37.37101354,-122.27645829 37.37203386,-122.27604423 37.37249110,-122.27632234 37.37343339,-122.27760980 37.37391082,-122.27812478 37.37800320,-122.26117222 37.39121007,-122.25572289 37.39566631,-122.25547269 37.39564971,-122.25366304 37.39552993,-122.24919976 37.39580268,-122.24417933 37.39366907,-122.24051443 37.39094143,-122.23246277 37.38100418,-122.23606766 37.38141338,-122.24001587 37.37738940,-122.23666848 37.37609347,-122.23057450 37.37882170,-122.22679803 37.37807143,-122.22525727 37.37448817,-122.22523229 37.37443000,-122.23083199 37.37609347,-122.23033486 37.37777891,-122.23169030 37.37732117,-122.23229178 37.37709687,-122.23237761 37.37631249,-122.23297776 37
.37438834,-122.23872850 37.37165986,-122.24044511 37.36934068,-122.24671067 37.36865847,-122.24825570 37.36981819,-122.25151719 37.36947713,-122.25357721 37.36756706,-122.26001451 37.36579354,-122.25615213 37.36545239,-122.25486458 37.36245083,-122.25357721 37.36108651,-122.25194642 37.36013139,-122.24885652 37.35958557,-122.24911401 37.35849399,-122.25357721 37.35808470,-122.25675286 37.35897159,-122.25855539 37.35753887,-122.26181687 37.35828939,-122.26713837 37.35897159,-122.26782510 37.36108651,-122.26662339 37.36456559,-122.27288911 37.36722601,-122.27366159 37.36531602,-122.27168740 37.36470213,-122.27391900 37.36374701,-122.27074326 37.36245083,-122.27134408 37.35951742,-122.27426240 37.36135926,-122.27709482 37.36115474,-122.27966974 37.36231438,-122.27958391 37.36463382,-122.27572152 37.36463382,-122.27563569 37.36524779,-122.27700899 37.36593000,-122.27709482 37.36763529,-122.27554978 37.36838573,-122.27667254 37.36931478,-122.27677932 37.36932073,-122.27769362 37.36853987,-122.27942490 37.36830803
,-122.28178776 37.36677917,-122.28509559 37.36443500,-122.28845129 37.36413744,-122.29194403 37.36695946,-122.29382577 37.36726817,-122.29600414 37.36898512,-122.29733083 37.36995398,-122.29593239 37.37141436,-122.29416649 37.37075898,-122.29325026 37.37108436,-122.29652910 37.37311697,-122.29584237 37.37374461,-122.29537583 37.37573372,-122.29487677 37.37752502,-122.30923212 37.37593011,-122.31122484 37.38230086,-122.31467994 37.38092472,-122.31715663 37.38252181,-122.32307970 37.38166978,-122.31985618 37.37667694,-122.32210304 37.37580220,-122.32581446 37.37589532,-122.32401730 37.37331839,-122.32960417 37.37189020,-122.33465527 37.37331906,-122.33425328 37.37623680,-122.33620676 37.37726132,-122.33397986 37.37822382,-122.33358918 37.38036590,-122.33202637 37.37986918,-122.33147954 37.38101784,-122.33394080 37.38198017,-122.33545239 37.38587943,-122.33478058 37.38785697,-122.33386050 37.38723721,-122.33350041 37.38571137,-122.33122003 37.38548891,-122.33140008 37.38650606,-122.33366042 37.38817490,-122.332
44019 37.39157602,-122.33298157 37.39419201,-122.33164013 37.39477028,-122.33202017 37.39518351,-122.33358038 37.39499282,-122.33376050 37.39597811,-122.33550067 37.39734478,-122.33556069 37.39481797,-122.33344040 37.39292676,-122.33638094 37.38892189,-122.34240644 37.38852719,-122.34906293 37.38726898,-122.35072321 37.39338769,-122.34910291 37.39445252,-122.34796272 37.39410291,-122.34449043 37.39640534,-122.34500223 37.39729709,-122.34936291 37.39670910,-122.35098322 37.39531066,-122.35364623 37.39554510,-122.35434369 37.39612111,-122.35798429 37.39600988,-122.35768430 37.39478621,-122.36334519 37.39206871,-122.36604726 37.39203267,-122.36778592 37.39335592,-122.36518870 37.40022011,-122.36554552 37.40247752,-122.36370519 37.40331974,-122.36270506 37.40530591,-122.36320512 37.40670418,-122.36149849 37.40851392,-122.36730580 37.41054938,-122.37263720 37.41378932,-122.37161871 37.42076600,-122.36566153 37.42006292,-122.36520547 37.42742106,-122.37165953 37.43661157,-122.35943972 37.44459022,-122.35356359 37.
44600810,-122.33792254 37.45796329,-122.35228518 37.47478091,-122.35127080 37.48181199,-122.34867342 37.48487322,-122.34359717 37.48801082,-122.33388431 37.48677650,-122.33142321 37.48429747,-122.32929580 37.48473149,-122.32609609 37.48291144,-122.32344850 37.48228229,-122.31924364 37.48410234,-122.31677299 37.48114051,-122.31431751 37.47848973,-122.31259201 37.47682190,-122.31515972 37.47568196,-122.31691389 37.47360309,-122.31292494 37.46960081,-122.31130153 37.46937743,-122.30889894 37.47124987,-122.30612839 37.47011613,-122.30149630 37.46568378,-122.30064277 37.46363784,-122.29283821 37.45922376,-122.28630141 37.45415497,-122.28883099 37.44629920,-122.28316717 37.44197138,-122.27554148 37.42297597,-122.25597410 37.40553692,-122.25196579 37.40129593,-122.25012043 37.40049143,-122.24823207 37.39897758,-122.24754551 37.39740941,-122.24778582 37.39621607,-122.24934787 37.39599102,-122.25005170 37.39871849,-122.25222328 37.39863668,-122.25342491 37.39737529,-122.25520162 37.39667289,-122.25528737 37.39522726,
-122.27747460 37.37809616,-122.27977493 37.37858717,-122.28157729 37.37920106,-122.28322534 37.37952846,-122.28416939 37.38092656,-122.28621223 37.37984219,-122.28638389 37.37613857,-122.28382607 37.37843722,-122.27930278 37.37718220,-122.28196361 37.37652740,-122.28295058 37.37568167,-122.28216101 37.37523148,-122.28114822 37.37543608,-122.27934569 37.37528613,-122.27996369 37.37448121,-122.28104521 37.37454944,-122.28185197 37.37422883,-122.28290767 37.37474038,-122.28376597 37.37467224,-122.28428104 37.37399012,-122.28402346 37.37338989,-122.28610922 37.37364914,-122.28651264 37.37327388,-122.28672722 37.37207343,-122.28628398 37.37205448,-122.28574460 37.37166682,-122.28479711 37.37200981,-122.28327731 37.37137228,-122.28285511 37.37100700,-122.28279409 37.37125669,-122.28315527 37.37173756,-122.28321872 37.37220569,-122.28187007 37.37231918,-122.28193109 37.37294908,-122.28139163 37.37319149))";
- test_one<polygon>("ticket17", ticket17,
- 1, 228, 0.00920834633689);
+ test_one<polygon, polygon>("ticket17", ticket17,
+ 1, 228, 0.00920834633689);
 }
 
 

Modified: sandbox/geometry/libs/geometry/test/algorithms/equals.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/equals.cpp (original)
+++ sandbox/geometry/libs/geometry/test/algorithms/equals.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -40,7 +40,7 @@
     test_geometry<ring, ring>("poly_degenerate", "POLYGON((0 0,0 2,2 2,2 2,0 0))", "POLYGON((0 0,0 2,0 2,2 2,0 0))", true);
 
     // Two different bends, same area, unequal
- test_geometry<ring, ring>("poly_bends",
+ test_geometry<ring, ring>("poly_bends",
         "POLYGON((4 0,5 3,8 4,7 7,4 8,0 4,4 0))",
         "POLYGON((4 0,7 1,8 4,5 5,4 8,0 4,4 0))", false);
 
@@ -51,22 +51,22 @@
     test_geometry<polygon, polygon>("poly_hole", "POLYGON((0 0,0 4,4 4,0 0))", "POLYGON((0 0,0 4,4 4,0 0),(1 1,2 1,2 2,1 2,1 1))", false);
 
     // Both having holes
- test_geometry<polygon, polygon>("poly_holes",
+ test_geometry<polygon, polygon>("poly_holes",
             "POLYGON((0 0,0 4,4 4,0 0),(1 1,2 1,2 2,1 2,1 1))",
             "POLYGON((0 0,0 4,4 4,0 0),(1 1,2 1,2 2,1 2,1 1))", true);
 
     // Both having holes, outer equal, inner not equal
- test_geometry<polygon, polygon>("poly_uneq_holes",
+ test_geometry<polygon, polygon>("poly_uneq_holes",
             "POLYGON((0 0,0 4,4 4,0 0),(1 1,2 1,2 2,1 2,1 1))",
             "POLYGON((0 0,0 4,4 4,0 0),(2 2,3 2,3 3,2 3,2 2))", false);
 
     // Both having 2 holes, equal but in different order
- test_geometry<polygon, polygon>("poly_holes_diff_order",
+ test_geometry<polygon, polygon>("poly_holes_diff_order",
             "POLYGON((0 0,0 4,4 4,0 0),(1 1,2 1,2 2,1 2,1 1),(2 2,3 2,3 3,2 3,2 2))",
             "POLYGON((0 0,0 4,4 4,0 0),(2 2,3 2,3 3,2 3,2 2),(1 1,2 1,2 2,1 2,1 1))", true);
 
     // Both having 3 holes, equal but in different order
- test_geometry<polygon, polygon>("poly_holes_diff_order_3",
+ test_geometry<polygon, polygon>("poly_holes_diff_order_3",
             "POLYGON((0 0,0 10,10 10,0 0),(1 1,2 1,2 2,1 2,1 1),(4 1,5 1,5 2,4 2,4 1),(2 2,3 2,3 3,2 3,2 2))",
             "POLYGON((0 0,0 10,10 10,0 0),(4 1,5 1,5 2,4 2,4 1),(2 2,3 2,3 3,2 3,2 2),(1 1,2 1,2 2,1 2,1 1))", true);
 
@@ -82,8 +82,8 @@
 
     test_geometry<polygon, box>("boxpoly2", "POLYGON((1 1,1 2,2 2,2 1,1 1))", "BOX(1 1,2 3)", false);
 
- // linestring/linestring
- // simplex
+ // linestring/linestring
+ // simplex
     test_geometry<linestring, linestring>("ls1", "LINESTRING(1 1,2 2)", "LINESTRING(1 1,2 2)", true);
     test_geometry<linestring, linestring>("ls1", "LINESTRING(1 1,2 2)", "LINESTRING(2 2,1 1)", true);
 

Modified: sandbox/geometry/libs/geometry/test/algorithms/reverse.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/reverse.cpp (original)
+++ sandbox/geometry/libs/geometry/test/algorithms/reverse.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -15,22 +15,22 @@
 template <typename Point>
 void test_all()
 {
- // Simplex
+ // Simplex
     test_geometry<boost::geometry::linestring<Point> >(
         "LINESTRING(0 0,1 1)",
         "LINESTRING(1 1,0 0)");
 
- // Three points, middle should stay the same
+ // Three points, middle should stay the same
     test_geometry<boost::geometry::linestring<Point> >(
         "LINESTRING(0 0,1 1,2 2)",
         "LINESTRING(2 2,1 1,0 0)");
 
- // Four points
+ // Four points
     test_geometry<boost::geometry::linestring<Point> >(
         "LINESTRING(0 0,1 1,2 2,3 3)",
         "LINESTRING(3 3,2 2,1 1,0 0)");
 
- // Polygon with holes
+ // Polygon with holes
     test_geometry<boost::geometry::polygon<Point> >(
         "POLYGON((4 0,8 2,8 7,4 9,0 7,0 2,2 1,4 0),(7 3,7 6,1 6,1 3,4 3,7 3))",
         "POLYGON((4 0,2 1,0 2,0 7,4 9,8 7,8 2,4 0),(7 3,4 3,1 3,1 6,7 6,7 3))");

Modified: sandbox/geometry/libs/geometry/test/algorithms/test_dissolve.hpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/test_dissolve.hpp (original)
+++ sandbox/geometry/libs/geometry/test/algorithms/test_dissolve.hpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -15,6 +15,7 @@
 #include <boost/geometry/algorithms/dissolve.hpp>
 
 // To check results
+#include <boost/geometry/algorithms/length.hpp>
 #include <boost/geometry/algorithms/area.hpp>
 #include <boost/geometry/algorithms/num_points.hpp>
 #include <boost/geometry/algorithms/unique.hpp>
@@ -32,28 +33,33 @@
 
 
 
-template <typename Geometry>
+template <typename GeometryOut, typename Geometry>
 void test_dissolve(std::string const& caseid, Geometry const& geometry,
         std::size_t expected_hole_count, std::size_t expected_point_count,
- double expected_area, double percentage)
+ double expected_length_or_area, double percentage)
 {
         namespace bg = boost::geometry;
     typedef typename bg::coordinate_type<Geometry>::type coordinate_type;
 
- std::vector<Geometry> dissolved_vector;
- bg::dissolve_inserter<Geometry>(geometry, std::back_inserter(dissolved_vector));
+ static const bool is_line = bg::geometry_id<GeometryOut>::type::value == 2;
 
- typename bg::area_result<Geometry>::type area = 0;
- std::size_t holes = 0;
+ std::vector<GeometryOut> dissolved_vector;
+ bg::dissolve_inserter<GeometryOut>(geometry, std::back_inserter(dissolved_vector));
+
+ typename bg::area_result<Geometry>::type length_or_area = 0;
+ //std::size_t holes = 0;
         std::size_t count = 0;
 
- BOOST_FOREACH(Geometry& dissolved, dissolved_vector)
+ BOOST_FOREACH(GeometryOut& dissolved, dissolved_vector)
         {
             bg::unique(dissolved);
 
- area += bg::area(dissolved);
- holes += boost::geometry::num_interior_rings(dissolved);
- count += boost::geometry::num_points(dissolved);
+
+ length_or_area +=
+ is_line ? bg::length(dissolved) : bg::area(dissolved);
+
+ //holes += bg::num_interior_rings(dissolved);
+ count += bg::num_points(dissolved);
         }
 
     BOOST_CHECK_MESSAGE(count == expected_point_count,
@@ -64,12 +70,12 @@
             );
 
 
- BOOST_CHECK_EQUAL(holes, expected_hole_count);
- BOOST_CHECK_CLOSE(area, expected_area, percentage);
+ //BOOST_CHECK_EQUAL(holes, expected_hole_count);
+ BOOST_CHECK_CLOSE(length_or_area, expected_length_or_area, percentage);
 
         // Compile check, it should also compile inplace, outputting to the same geometry
         {
- Geometry dissolved;
+ std::vector<GeometryOut> dissolved;
                 bg::dissolve(geometry, dissolved);
         }
 
@@ -84,14 +90,14 @@
 
         std::ofstream svg(filename.str().c_str());
 
- boost::geometry::svg_mapper
+ bg::svg_mapper
             <
- typename boost::geometry::point_type<Geometry>::type
+ typename bg::point_type<Geometry>::type
> mapper(svg, 500, 500);
         mapper.add(geometry);
 
         mapper.map(geometry, "opacity:0.6;fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:1");
- BOOST_FOREACH(Geometry& dissolved, dissolved_vector)
+ BOOST_FOREACH(GeometryOut& dissolved, dissolved_vector)
                 {
                    mapper.map(dissolved, "opacity:0.6;fill:none;stroke:rgb(255,0,0);stroke-width:5");
             }
@@ -100,17 +106,46 @@
 }
 
 
-template <typename Geometry>
+template <typename Geometry, typename GeometryOut>
 void test_one(std::string const& caseid, std::string const& wkt,
         std::size_t expected_hole_count, std::size_t expected_point_count,
- double expected_area, double percentage = 0.001)
+ double expected_length_or_area, double percentage = 0.001)
 {
     Geometry geometry;
     boost::geometry::read_wkt(wkt, geometry);
 
- test_dissolve(caseid, geometry,
+ test_dissolve<GeometryOut>(caseid, geometry,
         expected_hole_count, expected_point_count,
- expected_area, percentage);
+ expected_length_or_area, percentage);
+
+#ifdef BOOST_GEOMETRY_TEST_MULTI_PERMUTATIONS
+ // Test different combinations of a multi-polygon
+
+ int n = geometry.size();
+
+ // test them in all orders
+ std::vector<int> indices;
+ for (int i = 0; i < n; i++)
+ {
+ indices.push_back(i);
+ }
+ int permutation = 0;
+ do
+ {
+ std::ostringstream out;
+ out << caseid;
+ Geometry geometry2;
+ for (int i = 0; i < n; i++)
+ {
+ int index = indices[i];
+ out << "_" << index;
+ geometry2.push_back(geometry[index]);
+ }
+ test_dissolve<GeometryOut>(out.str(), geometry2, expected_hole_count,
+ expected_point_count, expected_length_or_area, percentage);
+ } while (std::next_permutation(indices.begin(), indices.end()));
+#endif
+
 }
 
 

Modified: sandbox/geometry/libs/geometry/test/algorithms/unique.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/unique.cpp (original)
+++ sandbox/geometry/libs/geometry/test/algorithms/unique.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -26,19 +26,20 @@
         "LINESTRING(0 0,0 0,1 1)",
         "LINESTRING(0 0,1 1)");
 
- // Consecutive points
+ // Consecutive points
     test_geometry<boost::geometry::linestring<Point> >(
         "LINESTRING(0 0,0 0,0 0,0 0,1 1,1 1,1 1)",
         "LINESTRING(0 0,1 1)");
 
- // Other types
+ // Other types
     test_geometry<boost::geometry::linear_ring<Point> >(
         "POLYGON((0 0,0 1,1 1,1 1,1 1,1 0,0 0,0 0))",
         "POLYGON((0 0,0 1,1 1,1 0,0 0))");
 
+ // With holes
     test_geometry<boost::geometry::polygon<Point> >(
- "POLYGON((0 0,0 1,1 1,1 1,1 1,1 0,0 0,0 0))",
- "POLYGON((0 0,0 1,1 1,1 0,0 0))");
+ "POLYGON((0 0,0 10,10 10,10 10,10 10,10 0,0 0,0 0))",
+ "POLYGON((0 0,0 10,10 10,10 0,0 0))");
 }
 
 

Modified: sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.cpp (original)
+++ sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -14,11 +14,13 @@
 #include <boost/geometry/multi/core/is_multi.hpp>
 
 #include <boost/geometry/multi/algorithms/area.hpp>
+#include <boost/geometry/multi/algorithms/length.hpp>
 #include <boost/geometry/multi/algorithms/dissolve.hpp>
 #include <boost/geometry/multi/algorithms/envelope.hpp>
 #include <boost/geometry/multi/algorithms/num_points.hpp>
 #include <boost/geometry/multi/core/interior_rings.hpp>
-
+
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
 #include <boost/geometry/multi/geometries/multi_polygon.hpp>
 
 #include <boost/geometry/extensions/gis/io/wkt/read_wkt_multi.hpp>
@@ -32,9 +34,50 @@
     typedef bg::polygon<P> polygon;
     typedef bg::multi_polygon<polygon> multi_polygon;
 
- test_one<multi_polygon>("three_triangles",
- "MULTIPOLYGON(((1 1,5 5,8 0,1 1)),((4 2,0 8,5 9,4 2)),((5 3,4 8,10 4,5 3)))" ,
- 1, 15, 42.614078674948232);
+ test_one<multi_polygon, polygon>("three_triangles",
+ "MULTIPOLYGON(((1 1,5 5,8 0,1 1)),((4 2,0 8,5 9,4 2)),((5 3,4 8,10 4,5 3)))" ,
+ 1, 13, 42.614078674948232);
+
+ test_one<multi_polygon, polygon>("simplex_two",
+ "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)))",
+ 0, 8, 14.7);
+ test_one<multi_polygon, polygon>("simplex_three",
+ "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)))",
+ 0, 14, 16.7945);
+ test_one<multi_polygon, polygon>("simplex_four",
+ "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((5 5,7 7,8 4,5 5)))",
+ 0, 18, 20.7581);
+
+ // disjoint
+ test_one<multi_polygon, polygon>("simplex_disjoint",
+ "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((1 6,2 10,5 7,1 6)),((3 4,5 6,6 2,3 4)),((6 5,8 7,9 4,6 5)))",
+ 0, 16, 24.0);
+
+ // new hole of four
+ test_one<multi_polygon, polygon>("new_hole",
+ "MULTIPOLYGON(((0 0,1 4,4 1,0 0)),((2 2,3 6,6 3,2 2)),((3 4,5 6,6 2,3 4)),((3 1,5 4,8 4,3 1)))",
+ 1, 18, 19.5206);
+
+ // Linestrings
+ typedef bg::linestring<P> linestring;
+ typedef bg::multi_linestring<linestring> multi_linestring;
+
+ test_one<multi_linestring, linestring>("ls_simplex",
+ "MULTILINESTRING((0 0,1 1),(1 1,2 2))",
+ 0, 3, 2 * std::sqrt(2.0));
+
+ // Opposites, forming one line
+ test_one<multi_linestring, linestring>("ls_simplex_opposite_to",
+ "MULTILINESTRING((0 0,1 1),(2 2,1 1))",
+ 0, 3, 2 * std::sqrt(2.0));
+ test_one<multi_linestring, linestring>("ls_simplex_opposite_from",
+ "MULTILINESTRING((1 1,0 0),(1 1,2 2))",
+ 0, 3, 2 * std::sqrt(2.0));
+
+ // Two output linestrings
+ test_one<multi_linestring, linestring>("ls_simplex_two",
+ "MULTILINESTRING((0 0,1 1),(1 1,2 2),(3 3,4 4),(4 4,5 5))",
+ 0, 6, 4 * std::sqrt(2.0));
 }
 
 

Modified: sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.vcproj
==============================================================================
--- sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.vcproj (original)
+++ sandbox/geometry/libs/geometry/test/multi/algorithms/multi_dissolve.vcproj 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -42,7 +42,7 @@
                                 Name="VCCLCompilerTool"
                                 Optimization="0"
                                 AdditionalIncludeDirectories="../../../../..;../..;."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;TEST_WITH_SVG;BOOST_GEOMETRY_TEST_MULTI_PERMUTATIONS"
                                 MinimalRebuild="true"
                                 ExceptionHandling="2"
                                 RuntimeLibrary="3"

Modified: sandbox/geometry/libs/geometry/test/multi/algorithms/multi_reverse.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/multi/algorithms/multi_reverse.cpp (original)
+++ sandbox/geometry/libs/geometry/test/multi/algorithms/multi_reverse.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -24,7 +24,7 @@
 template <typename P>
 void test_all()
 {
- // Multi point, should happen nothing.
+ // Multi point, should happen nothing.
     test_geometry<boost::geometry::multi_point<P> >(
         "MULTIPOINT((0 0),(1 1))",
         "MULTIPOINT((0 0),(1 1))");

Modified: sandbox/geometry/libs/geometry/test/multi/algorithms/multi_unique.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/multi/algorithms/multi_unique.cpp (original)
+++ sandbox/geometry/libs/geometry/test/multi/algorithms/multi_unique.cpp 2010-04-04 07:10:26 EDT (Sun, 04 Apr 2010)
@@ -24,7 +24,7 @@
 template <typename P>
 void test_all()
 {
- // Multi point, should happen nothing, even if there are duplicate points
+ // Multi point, should happen nothing, even if there are duplicate points
     test_geometry<boost::geometry::multi_point<P> >(
         "MULTIPOINT((0 0),(0 0),(1 1))",
         "MULTIPOINT((0 0),(0 0),(1 1))");
@@ -38,7 +38,7 @@
         "MULTIPOLYGON(((0 0,0 1,1 1,1 1,1 1,1 0,0 0,0 0)))",
         "MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)))");
 
- // With holes
+ // With holes
     test_geometry<mp>(
         "MULTIPOLYGON(((0 0,0 10,10 10,10 10,10 10,10 0,0 0,0 0)))",
         "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))");


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk