From 5fb11344e4b58de9bcc9e00860ba43b0dbeff898 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 24 May 2010 13:54:32 +0000 Subject: [PATCH] Corrected closure for area Added closure for centroid Modified/fixed closing iterator (didn't compile for MSVC 2010) [SVN r62172] --- example/custom_examples.sln | 6 ++ include/boost/geometry/algorithms/area.hpp | 3 +- .../boost/geometry/algorithms/centroid.hpp | 75 ++++++++++--------- include/boost/geometry/algorithms/correct.hpp | 12 ++- .../boost/geometry/algorithms/transform.hpp | 3 +- .../boost/geometry/geometries/linear_ring.hpp | 22 ++++++ .../geometry/iterators/closing_iterator.hpp | 24 +++--- .../geometry/multi/algorithms/centroid.hpp | 7 +- test/algorithms/centroid.cpp | 5 ++ test/algorithms/correct.cpp | 26 +++++-- test/iterators/closing_iterator.cpp | 25 +++++++ 11 files changed, 147 insertions(+), 61 deletions(-) diff --git a/example/custom_examples.sln b/example/custom_examples.sln index ce13494db..20678f139 100644 --- a/example/custom_examples.sln +++ b/example/custom_examples.sln @@ -18,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c07_custom_ring_pointer_exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c08_custom_non_std_example", "c08_custom_non_std_example.vcproj", "{C215F131-F021-4155-A96E-BB2D91918A17}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "c09_custom_fusion_example", "c09_custom_fusion_example.vcproj", "{DA36AD55-E448-43DE-A974-EA765AE3967A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -60,6 +62,10 @@ Global {C215F131-F021-4155-A96E-BB2D91918A17}.Debug|Win32.Build.0 = Debug|Win32 {C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.ActiveCfg = Release|Win32 {C215F131-F021-4155-A96E-BB2D91918A17}.Release|Win32.Build.0 = Release|Win32 + {DA36AD55-E448-43DE-A974-EA765AE3967A}.Debug|Win32.ActiveCfg = Debug|Win32 + {DA36AD55-E448-43DE-A974-EA765AE3967A}.Debug|Win32.Build.0 = Debug|Win32 + {DA36AD55-E448-43DE-A974-EA765AE3967A}.Release|Win32.ActiveCfg = Release|Win32 + {DA36AD55-E448-43DE-A974-EA765AE3967A}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/include/boost/geometry/algorithms/area.hpp b/include/boost/geometry/algorithms/area.hpp index 0972b381f..fc833e69d 100644 --- a/include/boost/geometry/algorithms/area.hpp +++ b/include/boost/geometry/algorithms/area.hpp @@ -31,7 +31,6 @@ #include -#include #include #include #include @@ -122,7 +121,7 @@ struct ring_area typedef closeable_view < rview_type const, - Closure == closed + Closure == open // close it if it is open > view_type; typedef typename boost::range_iterator::type iterator_type; diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index ca7463c5d..d9fb5ea8b 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -15,16 +15,19 @@ #include -#include +#include #include #include #include #include #include + +#include #include #include #include #include +#include #include #include @@ -182,41 +185,34 @@ inline bool range_ok(Range const& range, Point& centroid) /*! \brief Calculate the centroid of a ring. */ -template +template struct centroid_ring_state { static inline void apply(Ring const& ring, Strategy const& strategy, typename Strategy::state_type& state) { - typedef typename boost::range_iterator::type iterator_type; - iterator_type it = boost::begin(ring); + typedef closeable_view + < + Ring const, + Closure == open // close it if it is open + > view_type; + + typedef typename boost::range_iterator::type iterator_type; + + view_type view(ring); + iterator_type it = boost::begin(view); + iterator_type end = boost::end(view); + for (iterator_type previous = it++; - it != boost::end(ring); - previous = it++) + it != end; + ++previous, ++it) { Strategy::apply(*previous, *it, state); } - - /* using segment_iterator: nice, well looking, but much slower... - normal iterator: 0.156 s - segment iterator: 1.985 s... - typedef segment_iterator - < - typename boost::range_iterator::type, - typename point_type::type - > iterator_type; - - iterator_type it(boost::begin(ring), boost::end(ring)); - iterator_type end(boost::end(ring)); - for(; it != end; ++it) - { - Strategy::apply(it->first, it->second, state); - } - */ } }; -template +template struct centroid_ring { static inline void apply(Ring const& ring, Point& centroid, @@ -228,6 +224,7 @@ struct centroid_ring centroid_ring_state < Ring, + Closure, Strategy >::apply(ring, strategy, state); Strategy::result(state, centroid); @@ -279,7 +276,7 @@ struct centroid_linestring \note Because outer ring is clockwise, inners are counter clockwise, triangle approach is OK and works for polygons with rings. */ -template +template struct centroid_polygon_state { static inline void apply(Polygon const& poly, @@ -288,6 +285,7 @@ struct centroid_polygon_state typedef centroid_ring_state < typename ring_type::type, + Closure, Strategy > per_ring; @@ -305,7 +303,7 @@ struct centroid_polygon_state } }; -template +template struct centroid_polygon { static inline void apply(Polygon const& poly, Point& centroid, @@ -317,6 +315,7 @@ struct centroid_polygon centroid_polygon_state < Polygon, + Closure, Strategy >::apply(poly, strategy, state); Strategy::result(state, centroid); @@ -338,6 +337,7 @@ template typename Tag, typename Geometry, typename Point, + closure_selector Closure, typename Strategy > struct centroid {}; @@ -346,9 +346,10 @@ template < typename Geometry, typename Point, + closure_selector Closure, typename Strategy > -struct centroid +struct centroid : detail::centroid::centroid_point {}; @@ -356,25 +357,26 @@ template < typename Box, typename Point, + closure_selector Closure, typename Strategy > -struct centroid +struct centroid : detail::centroid::centroid_box {}; -template -struct centroid - : detail::centroid::centroid_ring +template +struct centroid + : detail::centroid::centroid_ring {}; -template -struct centroid +template +struct centroid : detail::centroid::centroid_linestring {}; -template -struct centroid - : detail::centroid::centroid_polygon +template +struct centroid + : detail::centroid::centroid_polygon {}; } // namespace dispatch @@ -405,6 +407,7 @@ inline void centroid(Geometry const& geometry, Point& c, typename tag::type, Geometry, Point, + geometry::closure::value, Strategy >::apply(geometry, c, strategy); } diff --git a/include/boost/geometry/algorithms/correct.hpp b/include/boost/geometry/algorithms/correct.hpp index 585625c40..cf4eb433f 100644 --- a/include/boost/geometry/algorithms/correct.hpp +++ b/include/boost/geometry/algorithms/correct.hpp @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -114,12 +115,21 @@ struct correct_ring if (boost::size(r) > 2) { // check if closed, if not, close it - if (geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1))) + bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1)); + closure_selector s = geometry::closure::value; + + if (disjoint && (s == closed)) { + // Close it point_type first; geometry::copy_coordinates(*boost::begin(r), first); *(std::back_inserter(r)++) = first; } + if (! disjoint && geometry::closure::value != closed) + { + // Open it, TODO! + std::cout << "TODO"; + } } // Check area Predicate predicate; diff --git a/include/boost/geometry/algorithms/transform.hpp b/include/boost/geometry/algorithms/transform.hpp index 1feed8701..615084bb8 100644 --- a/include/boost/geometry/algorithms/transform.hpp +++ b/include/boost/geometry/algorithms/transform.hpp @@ -220,7 +220,8 @@ struct transform_range { typedef typename point_type::type point_type; - geometry::clear(range2); + // Should NOT be done here! + // geometry::clear(range2); return transform_range_out(range1, std::back_inserter(range2), strategy); } diff --git a/include/boost/geometry/geometries/linear_ring.hpp b/include/boost/geometry/geometries/linear_ring.hpp index 4c911ddfa..4024420a6 100644 --- a/include/boost/geometry/geometries/linear_ring.hpp +++ b/include/boost/geometry/geometries/linear_ring.hpp @@ -86,7 +86,29 @@ struct point_order< linear_ring > static const order_selector value = clockwise; }; +template +< + typename P, + template class V, + bool PointOrder, + template class A +> +struct closure< linear_ring > +{ + static const closure_selector value = closed; +}; +template +< + typename P, + template class V, + bool PointOrder, + template class A +> +struct closure< linear_ring > +{ + static const closure_selector value = open; +}; } // namespace traits diff --git a/include/boost/geometry/iterators/closing_iterator.hpp b/include/boost/geometry/iterators/closing_iterator.hpp index 288bcbe71..d45c041da 100644 --- a/include/boost/geometry/iterators/closing_iterator.hpp +++ b/include/boost/geometry/iterators/closing_iterator.hpp @@ -13,7 +13,6 @@ #include #include -#include namespace boost { namespace geometry @@ -29,15 +28,14 @@ namespace boost { namespace geometry */ template struct closing_iterator - : public detail::iterators::iterator_base - < - closing_iterator, - typename boost::range_iterator::type, - boost::forward_traversal_tag - > + : public boost::iterator_adaptor + < + closing_iterator, + typename boost::range_iterator::type, + boost::use_default, + boost::forward_traversal_tag + > { - friend class boost::iterator_core_access; - explicit inline closing_iterator(Range& range) : m_range(range) , m_beyond(false) @@ -55,15 +53,15 @@ struct closing_iterator this->base_reference() = m_end; } - inline bool equal(closing_iterator const& other) const +private: + friend class boost::iterator_core_access; + + inline bool equal(closing_iterator const& other) const { return this->base() == other.base() && this->m_beyond == other.m_beyond; } - -private: - inline void increment() { if (m_beyond) diff --git a/include/boost/geometry/multi/algorithms/centroid.hpp b/include/boost/geometry/multi/algorithms/centroid.hpp index 23eaf8c0a..a2ec1dd61 100644 --- a/include/boost/geometry/multi/algorithms/centroid.hpp +++ b/include/boost/geometry/multi/algorithms/centroid.hpp @@ -103,9 +103,10 @@ template < typename MultiPolygon, typename Point, + closure_selector Closure, typename Strategy > -struct centroid +struct centroid : detail::centroid::centroid_multi < MultiPolygon, @@ -114,6 +115,7 @@ struct centroid detail::centroid::centroid_polygon_state < typename boost::range_value::type, + Closure, Strategy > > @@ -124,9 +126,10 @@ template < typename MultiPoint, typename Point, + closure_selector Closure, typename Strategy > -struct centroid +struct centroid : detail::centroid::centroid_multi < MultiPoint, diff --git a/test/algorithms/centroid.cpp b/test/algorithms/centroid.cpp index f6b0f8928..559daa8c1 100644 --- a/test/algorithms/centroid.cpp +++ b/test/algorithms/centroid.cpp @@ -43,6 +43,11 @@ void test_2d() ",3.7 1.6,3.4 1.2,2.8 1.8,2.4 1.7,2 1.3))", 4.06923363095238, 1.65055803571429); + // open / closed + test_centroid >( + "POLYGON((1 1,2 2,3 1,2 0,1 1))", 2.0, 1.0); + test_centroid >( + "POLYGON((1 1,2 2,3 1,2 0))", 2.0, 1.0); test_centroid >("POLYGON((1 2,3 4))", 2, 3); test_centroid

("POINT(3 3)", 3, 3); diff --git a/test/algorithms/correct.cpp b/test/algorithms/correct.cpp index 6084a205c..d3da3342b 100644 --- a/test/algorithms/correct.cpp +++ b/test/algorithms/correct.cpp @@ -67,10 +67,10 @@ template void test_all() { // Define clockwise and counter clockwise polygon - std::string cw_ring = - "POLYGON((0 0,0 1,1 1,1 0,0 0))"; - std::string ccw_ring = - "POLYGON((0 0,1 0,1 1,0 1,0 0))"; + std::string cw_ring = "POLYGON((0 0,0 1,1 1,1 0,0 0))"; + std::string ccw_ring = "POLYGON((0 0,1 0,1 1,0 1,0 0))"; + std::string cw_open_ring = "POLYGON((0 0,0 1,1 1,1 0))"; + std::string ccw_open_ring = "POLYGON((0 0,1 0,1 1,0 1))"; // already cw_ring test_geometry >(cw_ring, cw_ring); @@ -78,9 +78,23 @@ void test_all() // wrong order test_geometry >(ccw_ring, cw_ring); + // ccw-ring, input ccw-ring, already correct + test_geometry >(ccw_ring, ccw_ring); + + // ccw-ring, input cw-ring, corrected + test_geometry >(cw_ring, ccw_ring); + + // open-ring, input ccw-ring, already correct + test_geometry >(cw_open_ring, cw_open_ring); + + // ccw-ring, input cw-ring, corrected + test_geometry >(ccw_open_ring, "POLYGON((0 1,1 1,1 0,0 0))"); + + + // not closed test_geometry >( - "POLYGON((0 0,1 0,1 1,0 1))", + ccw_open_ring, cw_ring); // counter clockwise, cw_ring @@ -99,7 +113,7 @@ void test_all() cw_ring); // wrong order & not closed test_geometry >( - "POLYGON((0 0,1 0,1 1,0 1))", + ccw_open_ring, cw_ring); diff --git a/test/iterators/closing_iterator.cpp b/test/iterators/closing_iterator.cpp index 2b5b762fe..8f9046cde 100644 --- a/test/iterators/closing_iterator.cpp +++ b/test/iterators/closing_iterator.cpp @@ -21,6 +21,30 @@ +void test_minimal() +{ + std::vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + + typedef boost::geometry::closing_iterator + < + std::vector const + > closing_iterator; + + + closing_iterator it(v); + closing_iterator end(v, true); + + std::ostringstream out; + for (; it != end; ++it) + { + out << *it; + } + BOOST_CHECK_EQUAL(out.str(), "1231"); +} + @@ -78,6 +102,7 @@ void test_geometry(std::string const& wkt) template void test_all() { + test_minimal(); test_geometry >("POLYGON((1 1,1 4,4 4,4 1))"); }