From a5f0a565bc9fd500b46ba0dfc06b253f1627aeb8 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 28 May 2015 11:53:26 +0300 Subject: [PATCH 01/16] [test][algorithms][intersection] enable get_turns invariance checking only for linear/linear geometry combinations --- .../test_intersection_linear_linear.hpp | 27 ++++++++++++++----- .../test_get_turns_ll_invariance.hpp | 14 +++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp index 07105aa8b..b4ade8310 100644 --- a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp @@ -12,6 +12,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include @@ -69,7 +71,7 @@ private: std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl; std::cout << "intersection : " << bg::wkt(mls_output) << std::endl; std::cout << "expected intersection : " << bg::wkt(mls_int1) - << std::endl; + << " or: " << bg::wkt(mls_int2) << std::endl; std::cout << std::endl; std::cout << "************************************" << std::endl; std::cout << std::endl; @@ -120,8 +122,8 @@ private: std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl; std::cout << "Geometry #2: " << bg::wkt(geometry1) << std::endl; std::cout << "intersection : " << bg::wkt(mls_output) << std::endl; - std::cout << "expected intersection : " << bg::wkt(mls_int2) - << std::endl; + std::cout << "expected intersection : " << bg::wkt(mls_int1) + << " or: " << bg::wkt(mls_int2) << std::endl; std::cout << std::endl; std::cout << "************************************" << std::endl; std::cout << std::endl; @@ -192,14 +194,27 @@ public: Geometry2 rg2(geometry2); bg::reverse(rg2); - test_get_turns_ll_invariance<>::apply(geometry1, geometry2); + typedef typename bg::tag_cast + < + Geometry1, bg::linear_tag + >::type tag1_type; + + typedef typename bg::tag_cast + < + Geometry2, bg::linear_tag + >::type tag2_type; + + bool const are_linear + = boost::is_same::value + && boost::is_same::value; + + test_get_turns_ll_invariance::apply(geometry1, geometry2); #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << std::endl << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl << std::endl; #endif - test_get_turns_ll_invariance<>::apply(rg1, geometry2); - + test_get_turns_ll_invariance::apply(rg1, geometry2); base_test(geometry1, geometry2, mls_int1, mls_int2, case_id, tolerance); // base_test(rg1, rg2, mls_int1, mls_int2); diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index b2a962ada..221bcd09e 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -32,6 +32,7 @@ namespace bg_turns = bg_detail::turns; template < + bool Enable = true, bool EnableRemoveDuplicateTurns = true, bool EnableDegenerateTurns = true > @@ -166,6 +167,17 @@ public: } }; - +template +class test_get_turns_ll_invariance +< + false, EnableRemoveDuplicateTurns, EnableDegenerateTurns +> +{ +public: + template + static inline void apply(Linear1 const&, Linear2 const&) + { + } +}; #endif // BOOST_GEOMETRY_TEST_GET_TURNS_LL_INVARIANCE_HPP From fdfd875a55dc04809b0305906a1d7624c582233f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 28 May 2015 11:54:53 +0300 Subject: [PATCH 02/16] [views][identity view][closeable view] make indentity and closeable views copyable (by storing a reference wrapper to the range instead of a range reference) --- .../boost/geometry/views/closeable_view.hpp | 27 ++++++++++------- .../boost/geometry/views/identity_view.hpp | 29 ++++++++++++------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/include/boost/geometry/views/closeable_view.hpp b/include/boost/geometry/views/closeable_view.hpp index 1f1eb2720..d6891abd8 100644 --- a/include/boost/geometry/views/closeable_view.hpp +++ b/include/boost/geometry/views/closeable_view.hpp @@ -1,8 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -14,7 +17,7 @@ #ifndef BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP #define BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP - +#include #include #include @@ -44,19 +47,23 @@ struct closing_view { // Keep this explicit, important for nested views/ranges explicit inline closing_view(Range& r) - : m_range(r) + : m_range(boost::ref(r)) {} typedef closing_iterator iterator; typedef closing_iterator const_iterator; - inline const_iterator begin() const { return const_iterator(m_range); } - inline const_iterator end() const { return const_iterator(m_range, true); } + inline const_iterator begin() const { return const_iterator(cref()); } + inline const_iterator end() const { return const_iterator(cref(), true); } + + inline iterator begin() { return iterator(ref()); } + inline iterator end() { return iterator(ref(), true); } - inline iterator begin() { return iterator(m_range); } - inline iterator end() { return iterator(m_range, true); } private : - Range& m_range; + inline Range& ref() { return m_range; } + inline Range const& cref() const { return m_range; } + + boost::reference_wrapper m_range; }; } diff --git a/include/boost/geometry/views/identity_view.hpp b/include/boost/geometry/views/identity_view.hpp index 8947ebf6f..50f10b706 100644 --- a/include/boost/geometry/views/identity_view.hpp +++ b/include/boost/geometry/views/identity_view.hpp @@ -1,8 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -14,7 +19,7 @@ #ifndef BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP #define BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP - +#include #include @@ -39,16 +44,20 @@ struct identity_view typedef typename boost::range_iterator::type iterator; explicit inline identity_view(Range& r) - : m_range(r) + : m_range(boost::ref(r)) {} - inline const_iterator begin() const { return boost::begin(m_range); } - inline const_iterator end() const { return boost::end(m_range); } + inline const_iterator begin() const { return boost::begin(cref()); } + inline const_iterator end() const { return boost::end(cref()); } + + inline iterator begin() { return boost::begin(ref()); } + inline iterator end() { return boost::end(ref()); } - inline iterator begin() { return boost::begin(m_range); } - inline iterator end() { return boost::end(m_range); } private : - Range& m_range; + inline Range& ref() { return m_range; } + inline Range const& cref() const { return m_range; } + + boost::reference_wrapper m_range; }; #if defined(_MSC_VER) From 2080f49d07f196187ecc442b8d31f6d051fe4d5f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 28 May 2015 11:56:21 +0300 Subject: [PATCH 03/16] [test][algorithms][intersection] add unit test for intersection(areal, areal, linear) --- .../set_operations/intersection/Jamfile.v2 | 1 + .../intersection_areal_areal_linear.cpp | 318 ++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp diff --git a/test/algorithms/set_operations/intersection/Jamfile.v2 b/test/algorithms/set_operations/intersection/Jamfile.v2 index 1d174881f..3535df852 100644 --- a/test/algorithms/set_operations/intersection/Jamfile.v2 +++ b/test/algorithms/set_operations/intersection/Jamfile.v2 @@ -17,6 +17,7 @@ test-suite boost-geometry-algorithms-intersection : [ run intersection.cpp : : : BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ] + [ run intersection_areal_areal_linear.cpp ] [ run intersection_linear_linear.cpp ] [ run intersection_pl_l.cpp ] [ run intersection_pl_pl.cpp ] diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp new file mode 100644 index 000000000..de6ae81a1 --- /dev/null +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -0,0 +1,318 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit test + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_intersection_linear_linear_areal +#endif + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#define BOOST_GEOMETRY_DEBUG_TURNS +#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER +#endif + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "test_intersection_linear_linear.hpp" + +typedef bg::model::point point_type; +typedef bg::model::multi_linestring + < + bg::model::linestring + > multi_linestring_type; + +typedef bg::model::ring open_ring_type; +typedef bg::model::polygon open_polygon_type; +typedef bg::model::multi_polygon open_multipolygon_type; + + +template ::type> +struct closed_type +{}; + +template +struct closed_type +{ + typedef bg::model::ring + < + typename bg::point_type::type, true, false + > type; +}; + +template +struct closed_type +{ + typedef bg::model::polygon + < + typename bg::point_type::type, true, false + > type; +}; + +template +struct closed_type +{ + typedef bg::model::multi_polygon + < + typename closed_type + < + typename boost::range_value::type + >::type + > type; +}; + +template +struct test_intersection_aal +{ + static inline void apply(std::string const& case_id, + Areal1 const& areal1, + Areal2 const& areal2, + MultiLinestring const& expected1, + MultiLinestring const& expected2) + { + typedef test_intersection_of_geometries + < + Areal1, Areal2, MultiLinestring + > tester; + + tester::apply(areal1, areal2, expected1, expected2, case_id); + + bool const is_open1 = (bg::closure::value == bg::open); + bool const is_open2 = (bg::closure::value == bg::open); + + if (BOOST_GEOMETRY_CONDITION(is_open1 && is_open2)) + { + typedef typename closed_type::type closed_areal1_type; + typedef typename closed_type::type closed_areal2_type; + closed_areal1_type closed_areal1; + closed_areal2_type closed_areal2; + bg::convert(areal1, closed_areal1); + bg::convert(areal2, closed_areal2); + + typedef test_intersection_of_geometries + < + closed_areal1_type, closed_areal2_type, MultiLinestring + > tester_of_closed; + + std::string case_id_closed = case_id + "-closed"; + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "testing closed areal geometries..." << std::endl; +#endif + tester_of_closed::apply(closed_areal1, closed_areal2, + expected1, expected2, case_id_closed); + } + } + + static inline void apply(std::string const& case_id, + Areal1 const& areal1, + Areal2 const& areal2, + MultiLinestring const& expected) + { + apply(case_id, areal1, areal2, expected, expected); + } +}; + + +BOOST_AUTO_TEST_CASE( test_intersection_ring_ring_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** RING / RING / LINEAR INTERSECTION ***" << std::endl; + std::cout << std::endl; +#endif + typedef open_ring_type OG; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("r-r-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_ring_polygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** RING / POLYGON / LINEAR INTERSECTION ***" << std::endl; + std::cout << std::endl; +#endif + typedef open_ring_type OG1; + typedef open_polygon_type OG2; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("r-pg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_ring_multipolygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** RING / MULTIPOLYGON / LINEAR INTERSECTION ***" + << std::endl; + std::cout << std::endl; +#endif + typedef open_ring_type OG1; + typedef open_multipolygon_type OG2; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("r-mpg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_polygon_polygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** POLYGON / POLYGON / LINEAR INTERSECTION ***" << std::endl; + std::cout << std::endl; +#endif + typedef open_polygon_type OG; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("pg-pg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); + + tester::apply + ("pg-pg-02", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 2,2 7,7 7,7 2))"), + from_wkt("MULTILINESTRING((2 2,2 2),(2 2,2 7,7 7,7 2,2 2),(2 2,2 2))"), + from_wkt("MULTILINESTRING((2 2,2 2),(2 2,7 2,7 7,2 7,2 2),(2 2,2 2))") + ); + + tester::apply + ("pg-pg-03", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 6,6 6,6 3))"), + from_wkt("MULTILINESTRING((2 3,2 6),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-04", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 7,6 7,6 3))"), + from_wkt("MULTILINESTRING((2 3,2 7,6 7),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-05", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 7,7 7,7 3))"), + from_wkt("MULTILINESTRING((2 3,2 7,7 7,7 3),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-06", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 3,2 7,7 7,7 3))"), + from_wkt("MULTILINESTRING((2 3,2 7,7 7,7 3),(2 3,2 3))") + ); + + tester::apply + ("pg-pg-07", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 5,5 7,7 5,5 2))"), + from_wkt("MULTILINESTRING((2 5,2 5),(5 7,5 7),(7 5,7 5),(5 2,5 2))") + ); + + tester::apply + ("pg-pg-08", + from_wkt("POLYGON((0 0,0 10,10 10,10 0),(2 2,7 2,7 7,2 7))"), + from_wkt("POLYGON((2 5,4 7,6 7,7 5,5 2))"), + from_wkt("MULTILINESTRING((2 5,2 5),(4 7,6 7),(7 5,7 5),(5 2,5 2))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_polygon_multipolygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** POLYGON / MULTIPOLYGON / LINEAR INTERSECTION ***" + << std::endl; + std::cout << std::endl; +#endif + typedef open_polygon_type OG1; + typedef open_multipolygon_type OG2; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("pg-mpg-01", + from_wkt("POLYGON((0 0,0 2,2 2,2 0))"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} + + +BOOST_AUTO_TEST_CASE( test_intersection_multipolygon_multipolygon_linestring ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; + std::cout << "*** MULTIPOLYGON / MULTIPOLYGON / LINEAR INTERSECTION ***" + << std::endl; + std::cout << std::endl; +#endif + typedef open_multipolygon_type OG; + typedef multi_linestring_type ML; + + typedef test_intersection_aal tester; + + tester::apply + ("mpg-mpg-01", + from_wkt("MULTIPOLYGON(((0 0,0 2,2 2,2 0)))"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), + from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") + ); +} From bf2362ed52bc11edf18c3a90fc28bdabbead3b6d Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 28 May 2015 11:57:34 +0300 Subject: [PATCH 04/16] [algorithms][inbtersection] add dispatch implementation for intersection(areal, areal, linear) --- .../detail/overlay/intersection_insert.hpp | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 5b9562674..782639a96 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -574,6 +575,46 @@ struct intersection_insert_reversed }; +// dispatch for intersection(areal, areal, linear) +template +< + typename Geometry1, typename Geometry2, + typename LinestringOut, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag1, typename Tag2 +> +struct intersection_insert + < + Geometry1, Geometry2, + LinestringOut, + overlay_intersection, + Reverse1, Reverse2, ReverseOut, + Tag1, Tag2, linestring_tag, + true, true, false + > +{ + template + < + typename RobustPolicy, typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + detail::boundary_view view1(geometry1); + detail::boundary_view view2(geometry2); + + return detail::overlay::linear_linear_linestring + < + detail::boundary_view, + detail::boundary_view, + LinestringOut, + overlay_intersection + >::apply(view1, view2, robust_policy, oit, strategy); + } +}; // dispatch for non-areal geometries template From 6765cdc670201293a72e55a7c240fb385b4a27f3 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 28 May 2015 12:01:06 +0300 Subject: [PATCH 05/16] [views][detail][boundary view] add implementation for boundary view: for areal geometries, i.e., ring, polygon and multi-polygon, detail::boundary_view provides a view of the boundary of the geometry as a linear geometry (for rings the boundary view's geometry type is lineatring, whereas for the other two the boundary view's geometry type is multilinestring) --- .../geometry/views/detail/boundary_view.hpp | 16 + .../detail/boundary_view/implementation.hpp | 405 ++++++++++++++++++ .../views/detail/boundary_view/interface.hpp | 70 +++ 3 files changed, 491 insertions(+) create mode 100644 include/boost/geometry/views/detail/boundary_view.hpp create mode 100644 include/boost/geometry/views/detail/boundary_view/implementation.hpp create mode 100644 include/boost/geometry/views/detail/boundary_view/interface.hpp diff --git a/include/boost/geometry/views/detail/boundary_view.hpp b/include/boost/geometry/views/detail/boundary_view.hpp new file mode 100644 index 000000000..d4f88ccfc --- /dev/null +++ b/include/boost/geometry/views/detail/boundary_view.hpp @@ -0,0 +1,16 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP + +#include +#include + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp new file mode 100644 index 000000000..c44faaa2b --- /dev/null +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -0,0 +1,405 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace boundary_views +{ + + +template +< + typename Polygon, + typename Value = typename ring_type::type, + typename Reference = typename ring_return_type::type, + typename Difference = std::ptrdiff_t +> +class polygon_rings_iterator + : public boost::iterator_facade + < + polygon_rings_iterator, + Value, + boost::random_access_traversal_tag, + Reference + > +{ +public: + // default constructor + polygon_rings_iterator() + : m_polygon(NULL) + , m_index(0) + {} + + // for begin + polygon_rings_iterator(Polygon& polygon) + : m_polygon(boost::addressof(polygon)) + , m_index(0) + {} + + // for end + polygon_rings_iterator(Polygon& polygon, bool) + : m_polygon(boost::addressof(polygon)) + , m_index(num_rings(polygon)) + {} + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + polygon_rings_iterator(polygon_rings_iterator + < + OtherPolygon, + OtherValue, + OtherReference, + OtherDifference + > const& other) + : m_polygon(other.m_polygon) + , m_index(other.m_index) + { + static const bool is_convertible + = boost::is_convertible::value; + + BOOST_MPL_ASSERT_MSG((is_convertible), + NOT_CONVERTIBLE, + (types)); + } + +private: + friend class boost::iterator_core_access; + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + friend class polygon_rings_iterator; + + + static inline std::size_t num_rings(Polygon const& polygon) + { + return geometry::num_interior_rings(polygon) + 1; + } + + inline Reference dereference() const + { + if (m_index == 0) + { + return exterior_ring(*m_polygon); + } + return range::at(interior_rings(*m_polygon), m_index - 1); + } + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + inline bool equal(polygon_rings_iterator + < + OtherPolygon, + OtherValue, + OtherReference, + OtherDifference + > const& other) const + { + return m_polygon == other.m_polygon && m_index == other.m_index; + } + + inline void increment() + { + ++m_index; + } + + inline void decrement() + { + --m_index; + } + + template + < + typename OtherPolygon, + typename OtherValue, + typename OtherReference, + typename OtherDifference + > + inline Difference distance_to(polygon_rings_iterator + < + OtherPolygon, + OtherValue, + OtherReference, + OtherDifference + > const& other) const + { + return other.m_index - m_index; + } + + inline void advance(Difference n) + { + m_index += n; + } + +private: + Polygon* m_polygon; + std::size_t m_index; +}; + + +template +class ring_boundary : closeable_view::value>::type +{ +private: + typedef typename closeable_view::value>::type base_type; + +public: + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + + typedef linestring_tag tag_type; + + explicit ring_boundary(Ring& ring) + : base_type(ring) {} + + iterator begin() + { + return base_type::begin(); + } + + iterator end() + { + return base_type::end(); + } + + const_iterator begin() const + { + return base_type::begin(); + } + + const_iterator end() const + { + return base_type::end(); + } +}; + + +struct as_boundary_view +{ + template + inline boundary_view operator()(Ring& ring) const + { + return boundary_view(ring); + } +}; + + +template +class polygon_boundary +{ + typedef std::vector + < + boundary_view::type> + > views_vector_type; + + inline void initialize_views(Polygon& polygon) + { + polygon_rings_iterator first(polygon); + polygon_rings_iterator last(polygon, true); + std::transform(first, last, + std::back_inserter(m_views), + as_boundary_view()); + } + +public: + typedef typename views_vector_type::iterator iterator; + typedef typename views_vector_type::const_iterator const_iterator; + + typedef multi_linestring_tag tag_type; + + explicit polygon_boundary(Polygon& polygon) + { + initialize_views(polygon); + } + + inline iterator begin() + { + return m_views.begin(); + } + + inline iterator end() + { + return m_views.end(); + } + + inline const_iterator begin() const + { + return m_views.begin(); + } + + inline const_iterator end() const + { + return m_views.end(); + } + +private: + views_vector_type m_views; +}; + + +template +class multipolygon_boundary +{ +private: + typedef typename boost::mpl::if_ + < + boost::is_const, + typename boost::range_value::type const, + typename boost::range_value::type + >::type polygon_type; + + typedef std::vector + < + boundary_view::type> + > views_vector_type; + + inline void initialize_views(MultiPolygon& multipolygon) + { + std::back_insert_iterator oit(m_views); + for (typename boost::range_iterator::type + it = boost::begin(multipolygon); + it != boost::end(multipolygon); + ++it) + { + polygon_rings_iterator first(*it); + polygon_rings_iterator last(*it, true); + oit = std::transform(first, last, oit, as_boundary_view()); + } + } +public: + typedef typename views_vector_type::iterator iterator; + typedef typename views_vector_type::const_iterator const_iterator; + + typedef multi_linestring_tag tag_type; + + multipolygon_boundary(MultiPolygon& multipolygon) + { + initialize_views(multipolygon); + } + + inline iterator begin() + { + return m_views.begin(); + } + + inline iterator end() + { + return m_views.end(); + } + + inline const_iterator begin() const + { + return m_views.begin(); + } + + inline const_iterator end() const + { + return m_views.end(); + } + +private: + views_vector_type m_views; +}; + + +}} // namespace detail::boundary_view +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch +{ + + +template +struct boundary_view + : detail::boundary_views::ring_boundary +{ + explicit boundary_view(Ring& ring) + : detail::boundary_views::ring_boundary(ring) + {} +}; + +template +struct boundary_view + : detail::boundary_views::polygon_boundary +{ + explicit boundary_view(Polygon& polygon) + : detail::boundary_views::polygon_boundary(polygon) + {} +}; + +template +struct boundary_view + : detail::boundary_views::multipolygon_boundary +{ + explicit boundary_view(MultiPolygon& multipolygon) + : detail::boundary_views::multipolygon_boundary + < + MultiPolygon + >(multipolygon) + {} +}; + + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP diff --git a/include/boost/geometry/views/detail/boundary_view/interface.hpp b/include/boost/geometry/views/detail/boundary_view/interface.hpp new file mode 100644 index 000000000..4d0b6d030 --- /dev/null +++ b/include/boost/geometry/views/detail/boundary_view/interface.hpp @@ -0,0 +1,70 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch +{ + +template ::type> +struct boundary_view + : not_implemented +{}; + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct boundary_view + : detail_dispatch::boundary_view +{ + explicit boundary_view(Geometry& geometry) + : detail_dispatch::boundary_view(geometry) + {} +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS +namespace traits +{ + +template +struct tag< geometry::detail::boundary_view > +{ + typedef typename detail_dispatch::boundary_view + < + Geometry + >::tag_type type; +}; + +} // namespace traits +#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP From 2aec831e380adb3704ef8fa0036833ba63bd4033 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 28 May 2015 13:15:09 +0300 Subject: [PATCH 06/16] [view][detail][boundary view] fix copyright year --- include/boost/geometry/views/detail/boundary_view.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/geometry/views/detail/boundary_view.hpp b/include/boost/geometry/views/detail/boundary_view.hpp index d4f88ccfc..43bd5b202 100644 --- a/include/boost/geometry/views/detail/boundary_view.hpp +++ b/include/boost/geometry/views/detail/boundary_view.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle From 7cf9a968c928a79c25b6b1f037885f295ea05479 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 29 May 2015 01:30:01 +0300 Subject: [PATCH 07/16] [algorithms][overlay][relate][turns] propagate the robustness policy to the computation of turns for overlays of L/L geometries --- .../detail/overlay/linear_linear.hpp | 28 ++++++++++++++----- .../algorithms/detail/relate/turns.hpp | 22 +++++++++++++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index d4ebcf296..2b7e3ded1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -157,13 +157,18 @@ protected: < typename Turns, typename LinearGeometry1, - typename LinearGeometry2 + typename LinearGeometry2, + typename RobustPolicy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, - LinearGeometry2 const& linear2) + LinearGeometry2 const& linear2, + RobustPolicy const& robust_policy) { turns.clear(); + + detail::get_turns::no_interrupt_policy interrupt_policy; + geometry::detail::relate::turns::get_turns < LinearGeometry1, @@ -173,8 +178,9 @@ protected: LinearGeometry1, LinearGeometry2, assign_policy - > - >::apply(turns, linear1, linear2); + >, + RobustPolicy + >::apply(turns, linear1, linear2, interrupt_policy, robust_policy); } @@ -229,19 +235,27 @@ public: > static inline OutputIterator apply(Linear1 const& linear1, Linear2 const& linear2, - RobustPolicy const&, + RobustPolicy const& robust_policy, OutputIterator oit, Strategy const& ) { typedef typename detail::relate::turns::get_turns < - Linear1, Linear2 + Linear1, + Linear2, + detail::get_turns::get_turn_info_type + < + Linear1, + Linear2, + assign_policy + >, + RobustPolicy >::turn_info turn_info; typedef std::vector turns_container; turns_container turns; - compute_turns(turns, linear1, linear2); + compute_turns(turns, linear1, linear2, robust_policy); if ( turns.empty() ) { diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 636c9756d..38d88b7d2 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -84,14 +84,30 @@ struct get_turns Geometry2 const& geometry2, InterruptPolicy & interrupt_policy) { - static const bool reverse1 = detail::overlay::do_reverse::value>::value; - static const bool reverse2 = detail::overlay::do_reverse::value>::value; - RobustPolicy robust_policy = geometry::get_rescale_policy < RobustPolicy >(geometry1, geometry2); + apply(turns, geometry1, geometry2, interrupt_policy, robust_policy); + } + + template + static inline void apply(Turns & turns, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + InterruptPolicy & interrupt_policy, + RobustPolicy const& robust_policy) + { + static const bool reverse1 = detail::overlay::do_reverse + < + geometry::point_order::value + >::value; + + static const bool reverse2 = detail::overlay::do_reverse + < + geometry::point_order::value + >::value; dispatch::get_turns < From 3a658549d749399091335177a8dd76ffa9f7b8f9 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 5 Jun 2015 23:33:22 +0300 Subject: [PATCH 08/16] [test][algorithms][intersection] simplify unit test by replacing the meta-programming approach by a simpler one --- .../intersection_areal_areal_linear.cpp | 115 +++++++----------- 1 file changed, 45 insertions(+), 70 deletions(-) diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp index de6ae81a1..9c06a97c2 100644 --- a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -21,9 +21,6 @@ #include -#include -#include - #include #include #include @@ -42,90 +39,59 @@ typedef bg::model::ring open_ring_type; typedef bg::model::polygon open_polygon_type; typedef bg::model::multi_polygon open_multipolygon_type; +typedef bg::model::ring closed_ring_type; +typedef bg::model::polygon closed_polygon_type; +typedef bg::model::multi_polygon closed_multipolygon_type; -template ::type> -struct closed_type -{}; -template -struct closed_type -{ - typedef bg::model::ring - < - typename bg::point_type::type, true, false - > type; -}; - -template -struct closed_type -{ - typedef bg::model::polygon - < - typename bg::point_type::type, true, false - > type; -}; - -template -struct closed_type -{ - typedef bg::model::multi_polygon - < - typename closed_type - < - typename boost::range_value::type - >::type - > type; -}; - -template +template +< + typename OpenAreal1, + typename OpenAreal2, + typename ClosedAreal1, + typename ClosedAreal2, + typename MultiLinestring +> struct test_intersection_aal { static inline void apply(std::string const& case_id, - Areal1 const& areal1, - Areal2 const& areal2, + OpenAreal1 const& open_areal1, + OpenAreal2 const& open_areal2, MultiLinestring const& expected1, MultiLinestring const& expected2) { typedef test_intersection_of_geometries < - Areal1, Areal2, MultiLinestring + OpenAreal1, OpenAreal2, MultiLinestring > tester; - tester::apply(areal1, areal2, expected1, expected2, case_id); + tester::apply(open_areal1, open_areal2, expected1, expected2, case_id); - bool const is_open1 = (bg::closure::value == bg::open); - bool const is_open2 = (bg::closure::value == bg::open); + ClosedAreal1 closed_areal1; + ClosedAreal2 closed_areal2; + bg::convert(open_areal1, closed_areal1); + bg::convert(open_areal2, closed_areal2); - if (BOOST_GEOMETRY_CONDITION(is_open1 && is_open2)) - { - typedef typename closed_type::type closed_areal1_type; - typedef typename closed_type::type closed_areal2_type; - closed_areal1_type closed_areal1; - closed_areal2_type closed_areal2; - bg::convert(areal1, closed_areal1); - bg::convert(areal2, closed_areal2); + typedef test_intersection_of_geometries + < + ClosedAreal1, ClosedAreal2, MultiLinestring + > tester_of_closed; - typedef test_intersection_of_geometries - < - closed_areal1_type, closed_areal2_type, MultiLinestring - > tester_of_closed; - - std::string case_id_closed = case_id + "-closed"; + std::string case_id_closed = case_id + "-closed"; #ifdef BOOST_GEOMETRY_TEST_DEBUG - std::cout << "testing closed areal geometries..." << std::endl; + std::cout << "testing closed areal geometries..." << std::endl; #endif - tester_of_closed::apply(closed_areal1, closed_areal2, - expected1, expected2, case_id_closed); - } + tester_of_closed::apply(closed_areal1, closed_areal2, + expected1, expected2, case_id_closed); } static inline void apply(std::string const& case_id, - Areal1 const& areal1, - Areal2 const& areal2, + OpenAreal1 const& open_areal1, + OpenAreal2 const& open_areal2, MultiLinestring const& expected) { - apply(case_id, areal1, areal2, expected, expected); + apply(case_id, open_areal1, open_areal2, expected, expected); } }; @@ -138,9 +104,10 @@ BOOST_AUTO_TEST_CASE( test_intersection_ring_ring_linestring ) std::cout << std::endl; #endif typedef open_ring_type OG; + typedef closed_ring_type CG; typedef multi_linestring_type ML; - typedef test_intersection_aal tester; + typedef test_intersection_aal tester; tester::apply ("r-r-01", @@ -161,9 +128,11 @@ BOOST_AUTO_TEST_CASE( test_intersection_ring_polygon_linestring ) #endif typedef open_ring_type OG1; typedef open_polygon_type OG2; + typedef closed_ring_type CG1; + typedef closed_polygon_type CG2; typedef multi_linestring_type ML; - typedef test_intersection_aal tester; + typedef test_intersection_aal tester; tester::apply ("r-pg-01", @@ -185,9 +154,11 @@ BOOST_AUTO_TEST_CASE( test_intersection_ring_multipolygon_linestring ) #endif typedef open_ring_type OG1; typedef open_multipolygon_type OG2; + typedef closed_ring_type CG1; + typedef closed_multipolygon_type CG2; typedef multi_linestring_type ML; - typedef test_intersection_aal tester; + typedef test_intersection_aal tester; tester::apply ("r-mpg-01", @@ -207,9 +178,10 @@ BOOST_AUTO_TEST_CASE( test_intersection_polygon_polygon_linestring ) std::cout << std::endl; #endif typedef open_polygon_type OG; + typedef closed_polygon_type CG; typedef multi_linestring_type ML; - typedef test_intersection_aal tester; + typedef test_intersection_aal tester; tester::apply ("pg-pg-01", @@ -281,9 +253,11 @@ BOOST_AUTO_TEST_CASE( test_intersection_polygon_multipolygon_linestring ) #endif typedef open_polygon_type OG1; typedef open_multipolygon_type OG2; + typedef closed_polygon_type CG1; + typedef closed_multipolygon_type CG2; typedef multi_linestring_type ML; - typedef test_intersection_aal tester; + typedef test_intersection_aal tester; tester::apply ("pg-mpg-01", @@ -304,9 +278,10 @@ BOOST_AUTO_TEST_CASE( test_intersection_multipolygon_multipolygon_linestring ) std::cout << std::endl; #endif typedef open_multipolygon_type OG; + typedef closed_multipolygon_type CG; typedef multi_linestring_type ML; - typedef test_intersection_aal tester; + typedef test_intersection_aal tester; tester::apply ("mpg-mpg-01", From 6aa5d27754be84ce71b1e1317ad3cd3afb971d0c Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Sat, 6 Jun 2015 12:17:12 +0300 Subject: [PATCH 09/16] [views][identity view][closeable view] restore them to the state previously to modifications to make then copyable --- .../boost/geometry/views/closeable_view.hpp | 27 +++++++---------- .../boost/geometry/views/identity_view.hpp | 29 +++++++------------ 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/include/boost/geometry/views/closeable_view.hpp b/include/boost/geometry/views/closeable_view.hpp index d6891abd8..1f1eb2720 100644 --- a/include/boost/geometry/views/closeable_view.hpp +++ b/include/boost/geometry/views/closeable_view.hpp @@ -1,11 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. - -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015 Oracle and/or its affiliates. +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -17,7 +14,7 @@ #ifndef BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP #define BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP -#include + #include #include @@ -47,23 +44,19 @@ struct closing_view { // Keep this explicit, important for nested views/ranges explicit inline closing_view(Range& r) - : m_range(boost::ref(r)) + : m_range(r) {} typedef closing_iterator iterator; typedef closing_iterator const_iterator; - inline const_iterator begin() const { return const_iterator(cref()); } - inline const_iterator end() const { return const_iterator(cref(), true); } - - inline iterator begin() { return iterator(ref()); } - inline iterator end() { return iterator(ref(), true); } + inline const_iterator begin() const { return const_iterator(m_range); } + inline const_iterator end() const { return const_iterator(m_range, true); } + inline iterator begin() { return iterator(m_range); } + inline iterator end() { return iterator(m_range, true); } private : - inline Range& ref() { return m_range; } - inline Range const& cref() const { return m_range; } - - boost::reference_wrapper m_range; + Range& m_range; }; } diff --git a/include/boost/geometry/views/identity_view.hpp b/include/boost/geometry/views/identity_view.hpp index 50f10b706..8947ebf6f 100644 --- a/include/boost/geometry/views/identity_view.hpp +++ b/include/boost/geometry/views/identity_view.hpp @@ -1,13 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. - -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015 Oracle and/or its affiliates. - -// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -19,7 +14,7 @@ #ifndef BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP #define BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP -#include + #include @@ -44,20 +39,16 @@ struct identity_view typedef typename boost::range_iterator::type iterator; explicit inline identity_view(Range& r) - : m_range(boost::ref(r)) + : m_range(r) {} - inline const_iterator begin() const { return boost::begin(cref()); } - inline const_iterator end() const { return boost::end(cref()); } - - inline iterator begin() { return boost::begin(ref()); } - inline iterator end() { return boost::end(ref()); } + inline const_iterator begin() const { return boost::begin(m_range); } + inline const_iterator end() const { return boost::end(m_range); } + inline iterator begin() { return boost::begin(m_range); } + inline iterator end() { return boost::end(m_range); } private : - inline Range& ref() { return m_range; } - inline Range const& cref() const { return m_range; } - - boost::reference_wrapper m_range; + Range& m_range; }; #if defined(_MSC_VER) From c02761808d4bd03beac40951f0ed5190208c81a9 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Sat, 6 Jun 2015 12:30:40 +0300 Subject: [PATCH 10/16] [views][boundary view] replace vector with dynamically allocated array and placement new --- .../detail/boundary_view/implementation.hpp | 161 +++++++++--------- 1 file changed, 78 insertions(+), 83 deletions(-) diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp index c44faaa2b..adc0ad69e 100644 --- a/include/boost/geometry/views/detail/boundary_view/implementation.hpp +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -13,6 +13,9 @@ #include #include #include +#include +#include // for std::bad_alloc +#include #include #include @@ -206,88 +209,69 @@ public: explicit ring_boundary(Ring& ring) : base_type(ring) {} - iterator begin() - { - return base_type::begin(); - } - - iterator end() - { - return base_type::end(); - } - - const_iterator begin() const - { - return base_type::begin(); - } - - const_iterator end() const - { - return base_type::end(); - } -}; - - -struct as_boundary_view -{ - template - inline boundary_view operator()(Ring& ring) const - { - return boundary_view(ring); - } + iterator begin() { return base_type::begin(); } + iterator end() { return base_type::end(); } + const_iterator begin() const { return base_type::begin(); } + const_iterator end() const { return base_type::end(); } }; template class polygon_boundary { - typedef std::vector - < - boundary_view::type> - > views_vector_type; + typedef boundary_view::type> boundary_view_type; + typedef polygon_rings_iterator rings_iterator_type; inline void initialize_views(Polygon& polygon) { - polygon_rings_iterator first(polygon); - polygon_rings_iterator last(polygon, true); - std::transform(first, last, - std::back_inserter(m_views), - as_boundary_view()); + std::pair result + = std::get_temporary_buffer(m_num_rings); + + if ( result.second == 0 ) + { + throw std::bad_alloc(); + } + + m_views = result.first; + + std::ptrdiff_t ctr = 0; + rings_iterator_type first(polygon); + rings_iterator_type last(polygon, true); + for (rings_iterator_type rit = first; rit != last; ++rit, ++ctr) + { + new (m_views + ctr) boundary_view_type(*rit); + } } + public: - typedef typename views_vector_type::iterator iterator; - typedef typename views_vector_type::const_iterator const_iterator; + typedef boundary_view_type* iterator; + typedef boundary_view_type const* const_iterator; typedef multi_linestring_tag tag_type; explicit polygon_boundary(Polygon& polygon) + : m_num_rings(static_cast + < + std::ptrdiff_t + >(num_interior_rings(polygon) + 1)) { initialize_views(polygon); } - inline iterator begin() + ~polygon_boundary() { - return m_views.begin(); + std::return_temporary_buffer(m_views); } - inline iterator end() - { - return m_views.end(); - } - - inline const_iterator begin() const - { - return m_views.begin(); - } - - inline const_iterator end() const - { - return m_views.end(); - } + inline iterator begin() { return m_views; } + inline iterator end() { return m_views + m_num_rings; } + inline const_iterator begin() const { return m_views; } + inline const_iterator end() const { return m_views + m_num_rings; } private: - views_vector_type m_views; + std::ptrdiff_t m_num_rings; + boundary_view_type* m_views; }; @@ -302,57 +286,68 @@ private: typename boost::range_value::type >::type polygon_type; - typedef std::vector + typedef polygon_rings_iterator rings_iterator_type; + + typedef boundary_view < - boundary_view::type> - > views_vector_type; + typename ring_type::type + > boundary_view_type; inline void initialize_views(MultiPolygon& multipolygon) { - std::back_insert_iterator oit(m_views); + std::pair result + = std::get_temporary_buffer(m_num_rings); + + if ( result.second == 0 ) + { + throw std::bad_alloc(); + } + + m_views = result.first; + std::ptrdiff_t ctr = 0; for (typename boost::range_iterator::type it = boost::begin(multipolygon); it != boost::end(multipolygon); ++it) { - polygon_rings_iterator first(*it); - polygon_rings_iterator last(*it, true); - oit = std::transform(first, last, oit, as_boundary_view()); + rings_iterator_type first(*it); + rings_iterator_type last(*it, true); + for (rings_iterator_type rit = first; rit != last; ++rit, ++ctr) + { + new (m_views + ctr) boundary_view_type(*rit); + } } } + public: - typedef typename views_vector_type::iterator iterator; - typedef typename views_vector_type::const_iterator const_iterator; + typedef boundary_view_type* iterator; + typedef boundary_view_type const* const_iterator; typedef multi_linestring_tag tag_type; multipolygon_boundary(MultiPolygon& multipolygon) + : m_num_rings(static_cast + < + std::ptrdiff_t + >(geometry::num_interior_rings(multipolygon) + + boost::size(multipolygon))) { initialize_views(multipolygon); } - inline iterator begin() + ~multipolygon_boundary() { - return m_views.begin(); + std::return_temporary_buffer(m_views); } - inline iterator end() - { - return m_views.end(); - } - - inline const_iterator begin() const - { - return m_views.begin(); - } - - inline const_iterator end() const - { - return m_views.end(); - } + inline iterator begin() { return m_views; } + inline iterator end() { return m_views + m_num_rings; } + inline const_iterator begin() const { return m_views; } + inline const_iterator end() const { return m_views + m_num_rings; } private: - views_vector_type m_views; + std::ptrdiff_t m_num_rings; + boundary_view_type* m_views; }; From 0bdee12041045bace6b4f4688bef9ec8cd8b1744 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Sun, 7 Jun 2015 17:34:15 +0300 Subject: [PATCH 11/16] [views][boundary view] use std::uninitialized_copy instead of placement new; explicitly call destructors of elements of dynamically allocated array; --- .../detail/boundary_view/implementation.hpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp index adc0ad69e..467d50779 100644 --- a/include/boost/geometry/views/detail/boundary_view/implementation.hpp +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -233,14 +233,9 @@ class polygon_boundary } m_views = result.first; - - std::ptrdiff_t ctr = 0; - rings_iterator_type first(polygon); - rings_iterator_type last(polygon, true); - for (rings_iterator_type rit = first; rit != last; ++rit, ++ctr) - { - new (m_views + ctr) boundary_view_type(*rit); - } + std::uninitialized_copy(rings_iterator_type(polygon), + rings_iterator_type(polygon, true), + m_views); } @@ -261,6 +256,10 @@ public: ~polygon_boundary() { + for (std::ptrdiff_t i = 0; i < m_num_rings; ++i) + { + m_views[i].~boundary_view_type(); + } std::return_temporary_buffer(m_views); } @@ -304,18 +303,15 @@ private: } m_views = result.first; - std::ptrdiff_t ctr = 0; + boundary_view_type* cur_it = m_views; for (typename boost::range_iterator::type it = boost::begin(multipolygon); it != boost::end(multipolygon); ++it) { - rings_iterator_type first(*it); - rings_iterator_type last(*it, true); - for (rings_iterator_type rit = first; rit != last; ++rit, ++ctr) - { - new (m_views + ctr) boundary_view_type(*rit); - } + cur_it = std::uninitialized_copy(rings_iterator_type(*it), + rings_iterator_type(*it, true), + cur_it); } } @@ -337,6 +333,10 @@ public: ~multipolygon_boundary() { + for (std::ptrdiff_t i = 0; i < m_num_rings; ++i) + { + m_views[i].~boundary_view_type(); + } std::return_temporary_buffer(m_views); } From a331405d55b52da6895167cfd8845a653148f8ca Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Sun, 7 Jun 2015 17:35:07 +0300 Subject: [PATCH 12/16] [test][algorithms][intersection] add one more test case --- .../intersection/intersection_areal_areal_linear.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp index 9c06a97c2..a9dc61273 100644 --- a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -290,4 +290,11 @@ BOOST_AUTO_TEST_CASE( test_intersection_multipolygon_multipolygon_linestring ) from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") ); + + tester::apply + ("mpg-mpg-02", + from_wkt("MULTIPOLYGON(((0 0,0 10,10 10,10 0),(2 2,8 2,8 8,2 8)))"), + from_wkt("MULTIPOLYGON(((2 4,2 6,8 6,8 4)))"), + from_wkt("MULTILINESTRING((2 4,2 4),(2 4,2 6),(8 6,8 4))") + ); } From e5ff16ddb78f2411839905a1e9f2863ffdf0b207 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 8 Jun 2015 10:28:44 +0300 Subject: [PATCH 13/16] [views][boundary view] change the type of the index in polygon_rings_iterator to that of the size type of the interior rings range; refactor code for polygon and multipolygon boundary view into a single class; make the initialization method for areal boundary safe against exceptions thrown by constructors used inside std::uninitialized_copy; --- .../detail/boundary_view/implementation.hpp | 181 ++++++++++-------- 1 file changed, 96 insertions(+), 85 deletions(-) diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp index 467d50779..ee3774674 100644 --- a/include/boost/geometry/views/detail/boundary_view/implementation.hpp +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -55,17 +57,32 @@ template typename Polygon, typename Value = typename ring_type::type, typename Reference = typename ring_return_type::type, - typename Difference = std::ptrdiff_t + typename Difference = typename boost::range_difference + < + typename boost::remove_reference + < + typename interior_return_type::type + >::type + >::type > class polygon_rings_iterator : public boost::iterator_facade < - polygon_rings_iterator, + polygon_rings_iterator, Value, boost::random_access_traversal_tag, - Reference + Reference, + Difference > { + typedef typename boost::range_size + < + typename boost::remove_reference + < + typename interior_return_type::type + >::type + >::type size_type; + public: // default constructor polygon_rings_iterator() @@ -82,7 +99,7 @@ public: // for end polygon_rings_iterator(Polygon& polygon, bool) : m_polygon(boost::addressof(polygon)) - , m_index(num_rings(polygon)) + , m_index(static_cast(num_rings(polygon))) {} template @@ -152,7 +169,8 @@ private: OtherDifference > const& other) const { - return m_polygon == other.m_polygon && m_index == other.m_index; + BOOST_ASSERT(m_polygon == other.m_polygon); + return m_index == other.m_index; } inline void increment() @@ -180,7 +198,8 @@ private: OtherDifference > const& other) const { - return other.m_index - m_index; + return static_cast(other.m_index) + - static_cast(m_index); } inline void advance(Difference n) @@ -190,7 +209,7 @@ private: private: Polygon* m_polygon; - std::size_t m_index; + size_type m_index; }; @@ -216,68 +235,32 @@ public: }; +template ::type> +struct views_container_initializer +{}; + template -class polygon_boundary +struct views_container_initializer { - typedef boundary_view::type> boundary_view_type; typedef polygon_rings_iterator rings_iterator_type; - inline void initialize_views(Polygon& polygon) + static inline std::size_t num_rings(Polygon const& polygon) { - std::pair result - = std::get_temporary_buffer(m_num_rings); + return geometry::num_interior_rings(polygon) + 1; + } - if ( result.second == 0 ) - { - throw std::bad_alloc(); - } - - m_views = result.first; + template + static inline void apply(Polygon const& polygon, BoundaryView* views) + { std::uninitialized_copy(rings_iterator_type(polygon), rings_iterator_type(polygon, true), - m_views); + views); } - - -public: - typedef boundary_view_type* iterator; - typedef boundary_view_type const* const_iterator; - - typedef multi_linestring_tag tag_type; - - explicit polygon_boundary(Polygon& polygon) - : m_num_rings(static_cast - < - std::ptrdiff_t - >(num_interior_rings(polygon) + 1)) - { - initialize_views(polygon); - } - - ~polygon_boundary() - { - for (std::ptrdiff_t i = 0; i < m_num_rings; ++i) - { - m_views[i].~boundary_view_type(); - } - std::return_temporary_buffer(m_views); - } - - inline iterator begin() { return m_views; } - inline iterator end() { return m_views + m_num_rings; } - inline const_iterator begin() const { return m_views; } - inline const_iterator end() const { return m_views + m_num_rings; } - -private: - std::ptrdiff_t m_num_rings; - boundary_view_type* m_views; }; - template -class multipolygon_boundary +struct views_container_initializer { -private: typedef typename boost::mpl::if_ < boost::is_const, @@ -287,23 +270,17 @@ private: typedef polygon_rings_iterator rings_iterator_type; - typedef boundary_view - < - typename ring_type::type - > boundary_view_type; - - inline void initialize_views(MultiPolygon& multipolygon) + static inline std::size_t num_rings(MultiPolygon const& multipolygon) { - std::pair result - = std::get_temporary_buffer(m_num_rings); + return geometry::num_interior_rings(multipolygon) + + static_cast(boost::size(multipolygon)); + } - if ( result.second == 0 ) - { - throw std::bad_alloc(); - } - - m_views = result.first; - boundary_view_type* cur_it = m_views; + template + static inline void apply(MultiPolygon const& multipolygon, + BoundaryView* views) + { + BoundaryView* cur_it = views; for (typename boost::range_iterator::type it = boost::begin(multipolygon); it != boost::end(multipolygon); @@ -314,6 +291,45 @@ private: cur_it); } } +}; + + +template +class areal_boundary +{ + typedef boundary_view::type> boundary_view_type; + typedef views_container_initializer initializer; + + inline void initialize_views(Areal const& areal) + { + std::pair result + = std::get_temporary_buffer(m_num_rings); + + if ( result.second < m_num_rings ) + { + throw std::bad_alloc(); + } + + m_views = result.first; + try + { + initializer::apply(areal, m_views); + } + catch (...) + { + clear(); + throw; + } + } + + inline void clear() + { + for (std::ptrdiff_t i = 0; i < m_num_rings; ++i) + { + m_views[i].~boundary_view_type(); + } + std::return_temporary_buffer(m_views); + } public: typedef boundary_view_type* iterator; @@ -321,23 +337,18 @@ public: typedef multi_linestring_tag tag_type; - multipolygon_boundary(MultiPolygon& multipolygon) + explicit areal_boundary(Areal& areal) : m_num_rings(static_cast < std::ptrdiff_t - >(geometry::num_interior_rings(multipolygon) - + boost::size(multipolygon))) + >(initializer::num_rings(areal))) { - initialize_views(multipolygon); + initialize_views(areal); } - ~multipolygon_boundary() + ~areal_boundary() { - for (std::ptrdiff_t i = 0; i < m_num_rings; ++i) - { - m_views[i].~boundary_view_type(); - } - std::return_temporary_buffer(m_views); + clear(); } inline iterator begin() { return m_views; } @@ -371,19 +382,19 @@ struct boundary_view template struct boundary_view - : detail::boundary_views::polygon_boundary + : detail::boundary_views::areal_boundary { explicit boundary_view(Polygon& polygon) - : detail::boundary_views::polygon_boundary(polygon) + : detail::boundary_views::areal_boundary(polygon) {} }; template struct boundary_view - : detail::boundary_views::multipolygon_boundary + : detail::boundary_views::areal_boundary { explicit boundary_view(MultiPolygon& multipolygon) - : detail::boundary_views::multipolygon_boundary + : detail::boundary_views::areal_boundary < MultiPolygon >(multipolygon) From 8285b452983cafec1ded0a3215b39ee922011f36 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 9 Jun 2015 00:49:52 +0300 Subject: [PATCH 14/16] [test][algorithms][intersection] add more test cases for A/A -> L --- .../intersection_areal_areal_linear.cpp | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp index a9dc61273..c83c794c0 100644 --- a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -116,6 +116,27 @@ BOOST_AUTO_TEST_CASE( test_intersection_ring_ring_linestring ) from_wkt("MULTILINESTRING((2 1,2 2),(2 0,1 0),(2 1,2 1))"), from_wkt("MULTILINESTRING((2 2,2 1),(2 0,1 0),(2 1,2 1))") ); + + tester::apply + ("r-r-02", + from_wkt("POLYGON(())"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("r-r-03", + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("r-r-04", + from_wkt("POLYGON(())"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); } @@ -240,6 +261,41 @@ BOOST_AUTO_TEST_CASE( test_intersection_polygon_polygon_linestring ) from_wkt("POLYGON((2 5,4 7,6 7,7 5,5 2))"), from_wkt("MULTILINESTRING((2 5,2 5),(4 7,6 7),(7 5,7 5),(5 2,5 2))") ); + + tester::apply + ("pg-pg-09", + from_wkt("POLYGON(())"), + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-10", + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0))"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-11", + from_wkt("POLYGON(())"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-12", + from_wkt("POLYGON((),())"), + from_wkt("POLYGON((),(),())"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("pg-pg-13", + from_wkt("POLYGON((2 1,2 4,4 4,4 0,1 0),())"), + from_wkt("POLYGON(())"), + from_wkt("MULTILINESTRING()") + ); } @@ -297,4 +353,39 @@ BOOST_AUTO_TEST_CASE( test_intersection_multipolygon_multipolygon_linestring ) from_wkt("MULTIPOLYGON(((2 4,2 6,8 6,8 4)))"), from_wkt("MULTILINESTRING((2 4,2 4),(2 4,2 6),(8 6,8 4))") ); + + tester::apply + ("mpg-mpg-03", + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-04", + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0)))"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-05", + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-06", + from_wkt("MULTIPOLYGON((()),((),()))"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); + + tester::apply + ("mpg-mpg-07", + from_wkt("MULTIPOLYGON(((2 1,2 4,4 4,4 0,1 0),(),()))"), + from_wkt("MULTIPOLYGON()"), + from_wkt("MULTILINESTRING()") + ); } From 6e7ae868ee21718cbb0ae32dea3e9ea2cef412bc Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 9 Jun 2015 00:50:26 +0300 Subject: [PATCH 15/16] [views][boundary view] replace BOOST_ASSERT by BOOST_GEOMETRY_ASSERT; use flatten_iterator to get all rings of a multipolygon as a single range; separate initializer from num_rings computation; use operator new/operator delete for dynamic memory allocation of views' container; use automatic deallocator helper class instead of try/catch block; --- .../detail/boundary_view/implementation.hpp | 167 ++++++++++++------ 1 file changed, 112 insertions(+), 55 deletions(-) diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp index ee3774674..ba19c76f1 100644 --- a/include/boost/geometry/views/detail/boundary_view/implementation.hpp +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -14,11 +14,10 @@ #include #include #include -#include // for std::bad_alloc +#include #include #include -#include #include #include #include @@ -30,12 +29,15 @@ #include #include +#include #include #include #include #include #include +#include + #include #include @@ -169,7 +171,7 @@ private: OtherDifference > const& other) const { - BOOST_ASSERT(m_polygon == other.m_polygon); + BOOST_GEOMETRY_ASSERT(m_polygon == other.m_polygon); return m_index == other.m_index; } @@ -235,6 +237,30 @@ public: }; +template ::type> +struct num_rings +{}; + +template +struct num_rings +{ + static inline std::size_t apply(Polygon const& polygon) + { + return geometry::num_interior_rings(polygon) + 1; + } +}; + +template +struct num_rings +{ + static inline std::size_t apply(MultiPolygon const& multipolygon) + { + return geometry::num_interior_rings(multipolygon) + + static_cast(boost::size(multipolygon)); + } +}; + + template ::type> struct views_container_initializer {}; @@ -242,16 +268,11 @@ struct views_container_initializer template struct views_container_initializer { - typedef polygon_rings_iterator rings_iterator_type; - - static inline std::size_t num_rings(Polygon const& polygon) - { - return geometry::num_interior_rings(polygon) + 1; - } - template static inline void apply(Polygon const& polygon, BoundaryView* views) { + typedef polygon_rings_iterator rings_iterator_type; + std::uninitialized_copy(rings_iterator_type(polygon), rings_iterator_type(polygon, true), views); @@ -259,7 +280,7 @@ struct views_container_initializer }; template -struct views_container_initializer +class views_container_initializer { typedef typename boost::mpl::if_ < @@ -268,28 +289,44 @@ struct views_container_initializer typename boost::range_value::type >::type polygon_type; - typedef polygon_rings_iterator rings_iterator_type; + typedef polygon_rings_iterator inner_iterator_type; - static inline std::size_t num_rings(MultiPolygon const& multipolygon) + struct polygon_rings_begin { - return geometry::num_interior_rings(multipolygon) - + static_cast(boost::size(multipolygon)); - } + static inline inner_iterator_type apply(polygon_type& polygon) + { + return inner_iterator_type(polygon); + } + }; + struct polygon_rings_end + { + static inline inner_iterator_type apply(polygon_type& polygon) + { + return inner_iterator_type(polygon, true); + } + }; + + typedef flatten_iterator + < + typename boost::range_iterator::type, + inner_iterator_type, + typename std::iterator_traits::value_type, + polygon_rings_begin, + polygon_rings_end, + typename std::iterator_traits::reference + > rings_iterator_type; + +public: template static inline void apply(MultiPolygon const& multipolygon, BoundaryView* views) { - BoundaryView* cur_it = views; - for (typename boost::range_iterator::type - it = boost::begin(multipolygon); - it != boost::end(multipolygon); - ++it) - { - cur_it = std::uninitialized_copy(rings_iterator_type(*it), - rings_iterator_type(*it, true), - cur_it); - } + rings_iterator_type first(boost::begin(multipolygon), + boost::end(multipolygon)); + rings_iterator_type last(boost::end(multipolygon)); + + std::uninitialized_copy(first, last, views); } }; @@ -298,38 +335,55 @@ template class areal_boundary { typedef boundary_view::type> boundary_view_type; - typedef views_container_initializer initializer; + typedef views_container_initializer exception_safe_initializer; + + template + struct automatic_deallocator + { + automatic_deallocator() : m_ptr(NULL) {} + + ~automatic_deallocator() + { + operator delete(m_ptr); + } + + inline void lock(T* ptr) { m_ptr = ptr; } + inline void release() { m_ptr = NULL; } + + T* m_ptr; + }; inline void initialize_views(Areal const& areal) { - std::pair result - = std::get_temporary_buffer(m_num_rings); + // initialize number of rings + std::size_t n_rings = num_rings::apply(areal); - if ( result.second < m_num_rings ) + if (n_rings == 0) { - throw std::bad_alloc(); + return; } - m_views = result.first; - try - { - initializer::apply(areal, m_views); - } - catch (...) - { - clear(); - throw; - } + // allocate dynamic memory + boundary_view_type* views_ptr = static_cast + < + boundary_view_type* + >(operator new(sizeof(boundary_view_type) * n_rings)); + + // initialize; if exceptions are thrown by constructors + // they are handled automatically by automatic_deallocator + automatic_deallocator deallocator; + deallocator.lock(views_ptr); + exception_safe_initializer::apply(areal, views_ptr); + deallocator.release(); + + // now initialize member variables safely + m_views = views_ptr; + m_num_rings = n_rings; } - inline void clear() - { - for (std::ptrdiff_t i = 0; i < m_num_rings; ++i) - { - m_views[i].~boundary_view_type(); - } - std::return_temporary_buffer(m_views); - } + // disallow copies and/or assignments + areal_boundary(areal_boundary const&); + areal_boundary& operator=(areal_boundary const&); public: typedef boundary_view_type* iterator; @@ -338,17 +392,20 @@ public: typedef multi_linestring_tag tag_type; explicit areal_boundary(Areal& areal) - : m_num_rings(static_cast - < - std::ptrdiff_t - >(initializer::num_rings(areal))) + : m_views(NULL) + , m_num_rings(0) { initialize_views(areal); } ~areal_boundary() { - clear(); + boundary_view_type* last = m_views + m_num_rings; + for (boundary_view_type* it = m_views; it != last; ++it) + { + it->~boundary_view_type(); + } + operator delete(m_views); } inline iterator begin() { return m_views; } @@ -357,8 +414,8 @@ public: inline const_iterator end() const { return m_views + m_num_rings; } private: - std::ptrdiff_t m_num_rings; boundary_view_type* m_views; + std::size_t m_num_rings; }; From f23b88d3140adda550cb30a67647b7b78dc32860 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 9 Jun 2015 01:27:02 +0300 Subject: [PATCH 16/16] [views][boundary view] make the deallocator take the pointer at construction time --- .../geometry/views/detail/boundary_view/implementation.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/views/detail/boundary_view/implementation.hpp b/include/boost/geometry/views/detail/boundary_view/implementation.hpp index ba19c76f1..e6a09afd6 100644 --- a/include/boost/geometry/views/detail/boundary_view/implementation.hpp +++ b/include/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -340,14 +340,13 @@ class areal_boundary template struct automatic_deallocator { - automatic_deallocator() : m_ptr(NULL) {} + automatic_deallocator(T* ptr) : m_ptr(ptr) {} ~automatic_deallocator() { operator delete(m_ptr); } - inline void lock(T* ptr) { m_ptr = ptr; } inline void release() { m_ptr = NULL; } T* m_ptr; @@ -371,8 +370,7 @@ class areal_boundary // initialize; if exceptions are thrown by constructors // they are handled automatically by automatic_deallocator - automatic_deallocator deallocator; - deallocator.lock(views_ptr); + automatic_deallocator deallocator(views_ptr); exception_safe_initializer::apply(areal, views_ptr); deallocator.release();