From 9164a5bc0c2f332dbfc573a795a5b5c8f79a0ef7 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 14 Jul 2014 14:29:27 +0300 Subject: [PATCH 01/37] [multi][algorithms][num_points] add include for std::size_t; qualify with std:: an occurrence of unqualified size_t; --- include/boost/geometry/multi/algorithms/num_points.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/multi/algorithms/num_points.hpp b/include/boost/geometry/multi/algorithms/num_points.hpp index 180523a98..ac10ddff4 100644 --- a/include/boost/geometry/multi/algorithms/num_points.hpp +++ b/include/boost/geometry/multi/algorithms/num_points.hpp @@ -15,6 +15,7 @@ #ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP #define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP +#include #include @@ -34,7 +35,8 @@ namespace detail { namespace num_points struct multi_count { template - static inline size_t apply(MultiGeometry const& geometry, bool add_for_open) + static inline + std::size_t apply(MultiGeometry const& geometry, bool add_for_open) { typedef typename boost::range_value::type geometry_type; typedef typename boost::range_iterator From edf2c00db6351d623c6030b961811256252385e7 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 14 Jul 2014 16:05:26 +0200 Subject: [PATCH 02/37] [within][winding] Add more robust calculation of sides in winding strategy. This commit fixes the ticket https://svn.boost.org/trac/boost/ticket/9628. The side is calculated always WRT the vertical segment if the p<1> is "equal" to one of the segment endpoint's <1>. For more information see the comment in the code. --- .../agnostic/point_in_poly_winding.hpp | 68 +++++++++++++++++-- test/algorithms/within_pointlike_xxx.cpp | 42 ++++++++++++ 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index 24d7470ae..288be64d3 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -112,21 +112,21 @@ class winding template static inline int check_segment(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, - counter& state) + counter& state, bool& eq1, bool& eq2) { calculation_type const p = get(point); calculation_type const s1 = get(seg1); calculation_type const s2 = get(seg2); // Check if one of segment endpoints is at same level of point - bool eq1 = math::equals(s1, p); - bool eq2 = math::equals(s2, p); + eq1 = math::equals(s1, p); + eq2 = math::equals(s2, p); if (eq1 && eq2) { // Both equal p -> segment is horizontal (or vertical for D=0) // The only thing which has to be done is check if point is ON segment - return check_touch<1 - D>(point, seg1, seg2,state); + return check_touch<1 - D>(point, seg1, seg2, state); } return @@ -137,7 +137,48 @@ class winding : 0; } - + // Fix for https://svn.boost.org/trac/boost/ticket/9628 + // For floating point coordinates, the <1> coordinate of a point is compared + // with the segment's points using some EPS. If the coordinates are "equal" + // the sides are calculated. Therefore we can treat a segment as a long areal + // geometry having some width. There is a small ~triangular area somewhere + // between the segment's effective area and a segment's line used in sides + // calculation where the segment is on the one side of the line but on the + // other side of a segment (due to the width). + // For the s1 of a segment going NE the real side is RIGHT but the point may + // be detected as LEFT, like this: + // RIGHT + // ___-----> + // ^ O Pt __ __ + // EPS __ __ + // v__ __ BUT DETECTED AS LEFT OF THIS LINE + // _____7 + // _____/ + // _____/ + template + static inline int side_equal(Point const& point, + PointOfSegment const& se, + int count) + { + // TODO: possible optimization of cartesian CS + // math::equals(p<1-D>, se<1-D>) ? + // 0 : + // p<1-D> < se<1-D> ? + // (UP ? LEFT : RIGHT) : + // (UP ? RIGHT : LEFT) ; + + PointOfSegment ss1(se); + PointOfSegment ss2(se); + if ( count > 0 ) // UP + { + set(ss1, 0); set(ss2, 1); + } + else // DOWN + { + set(ss1, 1); set(ss2, 0); + } + return strategy_side_type::apply(ss1, ss2, point); + } public : @@ -151,10 +192,23 @@ public : PointOfSegment const& s1, PointOfSegment const& s2, counter& state) { - int count = check_segment<1>(point, s1, s2, state); + bool eq1 = false; + bool eq2 = false; + boost::ignore_unused(eq2); + + int count = check_segment<1>(point, s1, s2, state, eq1, eq2); if (count != 0) { - int side = strategy_side_type::apply(s1, s2, point); + int side = 0; + if ( count == 1 || count == -1 ) + { + side = side_equal<1>(point, eq1 ? s1 : s2, count); + } + else + { + side = strategy_side_type::apply(s1, s2, point); + } + if (side == 0) { // Point is lying on segment diff --git a/test/algorithms/within_pointlike_xxx.cpp b/test/algorithms/within_pointlike_xxx.cpp index db281aecf..ed058fa28 100644 --- a/test/algorithms/within_pointlike_xxx.cpp +++ b/test/algorithms/within_pointlike_xxx.cpp @@ -181,6 +181,46 @@ void test_large_integers() BOOST_CHECK_MESSAGE(wi == wd, "within different from within"); } +void test_tickets() +{ + typedef boost::geometry::model::d2::point_xy pt; + typedef boost::geometry::model::ring ring; + + https://svn.boost.org/trac/boost/ticket/9628 + { + ring r; + r.push_back(pt(-19155.669324773193,54820.312032458620)); + r.push_back(pt(-13826.169324773080,54820.312032458627)); + r.push_back(pt(-13826.169324773078,52720.312032458663)); + r.push_back(pt(-12755.169324773129,52720.312032458663)); + r.push_back(pt(-12755.169324773129,51087.312032458671)); + r.push_back(pt(-12760.669324773080,51087.312032458671)); + r.push_back(pt(-12760.669324773082,51070.312032458627)); + r.push_back(pt(-19155.669324779392,51070.312032458620)); + r.push_back(pt(-19155.669324773193,54820.312032458620)); + + pt p( -12260.669324773118, 54820.312032458634 ); + + //boost::geometry::correct(r); + + bool within = boost::geometry::within(p, r); + BOOST_CHECK_EQUAL(within, false); + } + // similar + { + ring r; + r.push_back(pt(-14155.6,54820.312032458620)); + r.push_back(pt(-13826.1,54820.312032458625)); + r.push_back(pt(-12155.6,53720.3)); + r.push_back(pt(-14155.6,54820.312032458620)); + + pt p( -13826.0, 54820.312032458634 ); + + bool within = boost::geometry::within(p, r); + BOOST_CHECK_EQUAL(within, false); + } +} + int test_main( int , char* [] ) { test_large_integers(); @@ -195,5 +235,7 @@ int test_main( int , char* [] ) test_spherical > >(); #endif + test_tickets(); + return 0; } From 95990f98b147cdb35706ed127e3124d7deef94f6 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 14 Jul 2014 19:05:28 +0200 Subject: [PATCH 03/37] [test][within] Comment out, mistakenly not commented out line --- test/algorithms/within_pointlike_xxx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/algorithms/within_pointlike_xxx.cpp b/test/algorithms/within_pointlike_xxx.cpp index ed058fa28..aa0a96929 100644 --- a/test/algorithms/within_pointlike_xxx.cpp +++ b/test/algorithms/within_pointlike_xxx.cpp @@ -186,7 +186,7 @@ void test_tickets() typedef boost::geometry::model::d2::point_xy pt; typedef boost::geometry::model::ring ring; - https://svn.boost.org/trac/boost/ticket/9628 + // https://svn.boost.org/trac/boost/ticket/9628 { ring r; r.push_back(pt(-19155.669324773193,54820.312032458620)); From c5241dd8ee682c28774459461b248c5aab42e9ee Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 14 Jul 2014 21:54:01 +0200 Subject: [PATCH 04/37] [distance] added missing include file --- .../strategies/cartesian/distance_projected_point_ax.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp index 71ac637f2..c4090044f 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include From 9ed4d83441b8843ad5f6571473980cd26fb7cf46 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 14 Jul 2014 22:00:57 +0200 Subject: [PATCH 05/37] [extensions][offset] Let offset compile again. Note: it does not generate correct offsets! --- .../geometry/extensions/algorithms/offset.hpp | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/include/boost/geometry/extensions/algorithms/offset.hpp b/include/boost/geometry/extensions/algorithms/offset.hpp index baf8f91ef..ec8943d2a 100644 --- a/include/boost/geometry/extensions/algorithms/offset.hpp +++ b/include/boost/geometry/extensions/algorithms/offset.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -39,43 +40,48 @@ template typename RangeOut > struct offset_range - : public geometry::detail::buffer::buffer_range - < - RangeOut, - linestring_tag - > { typedef geometry::detail::buffer::buffer_range < - RangeOut, - linestring_tag - > super; + Range + > per_range; + template < typename Collection, typename DistanceStrategy, + typename SideStrategy, typename JoinStrategy, - typename EndStrategy + typename EndStrategy, + typename RobustPolicy > static inline void apply(Collection& collection, Range const& range, DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + RobustPolicy const& robust_policy, bool reverse) { collection.start_new_ring(); + typedef typename point_type::type output_point_type; + output_point_type first_p1, first_p2, last_p1, last_p2; + if (reverse) { - super::iterate(collection, boost::rbegin(range), boost::rend(range), - buffer_side_left, - distance_strategy, join_strategy, end_strategy); + per_range::iterate(collection, 0, boost::rbegin(range), boost::rend(range), + strategy::buffer::buffer_side_left, + distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, + first_p1, first_p2, last_p1, last_p2); } else { - super::iterate(collection, boost::begin(range), boost::end(range), - buffer_side_left, - distance_strategy, join_strategy, end_strategy); + per_range::iterate(collection, 0, boost::begin(range), boost::end(range), + strategy::buffer::buffer_side_left, + distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, + first_p1, first_p2, last_p1, last_p2); } + collection.finish_ring(); } }; @@ -160,6 +166,8 @@ inline void offset(Geometry const& geometry, GeometryOut& out, point_type > end_strategy; + strategy::buffer::buffer_side side_strategy; + dispatch::offset < typename tag::type, @@ -169,11 +177,13 @@ inline void offset(Geometry const& geometry, GeometryOut& out, >::apply(collection, geometry, distance_strategy, + side_strategy, join_strategy, end_strategy, + robust_policy, reverse); - collection.assign_offsetted_rings(out); + // TODO collection.template assign(out); } From 2ba3e9a95b3a93c7faf7c546580b001bf7f2eb42 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 14 Jul 2014 23:17:09 +0200 Subject: [PATCH 06/37] [strategies][winding] Replace Points creation using copy-ctors with default-ctors + set<>() Also add some comments about what's going on in the code. --- .../strategies/agnostic/point_in_poly_winding.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index 288be64d3..4ed54c77e 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -167,16 +167,23 @@ class winding // (UP ? LEFT : RIGHT) : // (UP ? RIGHT : LEFT) ; - PointOfSegment ss1(se); - PointOfSegment ss2(se); + // Create a vertical segment intersecting the original segment's endpoint + // equal to the point, with the derived direction (UP/DOWN). + // Set only the 2 first coordinates, the other ones are ignored + PointOfSegment ss1, ss2; + set<1-D>(ss1, get<1-D>(se)); + set<1-D>(ss2, get<1-D>(se)); if ( count > 0 ) // UP { - set(ss1, 0); set(ss2, 1); + set(ss1, 0); + set(ss2, 1); } else // DOWN { - set(ss1, 1); set(ss2, 0); + set(ss1, 1); + set(ss2, 0); } + // Check the side using this vertical segment return strategy_side_type::apply(ss1, ss2, point); } From 8cc85dc3cdf14ed04350cea5b819f0392d44d180 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 14 Jul 2014 23:44:53 +0200 Subject: [PATCH 07/37] Add ticket 9628 to release notes, fix the ticket 10077 placement --- doc/release_notes.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 03304dbea..90462b54e 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -43,7 +43,9 @@ * [@https://svn.boost.org/trac/boost/ticket/8310 8310] Wrong results with overlapping polygons (fixed using point_on_surface for disjoint) * [@https://svn.boost.org/trac/boost/ticket/9871 9871] Remove spike in polygon with only a spike * [@https://svn.boost.org/trac/boost/ticket/9563 9563] (Sym)difference not successful, fixed by rescaling to robust type +* [@https://svn.boost.org/trac/boost/ticket/9628 9628] Wrong result of within() due to the winding strategy not working correctly for nearly-horizontal segments * [@https://svn.boost.org/trac/boost/ticket/10019 10019] Difference of Linestring and Box returns their intersection +* [@https://svn.boost.org/trac/boost/ticket/10077 10077] Wrong types in concept checks in boost/geometry/arithmetic/arithmetic.hpp [*Bugfixes] @@ -82,7 +84,6 @@ * [@https://svn.boost.org/trac/boost/ticket/8825 8825] Patch adding member variable documentation to doxygen_xml2qbk * [@https://svn.boost.org/trac/boost/ticket/8652 8652] Intersection fails for triangle-triangle intersection. Caused by spike, fixed * [@https://svn.boost.org/trac/boost/ticket/9047 9047] Boost files that include themselves (strategies/intersection.hpp), fixed -* [@https://svn.boost.org/trac/boost/ticket/10077 10077] Wrong types in concept checks in boost/geometry/arithmetic/arithmetic.hpp, fixed [*Internal changes] From 7808f77ce2b575edfd1fc80c52e696d4805a7fb2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 15 Jul 2014 00:42:16 +0200 Subject: [PATCH 08/37] [doc] Fix docs of Boost.Polygon adapters, add examples. --- doc/imports.qbk | 5 +- .../adapted/boost_polygon/point_data.qbk | 11 ++-- .../adapted/boost_polygon/polygon_data.qbk | 13 ++-- .../boost_polygon/polygon_with_holes_data.qbk | 13 ++-- .../adapted/boost_polygon/rectangle_data.qbk | 13 ++-- .../geometries/adapted/boost_polygon_box.cpp | 42 ++++++++++++ ...st_polygon.cpp => boost_polygon_point.cpp} | 7 +- .../adapted/boost_polygon_polygon.cpp | 64 +++++++++++++++++++ .../geometries/adapted/boost_polygon_ring.cpp | 52 +++++++++++++++ 9 files changed, 193 insertions(+), 27 deletions(-) create mode 100644 doc/src/examples/geometries/adapted/boost_polygon_box.cpp rename doc/src/examples/geometries/adapted/{boost_polygon.cpp => boost_polygon_point.cpp} (83%) create mode 100644 doc/src/examples/geometries/adapted/boost_polygon_polygon.cpp create mode 100644 doc/src/examples/geometries/adapted/boost_polygon_ring.cpp diff --git a/doc/imports.qbk b/doc/imports.qbk index 3463c511d..ad03bbfaf 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -82,7 +82,10 @@ [import src/examples/geometries/adapted/c_array.cpp] [import src/examples/geometries/adapted/boost_array.cpp] [import src/examples/geometries/adapted/boost_fusion.cpp] -[import src/examples/geometries/adapted/boost_polygon.cpp] +[import src/examples/geometries/adapted/boost_polygon_box.cpp] +[import src/examples/geometries/adapted/boost_polygon_point.cpp] +[import src/examples/geometries/adapted/boost_polygon_polygon.cpp] +[import src/examples/geometries/adapted/boost_polygon_ring.cpp] [import src/examples/geometries/adapted/boost_tuple.cpp] [import src/examples/geometries/adapted/boost_range/filtered.cpp] diff --git a/doc/reference/geometries/adapted/boost_polygon/point_data.qbk b/doc/reference/geometries/adapted/boost_polygon/point_data.qbk index ff013ed17..edc3f1f19 100644 --- a/doc/reference/geometries/adapted/boost_polygon/point_data.qbk +++ b/doc/reference/geometries/adapted/boost_polygon/point_data.qbk @@ -1,9 +1,10 @@ [/============================================================================ 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-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2008-2014 Bruno Lalande, Paris, France. + Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -29,8 +30,8 @@ algorithms from both Boost.Polygon and Boost.Geometry can be called. __not_in_boost_geometry_hpp__ [heading Example] -[boost_polygon] -[boost_polygon_output] +[boost_polygon_point] +[boost_polygon_point_output] [endsect] diff --git a/doc/reference/geometries/adapted/boost_polygon/polygon_data.qbk b/doc/reference/geometries/adapted/boost_polygon/polygon_data.qbk index e37628cb2..23c419014 100644 --- a/doc/reference/geometries/adapted/boost_polygon/polygon_data.qbk +++ b/doc/reference/geometries/adapted/boost_polygon/polygon_data.qbk @@ -1,9 +1,10 @@ [/============================================================================ 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-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2008-2014 Bruno Lalande, Paris, France. + Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -17,7 +18,7 @@ Boost.Polygon's polygon type (boost::polygon::polygon_data) is adapted to the Bo [heading Description] Boost.Polygon's points (as well as polygons) can be used by Boost.Geometry. The -two libraries can therefore be used together. Using a boost::polygon::point_data<...>, +two libraries can therefore be used together. Using a boost::polygon::polygon_data<...>, algorithms from both Boost.Polygon and Boost.Geometry can be called. [heading Model of] @@ -29,8 +30,8 @@ algorithms from both Boost.Polygon and Boost.Geometry can be called. __not_in_boost_geometry_hpp__ [heading Example] -[boost_polygon] -[boost_polygon_output] +[boost_polygon_ring] +[boost_polygon_ring_output] [endsect] diff --git a/doc/reference/geometries/adapted/boost_polygon/polygon_with_holes_data.qbk b/doc/reference/geometries/adapted/boost_polygon/polygon_with_holes_data.qbk index 52655a6f2..f9080cf20 100644 --- a/doc/reference/geometries/adapted/boost_polygon/polygon_with_holes_data.qbk +++ b/doc/reference/geometries/adapted/boost_polygon/polygon_with_holes_data.qbk @@ -1,9 +1,10 @@ [/============================================================================ 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-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2008-2014 Bruno Lalande, Paris, France. + Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -18,7 +19,7 @@ is adapted to the Boost.Geometry Polygon Concept. [heading Description] Boost.Polygon's points (as well as polygons) can be used by Boost.Geometry. The -two libraries can therefore be used together. Using a boost::polygon::point_data<...>, +two libraries can therefore be used together. Using a boost::polygon::polygon_with_holes_data<...>, algorithms from both Boost.Polygon and Boost.Geometry can be called. [heading Model of] @@ -30,8 +31,8 @@ algorithms from both Boost.Polygon and Boost.Geometry can be called. __not_in_boost_geometry_hpp__ [heading Example] -[boost_polygon] -[boost_polygon_output] +[boost_polygon_polygon] +[boost_polygon_polygon_output] [endsect] diff --git a/doc/reference/geometries/adapted/boost_polygon/rectangle_data.qbk b/doc/reference/geometries/adapted/boost_polygon/rectangle_data.qbk index 48b80416d..75b38e6b8 100644 --- a/doc/reference/geometries/adapted/boost_polygon/rectangle_data.qbk +++ b/doc/reference/geometries/adapted/boost_polygon/rectangle_data.qbk @@ -1,9 +1,10 @@ [/============================================================================ 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-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2008-2014 Bruno Lalande, Paris, France. + Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -17,7 +18,7 @@ Boost.Polygon's rectangle type (boost::polygon::rectangle_data) is adapted to th [heading Description] Boost.Polygon's points (as well as polygons) can be used by Boost.Geometry. The -two libraries can therefore be used together. Using a boost::polygon::point_data<...>, +two libraries can therefore be used together. Using a boost::polygon::rectangle_data<...>, algorithms from both Boost.Polygon and Boost.Geometry can be called. [heading Model of] @@ -29,8 +30,8 @@ algorithms from both Boost.Polygon and Boost.Geometry can be called. __not_in_boost_geometry_hpp__ [heading Example] -[boost_polygon] -[boost_polygon_output] +[boost_polygon_box] +[boost_polygon_box_output] [endsect] diff --git a/doc/src/examples/geometries/adapted/boost_polygon_box.cpp b/doc/src/examples/geometries/adapted/boost_polygon_box.cpp new file mode 100644 index 000000000..dd465513c --- /dev/null +++ b/doc/src/examples/geometries/adapted/boost_polygon_box.cpp @@ -0,0 +1,42 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[boost_polygon_box +//`Shows how to use Boost.Polygon rectangle_data within Boost.Geometry + +#include +#include +#include + +int main() +{ + typedef boost::polygon::rectangle_data rect; + + rect b = boost::polygon::construct(1, 2, 3, 4); + + std::cout << "Area (using Boost.Geometry): " + << boost::geometry::area(b) << std::endl; + std::cout << "Area (using Boost.Polygon): " + << boost::polygon::area(b) << std::endl; + + return 0; +} + +//] + +//[boost_polygon_box_output +/*` +Output: +[pre +Area (using Boost.Geometry): 4 +Area (using Boost.Polygon): 4 +] +*/ +//] diff --git a/doc/src/examples/geometries/adapted/boost_polygon.cpp b/doc/src/examples/geometries/adapted/boost_polygon_point.cpp similarity index 83% rename from doc/src/examples/geometries/adapted/boost_polygon.cpp rename to doc/src/examples/geometries/adapted/boost_polygon_point.cpp index b56a13d45..0f71f3f79 100644 --- a/doc/src/examples/geometries/adapted/boost_polygon.cpp +++ b/doc/src/examples/geometries/adapted/boost_polygon_point.cpp @@ -2,13 +2,14 @@ // QuickBook Example // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -//[boost_polygon -//`Shows how to use Boost.Polygon points within Boost.Geometry +//[boost_polygon_point +//`Shows how to use Boost.Polygon point_data within Boost.Geometry #include #include @@ -27,7 +28,7 @@ int main() //] -//[boost_polygon_output +//[boost_polygon_point_output /*` Output: [pre diff --git a/doc/src/examples/geometries/adapted/boost_polygon_polygon.cpp b/doc/src/examples/geometries/adapted/boost_polygon_polygon.cpp new file mode 100644 index 000000000..5444d832f --- /dev/null +++ b/doc/src/examples/geometries/adapted/boost_polygon_polygon.cpp @@ -0,0 +1,64 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[boost_polygon_polygon +//`Shows how to use Boost.Polygon polygon_with_holes_data within Boost.Geometry + +#include +#include +#include + +int main() +{ + typedef boost::polygon::polygon_with_holes_data polygon; + typedef boost::polygon::polygon_traits::point_type point; + typedef boost::polygon::polygon_with_holes_traits::hole_type hole; + + point pts[5] = { + boost::polygon::construct(0, 0), + boost::polygon::construct(0, 10), + boost::polygon::construct(10, 10), + boost::polygon::construct(10, 0), + boost::polygon::construct(0, 0) + }; + point hole_pts[5] = { + boost::polygon::construct(1, 1), + boost::polygon::construct(9, 1), + boost::polygon::construct(9, 9), + boost::polygon::construct(1, 9), + boost::polygon::construct(1, 1) + }; + + hole hls[1]; + boost::polygon::set_points(hls[0], hole_pts, hole_pts+5); + + polygon poly; + boost::polygon::set_points(poly, pts, pts+5); + boost::polygon::set_holes(poly, hls, hls+1); + + std::cout << "Area (using Boost.Geometry): " + << boost::geometry::area(poly) << std::endl; + std::cout << "Area (using Boost.Polygon): " + << boost::polygon::area(poly) << std::endl; + + return 0; +} + +//] + +//[boost_polygon_polygon_output +/*` +Output: +[pre +Area (using Boost.Geometry): 36 +Area (using Boost.Polygon): 36 +] +*/ +//] diff --git a/doc/src/examples/geometries/adapted/boost_polygon_ring.cpp b/doc/src/examples/geometries/adapted/boost_polygon_ring.cpp new file mode 100644 index 000000000..e0cfd6dcb --- /dev/null +++ b/doc/src/examples/geometries/adapted/boost_polygon_ring.cpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[boost_polygon_ring +//`Shows how to use Boost.Polygon polygon_data within Boost.Geometry + +#include +#include +#include + +int main() +{ + typedef boost::polygon::polygon_data polygon; + typedef boost::polygon::polygon_traits::point_type point; + + point pts[5] = { + boost::polygon::construct(0, 0), + boost::polygon::construct(0, 10), + boost::polygon::construct(10, 10), + boost::polygon::construct(10, 0), + boost::polygon::construct(0, 0) + }; + + polygon poly; + boost::polygon::set_points(poly, pts, pts+5); + + std::cout << "Area (using Boost.Geometry): " + << boost::geometry::area(poly) << std::endl; + std::cout << "Area (using Boost.Polygon): " + << boost::polygon::area(poly) << std::endl; + + return 0; +} + +//] + +//[boost_polygon_ring_output +/*` +Output: +[pre +Area (using Boost.Geometry): 100 +Area (using Boost.Polygon): 100 +] +*/ +//] From e6345b24410bbfee82272d6bf72502cfe845f5c2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 15 Jul 2014 00:46:34 +0200 Subject: [PATCH 09/37] [doc] Add Boost.Polygon examples to Jamfile --- doc/src/examples/geometries/adapted/Jamfile.v2 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/src/examples/geometries/adapted/Jamfile.v2 b/doc/src/examples/geometries/adapted/Jamfile.v2 index 2fd3aefaa..dd40a2494 100644 --- a/doc/src/examples/geometries/adapted/Jamfile.v2 +++ b/doc/src/examples/geometries/adapted/Jamfile.v2 @@ -16,7 +16,10 @@ project boost-geometry-doc-src-example-geometries-adapted exe c_array : c_array.cpp ; exe boost_array : boost_array.cpp ; exe boost_fusion : boost_fusion.cpp ; -exe boost_polygon : boost_polygon.cpp ; +exe boost_polygon_box : boost_polygon_box.cpp ; +exe boost_polygon_point : boost_polygon_point.cpp ; +exe boost_polygon_polygon : boost_polygon_polygon.cpp ; +exe boost_polygon_ring : boost_polygon_ring.cpp ; exe boost_tuple : boost_tuple.cpp ; build-project boost_range ; From 57854c276597b5dfc1f752da7d1290eee15b97a2 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 10:45:14 +0200 Subject: [PATCH 10/37] [buffer] optionally simplify using ax strategy --- .../detail/buffer/buffer_inserter.hpp | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index d67f09888..018dd8f0f 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -29,6 +29,10 @@ #include +#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX) +#include +#endif + namespace boost { namespace geometry { @@ -51,10 +55,41 @@ inline void simplify_input(Range const& range, // sensitive to small scale input features, however the result will // look better. // It also get rid of duplicate points +#if ! defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX) geometry::simplify(range, simplified, distance.simplify_distance()); - //simplified = range; +#else + + typedef typename boost::range_value::type point_type; + typedef strategy::distance::detail::projected_point_ax<> ax_type; + typedef typename strategy::distance::services::return_type + < + strategy::distance::detail::projected_point_ax<>, + point_type, + point_type + >::type return_type; + + typedef strategy::distance::detail::projected_point_ax_less + < + return_type + > comparator_type; + + typedef strategy::simplify::detail::douglas_peucker + < + point_type, + strategy::distance::detail::projected_point_ax<>, + comparator_type + > dp_ax; + + return_type max_distance(distance.simplify_distance() * 2.0, + distance.simplify_distance()); + comparator_type comparator(max_distance); + dp_ax strategy(comparator); + + geometry::simplify(range, simplified, max_distance, strategy); +#endif } + template struct buffer_range { From 58fa94c8973ee92894aee8998f338fd46f96ffcb Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 10:48:27 +0200 Subject: [PATCH 11/37] [buffer][test] use Aimes to test simplify with ax strategy, optionally count number of self-ips --- .../buffer/aimes_linestring_buffer.cpp | 9 ++- test/algorithms/buffer/test_buffer.hpp | 66 +++++++++++++++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/test/algorithms/buffer/aimes_linestring_buffer.cpp b/test/algorithms/buffer/aimes_linestring_buffer.cpp index ff930e7df..18a44e6ae 100644 --- a/test/algorithms/buffer/aimes_linestring_buffer.cpp +++ b/test/algorithms/buffer/aimes_linestring_buffer.cpp @@ -7,6 +7,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#define BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX + #include #include @@ -464,6 +466,8 @@ void test_aimes() #endif // Aimes tested originally with 0.000018 degrees (around 2 m) + std::size_t self_ip_count = 0; + int expectation_index = 0; for (int width = 18; width <= 36; width += 18, expectation_index += 2) { @@ -485,17 +489,18 @@ void test_aimes() name.str(), testcases[i], expectations[i][expectation_index], aimes_width, aimes_width, - false + self_ip_count, 0.00001 ); test_one ( name.str(), testcases[i], expectations[i][expectation_index + 1], aimes_width, aimes_width, - false + self_ip_count, 0.00001 ); } } + std::cout << "Total self-ips: " << self_ip_count << std::endl; } diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index b65fbc68e..ad17c1013 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -32,6 +32,7 @@ #include #include +#include #include @@ -46,7 +47,6 @@ #if defined(TEST_WITH_SVG) #include -#include template void post_map(Geometry const& geometry, Mapper& mapper, RescalePolicy const& rescale_policy) @@ -293,6 +293,29 @@ template<> struct EndTestProperties static std::string name() { return ""; } }; + + +template +std::size_t count_self_ips(Geometry const& geometry, RescalePolicy const& rescale_policy) +{ + typedef typename bg::point_type::type point_type; + typedef bg::detail::overlay::turn_info + < + point_type, + typename bg::segment_ratio_type::type + > turn_info; + + std::vector turns; + + bg::detail::self_get_turn_points::no_interrupt_policy policy; + bg::self_turns + < + bg::detail::overlay::assign_null_policy + >(geometry, rescale_policy, turns, policy); + + return turns.size(); +} + template < typename GeometryOut, @@ -303,7 +326,8 @@ template void test_buffer(std::string const& caseid, Geometry const& geometry, bool check_self_intersections, double expected_area, double distance_left, double distance_right, - double tolerance) + double tolerance, + std::size_t* self_ip_count) { namespace bg = boost::geometry; @@ -461,6 +485,17 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, post_map(polygon, mapper, rescale_policy); } #endif + + if (self_ip_count != NULL) + { + std::size_t count = 0; + BOOST_FOREACH(GeometryOut const& polygon, buffered) + { + count += count_self_ips(polygon, rescale_policy); + } + + *self_ip_count += count; + } } @@ -501,9 +536,32 @@ void test_one(std::string const& caseid, std::string const& wkt, test_buffer (caseid, g, check_self_intersections, expected_area, - distance_left, distance_right, tolerance); + distance_left, distance_right, tolerance, NULL); +} + +// Version (currently for the Aimes test) counting self-ip's instead of checking +template +< + typename Geometry, + template class JoinStrategy, + template class EndStrategy, + typename GeometryOut +> +void test_one(std::string const& caseid, std::string const& wkt, + double expected_area, + double distance_left, double distance_right, + std::size_t& self_ip_count, + double tolerance = 0.01) +{ + namespace bg = boost::geometry; + Geometry g; + bg::read_wkt(wkt, g); + bg::correct(g); + + test_buffer + (caseid, g, false, expected_area, + distance_left, distance_right, tolerance, &self_ip_count); } - #endif From 0f027b5ff93efd362f327a5ae5e361757a487a2f Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 11:31:35 +0200 Subject: [PATCH 12/37] [buffer] add buffer_circle strategy for points and multi-points, and pass it all the way through the dispatches --- .../detail/buffer/buffer_inserter.hpp | 148 +++++++----------- .../strategies/cartesian/buffer_circle.hpp | 85 ++++++++++ test/algorithms/buffer/test_buffer.hpp | 7 + 3 files changed, 146 insertions(+), 94 deletions(-) create mode 100644 include/boost/geometry/strategies/cartesian/buffer_circle.hpp diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 018dd8f0f..4d5fa2d85 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -300,85 +300,6 @@ struct buffer_range } }; - - -template -< - typename Point, - typename RingOutput -> -struct buffer_point -{ - typedef typename point_type::type output_point_type; - typedef typename coordinate_type::type coordinate_type; - - typedef typename geometry::select_most_precise - < - typename geometry::select_most_precise - < - typename geometry::coordinate_type::type, - typename geometry::coordinate_type::type - >::type, - double - >::type promoted_type; - - - template - static inline void generate_points(Point const& point, - promoted_type const& buffer_distance, - RangeOut& range_out) - { - - promoted_type two = 2.0; - promoted_type two_pi = two * geometry::math::pi(); - int point_buffer_count = 88; // 88 gives now fixed problem (collinear opposite / robustness. TODO: make this value flexible - - promoted_type diff = two_pi / promoted_type(point_buffer_count); - promoted_type a = 0; - - output_point_type first; - for (int i = 0; i < point_buffer_count; i++, a -= diff) - { - output_point_type p; - set<0>(p, get<0>(point) + buffer_distance * cos(a)); - set<1>(p, get<1>(point) + buffer_distance * sin(a)); - range_out.push_back(p); - if (i == 0) - { - first = p; - } - } - - // Close it: - range_out.push_back(first); - } - - - template - < - typename Collection, - typename DistanceStrategy, - typename JoinStrategy, - typename EndStrategy, - typename RobustPolicy - > - static inline void generate_circle(Point const& point, - Collection& collection, - DistanceStrategy const& distance, - JoinStrategy const& , - EndStrategy const& , - RobustPolicy const& ) - { - std::vector range_out; - - generate_points(point, - distance.apply(point, point, strategy::buffer::buffer_side_left), - range_out); - - collection.add_piece(strategy::buffer::buffered_circle, range_out, false); - } -}; - template < typename Multi, @@ -394,14 +315,16 @@ struct buffer_multi typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline void apply(Multi const& multi, Collection& collection, - DistanceStrategy const& distance, + DistanceStrategy const& distance_strategy, SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy) { for (typename boost::range_iterator::type @@ -409,7 +332,10 @@ struct buffer_multi it != boost::end(multi); ++it) { - Policy::apply(*it, collection, distance, side_strategy, join_strategy, end_strategy, robust_policy); + Policy::apply(*it, collection, + distance_strategy, side_strategy, + join_strategy, end_strategy, circle_strategy, + robust_policy); } } }; @@ -446,7 +372,6 @@ template typename RingOutput > struct buffer_inserter - : public detail::buffer::buffer_point { template < @@ -455,18 +380,23 @@ struct buffer_inserter typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline void apply(Point const& point, Collection& collection, - DistanceStrategy const& distance, + DistanceStrategy const& distance_strategy, SideStrategy const& , - JoinStrategy const& join_strategy, - EndStrategy const& end_strategy, - RobustPolicy const& robust_policy) + JoinStrategy const& , + EndStrategy const& , + CircleStrategy const& circle_strategy, + RobustPolicy const& ) { + typedef typename point_type::type output_point_type; + collection.start_new_ring(); - typedef detail::buffer::buffer_point base; - base::generate_circle(point, collection, distance, join_strategy, end_strategy, robust_policy); + std::vector range_out; + circle_strategy.apply(point, distance_strategy, range_out); + collection.add_piece(strategy::buffer::buffered_circle, range_out, false); collection.finish_ring(); } }; @@ -529,6 +459,7 @@ struct buffer_inserter typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline void apply(RingInput const& ring, @@ -537,6 +468,7 @@ struct buffer_inserter SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& , RobustPolicy const& robust_policy) { if (boost::size(ring) > 3) @@ -640,6 +572,7 @@ struct buffer_inserter typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline void apply(Linestring const& linestring, Collection& collection, @@ -647,6 +580,7 @@ struct buffer_inserter SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy) { if (boost::size(linestring) > 1) @@ -667,6 +601,10 @@ struct buffer_inserter first_p1); collection.finish_ring(); } + else + { + // Use circle_strategy to buffer degenerated circle + } } }; @@ -693,6 +631,7 @@ private: typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline @@ -702,12 +641,15 @@ private: SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy) { for (Iterator it = begin; it != end; ++it) { collection.start_new_ring(); - policy::apply(*it, collection, distance, side_strategy, join_strategy, end_strategy, robust_policy); + policy::apply(*it, collection, distance, side_strategy, + join_strategy, end_strategy, circle_strategy, + robust_policy); collection.finish_ring(); } } @@ -720,6 +662,7 @@ private: typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline @@ -729,10 +672,13 @@ private: SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy) { iterate(boost::begin(interior_rings), boost::end(interior_rings), - collection, distance, side_strategy, join_strategy, end_strategy, robust_policy); + collection, distance, side_strategy, + join_strategy, end_strategy, circle_strategy, + robust_policy); } public: @@ -743,6 +689,7 @@ public: typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > static inline void apply(PolygonInput const& polygon, @@ -751,17 +698,22 @@ public: SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy) { { collection.start_new_ring(); policy::apply(exterior_ring(polygon), collection, - distance, side_strategy, join_strategy, end_strategy, robust_policy); + distance, side_strategy, + join_strategy, end_strategy, circle_strategy, + robust_policy); collection.finish_ring(); } apply_interior_rings(interior_rings(polygon), - collection, distance, side_strategy, join_strategy, end_strategy, robust_policy); + collection, distance, side_strategy, + join_strategy, end_strategy, circle_strategy, + robust_policy); } }; @@ -801,6 +753,7 @@ template typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy, typename VisitPiecesPolicy > @@ -809,6 +762,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy, VisitPiecesPolicy& visit_pieces_policy ) @@ -830,7 +784,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator >::type, GeometryInput, GeometryOutput - >::apply(geometry_input, collection, distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy); + >::apply(geometry_input, collection, + distance_strategy, side_strategy, join_strategy, + end_strategy, circle_strategy, + robust_policy); collection.get_turns(geometry_input, distance_strategy); @@ -871,6 +828,7 @@ template typename SideStrategy, typename JoinStrategy, typename EndStrategy, + typename CircleStrategy, typename RobustPolicy > inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, @@ -878,11 +836,13 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy, RobustPolicy const& robust_policy) { detail::buffer::visit_pieces_default_policy visitor; buffer_inserter(geometry_input, out, - distance_strategy, side_strategy, join_strategy, end_strategy, + distance_strategy, side_strategy, join_strategy, + end_strategy, circle_strategy, robust_policy, visitor); } diff --git a/include/boost/geometry/strategies/cartesian/buffer_circle.hpp b/include/boost/geometry/strategies/cartesian/buffer_circle.hpp new file mode 100644 index 000000000..e5a12dd1c --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/buffer_circle.hpp @@ -0,0 +1,85 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_CIRCLE_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_CIRCLE_HPP + +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace buffer +{ + +// Strategy to create a buffer around a point using a specified amount of points +class buffer_circle +{ +public : + explicit buffer_circle(std::size_t count) + : m_count(count) + {} + + template + < + typename Point, + typename OutputRange, + typename DistanceStrategy + > + inline void apply(Point const& point, + DistanceStrategy const& distance_strategy, + OutputRange& output_range) const + { + typedef typename boost::range_value::type output_point_type; + + typedef typename geometry::select_most_precise + < + typename geometry::select_most_precise + < + typename geometry::coordinate_type::type, + typename geometry::coordinate_type::type + >::type, + double + >::type promoted_type; + + promoted_type const buffer_distance = distance_strategy.apply(point, point, + strategy::buffer::buffer_side_left); + + promoted_type const two = 2.0; + promoted_type const two_pi = two * geometry::math::pi(); + + promoted_type const diff = two_pi / promoted_type(m_count); + promoted_type a = 0; + + for (std::size_t i = 0; i < m_count; i++, a -= diff) + { + output_point_type p; + set<0>(p, get<0>(point) + buffer_distance * cos(a)); + set<1>(p, get<1>(point) + buffer_distance * sin(a)); + output_range.push_back(p); + } + + // Close it: + output_range.push_back(output_range.front()); + } + +private : + std::size_t m_count; +}; + + +}} // namespace strategy::buffer + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_CIRCLE_HPP diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index ad17c1013..ab897993e 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -38,6 +38,7 @@ #include #include +#include @@ -416,6 +417,11 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, bg::strategy::buffer::buffer_side side_strategy; + // For (multi)points a buffer with 88 points is used for testing. + // More points will give a more precise result - expected area should be + // adapted then + bg::strategy::buffer::buffer_circle circle_strategy(88); + typedef typename bg::point_type::type point_type; typedef typename bg::rescale_policy_type::type rescale_policy_type; @@ -430,6 +436,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, side_strategy, join_strategy, end_strategy, + circle_strategy, rescale_policy, visitor); From 2bdca94e52b2da21debee76f76cc565e589a09e5 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 11:35:29 +0200 Subject: [PATCH 13/37] [buffer] changed comments --- .../geometry/algorithms/detail/buffer/buffer_inserter.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 4d5fa2d85..b34650c64 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -159,7 +159,7 @@ struct buffer_range } // The corner is convex, we create a join - // TODO - try to avoid a separate vector, add the piece directly + // TODO (future) - avoid a separate vector, add the piece directly std::vector range_out; join_strategy.apply(intersection_point, previous_input, prev_perp2, perp1, @@ -449,7 +449,6 @@ struct buffer_inserter robust_policy); // Buffer is closed automatically by last closing corner - // (OPEN IT FOR OPEN POLYGONS - TODO) } template From fc0819b8ae911c1e3a0ec535f4f47501f50dd2be Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 11:36:06 +0200 Subject: [PATCH 14/37] [buffer] removed non-used phase parameter --- .../detail/buffer/buffer_inserter.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index b34650c64..a323cd602 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -107,7 +107,6 @@ struct buffer_range > static inline void add_join(Collection& collection, - int phase, Point const& penultimate_input, Point const& previous_input, output_point_type const& prev_perp1, @@ -145,7 +144,6 @@ struct buffer_range previous_input, prev_perp2, perp1); return; case strategy::buffer::join_spike : - //if (phase == 0) avoid duplicate joins at spikes? this still causes other issues { // For linestrings, only add spike at one side to avoid // duplicates @@ -203,7 +201,6 @@ struct buffer_range typename RobustPolicy > static inline void iterate(Collection& collection, - int phase, // 0/1 for left/right of rings. For polygons: 0 Iterator begin, Iterator end, strategy::buffer::buffer_side_selector side, DistanceStrategy const& distance_strategy, @@ -270,7 +267,7 @@ struct buffer_range if (! first) { - add_join(collection, phase, + add_join(collection, penultimate_point, *prev, last_p1, last_p2, *it, generated_side.front(), generated_side.back(), @@ -434,13 +431,13 @@ struct buffer_inserter typedef detail::buffer::buffer_range buffer_range; - buffer_range::iterate(collection, 0, begin, end, + buffer_range::iterate(collection, begin, end, side, distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, first_p1, first_p2, last_p1, last_p2); // Generate closing join - buffer_range::add_join(collection, 0, + buffer_range::add_join(collection, *(end - 2), *(end - 1), last_p1, last_p2, *(begin + 1), first_p1, first_p2, @@ -530,7 +527,7 @@ struct buffer_inserter typename EndStrategy, typename RobustPolicy > - static inline void iterate(Collection& collection, int phase, + static inline void iterate(Collection& collection, Iterator begin, Iterator end, strategy::buffer::buffer_side_selector side, DistanceStrategy const& distance_strategy, @@ -555,7 +552,7 @@ struct buffer_inserter output_point_type first_p2, last_p1, last_p2; detail::buffer::buffer_range::iterate(collection, - phase, begin, end, side, + begin, end, side, distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, first_p1, first_p2, last_p1, last_p2); @@ -589,12 +586,12 @@ struct buffer_inserter collection.start_new_ring(); output_point_type first_p1; - iterate(collection, 0, boost::begin(simplified), boost::end(simplified), + iterate(collection, boost::begin(simplified), boost::end(simplified), strategy::buffer::buffer_side_left, distance, side_strategy, join_strategy, end_strategy, robust_policy, first_p1); - iterate(collection, 1, boost::rbegin(simplified), boost::rend(simplified), + iterate(collection, boost::rbegin(simplified), boost::rend(simplified), strategy::buffer::buffer_side_right, distance, side_strategy, join_strategy, end_strategy, robust_policy, first_p1); From 4966ff5359814bb0a5cbea186d88836162aa064f Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 11:39:13 +0200 Subject: [PATCH 15/37] [buffer] removed many unnecessary includes from buffer_side --- .../geometry/strategies/cartesian/buffer_side.hpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/buffer_side.hpp b/include/boost/geometry/strategies/cartesian/buffer_side.hpp index abae27e6f..d84b24918 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_side.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_side.hpp @@ -8,24 +8,16 @@ #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_HPP #include -#include -#include - -#include - -#include -#include +#include +#include +#include #include #include #include -#include -#include -#include -#include namespace boost { namespace geometry From bac1ac66af5defd631d262435d42b3e92dd43263 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 15:11:55 +0200 Subject: [PATCH 16/37] [buffer] avoid having point types in strategies which can be deferred --- .../strategies/agnostic/buffer_end_skip.hpp | 15 ++--- .../strategies/cartesian/buffer_end_flat.hpp | 36 ++++------- .../strategies/cartesian/buffer_end_round.hpp | 63 +++++++++---------- .../cartesian/buffer_join_miter.hpp | 48 ++++++++------ .../cartesian/buffer_join_round.hpp | 60 ++++++++---------- .../cartesian/buffer_join_round_by_divide.hpp | 60 ++++++++---------- test/algorithms/buffer/test_buffer.hpp | 28 +++------ 7 files changed, 140 insertions(+), 170 deletions(-) diff --git a/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp b/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp index 798980194..fd2ee70c2 100644 --- a/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp +++ b/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp @@ -20,20 +20,15 @@ namespace strategy { namespace buffer { -template -< - typename PointIn, - typename PointOut -> class end_skip { public : - template - inline void apply(PointIn const& , - PointIn const& , - PointIn const& , - PointIn const& , + template + inline void apply(Point const& , + Point const& , + Point const& , + Point const& , buffer_side_selector , DistanceStrategy const& , RangeOut& ) const diff --git a/include/boost/geometry/strategies/cartesian/buffer_end_flat.hpp b/include/boost/geometry/strategies/cartesian/buffer_end_flat.hpp index 871902c5f..88b2938c9 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_end_flat.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_end_flat.hpp @@ -27,38 +27,28 @@ namespace strategy { namespace buffer { -template -< - typename PointIn, - typename PointOut -> class end_flat { - typedef typename strategy::side::services::default_strategy::type>::type side; - typedef typename coordinate_type::type coordinate_type; - - typedef typename geometry::select_most_precise - < - typename geometry::select_most_precise - < - typename geometry::coordinate_type::type, - typename geometry::coordinate_type::type - >::type, - double - >::type promoted_type; - public : - template - inline void apply(PointIn const& penultimate_point, - PointIn const& perp_left_point, - PointIn const& ultimate_point, - PointIn const& perp_right_point, + template + inline void apply(Point const& penultimate_point, + Point const& perp_left_point, + Point const& ultimate_point, + Point const& perp_right_point, buffer_side_selector side, DistanceStrategy const& distance, RangeOut& range_out) const { + typedef typename coordinate_type::type coordinate_type; + + typedef typename geometry::select_most_precise + < + coordinate_type, + double + >::type promoted_type; + promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left); promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right); diff --git a/include/boost/geometry/strategies/cartesian/buffer_end_round.hpp b/include/boost/geometry/strategies/cartesian/buffer_end_round.hpp index 76f9411ab..bfc04c3d1 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_end_round.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_end_round.hpp @@ -11,13 +11,13 @@ #include #include -#include #include #include #include +#include namespace boost { namespace geometry { @@ -27,40 +27,29 @@ namespace strategy { namespace buffer { -template -< - typename PointIn, - typename PointOut -> class end_round { - typedef typename strategy::side::services::default_strategy::type>::type side; - typedef typename coordinate_type::type coordinate_type; - - typedef typename geometry::select_most_precise - < - typename geometry::select_most_precise - < - typename geometry::coordinate_type::type, - typename geometry::coordinate_type::type - >::type, - double - >::type promoted_type; - +private : int m_steps_per_circle; - template - inline void generate_points(PointIn const& point, - promoted_type alpha, - promoted_type const& buffer_distance, + template + < + typename Point, + typename PromotedType, + typename DistanceType, + typename RangeOut + > + inline void generate_points(Point const& point, + PromotedType alpha, // by value + DistanceType const& buffer_distance, RangeOut& range_out) const { - promoted_type const two = 2.0; - promoted_type const two_pi = two * geometry::math::pi(); + PromotedType const two = 2.0; + PromotedType const two_pi = two * geometry::math::pi(); int point_buffer_count = m_steps_per_circle; - promoted_type const diff = two_pi / promoted_type(point_buffer_count); + PromotedType const diff = two_pi / PromotedType(point_buffer_count); // For half circle: point_buffer_count /= 2; @@ -89,16 +78,24 @@ public : : m_steps_per_circle(steps_per_circle) {} - template - inline void apply(PointIn const& penultimate_point, - PointIn const& perp_left_point, - PointIn const& ultimate_point, - PointIn const& , + template + inline void apply(Point const& penultimate_point, + Point const& perp_left_point, + Point const& ultimate_point, + Point const& , buffer_side_selector side, DistanceStrategy const& distance, RangeOut& range_out) const { - promoted_type alpha = calculate_angle(perp_left_point, ultimate_point); + typedef typename coordinate_type::type coordinate_type; + + typedef typename geometry::select_most_precise + < + coordinate_type, + double + >::type promoted_type; + + promoted_type const alpha = calculate_angle(perp_left_point, ultimate_point); promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left); promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right); @@ -116,7 +113,7 @@ public : dist_half_diff = -dist_half_diff; } - PointIn shifted_point; + Point shifted_point; set<0>(shifted_point, get<0>(ultimate_point) + dist_half_diff * cos(alpha)); set<1>(shifted_point, get<1>(ultimate_point) + dist_half_diff * sin(alpha)); generate_points(shifted_point, alpha, (dist_left + dist_right) / two, range_out); diff --git a/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp b/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp index c3989b887..2e81f6321 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp @@ -9,8 +9,9 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP +#include #include -#include +#include #include #include @@ -25,42 +26,51 @@ namespace strategy { namespace buffer // TODO: condider merging/baseclassing join strategies to avoid duplicate code -template -< - typename PointIn, - typename PointOut -> struct join_miter { - typedef typename coordinate_type::type coordinate_type; // Constructor compatible with other join strategies: inline join_miter(int = 0) {} - template - inline bool apply(PointIn const& ip, PointIn const& vertex, - PointIn const& perp1, PointIn const& perp2, - coordinate_type const& buffer_distance, + template + inline bool apply(Point const& ip, Point const& vertex, + Point const& perp1, Point const& perp2, + DistanceType const& buffer_distance, RangeOut& range_out) const { - PointIn p = ip; + geometry::equal_to equals; + if (equals(ip, vertex)) + { + return false; + } + + typedef typename coordinate_type::type coordinate_type; + typedef typename geometry::select_most_precise + < + coordinate_type, + double + >::type promoted_type; + + Point p = ip; // Normalize it and give it X*dist. - coordinate_type dx = get<0>(ip) - get<0>(vertex); - coordinate_type dy = get<1>(ip) - get<1>(vertex); + coordinate_type const dx = get<0>(ip) - get<0>(vertex); + coordinate_type const dy = get<1>(ip) - get<1>(vertex); - coordinate_type length = geometry::math::sqrt(dx * dx + dy * dy); + promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy); + + BOOST_ASSERT(length != 0.0); // because ip/vertex are not equal // TODO: make max-mitre-limit flexible - const coordinate_type ten = 10.0; - const coordinate_type zero_seven = 1.7; + promoted_type const ten = 10.0; + promoted_type const zero_seven = 0.7; - const coordinate_type max = ten * geometry::math::abs(buffer_distance); + promoted_type const max = ten * geometry::math::abs(buffer_distance); if (length > max) { - const coordinate_type prop = zero_seven * buffer_distance / length; + promoted_type const prop = zero_seven * buffer_distance / length; set<0>(p, get<0>(vertex) + dx * prop); set<1>(p, get<1>(vertex) + dy * prop); } diff --git a/include/boost/geometry/strategies/cartesian/buffer_join_round.hpp b/include/boost/geometry/strategies/cartesian/buffer_join_round.hpp index 00d4a40a8..0e9b2b0b0 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_join_round.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_join_round.hpp @@ -9,10 +9,10 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP +#include #include #include #include -#include #include #include @@ -29,47 +29,35 @@ namespace strategy { namespace buffer { -template -< - typename PointIn, - typename PointOut -> class join_round { -private : - geometry::equal_to equals; - public : inline join_round(int steps_per_circle = 100) : m_steps_per_circle(steps_per_circle) {} - typedef typename coordinate_type::type coordinate_type; + template + inline void generate_points(Point const& vertex, + Point const& perp1, Point const& perp2, + DistanceType const& buffer_distance, + RangeOut& range_out) const + { + typedef typename coordinate_type::type coordinate_type; - typedef typename geometry::select_most_precise + typedef typename geometry::select_most_precise < - typename geometry::select_most_precise - < - typename geometry::coordinate_type::type, - typename geometry::coordinate_type::type - >::type, + coordinate_type, double >::type promoted_type; - int m_steps_per_circle; - - template - inline void generate_points(PointIn const& vertex, - PointIn const& perp1, PointIn const& perp2, - promoted_type const& buffer_distance, - RangeOut& range_out) const - { promoted_type dx1 = get<0>(perp1) - get<0>(vertex); promoted_type dy1 = get<1>(perp1) - get<1>(vertex); promoted_type dx2 = get<0>(perp2) - get<0>(vertex); promoted_type dy2 = get<1>(perp2) - get<1>(vertex); + BOOST_ASSERT(buffer_distance != 0); + dx1 /= buffer_distance; dy1 /= buffer_distance; dx2 /= buffer_distance; @@ -82,6 +70,8 @@ public : int n = boost::numeric_cast(steps * angle_diff / (two * geometry::math::pi())); +//std::cout << "n= " << n << " angle=" << geometry::math::r2d * angle_diff << std::endl; + if (n > 1000) { #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN @@ -102,19 +92,22 @@ public : for (int i = 0; i < n - 1; i++, a -= diff) { - PointIn p; + Point p; set<0>(p, get<0>(vertex) + buffer_distance * cos(a)); set<1>(p, get<1>(vertex) + buffer_distance * sin(a)); range_out.push_back(p); } } - template - inline bool apply(PointIn const& ip, PointIn const& vertex, - PointIn const& perp1, PointIn const& perp2, - coordinate_type const& buffer_distance, + template + inline bool apply(Point const& ip, Point const& vertex, + Point const& perp1, Point const& perp2, + DistanceType const& buffer_distance, RangeOut& range_out) const { + typedef typename coordinate_type::type coordinate_type; + + geometry::equal_to equals; if (equals(perp1, perp2)) { #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN @@ -127,13 +120,11 @@ public : coordinate_type vix = (get<0>(ip) - get<0>(vertex)); coordinate_type viy = (get<1>(ip) - get<1>(vertex)); - coordinate_type length_i = - geometry::math::sqrt(vix * vix + viy * viy); - + coordinate_type length_i = geometry::math::sqrt(vix * vix + viy * viy); coordinate_type const bd = geometry::math::abs(buffer_distance); coordinate_type prop = bd / length_i; - PointIn bp; + Point bp; set<0>(bp, get<0>(vertex) + vix * prop); set<1>(bp, get<1>(vertex) + viy * prop); @@ -142,6 +133,9 @@ public : range_out.push_back(perp2); return true; } + +private : + int m_steps_per_circle; }; diff --git a/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp b/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp index ee1267257..69ac079e0 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp @@ -9,10 +9,10 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP +#include #include #include #include -#include #include #include @@ -28,44 +28,23 @@ namespace strategy { namespace buffer { -template -< - typename PointIn, - typename PointOut -> class join_round_by_divide { -private : - geometry::equal_to equals; - public : inline join_round_by_divide(int max_level = 4) : m_max_level(max_level) {} - typedef typename coordinate_type::type coordinate_type; - - typedef typename geometry::select_most_precise - < - typename geometry::select_most_precise - < - typename geometry::coordinate_type::type, - typename geometry::coordinate_type::type - >::type, - double - >::type promoted_type; - - - int m_max_level; - - template - inline void mid_points(PointIn const& vertex, - PointIn const& p1, PointIn const& p2, - coordinate_type const& buffer_distance, + template + inline void mid_points(Point const& vertex, + Point const& p1, Point const& p2, + DistanceType const& buffer_distance, RangeOut& range_out, int level = 1) const { + typedef typename coordinate_type::type coordinate_type; + // Generate 'vectors' coordinate_type vp1_x = get<0>(p1) - get<0>(vertex); coordinate_type vp1_y = get<1>(p1) - get<1>(vertex); @@ -82,7 +61,7 @@ public : coordinate_type prop = buffer_distance / length2; - PointIn mid_point; + Point mid_point; set<0>(mid_point, get<0>(vertex) + v_x * prop); set<1>(mid_point, get<1>(vertex) + v_y * prop); @@ -97,12 +76,22 @@ public : } } - template - inline bool apply(PointIn const& ip, PointIn const& vertex, - PointIn const& perp1, PointIn const& perp2, - coordinate_type const& buffer_distance, + template + inline bool apply(Point const& ip, Point const& vertex, + Point const& perp1, Point const& perp2, + DistanceType const& buffer_distance, RangeOut& range_out) const { + typedef typename coordinate_type::type coordinate_type; + + typedef typename geometry::select_most_precise + < + coordinate_type, + double + >::type promoted_type; + + geometry::equal_to equals; + if (equals(perp1, perp2)) { #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN @@ -121,7 +110,7 @@ public : coordinate_type const bd = geometry::math::abs(buffer_distance); coordinate_type prop = bd / length_i; - PointIn bp; + Point bp; set<0>(bp, get<0>(vertex) + vix * prop); set<1>(bp, get<1>(vertex) + viy * prop); @@ -141,6 +130,9 @@ public : range_out.push_back(perp2); return true; } + +private : + int m_max_level; }; diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index ab897993e..8d8bd04ec 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -256,7 +256,7 @@ struct svg_visitor #endif //----------------------------------------------------------------------------- -template class JoinStrategy> +template struct JoinTestProperties { }; template<> struct JoinTestProperties @@ -276,7 +276,7 @@ template<> struct JoinTestProperties class EndStrategy> +template struct EndTestProperties { }; template<> struct EndTestProperties @@ -320,8 +320,8 @@ std::size_t count_self_ips(Geometry const& geometry, RescalePolicy const& rescal template < typename GeometryOut, - template class JoinStrategy, - template class EndStrategy, + typename JoinStrategy, + typename EndStrategy, typename Geometry > void test_buffer(std::string const& caseid, Geometry const& geometry, @@ -397,17 +397,9 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, bg::detail::buffer::visit_pieces_default_policy visitor; #endif - JoinStrategy - < - point_type, - output_point_type - > join_strategy; + JoinStrategy join_strategy; - EndStrategy - < - point_type, - output_point_type - > end_strategy; + EndStrategy end_strategy; bg::strategy::buffer::distance_asymmetric < @@ -513,8 +505,8 @@ static int counter = 0; template < typename Geometry, - template class JoinStrategy, - template class EndStrategy, + typename JoinStrategy, + typename EndStrategy, typename GeometryOut > void test_one(std::string const& caseid, std::string const& wkt, @@ -550,8 +542,8 @@ void test_one(std::string const& caseid, std::string const& wkt, template < typename Geometry, - template class JoinStrategy, - template class EndStrategy, + typename JoinStrategy, + typename EndStrategy, typename GeometryOut > void test_one(std::string const& caseid, std::string const& wkt, From 61ed918240bc3d5b989b4297402fb78e5640dd4d Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 15:12:52 +0200 Subject: [PATCH 17/37] [buffer] add side/circle strategies to include --- include/boost/geometry/strategies/strategies.hpp | 2 ++ test/algorithms/buffer/test_buffer.hpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 2183add15..2fc00d7e9 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -35,11 +35,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index 8d8bd04ec..927a3d748 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -37,8 +37,6 @@ #include #include -#include -#include From 038253e8f55dbbe30389398326e3dbc2a763ae04 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 15:21:11 +0200 Subject: [PATCH 18/37] [buffer] remove end_skip strategy --- .../strategies/agnostic/buffer_end_skip.hpp | 49 ---- .../boost/geometry/strategies/strategies.hpp | 1 - .../buffer/multi_polygon_buffer.cpp | 178 ++++++------- test/algorithms/buffer/polygon_buffer.cpp | 240 +++++++++--------- test/algorithms/buffer/test_buffer.hpp | 5 - 5 files changed, 209 insertions(+), 264 deletions(-) delete mode 100644 include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp diff --git a/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp b/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp deleted file mode 100644 index fd2ee70c2..000000000 --- a/include/boost/geometry/strategies/agnostic/buffer_end_skip.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_END_SKIP_HPP -#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_END_SKIP_HPP - -#include - - -namespace boost { namespace geometry -{ - - -namespace strategy { namespace buffer -{ - - -class end_skip -{ -public : - - template - inline void apply(Point const& , - Point const& , - Point const& , - Point const& , - buffer_side_selector , - DistanceStrategy const& , - RangeOut& ) const - { - } - - static inline piece_type get_piece_type() - { - return buffered_flat_end; - } -}; - - -}} // namespace strategy::buffer - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_END_SKIP_HPP diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 2fc00d7e9..eea784e4f 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -64,7 +64,6 @@ #include #include -#include #include #include #include diff --git a/test/algorithms/buffer/multi_polygon_buffer.cpp b/test/algorithms/buffer/multi_polygon_buffer.cpp index af9747060..eb77f30dc 100644 --- a/test/algorithms/buffer/multi_polygon_buffer.cpp +++ b/test/algorithms/buffer/multi_polygon_buffer.cpp @@ -228,112 +228,112 @@ void test_all() typedef bg::model::polygon

polygon_type; typedef bg::model::multi_polygon multi_polygon_type; - test_one("triangles424", triangles, 417.910, 4.24); - test_one("triangles425", triangles, 418.918, 4.25); - test_one("triangles426", triangles, 419.927, 4.26); - test_one("zonethru_10", zonethru, 96.0000, 1.0); + test_one("triangles424", triangles, 417.910, 4.24); + test_one("triangles425", triangles, 418.918, 4.25); + test_one("triangles426", triangles, 419.927, 4.26); + test_one("zonethru_10", zonethru, 96.0000, 1.0); - test_one("multi_simplex_05", simplex, 23.7030, 0.5); - test_one("multi_simplex_05", simplex, 24.5965, 0.5); - test_one("multi_simplex_10", simplex, 34.2532, 1.0); - test_one("multi_simplex_10", simplex, 38.1379, 1.0); - test_one("multi_simplex_20", simplex, 59.9159, 2.0); - test_one("multi_simplex_20", simplex, 77.7060, 2.0); - test_one("multi_simplex_50", simplex, 174.46, 5.0); - test_one("multi_simplex_50", simplex, 298.797, 5.0); + test_one("multi_simplex_05", simplex, 23.7030, 0.5); + test_one("multi_simplex_05", simplex, 24.5965, 0.5); + test_one("multi_simplex_10", simplex, 34.2532, 1.0); + test_one("multi_simplex_10", simplex, 38.1379, 1.0); + test_one("multi_simplex_20", simplex, 59.9159, 2.0); + test_one("multi_simplex_20", simplex, 77.7060, 2.0); + test_one("multi_simplex_50", simplex, 174.46, 5.0); + test_one("multi_simplex_50", simplex, 298.797, 5.0); // This one does not work: - // test_one("multi_simplex_50", simplex, 'd', 174.46, 5.0); + // test_one("multi_simplex_50", simplex, 'd', 174.46, 5.0); - test_one("zonethru_05", zonethru, 67.4627, 0.5); - test_one("zonethru_05", zonethru, 68.0000, 0.5); - test_one("zonethru_10", zonethru, 93.8508, 1.0); - test_one("zonethru_10", zonethru, 96.0000, 1.0); - test_one("zonethru_15", zonethru, 114.584, 1.5); - test_one("zonethru_15", zonethru, 117.000, 1.5); - test_one("wrapped_05", wrapped, 104.570, 0.5); - test_one("wrapped_05", wrapped, 105.000, 0.5); - test_one("wrapped_10", wrapped, 142.281, 1.0); - test_one("wrapped_10", wrapped, 144.000, 1.0); - test_one("wrapped_15", wrapped, 167.066, 1.5); - test_one("wrapped_15", wrapped, 169.000, 1.5); + test_one("zonethru_05", zonethru, 67.4627, 0.5); + test_one("zonethru_05", zonethru, 68.0000, 0.5); + test_one("zonethru_10", zonethru, 93.8508, 1.0); + test_one("zonethru_10", zonethru, 96.0000, 1.0); + test_one("zonethru_15", zonethru, 114.584, 1.5); + test_one("zonethru_15", zonethru, 117.000, 1.5); + test_one("wrapped_05", wrapped, 104.570, 0.5); + test_one("wrapped_05", wrapped, 105.000, 0.5); + test_one("wrapped_10", wrapped, 142.281, 1.0); + test_one("wrapped_10", wrapped, 144.000, 1.0); + test_one("wrapped_15", wrapped, 167.066, 1.5); + test_one("wrapped_15", wrapped, 169.000, 1.5); // TODO: there is still an undetected hole inside rt_a - test_one("rt_a", rt_a, 34.5381, 1.0); + test_one("rt_a", rt_a, 34.5381, 1.0); - test_one("rt_a", rt_a, 36, 1.0); - test_one("rt_b", rt_b, 31.4186, 1.0); - test_one("rt_b", rt_b, 34, 1.0); - test_one("rt_c", rt_c, 14.7093, 1.0); - test_one("rt_c", rt_c, 16, 1.0); - test_one("rt_d", rt_d, 18.8726, 0.3); - test_one("rt_d", rt_d, 19.8823, 0.3); - test_one("rt_e", rt_e, 14.1866, 0.3); - test_one("rt_e", rt_e, 15.1198, 0.3); - // This does not add anything: test_one("rt_f", rt_f, 4.28937, 0.3); + test_one("rt_a", rt_a, 36, 1.0); + test_one("rt_b", rt_b, 31.4186, 1.0); + test_one("rt_b", rt_b, 34, 1.0); + test_one("rt_c", rt_c, 14.7093, 1.0); + test_one("rt_c", rt_c, 16, 1.0); + test_one("rt_d", rt_d, 18.8726, 0.3); + test_one("rt_d", rt_d, 19.8823, 0.3); + test_one("rt_e", rt_e, 14.1866, 0.3); + test_one("rt_e", rt_e, 15.1198, 0.3); + // This does not add anything: test_one("rt_f", rt_f, 4.28937, 0.3); - test_one("rt_f", rt_f, 4.60853, 0.3); + test_one("rt_f", rt_f, 4.60853, 0.3); - test_one("rt_g1", rt_g1, 24.719, 1.0); - test_one("rt_g1", rt_g1, 30.3137, 1.0); - test_one("rt_g2", rt_g2, 18.5711, 1.0); - test_one("rt_g3", rt_g3, 16.5711, 1.0); + test_one("rt_g1", rt_g1, 24.719, 1.0); + test_one("rt_g1", rt_g1, 30.3137, 1.0); + test_one("rt_g2", rt_g2, 18.5711, 1.0); + test_one("rt_g3", rt_g3, 16.5711, 1.0); - test_one("rt_h", rt_h, 47.6012, 1.0); - test_one("rt_h", rt_h, 61.7058, 1.0); - test_one("rt_i", rt_i, 10.7528, 1.0); - test_one("rt_i", rt_i, 13.6569, 1.0); - test_one("rt_j", rt_j, 28.7309, 1.0); - test_one("rt_j", rt_j, 35.1421, 1.0); - test_one("rt_k", rt_k, 42.0092, 1.0); - test_one("rt_k", rt_k, 48.0563, 1.0); - // This does not add anything: test_one("rt_l", rt_l, 14.1074, 1.0); - test_one("rt_l", rt_l, 19.3995, 1.0); - test_one("rt_m1", rt_m1, 14.1074, 1.0); - test_one("rt_m1", rt_m1, 19.4853, 1.0); - test_one("rt_m2", rt_m2, 21.4853, 1.0); + test_one("rt_h", rt_h, 47.6012, 1.0); + test_one("rt_h", rt_h, 61.7058, 1.0); + test_one("rt_i", rt_i, 10.7528, 1.0); + test_one("rt_i", rt_i, 13.6569, 1.0); + test_one("rt_j", rt_j, 28.7309, 1.0); + test_one("rt_j", rt_j, 35.1421, 1.0); + test_one("rt_k", rt_k, 42.0092, 1.0); + test_one("rt_k", rt_k, 48.0563, 1.0); + // This does not add anything: test_one("rt_l", rt_l, 14.1074, 1.0); + test_one("rt_l", rt_l, 19.3995, 1.0); + test_one("rt_m1", rt_m1, 14.1074, 1.0); + test_one("rt_m1", rt_m1, 19.4853, 1.0); + test_one("rt_m2", rt_m2, 21.4853, 1.0); - // This does not add anything: test_one("rt_n", rt_n, 14.1074, 1.0); - test_one("rt_n", rt_n, 18.4853, 1.0); + // This does not add anything: test_one("rt_n", rt_n, 14.1074, 1.0); + test_one("rt_n", rt_n, 18.4853, 1.0); - test_one("rt_o1", rt_o1, 17.536, 1.0); - //test_one("rt_o1", rt_o1, 20.9142, 1.0); + test_one("rt_o1", rt_o1, 17.536, 1.0); + //test_one("rt_o1", rt_o1, 20.9142, 1.0); - test_one("rt_o2", rt_o2, 25.7426, 1.0); - test_one("rt_o3", rt_o3, 28.8247, 1.0); - test_one("rt_o4", rt_o4, 34.6532, 1.0); + test_one("rt_o2", rt_o2, 25.7426, 1.0); + test_one("rt_o3", rt_o3, 28.8247, 1.0); + test_one("rt_o4", rt_o4, 34.6532, 1.0); - test_one("rt_p1", rt_p1, 24.8211, 1.0); - test_one("rt_p2", rt_p2, 21.4853, 1.0); - test_one("rt_p3", rt_p3, 22.3995, 1.0); - test_one("rt_p4", rt_p4, 33.0563, 1.0); - test_one("rt_p5", rt_p5, 17, 1.0); - test_one("rt_p6", rt_p6, 18.4853, 1.0); - test_one("rt_p7", rt_p7, 26.2279, 1.0); - test_one("rt_p8", rt_p8, 29.0563, 1.0); - test_one("rt_p9", rt_p9, 26.1421, 1.0); - test_one("rt_p10", rt_p10, 23.3995, 1.0); + test_one("rt_p1", rt_p1, 24.8211, 1.0); + test_one("rt_p2", rt_p2, 21.4853, 1.0); + test_one("rt_p3", rt_p3, 22.3995, 1.0); + test_one("rt_p4", rt_p4, 33.0563, 1.0); + test_one("rt_p5", rt_p5, 17, 1.0); + test_one("rt_p6", rt_p6, 18.4853, 1.0); + test_one("rt_p7", rt_p7, 26.2279, 1.0); + test_one("rt_p8", rt_p8, 29.0563, 1.0); + test_one("rt_p9", rt_p9, 26.1421, 1.0); + test_one("rt_p10", rt_p10, 23.3995, 1.0); - test_one("rt_p11", rt_p11, 28.7426, 1.0); - test_one("rt_p12", rt_p12, 22.5711, 1.0); - test_one("rt_p13", rt_p13, 19.9142, 1.0); - test_one("rt_p14", rt_p14, 20.8284, 1.0); - test_one("rt_p15", rt_p15, 23.6569, 1.0); - test_one("rt_p16", rt_p16, 23.4853, 1.0); - test_one("rt_p17", rt_p17, 25.3137, 1.0); - test_one("rt_p18", rt_p18, 23.3137, 1.0); - test_one("rt_p19", rt_p19, 25.5637, 1.0); - test_one("rt_p20", rt_p20, 25.4853, 1.0); - test_one("rt_p21", rt_p21, 17.1716, 1.0); - test_one("rt_p22", rt_p22, 26.5711, 1.0); + test_one("rt_p11", rt_p11, 28.7426, 1.0); + test_one("rt_p12", rt_p12, 22.5711, 1.0); + test_one("rt_p13", rt_p13, 19.9142, 1.0); + test_one("rt_p14", rt_p14, 20.8284, 1.0); + test_one("rt_p15", rt_p15, 23.6569, 1.0); + test_one("rt_p16", rt_p16, 23.4853, 1.0); + test_one("rt_p17", rt_p17, 25.3137, 1.0); + test_one("rt_p18", rt_p18, 23.3137, 1.0); + test_one("rt_p19", rt_p19, 25.5637, 1.0); + test_one("rt_p20", rt_p20, 25.4853, 1.0); + test_one("rt_p21", rt_p21, 17.1716, 1.0); + test_one("rt_p22", rt_p22, 26.5711, 1.0); - test_one("rt_q1", rt_q1, 27, 1.0); - test_one("rt_q2", rt_q2, 26.4853, 1.0); + test_one("rt_q1", rt_q1, 27, 1.0); + test_one("rt_q2", rt_q2, 26.4853, 1.0); - test_one("rt_r", rt_r, 21.0761, 1.0); - test_one("rt_s1", rt_s1, 20.4853, 1.0); - test_one("rt_s2", rt_s2, 24.6495, 1.0); - test_one("rt_t", rt_t, 15.6569, 1.0); + test_one("rt_r", rt_r, 21.0761, 1.0); + test_one("rt_s1", rt_s1, 20.4853, 1.0); + test_one("rt_s2", rt_s2, 24.6495, 1.0); + test_one("rt_t", rt_t, 15.6569, 1.0); } int point_buffer_count; diff --git a/test/algorithms/buffer/polygon_buffer.cpp b/test/algorithms/buffer/polygon_buffer.cpp index 78229e594..f858c84b3 100644 --- a/test/algorithms/buffer/polygon_buffer.cpp +++ b/test/algorithms/buffer/polygon_buffer.cpp @@ -89,11 +89,11 @@ void test_all() typedef bg::model::polygon

polygon_type; - test_one("simplex", simplex, 47.9408, 1.5); - test_one("simplex", simplex, 52.8733, 1.5); + test_one("simplex", simplex, 47.9408, 1.5); + test_one("simplex", simplex, 52.8733, 1.5); - test_one("concave_simplex", concave_simplex, 14.5616, 0.5); - test_one("concave_simplex", concave_simplex, 16.3861, 0.5); + test_one("concave_simplex", concave_simplex, 14.5616, 0.5); + test_one("concave_simplex", concave_simplex, 16.3861, 0.5); test_one("spike_simplex15", spike_simplex, 50.3633, 1.5); test_one("spike_simplex15", spike_simplex, 51.5509, 1.5); @@ -109,110 +109,110 @@ void test_all() test_one("join_types", join_types, 88.2060, 1.5); - test_one("chained_box", chained_box, 83.1403, 1.0); - test_one("chained_box", chained_box, 84, 1.0); - test_one("L", letter_L, 13.7314, 0.5); - test_one("L", letter_L, 14.0, 0.5); + test_one("chained_box", chained_box, 83.1403, 1.0); + test_one("chained_box", chained_box, 84, 1.0); + test_one("L", letter_L, 13.7314, 0.5); + test_one("L", letter_L, 14.0, 0.5); - test_one("chained_box", chained_box, 84, 1.0); - test_one("chained_box", chained_box, 83.1403, 1.0); + test_one("chained_box", chained_box, 84, 1.0); + test_one("chained_box", chained_box, 83.1403, 1.0); - test_one("indentation4", indentation, 25.7741, 0.4); - test_one("indentation4", indentation, 25.5695, 0.4); - test_one("indentation5", indentation, 28.2426, 0.5); - test_one("indentation5", indentation, 27.9953, 0.5); - test_one("indentation6", indentation, 30.6712, 0.6); + test_one("indentation4", indentation, 25.7741, 0.4); + test_one("indentation4", indentation, 25.5695, 0.4); + test_one("indentation5", indentation, 28.2426, 0.5); + test_one("indentation5", indentation, 27.9953, 0.5); + test_one("indentation6", indentation, 30.6712, 0.6); // SQL Server gives 30.34479159164 - test_one("indentation6", indentation, 30.3445, 0.6); + test_one("indentation6", indentation, 30.3445, 0.6); - test_one("indentation7", indentation, 33.0958, 0.7); - test_one("indentation7", indentation, 32.6533, 0.7); + test_one("indentation7", indentation, 33.0958, 0.7); + test_one("indentation7", indentation, 32.6533, 0.7); - test_one("indentation8", indentation, 35.5943, 0.8); - test_one("indentation8", indentation, 35.0164, 0.8); - test_one("indentation12", indentation, 46.3541, 1.2); - test_one("indentation12", indentation, 45.0537, 1.2); + test_one("indentation8", indentation, 35.5943, 0.8); + test_one("indentation8", indentation, 35.0164, 0.8); + test_one("indentation12", indentation, 46.3541, 1.2); + test_one("indentation12", indentation, 45.0537, 1.2); // TODO: fix, the buffered pieces are currently counterclockwise, that should be reversed - //test_one("indentation4_neg", indentation, 6.99098413022335, -0.4); - //test_one("indentation4_neg", indentation, 7.25523322189147, -0.4); - //test_one("indentation8_neg", indentation, 1.36941992048731, -0.8); - //test_one("indentation8_neg", indentation, 1.37375487490664, -0.8); - //test_one("indentation12_neg", indentation, 0, -1.2); - //test_one("indentation12_neg", indentation, 0, -1.2); + //test_one("indentation4_neg", indentation, 6.99098413022335, -0.4); + //test_one("indentation4_neg", indentation, 7.25523322189147, -0.4); + //test_one("indentation8_neg", indentation, 1.36941992048731, -0.8); + //test_one("indentation8_neg", indentation, 1.37375487490664, -0.8); + //test_one("indentation12_neg", indentation, 0, -1.2); + //test_one("indentation12_neg", indentation, 0, -1.2); - test_one("donut_simplex6", donut_simplex, 53.648, 0.6); - test_one("donut_simplex6", donut_simplex, 52.820, 0.6); - test_one("donut_simplex8", donut_simplex, 61.132, 0.8); - test_one("donut_simplex8", donut_simplex, 59.6713, 0.8); - test_one("donut_simplex10", donut_simplex, 68.670, 1.0); - test_one("donut_simplex10", donut_simplex, 66.387, 1.0); - test_one("donut_simplex12", donut_simplex, 76.605, 1.2); - test_one("donut_simplex12", donut_simplex, 73.3179, 1.2); - test_one("donut_simplex14", donut_simplex, 84.974, 1.4); - test_one("donut_simplex14", donut_simplex, 80.500, 1.4); - test_one("donut_simplex16", donut_simplex, 93.777, 1.6); - test_one("donut_simplex16", donut_simplex, 87.933, 1.6); + test_one("donut_simplex6", donut_simplex, 53.648, 0.6); + test_one("donut_simplex6", donut_simplex, 52.820, 0.6); + test_one("donut_simplex8", donut_simplex, 61.132, 0.8); + test_one("donut_simplex8", donut_simplex, 59.6713, 0.8); + test_one("donut_simplex10", donut_simplex, 68.670, 1.0); + test_one("donut_simplex10", donut_simplex, 66.387, 1.0); + test_one("donut_simplex12", donut_simplex, 76.605, 1.2); + test_one("donut_simplex12", donut_simplex, 73.3179, 1.2); + test_one("donut_simplex14", donut_simplex, 84.974, 1.4); + test_one("donut_simplex14", donut_simplex, 80.500, 1.4); + test_one("donut_simplex16", donut_simplex, 93.777, 1.6); + test_one("donut_simplex16", donut_simplex, 87.933, 1.6); - test_one("donut_diamond1", donut_diamond, 280.0, 1.0); - test_one("donut_diamond4", donut_diamond, 529.0, 4.0); - test_one("donut_diamond5", donut_diamond, 625.0, 5.0); - test_one("donut_diamond6", donut_diamond, 729.0, 6.0); + test_one("donut_diamond1", donut_diamond, 280.0, 1.0); + test_one("donut_diamond4", donut_diamond, 529.0, 4.0); + test_one("donut_diamond5", donut_diamond, 625.0, 5.0); + test_one("donut_diamond6", donut_diamond, 729.0, 6.0); - test_one("arrow4", arrow, 28.265, 0.4); - test_one("arrow4", arrow, 27.039, 0.4); - test_one("arrow5", arrow, 31.500, 0.5); - test_one("arrow5", arrow, 29.621, 0.5); - test_one("arrow6", arrow, 34.903, 0.6); - test_one("arrow6", arrow, 32.268, 0.6); + test_one("arrow4", arrow, 28.265, 0.4); + test_one("arrow4", arrow, 27.039, 0.4); + test_one("arrow5", arrow, 31.500, 0.5); + test_one("arrow5", arrow, 29.621, 0.5); + test_one("arrow6", arrow, 34.903, 0.6); + test_one("arrow6", arrow, 32.268, 0.6); - test_one("tipped_aitch3", tipped_aitch, 55.36, 0.3); - test_one("tipped_aitch9", tipped_aitch, 77.44, 0.9); - test_one("tipped_aitch13", tipped_aitch, 92.16, 1.3); + test_one("tipped_aitch3", tipped_aitch, 55.36, 0.3); + test_one("tipped_aitch9", tipped_aitch, 77.44, 0.9); + test_one("tipped_aitch13", tipped_aitch, 92.16, 1.3); // SQL Server: 55.205415532967 76.6468846383224 90.642916957136 - test_one("tipped_aitch3", tipped_aitch, 55.2053, 0.3); - test_one("tipped_aitch9", tipped_aitch, 76.6457, 0.9); - test_one("tipped_aitch13", tipped_aitch, 90.641, 1.3); + test_one("tipped_aitch3", tipped_aitch, 55.2053, 0.3); + test_one("tipped_aitch9", tipped_aitch, 76.6457, 0.9); + test_one("tipped_aitch13", tipped_aitch, 90.641, 1.3); - test_one("snake4", snake, 64.44, 0.4); - test_one("snake5", snake, 72, 0.5); - test_one("snake6", snake, 75.44, 0.6); - test_one("snake16", snake, 114.24, 1.6); + test_one("snake4", snake, 64.44, 0.4); + test_one("snake5", snake, 72, 0.5); + test_one("snake6", snake, 75.44, 0.6); + test_one("snake16", snake, 114.24, 1.6); - test_one("funnelgate2", funnelgate, 120.982, 2); - test_one("funnelgate3", funnelgate, 13*13, 3); - test_one("funnelgate4", funnelgate, 15*15, 4); - test_one("gammagate1", gammagate, 88, 1); - test_one("fork_a1", fork_a, 88, 1); - test_one("fork_b1", fork_b, 154, 1); - test_one("fork_c1", fork_c, 152, 1); - test_one("triangle", triangle, 14.6569, 1.0); + test_one("funnelgate2", funnelgate, 120.982, 2); + test_one("funnelgate3", funnelgate, 13*13, 3); + test_one("funnelgate4", funnelgate, 15*15, 4); + test_one("gammagate1", gammagate, 88, 1); + test_one("fork_a1", fork_a, 88, 1); + test_one("fork_b1", fork_b, 154, 1); + test_one("fork_c1", fork_c, 152, 1); + test_one("triangle", triangle, 14.6569, 1.0); - test_one("gammagate2", gammagate, 130, 2); + test_one("gammagate2", gammagate, 130, 2); - test_one("flower1", flower, 67.614, 0.1); - test_one("flower20", flower, 74.894, 0.20); - test_one("flower25", flower, 78.226, 0.25); - test_one("flower30", flower, 81.492494146177947, 0.30); - test_one("flower35", flower, 84.694183819917185, 0.35); - test_one("flower40", flower, 87.8306529577, 0.40); - test_one("flower45", flower, 90.901901559536029, 0.45); - test_one("flower50", flower, 93.907929625415662, 0.50); - test_one("flower55", flower, 96.848737155342079, 0.55); - test_one("flower60", flower, 99.724324149315279, 0.60); + test_one("flower1", flower, 67.614, 0.1); + test_one("flower20", flower, 74.894, 0.20); + test_one("flower25", flower, 78.226, 0.25); + test_one("flower30", flower, 81.492494146177947, 0.30); + test_one("flower35", flower, 84.694183819917185, 0.35); + test_one("flower40", flower, 87.8306529577, 0.40); + test_one("flower45", flower, 90.901901559536029, 0.45); + test_one("flower50", flower, 93.907929625415662, 0.50); + test_one("flower55", flower, 96.848737155342079, 0.55); + test_one("flower60", flower, 99.724324149315279, 0.60); - test_one("flower10", flower, 67.486, 0.10); - test_one("flower20", flower, 74.702, 0.20); - test_one("flower25", flower, 78.071, 0.25); - test_one("flower30", flower, 81.352, 0.30); - test_one("flower35", flower, 84.547, 0.35); - test_one("flower40", flower, 87.665, 0.40); - test_one("flower45", flower, 90.709, 0.45); - test_one("flower50", flower, 93.680, 0.50); - test_one("flower55", flower, 96.580, 0.55); - test_one("flower60", flower, 99.408, 0.60); + test_one("flower10", flower, 67.486, 0.10); + test_one("flower20", flower, 74.702, 0.20); + test_one("flower25", flower, 78.071, 0.25); + test_one("flower30", flower, 81.352, 0.30); + test_one("flower35", flower, 84.547, 0.35); + test_one("flower40", flower, 87.665, 0.40); + test_one("flower45", flower, 90.709, 0.45); + test_one("flower50", flower, 93.680, 0.50); + test_one("flower55", flower, 96.580, 0.55); + test_one("flower60", flower, 99.408, 0.60); // Saw { @@ -235,8 +235,8 @@ void test_all() { std::ostringstream out; out << "saw_" << i; - test_one(out.str(), saw, expected_round[i - 1], double(i) / 2.0, -999, true, 0.1); - test_one(out.str(), saw, expected_miter[i - 1], double(i) / 2.0); + test_one(out.str(), saw, expected_round[i - 1], double(i) / 2.0, -999, true, 0.1); + test_one(out.str(), saw, expected_miter[i - 1], double(i) / 2.0); } } @@ -262,33 +262,33 @@ void test_all() { std::ostringstream out; out << "bowl_" << i; - test_one(out.str(), bowl, expected_round[i - 1], double(i) / 2.0, -999, true, 0.1); - test_one(out.str(), bowl, expected_miter[i - 1], double(i) / 2.0); + test_one(out.str(), bowl, expected_round[i - 1], double(i) / 2.0, -999, true, 0.1); + test_one(out.str(), bowl, expected_miter[i - 1], double(i) / 2.0); } } - test_one("county1", county1, 0.00114092, 0.01); - test_one("county1", county1, 0.00132859, 0.01); + test_one("county1", county1, 0.00114092, 0.01); + test_one("county1", county1, 0.00132859, 0.01); - test_one("parcel1_10", parcel1, 7571.39121246337891, 10.0); - test_one("parcel1_10", parcel1, 8207.45314788818359, 10.0); - test_one("parcel1_20", parcel1, 11648.0537185668945, 20.0); - test_one("parcel1_20", parcel1, 14184.0223083496094, 20.0); - test_one("parcel1_30", parcel1, 16350.3611068725586, 30.0); - test_one("parcel1_30", parcel1, 22046.5098342895508, 30.0); + test_one("parcel1_10", parcel1, 7571.39121246337891, 10.0); + test_one("parcel1_10", parcel1, 8207.45314788818359, 10.0); + test_one("parcel1_20", parcel1, 11648.0537185668945, 20.0); + test_one("parcel1_20", parcel1, 14184.0223083496094, 20.0); + test_one("parcel1_30", parcel1, 16350.3611068725586, 30.0); + test_one("parcel1_30", parcel1, 22046.5098342895508, 30.0); - test_one("parcel2_10", parcel2, 5000.85063171386719, 10.0); - test_one("parcel2_10", parcel2, 5091.12226867675781, 10.0); - test_one("parcel2_20", parcel2, 9049.60844421386719, 20.0); - test_one("parcel2_20", parcel2, 9410.69154357910156, 20.0); - test_one("parcel2_30", parcel2, 13726.3790588378906, 30.0); - test_one("parcel2_30", parcel2, 14535.2319564819336, 30.0); + test_one("parcel2_10", parcel2, 5000.85063171386719, 10.0); + test_one("parcel2_10", parcel2, 5091.12226867675781, 10.0); + test_one("parcel2_20", parcel2, 9049.60844421386719, 20.0); + test_one("parcel2_20", parcel2, 9410.69154357910156, 20.0); + test_one("parcel2_30", parcel2, 13726.3790588378906, 30.0); + test_one("parcel2_30", parcel2, 14535.2319564819336, 30.0); test_one("parcel3_10", parcel3, 19992.6824035644531, 10.0); - test_one("parcel3_10", parcel3, 20024.5579376220703, 10.0); - test_one("parcel3_20", parcel3, 34505.0746192932129, 20.0); - test_one("parcel3_20", parcel3, 34633.2606201171875, 20.0); - test_one("parcel3_30", parcel3, 45261.4196014404297, 30.0); - test_one("parcel3_30", parcel3, 45567.3875694274902, 30.0); + test_one("parcel3_10", parcel3, 20024.5579376220703, 10.0); + test_one("parcel3_20", parcel3, 34505.0746192932129, 20.0); + test_one("parcel3_20", parcel3, 34633.2606201171875, 20.0); + test_one("parcel3_30", parcel3, 45261.4196014404297, 30.0); + test_one("parcel3_30", parcel3, 45567.3875694274902, 30.0); test_one("parcel3_bend_10", parcel3_bend, 155.6188, 5.0); test_one("parcel3_bend_10", parcel3_bend, 458.4187, 10.0); @@ -297,15 +297,15 @@ void test_all() // Negative buffers making polygons smaller - test_one("simplex", simplex, 7.04043, -0.5); - test_one("simplex", simplex, 7.04043, -0.5); - test_one("concave_simplex", concave_simplex, 0.777987, -0.5); - test_one("concave_simplex", concave_simplex, 0.724208, -0.5); + test_one("simplex", simplex, 7.04043, -0.5); + test_one("simplex", simplex, 7.04043, -0.5); + test_one("concave_simplex", concave_simplex, 0.777987, -0.5); + test_one("concave_simplex", concave_simplex, 0.724208, -0.5); - test_one("donut_simplex3", donut_simplex, 19.7636, -0.3); - test_one("donut_simplex3", donut_simplex, 19.8861, -0.3); - test_one("donut_simplex6", donut_simplex, 12.8920, -0.6); - test_one("donut_simplex6", donut_simplex, 12.9157, -0.6); + test_one("donut_simplex3", donut_simplex, 19.7636, -0.3); + test_one("donut_simplex3", donut_simplex, 19.8861, -0.3); + test_one("donut_simplex6", donut_simplex, 12.8920, -0.6); + test_one("donut_simplex6", donut_simplex, 12.9157, -0.6); } diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index 927a3d748..085b57af9 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -287,11 +287,6 @@ template<> struct EndTestProperties static std::string name() { return "flat"; } }; -template<> struct EndTestProperties -{ - static std::string name() { return ""; } -}; - template From 97fd8f5332e5f584c3dc2b36882e3b78398dff03 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 16:58:02 +0200 Subject: [PATCH 19/37] [buffer] move buffer_inserter to namespace detail::buffer, add overload using 5 strategies --- include/boost/geometry/algorithms/buffer.hpp | 49 ++++++++++++++++--- .../detail/buffer/buffer_inserter.hpp | 7 +++ .../buffer/buffered_piece_collection.hpp | 2 + .../detail/buffer/turn_in_piece_visitor.hpp | 1 + test/algorithms/buffer/test_buffer.hpp | 3 +- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 13d48c0d5..ed861877a 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -28,6 +28,7 @@ #include #include +#include namespace boost { namespace geometry { @@ -99,11 +100,6 @@ struct buffer } }; -// Many things to do. Point is easy, other geometries require self intersections -// For point, note that it should output as a polygon (like the rest). Buffers -// of a set of geometries are often lateron combined using a "dissolve" operation. -// Two points close to each other get a combined kidney shaped buffer then. - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -174,7 +170,6 @@ struct buffer > \param geometry_out \param_geometry \param distance The distance to be used for the buffer \param chord_length (optional) The length of the chord's in the generated arcs around points or bends -\note Currently only implemented for box, the trivial case, but still useful \qbk{[include reference/algorithms/buffer.qbk]} */ @@ -198,7 +193,7 @@ inline void buffer(Input const& geometry_in, Output& geometry_out, \param geometry \param_geometry \param distance The distance to be used for the buffer \param chord_length (optional) The length of the chord's in the generated arcs - around points or bends + around points or bends (RESERVED, NOT YET USED) \return \return_calc{buffer} */ template @@ -214,6 +209,46 @@ Output return_buffer(Input const& geometry, Distance const& distance, Distance c return geometry_out; } +template +< + typename GeometryIn, + typename MultiPolygon, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename CircleStrategy +> +inline void buffer(GeometryIn const& geometry_in, + MultiPolygon& geometry_out, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + CircleStrategy const& circle_strategy) +{ + typedef typename boost::range_value::type polygon_type; + concept::check(); + concept::check(); + + typedef typename point_type::type point_type; + typedef typename rescale_policy_type::type rescale_policy_type; + + geometry_out.clear(); + + rescale_policy_type rescale_policy + = boost::geometry::get_rescale_policy(geometry_in); + + detail::buffer::buffer_inserter(geometry_in, std::back_inserter(geometry_out), + distance_strategy, + side_strategy, + join_strategy, + end_strategy, + circle_strategy, + rescale_policy); +} + + }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index a323cd602..5ac47651b 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -740,6 +740,10 @@ struct buffer_inserter } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + template < typename GeometryOutput, @@ -841,6 +845,9 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator end_strategy, circle_strategy, robust_policy, visitor); } +#endif // DOXYGEN_NO_DETAIL + +}} // namespace detail::buffer }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 828547040..39b9d0e3f 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -23,6 +23,8 @@ #include +#include + #include #include #include diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index b82cb1e6d..3328b174d 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -11,6 +11,7 @@ #include +#include #include #include #include diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index 085b57af9..bcbcc12d3 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -416,7 +416,8 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, std::vector buffered; - bg::buffer_inserter(geometry, std::back_inserter(buffered), + bg::detail::buffer::buffer_inserter(geometry, + std::back_inserter(buffered), distance_strategy, side_strategy, join_strategy, From 5df31ddd0edbf69037023d773a384b399e5b915c Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Jul 2014 17:01:50 +0200 Subject: [PATCH 20/37] [buffer] add documentation for buffer with 5 strategies --- doc/html/svg_buffer_linestring.png | Bin 0 -> 15155 bytes doc/html/svg_buffer_multi_point.png | Bin 0 -> 13451 bytes doc/html/svg_buffer_multi_polygon.png | Bin 0 -> 19624 bytes doc/imports.qbk | 1 + .../algorithms/buffer_with_strategies.qbk | 28 +++++++ doc/src/examples/algorithms/Jamfile.v2 | 1 + .../algorithms/buffer_with_strategies.cpp | 70 ++++++++++++++++++ include/boost/geometry/algorithms/buffer.hpp | 22 ++++++ 8 files changed, 122 insertions(+) create mode 100644 doc/html/svg_buffer_linestring.png create mode 100644 doc/html/svg_buffer_multi_point.png create mode 100644 doc/html/svg_buffer_multi_polygon.png create mode 100644 doc/reference/algorithms/buffer_with_strategies.qbk create mode 100644 doc/src/examples/algorithms/buffer_with_strategies.cpp diff --git a/doc/html/svg_buffer_linestring.png b/doc/html/svg_buffer_linestring.png new file mode 100644 index 0000000000000000000000000000000000000000..4c42c7ec2b59fa976012fbd403497e0367e7c5d7 GIT binary patch literal 15155 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 literal 0 HcmV?d00001 diff --git a/doc/html/svg_buffer_multi_polygon.png b/doc/html/svg_buffer_multi_polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf482d1dca2d7b4a8d582c0f3040b4d70eaeb30 GIT binary patch literal 19624 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 Xzr1u~jnPU51_lOCS3j3^P6w44 literal 0 HcmV?d00001 diff --git a/doc/imports.qbk b/doc/imports.qbk index ad03bbfaf..f490a0ab0 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -20,6 +20,7 @@ [import src/examples/algorithms/assign_3d_point.cpp] [import src/examples/algorithms/assign_inverse.cpp] [import src/examples/algorithms/assign_points.cpp] +[import src/examples/algorithms/buffer_with_strategies.cpp] [import src/examples/algorithms/clear.cpp] [import src/examples/algorithms/centroid.cpp] [import src/examples/algorithms/comparable_distance.cpp] diff --git a/doc/reference/algorithms/buffer_with_strategies.qbk b/doc/reference/algorithms/buffer_with_strategies.qbk new file mode 100644 index 000000000..0ca3c7f9a --- /dev/null +++ b/doc/reference/algorithms/buffer_with_strategies.qbk @@ -0,0 +1,28 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + Copyright (c) 2009-2012 Bruno Lalande, Paris, France. + + Use, modification and distribution is subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================/] + +[def __this_function__ buffer] + +[heading_conformance_ogc __this_function__..Buffer] + +[heading Examples] +[buffer_with_strategies] + +[heading Output] +The linestring case +[$svg_buffer_linestring.png] + +The multi_point case +[$svg_buffer_multi_point.png] + +The multi_polygon case +[$svg_buffer_multi_polygon.png] diff --git a/doc/src/examples/algorithms/Jamfile.v2 b/doc/src/examples/algorithms/Jamfile.v2 index 6da320270..d8e25d9fb 100644 --- a/doc/src/examples/algorithms/Jamfile.v2 +++ b/doc/src/examples/algorithms/Jamfile.v2 @@ -27,6 +27,7 @@ exe assign_points : assign_points.cpp ; # exe assign_point_from_index : assign_point_from_index.cpp ; # exe assign_point_to_index : assign_point_to_index.cpp ; +exe buffer_with_strategies : buffer_with_strategies.cpp ; exe centroid : centroid.cpp ; exe clear : clear.cpp ; exe comparable_distance : comparable_distance.cpp ; diff --git a/doc/src/examples/algorithms/buffer_with_strategies.cpp b/doc/src/examples/algorithms/buffer_with_strategies.cpp new file mode 100644 index 000000000..2f47cee17 --- /dev/null +++ b/doc/src/examples/algorithms/buffer_with_strategies.cpp @@ -0,0 +1,70 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2013, 2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[buffer_with_strategies +//` Shows how the buffer algorithm can be used to create a buffer of a linestring + +#include +#include +#include +/*<-*/ #include "create_svg_two.hpp" /*->*/ + +int main() +{ + typedef double coordinate_type; + typedef boost::geometry::model::d2::point_xy point; + typedef boost::geometry::model::polygon polygon; + + // Declare strategies + const double buffer_distance = 1.0; + const int points_per_circle = 36; + boost::geometry::strategy::buffer::distance_symmetric distance_strategy(buffer_distance); + boost::geometry::strategy::buffer::join_round join_strategy(points_per_circle); + boost::geometry::strategy::buffer::end_round end_strategy(points_per_circle); + boost::geometry::strategy::buffer::buffer_circle circle_strategy(points_per_circle); + boost::geometry::strategy::buffer::buffer_side side_strategy; + + // Declare output + boost::geometry::model::multi_polygon result; + + // Declare/fill a linestring + boost::geometry::model::linestring ls; + boost::geometry::read_wkt("LINESTRING(0 0,4 5,7 4,10 6)", ls); + + // Create the buffer of a linestring + boost::geometry::buffer(ls, result, + distance_strategy, side_strategy, + join_strategy, end_strategy, circle_strategy); + /*<-*/ create_svg("buffer_linestring.svg", ls, result); /*->*/ + + // Declare/fill of a multi point + boost::geometry::model::multi_point mp; + boost::geometry::read_wkt("MULTIPOINT((3 3),(4 4))", mp); + + // Create the buffer of a multi point + boost::geometry::buffer(mp, result, + distance_strategy, side_strategy, + join_strategy, end_strategy, circle_strategy); + /*<-*/ create_svg("buffer_multi_point.svg", mp, result); /*->*/ + + // Declare/fill of a multi_polygon + boost::geometry::model::multi_polygon mpol; + boost::geometry::read_wkt("MULTIPOLYGON(((0 1,2 5,5 3,0 1)),((1 1,5 2,5 0,1 1)))", mpol); + + // Create the buffer of a polygon + boost::geometry::buffer(mpol, result, + distance_strategy, side_strategy, + join_strategy, end_strategy, circle_strategy); + /*<-*/ create_svg("buffer_multi_polygon.svg", mpol, result); /*->*/ + + return 0; +} + +//] + diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index ed861877a..689651ef3 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -209,6 +209,28 @@ Output return_buffer(Input const& geometry, Distance const& distance, Distance c return geometry_out; } +/*! +\brief \brief_calc{buffer} +\ingroup buffer +\details \details_calc{buffer, \det_buffer}. +\tparam GeometryIn \tparam_geometry +\tparam MultiPolygon \tparam_geometry +\tparam DistanceStrategy A strategy defining distance behaviour (symmetric, asymetric) +\tparam SideStrategy A strategy defining side behaviour +\tparam JoinStrategy A strategy defining join behaviour (round, miter) +\tparam EndStrategy A strategy defining end behaviour (round, flat) +\tparam CircleStrategy A strategy defining circle behaviour +\param geometry_in \param_geometry +\param geometry_out output multi polygon (or std:: collection of polygons), contains buffer of input geometry +\param distance_strategy The distance strategy to be used +\param side_strategy The side strategy to be used +\param join_strategy The join strategy to be used +\param end_strategy The end strategy to be used +\param circle_strategy The circle strategy to be used + +\qbk{distinguish,with strategies} +\qbk{[include reference/algorithms/buffer_with_strategies.qbk]} + */ template < typename GeometryIn, From 36da68460913d562896d23f5a51759cccd98dcad Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 16 Jul 2014 20:44:07 +0200 Subject: [PATCH 21/37] [winding] Add winding_side_equal optimized for cartesian CS. --- .../agnostic/point_in_poly_winding.hpp | 125 +++++++++++------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index 4ed54c77e..e6161b677 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -33,6 +33,78 @@ namespace boost { namespace geometry namespace strategy { namespace within { + +// Fix for https://svn.boost.org/trac/boost/ticket/9628 +// For floating point coordinates, the <1> coordinate of a point is compared +// with the segment's points using some EPS. If the coordinates are "equal" +// the sides are calculated. Therefore we can treat a segment as a long areal +// geometry having some width. There is a small ~triangular area somewhere +// between the segment's effective area and a segment's line used in sides +// calculation where the segment is on the one side of the line but on the +// other side of a segment (due to the width). +// For the s1 of a segment going NE the real side is RIGHT but the point may +// be detected as LEFT, like this: +// RIGHT +// ___-----> +// ^ O Pt __ __ +// EPS __ __ +// v__ __ BUT DETECTED AS LEFT OF THIS LINE +// _____7 +// _____/ +// _____/ +template +struct winding_side_equal +{ + typedef typename strategy::side::services::default_strategy + < + CSTag + >::type strategy_side_type; + + template + static inline int apply(Point const& point, + PointOfSegment const& se, + int count) + { + // Create a vertical segment intersecting the original segment's endpoint + // equal to the point, with the derived direction (UP/DOWN). + // Set only the 2 first coordinates, the other ones are ignored + PointOfSegment ss1, ss2; + set<1-D>(ss1, get<1-D>(se)); + set<1-D>(ss2, get<1-D>(se)); + if ( count > 0 ) // UP + { + set(ss1, 0); + set(ss2, 1); + } + else // DOWN + { + set(ss1, 1); + set(ss2, 0); + } + // Check the side using this vertical segment + return strategy_side_type::apply(ss1, ss2, point); + } +}; + +// The optimization for cartesian +template <> +struct winding_side_equal +{ + template + static inline int apply(Point const& point, + PointOfSegment const& se, + int count) + { + return math::equals(get<1-D>(point), get<1-D>(se)) ? + 0 : + get<1-D>(point) < get<1-D>(se) ? + // assuming count is equal to 1 or -1 + count : // ( count > 0 ? 1 : -1) : + -count; // ( count > 0 ? -1 : 1) ; + } +}; + + /*! \brief Within detection using winding rule \ingroup strategies @@ -137,56 +209,6 @@ class winding : 0; } - // Fix for https://svn.boost.org/trac/boost/ticket/9628 - // For floating point coordinates, the <1> coordinate of a point is compared - // with the segment's points using some EPS. If the coordinates are "equal" - // the sides are calculated. Therefore we can treat a segment as a long areal - // geometry having some width. There is a small ~triangular area somewhere - // between the segment's effective area and a segment's line used in sides - // calculation where the segment is on the one side of the line but on the - // other side of a segment (due to the width). - // For the s1 of a segment going NE the real side is RIGHT but the point may - // be detected as LEFT, like this: - // RIGHT - // ___-----> - // ^ O Pt __ __ - // EPS __ __ - // v__ __ BUT DETECTED AS LEFT OF THIS LINE - // _____7 - // _____/ - // _____/ - template - static inline int side_equal(Point const& point, - PointOfSegment const& se, - int count) - { - // TODO: possible optimization of cartesian CS - // math::equals(p<1-D>, se<1-D>) ? - // 0 : - // p<1-D> < se<1-D> ? - // (UP ? LEFT : RIGHT) : - // (UP ? RIGHT : LEFT) ; - - // Create a vertical segment intersecting the original segment's endpoint - // equal to the point, with the derived direction (UP/DOWN). - // Set only the 2 first coordinates, the other ones are ignored - PointOfSegment ss1, ss2; - set<1-D>(ss1, get<1-D>(se)); - set<1-D>(ss2, get<1-D>(se)); - if ( count > 0 ) // UP - { - set(ss1, 0); - set(ss2, 1); - } - else // DOWN - { - set(ss1, 1); - set(ss2, 0); - } - // Check the side using this vertical segment - return strategy_side_type::apply(ss1, ss2, point); - } - public : @@ -209,7 +231,8 @@ public : int side = 0; if ( count == 1 || count == -1 ) { - side = side_equal<1>(point, eq1 ? s1 : s2, count); + side = winding_side_equal::type> + ::template apply<1>(point, eq1 ? s1 : s2, count); } else { From d16a343c0a708e356627329d75ee26fc888be13c Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 16 Jul 2014 22:28:10 +0200 Subject: [PATCH 22/37] [buffer] Fix buffer_inserter() call in multi_point_buffer test Function was moved to namespace bg::detail::buffer --- test/algorithms/buffer/multi_point_buffer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/algorithms/buffer/multi_point_buffer.cpp b/test/algorithms/buffer/multi_point_buffer.cpp index 1b92b8d9d..2a134d6d4 100644 --- a/test/algorithms/buffer/multi_point_buffer.cpp +++ b/test/algorithms/buffer/multi_point_buffer.cpp @@ -114,7 +114,8 @@ double test_growth(Geometry const& geometry, int n, int d, double distance) rescale_policy_type rescale_policy = bg::get_rescale_policy(geometry); - bg::buffer_inserter(geometry, std::back_inserter(buffered), + bg::detail::buffer::buffer_inserter(geometry, + std::back_inserter(buffered), distance_strategy, join_strategy, end_strategy, From fa203789db8ee75905eb483fe8ac465304633135 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 17 Jul 2014 02:30:21 +0300 Subject: [PATCH 23/37] [algorithms][distance] check distance against 0 only when the minimum distance is updated --- .../algorithms/detail/distance/multi_to_multi.hpp | 8 ++++---- .../algorithms/detail/distance/single_to_multi.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/distance/multi_to_multi.hpp b/include/boost/geometry/algorithms/detail/distance/multi_to_multi.hpp index 29ceb96be..0d541cc3a 100644 --- a/include/boost/geometry/algorithms/detail/distance/multi_to_multi.hpp +++ b/include/boost/geometry/algorithms/detail/distance/multi_to_multi.hpp @@ -104,10 +104,10 @@ public: if (first || cdist < min_cdist) { min_cdist = cdist; - } - if ( geometry::math::equals(min_cdist, 0) ) - { - break; + if ( geometry::math::equals(min_cdist, 0) ) + { + break; + } } } diff --git a/include/boost/geometry/algorithms/detail/distance/single_to_multi.hpp b/include/boost/geometry/algorithms/detail/distance/single_to_multi.hpp index 9966381e5..59cf17230 100644 --- a/include/boost/geometry/algorithms/detail/distance/single_to_multi.hpp +++ b/include/boost/geometry/algorithms/detail/distance/single_to_multi.hpp @@ -111,10 +111,10 @@ public: if (first || cdist < min_cdist) { min_cdist = cdist; - } - if ( geometry::math::equals(min_cdist, 0) ) - { - break; + if ( geometry::math::equals(min_cdist, 0) ) + { + break; + } } } From bf9c8aa3e41283131a5ec5e73b7629805439cedc Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 17 Jul 2014 03:10:55 +0300 Subject: [PATCH 24/37] [doc][support status] fix typo: num_interior_rings should have been num_points --- doc/src/docutils/tools/support_status/support_status.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/docutils/tools/support_status/support_status.cpp b/doc/src/docutils/tools/support_status/support_status.cpp index 2fbc46a14..47c167642 100644 --- a/doc/src/docutils/tools/support_status/support_status.cpp +++ b/doc/src/docutils/tools/support_status/support_status.cpp @@ -260,7 +260,7 @@ void support_status() test_unary_algorithm("length"); test_unary_algorithm("num_geometries"); test_unary_algorithm("num_interior_rings"); - test_unary_algorithm("num_points"); + test_unary_algorithm("num_points"); test_binary_algorithm("overlaps"); test_unary_algorithm("perimeter"); test_unary_algorithm("reverse"); From 439bc5198bb8e3b5d311ff0b1dc85729ea54f315 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 17 Jul 2014 03:15:37 +0300 Subject: [PATCH 25/37] [doc][support status] add algorithms is_simple and is_valid --- doc/src/docutils/tools/support_status/support_status.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/src/docutils/tools/support_status/support_status.cpp b/doc/src/docutils/tools/support_status/support_status.cpp index 47c167642..4cf636d74 100644 --- a/doc/src/docutils/tools/support_status/support_status.cpp +++ b/doc/src/docutils/tools/support_status/support_status.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include #include @@ -121,6 +123,8 @@ DECLARE_BINARY_ALGORITHM(equals) DECLARE_BINARY_ALGORITHM(expand) DECLARE_UNARY_ALGORITHM(for_each_point) DECLARE_UNARY_ALGORITHM(for_each_segment) +DECLARE_UNARY_ALGORITHM(is_simple) +DECLARE_UNARY_ALGORITHM(is_valid) DECLARE_UNARY_ALGORITHM(length) DECLARE_UNARY_ALGORITHM(num_geometries) DECLARE_UNARY_ALGORITHM(num_interior_rings) @@ -257,6 +261,8 @@ void support_status() test_binary_algorithm("expand"); test_unary_algorithm("for_each_point"); test_unary_algorithm("for_each_segment"); + test_unary_algorithm("is_simple"); + test_unary_algorithm("is_valid"); test_unary_algorithm("length"); test_unary_algorithm("num_geometries"); test_unary_algorithm("num_interior_rings"); From 64d967a3cbd4ac3a1100fedba8ccec0ef8fc429e Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 17 Jul 2014 22:51:04 +0200 Subject: [PATCH 26/37] [doc] Move the description of WKT one level above and add info about the output of non-OGC geometries --- doc/html/index.html | 12 ++++++++---- doc/reference.qbk | 3 ++- doc/reference/io/read_wkt.qbk | 12 +----------- doc/reference/io/wkt_format.qbk | 29 +++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 doc/reference/io/wkt_format.qbk diff --git a/doc/html/index.html b/doc/html/index.html index 9719e84fa..841fbf5b1 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -3,7 +3,7 @@ Chapter 1. Geometry - + @@ -100,12 +100,12 @@

- Contributions + Contributions

Boost.Geometry contains contributions by:

-
    +
    • Akira Takahashi (adaption of Boost.Fusion)
    • @@ -124,10 +124,14 @@
    • Mats Taraldsvik (documentation: adapting a legacy model)
    • +
    • + Samuel Debionne (variant support for distance, assign, crosses, intersection, + ...) +
- +

Last revised: May 07, 2014 at 10:12:25 GMT

Last revised: July 17, 2014 at 20:45:09 GMT


diff --git a/doc/reference.qbk b/doc/reference.qbk index 5ae619b58..ffbc95f40 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -4,7 +4,7 @@ Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Copyright (c) 2009-2012 Bruno Lalande, Paris, France. - Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. + Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -230,6 +230,7 @@ [section:io IO (input/output)] [section:wkt WKT (Well-Known Text)] +[include reference/io/wkt_format.qbk] [include generated/wkt.qbk] [endsect] [section:svg SVG (Scalable Vector Graphics)] diff --git a/doc/reference/io/read_wkt.qbk b/doc/reference/io/read_wkt.qbk index d34e90647..8022d8474 100644 --- a/doc/reference/io/read_wkt.qbk +++ b/doc/reference/io/read_wkt.qbk @@ -2,23 +2,13 @@ Boost.Geometry (aka GGL, Generic Geometry Library) Copyright (c) 2009-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================/] -[heading The WKT Format] -WKT is a general markup format in ASCII. -It is described in detail on [@http://en.wikipedia.org/wiki/Well-known_text Wikipedia] - -Boost Geometry supports the common formats (POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON). Because Boost.Geometry -also supports Box and Segment geometries, which are not standard OGC geometries, there are some extensions: - -* a Box can be read from WKT by specifying either a polygon (with 4 points) or a specific BOX string (non OGC) -* a Segment can be read from WKT by specifying either a linestring (with 2 points) or a specific SEGMENT string (non OGC) -* a Ring can be read from WKT by specifying a polygon (with no holes) - [heading Conformance] Other libraries refer to this functionality as [*ST_GeomFromText] or [*STGeomFromText]. That is not done here because Boost.Geometry support more text formats. The name GeomFromText diff --git a/doc/reference/io/wkt_format.qbk b/doc/reference/io/wkt_format.qbk new file mode 100644 index 000000000..3c99fe808 --- /dev/null +++ b/doc/reference/io/wkt_format.qbk @@ -0,0 +1,29 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + + Use, modification and distribution is subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================/] + +WKT is a general markup format in ASCII. +It is described in detail on [@http://en.wikipedia.org/wiki/Well-known_text Wikipedia] + +Boost Geometry supports the common formats (POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON). + +Because Boost.Geometry also supports Box and Segment geometries, which are not standard OGC geometries, there are some extensions: + +[heading Box] +* can be read from WKT by specifying either a polygon (with 4 points) or a specific BOX string (non OGC) +* streamed to WKT as a POLYGON + +[heading Segment] +* can be read from WKT by specifying either a linestring (with 2 points) or a specific SEGMENT string (non OGC) +* streamed to WKT as a LINESTRING + +[heading Ring] +* can be read from WKT by specifying a polygon (with no holes) +* streamed to WKT as POLYGON From c48b92fe81a9b55a8d192c085392feead164892b Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 17 Jul 2014 22:57:29 +0200 Subject: [PATCH 27/37] [doc] Add ticket to release notes, rearrange tickets (asc order) --- doc/release_notes.qbk | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 90462b54e..7ae7a5ce7 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -38,12 +38,13 @@ [*Solved tickets] -* [@https://svn.boost.org/trac/boost/ticket/9245 9245] Check for process errors in make_qbk.py -* [@https://svn.boost.org/trac/boost/ticket/9081 9081] Booleans create self-intersecting polygons from non-self-intersecting polygons * [@https://svn.boost.org/trac/boost/ticket/8310 8310] Wrong results with overlapping polygons (fixed using point_on_surface for disjoint) -* [@https://svn.boost.org/trac/boost/ticket/9871 9871] Remove spike in polygon with only a spike +* [@https://svn.boost.org/trac/boost/ticket/9081 9081] Booleans create self-intersecting polygons from non-self-intersecting polygons +* [@https://svn.boost.org/trac/boost/ticket/9245 9245] Check for process errors in make_qbk.py * [@https://svn.boost.org/trac/boost/ticket/9563 9563] (Sym)difference not successful, fixed by rescaling to robust type * [@https://svn.boost.org/trac/boost/ticket/9628 9628] Wrong result of within() due to the winding strategy not working correctly for nearly-horizontal segments +* [@https://svn.boost.org/trac/boost/ticket/9871 9871] Remove spike in polygon with only a spike +* [@https://svn.boost.org/trac/boost/ticket/9947 9947] Missing info about WKT in documentation * [@https://svn.boost.org/trac/boost/ticket/10019 10019] Difference of Linestring and Box returns their intersection * [@https://svn.boost.org/trac/boost/ticket/10077 10077] Wrong types in concept checks in boost/geometry/arithmetic/arithmetic.hpp From 34d148dfb712f1859e794ca6fbb0a05a1f149f64 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 17 Jul 2014 23:08:47 +0200 Subject: [PATCH 28/37] [doc] Add IO to reference matrix --- doc/quickref.xml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/quickref.xml b/doc/quickref.xml index e1d816729..71e470d29 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -630,6 +630,37 @@ + + + + + + + + + IO + + + + + + + WKT (Well-Known Text) + + read_wkt + wkt + + + + SVG (Scalable Vector Graphics) + + svg + svg_mapper + + + + + From 61a5aff3fee99d3561ae014ddffe4cd8777dbb33 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 17 Jul 2014 23:12:17 +0200 Subject: [PATCH 29/37] [doc] Fix strategies section in reference matrix, change columns number to 2. --- doc/quickref.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/quickref.xml b/doc/quickref.xml index 71e470d29..c57426c4b 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -487,13 +487,12 @@ --> - + - - + Strategies From 68b71f9967ce13726c5c4b0e8432a76723553758 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 18 Jul 2014 01:51:49 +0200 Subject: [PATCH 30/37] [doc][index] Add iterative query example --- doc/index/rtree/examples.qbk | 6 ++ doc/index/src/examples/rtree/Jamfile.v2 | 9 +-- .../src/examples/rtree/iterative_query.cpp | 65 +++++++++++++++++++ .../src/examples/rtree/iterative_query.qbk | 16 +++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 doc/index/src/examples/rtree/iterative_query.cpp create mode 100644 doc/index/src/examples/rtree/iterative_query.qbk diff --git a/doc/index/rtree/examples.qbk b/doc/index/rtree/examples.qbk index 24d54d466..ba82e88f0 100644 --- a/doc/index/rtree/examples.qbk +++ b/doc/index/rtree/examples.qbk @@ -46,6 +46,12 @@ [include ../src/examples/rtree/value_index_results.qbk] [endsect] +[section Iterative query] +[rtree_iterative_query] +[h4 Expected results] +[include ../src/examples/rtree/iterative_query.qbk] +[endsect] + [section Index stored in shared memory using Boost.Interprocess] [rtree_interprocess] [h4 Expected results] diff --git a/doc/index/src/examples/rtree/Jamfile.v2 b/doc/index/src/examples/rtree/Jamfile.v2 index f45b5cb30..3e03c6000 100644 --- a/doc/index/src/examples/rtree/Jamfile.v2 +++ b/doc/index/src/examples/rtree/Jamfile.v2 @@ -6,12 +6,13 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -exe quick_start : quick_start.cpp ; -exe polygons_vector : polygons_vector.cpp ; +exe iterative_query : iterative_query.cpp ; exe polygons_shared_ptr : polygons_shared_ptr.cpp ; -exe variants_map : variants_map.cpp ; -exe value_shared_ptr : value_shared_ptr.cpp ; +exe polygons_vector : polygons_vector.cpp ; +exe quick_start : quick_start.cpp ; exe value_index : value_index.cpp ; +exe value_shared_ptr : value_shared_ptr.cpp ; +exe variants_map : variants_map.cpp ; exe interprocess : interprocess.cpp /boost/thread//boost_thread : diff --git a/doc/index/src/examples/rtree/iterative_query.cpp b/doc/index/src/examples/rtree/iterative_query.cpp new file mode 100644 index 000000000..375a20056 --- /dev/null +++ b/doc/index/src/examples/rtree/iterative_query.cpp @@ -0,0 +1,65 @@ +// Boost.Geometry Index +// +// Quickbook Examples +// +// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +// +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[rtree_iterative_query + +#include +#include +#include + +#include + +// just for output +#include + +namespace bg = boost::geometry; +namespace bgi = boost::geometry::index; + +int main(void) +{ + typedef bg::model::point point; + typedef point value; + typedef bgi::rtree< value, bgi::linear<16> > rtree_t; + + // create the rtree using default constructor + rtree_t rtree; + + // create some values + for ( float f = 0 ; f < 10 ; f += 1 ) + { + // insert new value + rtree.insert(point(f, f)); + } + + // query point + point pt(5.1, 5.1); + + // iterate over nearest Values + for ( rtree_t::const_query_iterator + it = rtree.qbegin(bgi::nearest(pt, 100)) ; + it != rtree.qend() ; + ++it ) + { + double d = bg::distance(pt, *it); + + std::cout << bg::wkt(*it) << ", distance= " << d << std::endl; + + // break if the distance is too big + if ( d > 2 ) + { + std::cout << "break!" << std::endl; + break; + } + } + + return 0; +} + +//] diff --git a/doc/index/src/examples/rtree/iterative_query.qbk b/doc/index/src/examples/rtree/iterative_query.qbk new file mode 100644 index 000000000..816f04c27 --- /dev/null +++ b/doc/index/src/examples/rtree/iterative_query.qbk @@ -0,0 +1,16 @@ +[/============================================================================ + Boost.Geometry Index + + Copyright (c) 2011-2014 Adam Wulkiewicz. + + Use, modification and distribution is subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================/] + + POINT(5 5), distance= 0.141421 + POINT(6 6), distance= 1.27279 + POINT(4 4), distance= 1.55563 + POINT(7 7), distance= 2.68701 + break! + From f02ab872329aead0224b2fdedc4e93a5e01f3317 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 18 Jul 2014 02:04:00 +0200 Subject: [PATCH 31/37] [doc][index] Add iterative_query example to imports and tweak it slightly. --- doc/index/imports.qbk | 1 + doc/index/src/examples/rtree/iterative_query.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/index/imports.qbk b/doc/index/imports.qbk index 45a613f75..4502ee41c 100644 --- a/doc/index/imports.qbk +++ b/doc/index/imports.qbk @@ -14,5 +14,6 @@ [import src/examples/rtree/variants_map.cpp] [import src/examples/rtree/value_shared_ptr.cpp] [import src/examples/rtree/value_index.cpp] +[import src/examples/rtree/iterative_query.cpp] [import src/examples/rtree/interprocess.cpp] [import src/examples/rtree/mapped_file.cpp] diff --git a/doc/index/src/examples/rtree/iterative_query.cpp b/doc/index/src/examples/rtree/iterative_query.cpp index 375a20056..32ce87606 100644 --- a/doc/index/src/examples/rtree/iterative_query.cpp +++ b/doc/index/src/examples/rtree/iterative_query.cpp @@ -32,7 +32,7 @@ int main(void) rtree_t rtree; // create some values - for ( float f = 0 ; f < 10 ; f += 1 ) + for ( double f = 0 ; f < 10 ; f += 1 ) { // insert new value rtree.insert(point(f, f)); From d3b135a939c6d48c964cb03cbfebaae34c530be9 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 18 Jul 2014 20:57:56 +0200 Subject: [PATCH 32/37] [buffer] use promoted type and made variables const --- .../cartesian/buffer_join_round_by_divide.hpp | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp b/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp index 69ac079e0..525828475 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp @@ -36,7 +36,13 @@ public : : m_max_level(max_level) {} - template + template + < + typename PromotedType, + typename Point, + typename DistanceType, + typename RangeOut + > inline void mid_points(Point const& vertex, Point const& p1, Point const& p2, DistanceType const& buffer_distance, @@ -46,20 +52,20 @@ public : typedef typename coordinate_type::type coordinate_type; // Generate 'vectors' - coordinate_type vp1_x = get<0>(p1) - get<0>(vertex); - coordinate_type vp1_y = get<1>(p1) - get<1>(vertex); + coordinate_type const vp1_x = get<0>(p1) - get<0>(vertex); + coordinate_type const vp1_y = get<1>(p1) - get<1>(vertex); - coordinate_type vp2_x = (get<0>(p2) - get<0>(vertex)); - coordinate_type vp2_y = (get<1>(p2) - get<1>(vertex)); + coordinate_type const vp2_x = (get<0>(p2) - get<0>(vertex)); + coordinate_type const vp2_y = (get<1>(p2) - get<1>(vertex)); // Average them to generate vector in between - coordinate_type two = 2; - coordinate_type v_x = (vp1_x + vp2_x) / two; - coordinate_type v_y = (vp1_y + vp2_y) / two; + coordinate_type const two = 2; + coordinate_type const v_x = (vp1_x + vp2_x) / two; + coordinate_type const v_y = (vp1_y + vp2_y) / two; - coordinate_type length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y); + PromotedType const length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y); - coordinate_type prop = buffer_distance / length2; + PromotedType prop = buffer_distance / length2; Point mid_point; set<0>(mid_point, get<0>(vertex) + v_x * prop); @@ -67,12 +73,12 @@ public : if (level < m_max_level) { - mid_points(vertex, p1, mid_point, buffer_distance, range_out, level + 1); + mid_points(vertex, p1, mid_point, buffer_distance, range_out, level + 1); } range_out.push_back(mid_point); if (level < m_max_level) { - mid_points(vertex, mid_point, p2, buffer_distance, range_out, level + 1); + mid_points(vertex, mid_point, p2, buffer_distance, range_out, level + 1); } } @@ -101,14 +107,13 @@ public : } // Generate 'vectors' - coordinate_type vix = (get<0>(ip) - get<0>(vertex)); - coordinate_type viy = (get<1>(ip) - get<1>(vertex)); + coordinate_type const vix = (get<0>(ip) - get<0>(vertex)); + coordinate_type const viy = (get<1>(ip) - get<1>(vertex)); - coordinate_type length_i = - geometry::math::sqrt(vix * vix + viy * viy); + promoted_type const length_i = geometry::math::sqrt(vix * vix + viy * viy); - coordinate_type const bd = geometry::math::abs(buffer_distance); - coordinate_type prop = bd / length_i; + promoted_type const bd = geometry::math::abs(buffer_distance); + promoted_type prop = bd / length_i; Point bp; set<0>(bp, get<0>(vertex) + vix * prop); @@ -118,9 +123,9 @@ public : if (m_max_level > 1) { - mid_points(vertex, perp1, bp, bd, range_out); + mid_points(vertex, perp1, bp, bd, range_out); range_out.push_back(bp); - mid_points(vertex, bp, perp2, bd, range_out); + mid_points(vertex, bp, perp2, bd, range_out); } else if (m_max_level == 1) { From e4d40a2287b38ba4fcfc038dbf019eaaf5099ab6 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 18 Jul 2014 21:29:59 +0200 Subject: [PATCH 33/37] [buffer] rename CircleStrategy template argument to PointStrategy because it might also generate squares etc. --- include/boost/geometry/algorithms/buffer.hpp | 16 +++--- .../detail/buffer/buffer_inserter.hpp | 56 +++++++++---------- include/boost/geometry/strategies/buffer.hpp | 2 +- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 689651ef3..ca2e39f20 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -216,17 +216,17 @@ Output return_buffer(Input const& geometry, Distance const& distance, Distance c \tparam GeometryIn \tparam_geometry \tparam MultiPolygon \tparam_geometry \tparam DistanceStrategy A strategy defining distance behaviour (symmetric, asymetric) -\tparam SideStrategy A strategy defining side behaviour -\tparam JoinStrategy A strategy defining join behaviour (round, miter) -\tparam EndStrategy A strategy defining end behaviour (round, flat) -\tparam CircleStrategy A strategy defining circle behaviour +\tparam SideStrategy A strategy defining creation of buffer along sides +\tparam JoinStrategy A strategy defining creation of buffer around convex joins (round, miter) +\tparam EndStrategy A strategy defining creation of buffer at linestring ends (round, flat) +\tparam PointStrategy A strategy defining creation of buffer around points \param geometry_in \param_geometry \param geometry_out output multi polygon (or std:: collection of polygons), contains buffer of input geometry \param distance_strategy The distance strategy to be used \param side_strategy The side strategy to be used \param join_strategy The join strategy to be used \param end_strategy The end strategy to be used -\param circle_strategy The circle strategy to be used +\param point_strategy The point strategy to be used \qbk{distinguish,with strategies} \qbk{[include reference/algorithms/buffer_with_strategies.qbk]} @@ -239,7 +239,7 @@ template typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy + typename PointStrategy > inline void buffer(GeometryIn const& geometry_in, MultiPolygon& geometry_out, @@ -247,7 +247,7 @@ inline void buffer(GeometryIn const& geometry_in, SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy) + PointStrategy const& point_strategy) { typedef typename boost::range_value::type polygon_type; concept::check(); @@ -266,7 +266,7 @@ inline void buffer(GeometryIn const& geometry_in, side_strategy, join_strategy, end_strategy, - circle_strategy, + point_strategy, rescale_policy); } diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 5ac47651b..d3f2aeebc 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -312,7 +312,7 @@ struct buffer_multi typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline void apply(Multi const& multi, @@ -321,7 +321,7 @@ struct buffer_multi SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy) { for (typename boost::range_iterator::type @@ -331,7 +331,7 @@ struct buffer_multi { Policy::apply(*it, collection, distance_strategy, side_strategy, - join_strategy, end_strategy, circle_strategy, + join_strategy, end_strategy, point_strategy, robust_policy); } } @@ -377,7 +377,7 @@ struct buffer_inserter typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline void apply(Point const& point, Collection& collection, @@ -385,15 +385,15 @@ struct buffer_inserter SideStrategy const& , JoinStrategy const& , EndStrategy const& , - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& ) { typedef typename point_type::type output_point_type; collection.start_new_ring(); std::vector range_out; - circle_strategy.apply(point, distance_strategy, range_out); - collection.add_piece(strategy::buffer::buffered_circle, range_out, false); + point_strategy.apply(point, distance_strategy, range_out); + collection.add_piece(strategy::buffer::buffered_point, range_out, false); collection.finish_ring(); } }; @@ -455,7 +455,7 @@ struct buffer_inserter typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline void apply(RingInput const& ring, @@ -464,7 +464,7 @@ struct buffer_inserter SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& , + PointStrategy const& , RobustPolicy const& robust_policy) { if (boost::size(ring) > 3) @@ -568,7 +568,7 @@ struct buffer_inserter typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline void apply(Linestring const& linestring, Collection& collection, @@ -576,7 +576,7 @@ struct buffer_inserter SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy) { if (boost::size(linestring) > 1) @@ -599,7 +599,7 @@ struct buffer_inserter } else { - // Use circle_strategy to buffer degenerated circle + // Use point_strategy to buffer degenerated linestring } } }; @@ -627,7 +627,7 @@ private: typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline @@ -637,14 +637,14 @@ private: SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy) { for (Iterator it = begin; it != end; ++it) { collection.start_new_ring(); policy::apply(*it, collection, distance, side_strategy, - join_strategy, end_strategy, circle_strategy, + join_strategy, end_strategy, point_strategy, robust_policy); collection.finish_ring(); } @@ -658,7 +658,7 @@ private: typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline @@ -668,12 +668,12 @@ private: SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy) { iterate(boost::begin(interior_rings), boost::end(interior_rings), collection, distance, side_strategy, - join_strategy, end_strategy, circle_strategy, + join_strategy, end_strategy, point_strategy, robust_policy); } @@ -685,7 +685,7 @@ public: typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > static inline void apply(PolygonInput const& polygon, @@ -694,21 +694,21 @@ public: SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy) { { collection.start_new_ring(); policy::apply(exterior_ring(polygon), collection, distance, side_strategy, - join_strategy, end_strategy, circle_strategy, + join_strategy, end_strategy, point_strategy, robust_policy); collection.finish_ring(); } apply_interior_rings(interior_rings(polygon), collection, distance, side_strategy, - join_strategy, end_strategy, circle_strategy, + join_strategy, end_strategy, point_strategy, robust_policy); } }; @@ -753,7 +753,7 @@ template typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy, typename VisitPiecesPolicy > @@ -762,7 +762,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy, VisitPiecesPolicy& visit_pieces_policy ) @@ -786,7 +786,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator GeometryOutput >::apply(geometry_input, collection, distance_strategy, side_strategy, join_strategy, - end_strategy, circle_strategy, + end_strategy, point_strategy, robust_policy); collection.get_turns(geometry_input, distance_strategy); @@ -828,7 +828,7 @@ template typename SideStrategy, typename JoinStrategy, typename EndStrategy, - typename CircleStrategy, + typename PointStrategy, typename RobustPolicy > inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, @@ -836,13 +836,13 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - CircleStrategy const& circle_strategy, + PointStrategy const& point_strategy, RobustPolicy const& robust_policy) { detail::buffer::visit_pieces_default_policy visitor; buffer_inserter(geometry_input, out, distance_strategy, side_strategy, join_strategy, - end_strategy, circle_strategy, + end_strategy, point_strategy, robust_policy, visitor); } #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/strategies/buffer.hpp b/include/boost/geometry/strategies/buffer.hpp index 6b27c35bd..7dbe03b4a 100644 --- a/include/boost/geometry/strategies/buffer.hpp +++ b/include/boost/geometry/strategies/buffer.hpp @@ -65,7 +65,7 @@ enum piece_type buffered_join, buffered_round_end, buffered_flat_end, - buffered_circle, + buffered_point, buffered_concave // always on the inside }; From bfa80944ecddfd8ebd535d9e608675663b6b0589 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 18 Jul 2014 21:56:11 +0200 Subject: [PATCH 34/37] [buffer] avoid compiler warnings --- .../boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp | 2 +- .../algorithms/detail/buffer/buffered_piece_collection.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index d3f2aeebc..1ed549bc0 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -576,7 +576,7 @@ struct buffer_inserter SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, - PointStrategy const& point_strategy, + PointStrategy const& , RobustPolicy const& robust_policy) { if (boost::size(linestring) > 1) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 39b9d0e3f..216b17143 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -573,7 +573,7 @@ struct buffered_piece_collection inline void finish_ring() { BOOST_ASSERT(m_first_piece_index != -1); - if (m_first_piece_index < boost::size(m_pieces)) + if (m_first_piece_index < static_cast(boost::size(m_pieces))) { // If piece was added // Reassign left-of-first and right-of-last From 52d3c3a37106fd3d4fc5c3cb4af75d7c812a59e4 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 18 Jul 2014 22:27:43 +0200 Subject: [PATCH 35/37] [buffer] update doc and images --- doc/html/img/algorithms/buffer_linestring.png | Bin 0 -> 23637 bytes .../img/algorithms/buffer_multi_point.png | Bin 0 -> 20392 bytes .../img/algorithms/buffer_multi_polygon.png | Bin 0 -> 29751 bytes doc/html/svg_buffer_linestring.png | Bin 15155 -> 0 bytes doc/html/svg_buffer_multi_point.png | Bin 13451 -> 0 bytes doc/html/svg_buffer_multi_polygon.png | Bin 19624 -> 0 bytes .../algorithms/buffer_with_strategies.qbk | 18 +++--- .../algorithms/buffer_with_strategies.cpp | 14 ++--- .../examples_utils/create_svg_buffer.hpp | 52 ++++++++++++++++++ 9 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 doc/html/img/algorithms/buffer_linestring.png create mode 100644 doc/html/img/algorithms/buffer_multi_point.png create mode 100644 doc/html/img/algorithms/buffer_multi_polygon.png delete mode 100644 doc/html/svg_buffer_linestring.png delete mode 100644 doc/html/svg_buffer_multi_point.png delete mode 100644 doc/html/svg_buffer_multi_polygon.png create mode 100644 doc/src/examples/examples_utils/create_svg_buffer.hpp diff --git a/doc/html/img/algorithms/buffer_linestring.png b/doc/html/img/algorithms/buffer_linestring.png new file mode 100644 index 0000000000000000000000000000000000000000..2e135613e0ca8ce81109327b4e644529467eeddc GIT binary patch literal 23637 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 literal 0 HcmV?d00001 diff --git a/doc/html/img/algorithms/buffer_multi_point.png b/doc/html/img/algorithms/buffer_multi_point.png new file mode 100644 index 0000000000000000000000000000000000000000..2d21c6e3f8677893ee5fd54a2f80db4cd596d8c1 GIT binary patch literal 20392 zcmeAS@N?(olHy`uVBq!ia0y~yV4MoV9Bd2>3}(?e)(i{`EX7WqAsieW95oy%9SjT% zoCO|{#S9F**Fl)kNn>^e0|SF(iEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$ zQVa|V44y8IAr*7p+%2z=dAjra$M-pb>$ipKo}MQC?uLZ4!P!N#q_UhE1o#wLgZzXP z)KAV%nK60Z z+l!{}I3nci>YBo`p-1O|v4hkHy$|_k*6sf@tx)KL^@BU>uB|ytG1j00C$xG&Yt`1Zd4YkcDoHc`=u z3(pz(DgRh9;kJ4dN6og^&!ahYH4-H3kCng6vRRiRWGjC075CosqB|@P>=@KiBy!es z+Qv_aKhI~L|L#{M&j*HS6Pq*Z z-y7`TdPD&^q8B=z)s!k67HpkvF-8O&fJn5ppckZlZ ziLZ3@+tgp%tGN86mmKTS`>GKod0hb|dJOxnf34PM*~dMH!ysjzAYZqi-8=E25N)*IWn8P@Nf`}1dZ^(`^+ z+=JpDHtb%>8~jeS#Ud3QIu zH>`|JKgRq%QSy1xt@m<&_q%k8m0syS!gYFv!w2aq>km@PV(*FWXZumT|6BOHFX_*o zZVil@e=s?F{gT7;85|ZZpV{wI-8%VL$d@g;`98_sp>k$y+{fOjn669SP(N2-E~9uh ze-CRynV)50Uj6xu>c&tTZY|3`e;-g<+2SxXa9(TNcWlJd$wOeWnCy~#DFb?1&*_jP_-P1U{szWnUk z;`u2xZUqtV=l$X-yO#FYDCgO;cZ$0E_QwB?xPC#d|G22a$=i}b|36xrUwr1x*Ln8D zFX`*&|ESi-K2Og6`kIAZyks@&v7}px@BgSsefj0Ba!W^<@k8RReRjwD+qcd-HRU2d zQQvcZH3O((;{d;S?MVaPwAI@*JAzM{8*4$6A`V*&?HqF>N{mI^YH}6mJa&yw| zoOf?wR<-n{%8aYW4@KRIvH5v>PTU6_`>JZexBu?9%>6I7?C)F0^W`l;fr6cEr+?^t zxIH0aQn~W?IX~5F8c*8n_+-Rq*8kRW`ow^^}cu%a$L{ z>fZ7iRn=|lDP(zmyMn{c)=uQxec!%`U0o*}Hujh_3IAHhuqWc!cEh*toePB)3km-^ zD=IlV?AqtzN!usCPOA|(ThcDtuYKUgmA1N%-pkf3++{lX(yo)X8$YY<<3D;ovHY&r zgY++a;cPo(PVaD>`{%g-`u#3!O{pqO>zTTp9xZ?Nf76@!fe%hui0cxUjkL zJ!EA)@OT#U8g<=$bI+fvpZCm9zw_R?I$@5~0@n7p>upCaJ>vgrVzleI`sp7W27D{n z=Uoy$GjZn}KZg{LjXlL1d$vZnX;0h8e43+-Nq^=XjuyLbyLsgwU(&Abk7c~{=yqs8 zl8a-M?eb^sdfz9_j5rxCezx(E@y~g`wOOu*{8s&t{(xCW`Fx{KyNK<|4jJ9k7Qz*M z_c*(R3nkw>f2=Q#IvA1@_w?%Aqd%DCglu$UOkVP)rO1{TBwJ28y=-0Ds~JXKuQxG9 zOxQp9$_||eVm9k$e`vq*|0aw0{yoOOI{9R^w3OW6b5(JB1sw2OY;3^0Ui-jH*4;BE zhW6P%P_kXfJAEPF>4gcWR%k6N`MUXw==;3owmE9`1$#HeO`F)ADKBy4O`FW#e?px{ zjKmTo|F@=|;biOLJ*Lun{tn+hy_dhYYv}Hqd*(=(=#<0t( zy|j)P#W8$KmbBj3qi;Pq<;}$x`V$MLeH1vz%Eg$&b?M)M<$fy{oSl9;{+d|uwEz}} zvLZ|K`G1P8h^J3^aWi)M$y1*+e=x~?3f8u$t|@rheEj;J-)dCj*<_T_1zRy+-3Z#@`!?{=)`?7$GZO}J@2WHuT>FB`q;Ae z%(c>9R!WHZM?8HQPHFb$UdL6zUaqDk&Y z%snMtj5qO5n7l{-(9GPx^G6l6w2X`*+}_VGy_~10s#kJ$`Now?=Y(yrJ{5VgAeq7Z zT;o(_zba#$DzayEtYr+c@vJecpBQHQ_(qx<(ei)_KI<+@tX3jm`u2 z1J4)Fyp(YHwZ7yzJLh~y&a8~{OSf(PFBPZMe70|g>g^dTo*SMB2}!Yd{Xa@ky>foq z;cn$=K6U)tA98o9R=3}syy;g+%8y?KzcTmi`73&>W+j74&@SC?BDORn^K zZ4|lfy^7ZC%`+zMZ9OU+#$11_>M;Ku)*LpuLtEP4*x6`l8QDY}t9VfDVE7?F&+ezM zTIxLS^aF=?SF25alKcG09ivBg|0&<`RM}N_rRUkjt=ApSzup*?V7P4WwS#N=W?Q{V zeX+SG<$>&i1=^o1r%j!Ec*&Xa54)Ij=54ro@Qn*!eypot%a`pbO!h2##cB(M7u$(S z^4YoNJ96HNHNQAB#HBCLE5^Ge_4|uUBJaFQ|qef~>^{iq{vOT`P)wj=IqxoBmQi%U|#*@8yh^VKDep}S&C_C8I?pF<9YC9Ld1cx;QP}a z_&6ywuP|6^;$-qHyg49n;=(0@FL*jr)WVDmgMTkL@uB$S6wxI|uYZ%--BWhwn7z!I z7b{lyyS7cczx3bSX5aASBgzlKRF{Gb*CkNi($#fj)$8A` zZt5%FySQ!3OxBW^T%w?Ji*Zev(p-;_5S6gjb+sbzGar6wlI44MA@dJ&$w~`k?he*+=fGK6sc9zR^2RlQq1nQsL+*7zC zcJ>GMNgsFJ-dT{u$$jiyp_T4L#pP=h=ep#pFBaBrc<B`08>czY3WjYz21z4&>Tw{aCbI zSV%Ig>}ublmCCj{RnpT0<)jO=w1i@(88YrLQwh5l@WMq)>2O$J8gJpdZyQ#K&oH?m zzjl$*MYHwsD#{ygHQKne=}%8At~wahGhyP?_ioAeMZd1}*rLm-#qlmm+{8YAZt~3z zp75it(K99lo{V0qZmhPljZ<=e-?8IaU#7dT+pM6=C9?(an2+MM(CXM@q^^)|fxv_WIqL zcy^tGTTZioO1`pOsrfXh(9>_Y>!ABxzg}2WWa5kJ^7BvZSXmRy4*t|;_HuP)yFI-@ zpNWk@^z7!!)g@hvB|CduKF;$Hme+rOt1RijiWMgkb}xxPvW=JhlYr#SXHTX~e83sM zqEvL5ti*}_z`%(I&9=p-BrQwceW|l2!tCnQPc z#4GGzoZi@Yc4e}CLQK^a@twkg2{l!+Kq;$kM9DHUQKhFciZaz#W^lZ_N(OoXqwD$+3(9XEiI!9dJA?h z=o4BRX>8SaWcvW5_`vcQ!gSQ`Ues_0ub!Bt>c)d|+`DTHM z$sg`q+qp&~{zmB+vjWLwcPrLxzZl>zDKYJ1@Pi;5J%00Zan6Bhy_YpRPXyk&KH=D@ zPpq{{>CF3C@@%g~uUs7GHz&1*cL(>3K7E7Moc66A#+=o9hw`TfUaZkw zRvQv8b9K4W@#98$>i7Qcueeii>xSqY+q&JL2wRZB^sa5vVl6Q(t)e+ylN;tQjFoe3 z+a5N*egC@J-o3oD8%<|?OZ@H@G`~y6`t*kl8$a=c1h}+q|Fw-pE~e75TKXT;8kT+a zOT0rup4^ByCf`ss@752d^SN`q4}>KOO0K)7HP_EKyKMf6>l=D5^Otvab;;PC{vlBy zJ)tGHIx=wIgiE`8mR}Z{=y>VYOaU>&hGK}C?$y6twPszGIpOTGNYQ?+k<*tAyB$}p zII(fXD{)VMi*>bYTvIqKRu@=5zEu9La}CQpt2?S%T17fu4fiI>SFWs{VYckh&JvfD z3wJGk^RBabS?Q<$Lwke7WxF@`D|t1iB_~TR51#R_`ctrUM8t-pzYdk3Gw$ ze(t)L_VC7CzI0WkjfwnIYV2)REK+h0vpSzt&c&`3ZlOo{m{}X%9v&-{zEC)ZT^{`uF)qvGmETL1v?q*W6Ldb z_bpksIJ)8Kf%OiuUyC%R8FEH2-Z{4I)lZu*4^4kC|N5+CbV)YH>t%4juG)3K+5h@G z@jWeW*!_IP;rR!4b=f?>Bsg)#gcomnHt^J)Z>!bPD$;oQSIJj))?y{2OG}S#H%|Ss zY{QG!ckNfKII(b#K+zMknlq>LiZ#RqJ5{Iq#-97KrgX{C_e}dZ?_90*a_&+!I_<$w z*LqOh<3m|N)<3Ot+PB`6L@5ac^Eq_hG+(etseSwNDcTwyyPbY7@9?ny*D$|6=af#s5OD>$F~ zSe%$Mr)YVw&_sz(Puf(sl$5Oxs1ZCEdiH&2;KYAAhZ*7+mj&MC`hSNd@3CZBntXwk zsbD7~@7s^HTwdF6H&mPc@>a5xo*^a_8E$xTW{8W*GnI;(9X$0BTbNCjL?}sL)xUIW zrKOgVkjV3I#@6Yj5nt{v*t%b3)Afe11=}b1NbbG8GQ~xOE!HU2G*9`!yk8=#qUzZH zFq!=F<~wR+$9kvx_SDl$&aAB|c~-q6mT~#zNiS}1*H?Y`uzk7z?TyN{XBwGLN+uuM zV&*d^BEI(T*W269&Ir8xprr26jwp?vRo@%Cx@2zM3*IC-^+)og$5wOvT<3f|p?q2G z-@osh&t+wPRBM_4xr%w8bl#0kU%ca^HebA8vTWk&yYC;#OYc8*e6^ILt1I8?3Y&wf z5-BWI9}Y$a*ZsbI^Qe1P`O~S^;Wf{#<=1q%`3WU&3+;b6Q}_ABD-(Ivu;>NO@A{H1 zdGdhnk!rh>D}TYtxf4}bfqin*?#r{~+W zIdi7{Dt+zNpP%C#&_(Wwv57#$P3Bd*F@ zAzs0CnXhE-Y)%`G54Twz)TagZWbWs_BUdzk?$*g0BD)0F9yyw6UA`>6^nXmmjgX76 z0lRj_Y_m;tI((2<+RdNg#%A?WpDDp2%T+6CDq>`RFcsD=`l_YnJT-MkgFiz#^U4F! z2f_{Cu3Go`I%EB^@`w-98}ym&-&_4N+RMs%fcsCM@8)x?PUWSqKd7%*(4)i7r;=Ls zf6k;!7sXckW@V-O@7ZRixOSuAxyiF`J?wU?6Jm~OJNxI))S7@YxA`yjhlI2-oi6xl zllbMA{sZ>fK6}Rkqt|C+kDFgEpU2sdSR;Rbr~ISBr4wH4op9~k1?y!;dQ+>e@t^S5 zUB0KV#($4O?stbjQbr|9mY18Dn^y}n-nxBv-V&Ag{elf|-{$3iKi}E8uS|4`;EO|@ z(gquD#w7<|{lu~CueIpZh&0J`W_||sM9HfMOlN$%9h-js{q=jPG2RIugJRsY77ITQ zyem~@XS`6d|Fs%}pZ*Qclj}YzKJPXvW8SbMLv{U|4?$PwxaWCEiu*(vF4#Z)$eu%o z+E#t~^u&C=;ojg4rvn%>} zrzIw|^}gNKlk_09>c4a^fXE|A+qFc+Q}zNdwgHdeHe3b&Y5YeY;t(~&ffQ(w0-mazbT7DaQd=i)^ zTvyLB*8FUiXScIUeEa<~?5XnHJJk+eJ`;YfV$Ke`Vz(%(y(PcyE>U-R<0EPr$IDwd zZ})q<-*ZA&Z&H_Eb@s~2(p3AOCvU5=vih!V&r&{o<y2ZRPJT7nwm!A^s!z^s*E}!D>*s5fmn>j7xSZd% z@x%dd@7Et}KOD$jZ~yPdmAU>lhNbWR{XMz3#%}uYx7(O+-qhXdJ#9+fpFhv9=M-7_ z7oO;wRVcXVsFqgqYsCl4?2d1r_+)M4qx7A1X@>r}JPEh=-sa!Y!(e&xtL^cFobBE( zd3JorGITFI#%rE)xArh^bouWZz2w)|daiT|zn(25^yk-Si%Uz7n!9z#U8vJ)etoNM z;+-kl4bn3wPCfq9Rn=Dd?vi8I3;&);x5)Hy-Jcy2pu$#R!&rT+XBL~N2xEfVH94MN z-{$AA#D&d2<*=crpIMxN^T2k4x3K{-$NBHw^ITq^<8hlcd3w>yDO(jcmhF$u&h9)h zVe@jk=I7h`mM!|p`apliH%8H^!l{zqnbPKa*oOP=o;|sE`NqX*O#kncD4w00SrH>U zCu~Cxw_09_MzG+-gCE2-Dp&t@aDD0$aZD#6cK?q_C-sY?4(2i3s+Ie*&2i7|^}g#| zQX*Dn_$8*lmA9z9{rawA=@oh1(;m!f%)T?qzPqgd){*=8&fe3ZN2<4!w07|5|7+;B zuc;7ZmpYzUY^yK1|G<{_Z4aUXi&Ul+G6%R72+#T&acufRi}vbsHq!$;*`06Ao3ndT zWo4@05=|u`(f4m=p80poDTk-2`{KRU)E;Krl`=C^=djxN6r302_{aUn{#NZ~k59jL z79ZSSnflx(=XOHPF~_tNS(`6sU0m84@0KPjyPRi}3l6m0wDXJDl(^8fCwqKz54`2t zkW%!&PE>H>LoMZnicVWZzAU+P+K8*Mx^d-!_5*iklvxM6{k$o*%{wdcm*1yg<-gvd zf|CEzQs1Y&Jy>bWeeKZgSm{5RU&I-vP2|g2^nR13=RNZs&(DN6I>p^L?Oj^!fBf;Q zl$a{b>*p%=-!IZsQc^zoZ&}E^n{$pdF5A!i|HZw&7+2N#a8LLc_xqjeow_LfJ zqTocuhl(0M7vwuE-rw}=yu9Z(Gs_9>9Vaeq*jy%}pX<-d-@nIB^z;V?ZbtcKdwCiv zE2ATd5BMM8dnY_m=K6u->HA;BOj1%ZTy^*P!*cEQ3$~eZ@0hjpSia#~{gU`c%ihA) z0?e0-T)$r@S@A>p0tSZdANBW@zT-YnqctnIBK>^Hrb$^d=f|(&UF+haRFU~xXWBH~ zSHc?`nS6H3xLumum3oA^|59uK!=G=VZ`Qs~h^dmjdD1t=xOQjq&(01W*56XU-ZQhN z3;a1`x9C@h7<2G1SM6E9_X>*$PINxuv8G$#?zO*%J+!pmGcP>cuzAw=Vy}O3>6Zir zC7aUHrha?FEc%6K+1<@^kAHX*ys;;^(Yo>Ff%Q9z4^B=|jXxW`bpFG?dzW8)*{`m@ zwWr^wy4}!ImoHsg$!JT+R+W#>uZEhG?P1!}llfg|j`g3euGBM(VFEFWwO?#$dLCg^ zDK8+ivmr4%SVwT;<7*sum{tFBohW#-V*mVotgH#~hkXSf~3$K6Xe`QaXHmwRQS;O$`Qh;h3YgM=sO`ajw()ll~xP zLEr!0|B~gpuO3|6S!WhzcXn6vWQo~f2Qyi%KW0eB3r-Xcx;{%zahANC#4cA>IdzMN zYzob0_qS)fs_2=rgD)*5bF+@%#KtMt^7*HhJ$U;e&H3}!>8WRyZePIilc_LdtBUpH z2^}X4wimoHb5ji~k-Z5jLu?tH6=GBiB;GrOW9mpaH8;}`L_xLV9<))%3oO6C9uJ-LtIa;&M={{XbtuZCiI&>W+rlzm8shwDs!x4iA$b z%oCT*Q;}U&nIkTGnU7)N?O$pYQ5K66mK$?+cJvs$LoWVYAqweqD*FBphd72?4z{N%8 z(zDxMhc24-&RxVLzj*rsmfZC-nRJR(qy;BVJR@K5@x!do7B@`9>K}0ZIacSh`-#W& zqe1geHPuZle7ThGiK3E{e$M>E_kMMj{CNEFcIAQ35p9J_PA9Eg@ki~6#<{!4EFWLD zn$q2I;>5P4Sy>S(j2ae~Qa677bvkCw*;&lzH*G9ZDtyP+)qTxSYva|ITU=b+RCeEY zc4sd*V%c;~RP^)?i65*Nj_mmI^p4s22T$%4`JK}(*HIS~bvMS=79K z;4w!sC`aCB-l$3;wbModDi%$uW*_o-oyzA7Sx`~IrBzwiUxUe1E)m-^z&Dq6Q!;el|WpyTb z_nnm&Z4GfZa?WX7a}wE{{E*mMG|{ zOnPw9r&4fYgt6Y*dDh}{*eeX*M$Y(lFnO=5$*+({zg>?lo$mUu*wy7p21`!!uWc;1 z{+d2nw&u9azsQdlX9oUPKEHa)@AK>nG?Jyw&(w8WY_I=dAK~J{w|b*;AA5M5r}J+O z9;=NzSufZ9smK>^T@)nKes=qcta%>6?l!J7O`HETDk&9h`M2eljn`|n@0~XsgqGbc zv)L{^=XyM7dbM=HoX_fcPuCoh*)(bPNv}M)Dd&X+CqCZ1zc41^2*VzS9ud*gJ2)%0 zJpXamR`<-gx~?xRkG%q1T-ZW?yk1qb;Aus^nZ)A#`-FYXP2GwN|0Ul_gv?l zya(2=bRTCvI5qF_qMqD4M%z;o>|I=3*gT{^m}+Focg*IknSbi$ z_VK2btJ(h;ySO|#vS&js-*2hn%+GI^?^0!)ETN;7FH&i-{)N_q7PQpGerr~+xL3zY z3Vr_hSjk*WQ1H0#i4}^f>+E!@^q0Mr?zlbw#pJH;53i;@uzlxgtfXXg;*qUgSNA(* z3(s230`6shn;Uoi?fkZ~MBt5oBvV7<*_*BMb25UIl#Cj363#YmTyk{#r1`sggFn@s z(45VlvL$?n@ciXTl5xxW{)vBlS95Hse8RySw#<`fb#%dp5lII^$b#^T)#D-+!Gpx^uw1!P7_X z>CWS>k2QM?>l;1^3QlZ%WR#;fD~5?>m(uUXY=gJQ9Dkp9yd%xz z;a~MU=V<2cjw6e9?%dCIsp01VAD`b}5B}Nlxbp8+hk|cQx2qRjn(>x->V%GtISqG9 zXWDH4nv;{@^GGUh#$Tajxy-8#XCs{4aV-kj1{fs^X7X4-8FuB3x9;bnct0u36wvP*l|;CVF}XHov?e)Tw>_HuFQyE|u&Z{ozY z2ZS&BJbdvhMCY+ef^cnoxoB$M(`l3MORPEK;__t1)(`vNzg@aAneU)u=>0=mq!-OR zaB<(iS?(48JrBrr?2T}7dE%0@?o?WMu3m9bnX%d1x_4RSCEVW^>uUX#PcI7AVmA{N z6tq;UkF4gqoxO~4L(ct|2ZCoUuCX+*blRfzs;;cG$c66M$C^diM{I{l;4=?&|J;__XU0-Y3M4mqq5gvhQGS|;WxK7$`tTnT< zo|!zN6*Asl)e=ZJA$awe~Q-=C+=A=JIbc&zDd8^zx@ZZ(Wp<(k0~t z={=!VtzShiOU{iryJye#8D`J211@!>vZP;_UFK8s(EiJ0uMe6}zfFjUy}iQmoV$z5 zA=|AFOUy#gvMt!9+Ma8wm$RF5@(fM2yL{%qv>onG?O@DV`&Cs*DD-PCXAb9Wz8l+? z3&xzXdnU7M#f&oT4caPZ%Gr+-R&IOZ zWSQ%XZ=Np<_20bxVOE0F2XCL>x$VX_OO$*6oq8Jm{7&C(Q@tw9&W@e{#@i3#XZxon zKh4Rx?dtbQEN^Bt8)yD?>$$fscEyC~JT`gYnIJQ>b83v~+Ll9Kc4ermD;X`?vnN^X z{rgxEvAukk|Ls=(DbxP1R%_ZrCOO6?fAy_vBlqk|b}YFpBq-T^_FlB;=vwKv?CP6{Tl}-A+O1`%%EOvFync?BO^nX)|=e=hK{asyBSd1HjKgF^B ziJj>8K+dOncCn}I?tiXFw`ezP-K*Qf@LXKCKgmx?>G1t~Z6)*W6j<@Ei8(Zj`R4&f zG5;ST6WH%C`5f9(|0-wF@pl2TUq3!sZg*hDlE^tG%X%au*%!^9)p5dL>vFqh`}I57 z>KBx+Tyy1z|A(vF+-1*XIk?3AKE37k!V1d^Vs}eiT-+Mcx6hFc3Sf}BeV)B7GH@dg z^NhaRrEKLoGfuy7sef|X#pTJ4tv`j8UB0{6_B#sPTmH#3f%)Ho=09~udvn&DDOJ)G zoS2we9;>E1cQ5ysG!-4*?2TeS97BqwRQCFVs^^;R&v)FNe_|H%F~+h zOO30!yv%1a=_p@b*t2L+e&9{kKU<$`sIKc%oxJr5s9$lyyZ6h|Kig-Nz4% zDZg@`ZOJ#6+chWGSQ=cL*yG}o6zE)SlmBkssr}o}EM8<8;c-bg%HvDhdZj=9KELN* z^fxdo+5d0WjrTsO-fRJ4S94rkk}lqBE0K%+ENJzIlVQ#J8D~?2|DTyNNB-iiO8x@= z0;3NyAKclEOJm9dD|vSqKRNRx@M++AHy4#_Hx3BD)_{XB!!pO1o3OWitpD-ME6O6GIV zdl$`~F?Vyz#ZKLG%T$$wQhDEgwAuMk=9_u%;cdL!+5aMN=ZrCz5V{#W^MhYn^g5x?Cc&dz7zFZW!gj49bF$x5^M|Pm(^Zq z^hu8UJ|RiJfcNK0^TLx;#JDcKn(OQBqSEE{+W5DqNW-OF5B8}qlf9!K*SBK#;(zf6 zmQFE03~oPgnWZ%8m}6McciWw}^-|+}aki@B6jtfJ+^j|Ji0R^)Ra?+{(9@ z@N~j+#%WBs4(}!2G?|df53$8g(BY0Ep6A1Oj9w+<)G zuTbA<@K&v9u~gIHj?I(4Z>~7x=Dt}-&{EDn->y}Bd;F1q$DF>Ii+ysuDY<7)vRXjf z?XL<4m%jMDOZM`$Q;N(h$~`_NCx5co{lV_o(*BO8GhI_UwAP+~aQ1F-=6BTz69bN4 zy*&M4AuGd=`Q`S0-svxvxNLu2x$o(I9){BzEc-Z3n9e8M%6B*a`EY&t%iq%JzZpcQ z2(H^^cJKEYV`1*?IVWXmKO_W2IXVX4{qoW@G(2`|vcFT4{ezM^qeE+N+4qTW`}*#8 z+`R~o;&h?y=W5w*`0QT)-^RK=A^iOLgV&?ycL!}#4*G60)m7zq?X;u9n`X}6-|mqw zmwKc6+s#EAzuz@~e`nXOA5-4lm}MGi^F2ne-_C09GwJ&g|BlT}pB8R8b8!!Y?%cSz zTXxf5UGsT#_pQ#%Jxyz#q%oL<_`KTw{`b6HF%R-IHhz>|$|7F+=HH<|A|HA+((E5e ze%pJ8@y{}KBjs$}>*r%$#dtkxVV9d>`?ZlhP1i0)dirTT(9Fu7f}c-!e{ zLtE0n$gq}2>9A-SzP;M~ceRHG|A*EIC)VxiyrFaT@~IOWlijO69p?9szf$|A?DoGm zZ>H^PVX1fb?pEKo$;i-Hz@W$BK*8Pe`+JJd+id=G^30jCw>(-COW9)fY|OU$EmeHN zV?}!1y}o(-qNFQo?ndUUpXqjhPw$q6S+4o^`Jap!X0QI_%*Ey4{9B`L^B=}{FC+Zc zeiZp2H{pJ18FxXf$L|Mz-O5?pk48LVJl5_KWgYy1J;qix-ssKWH|fjg+`9L!kGZ4& zd-<7Jp|Mi(@4uJMKYuoN<=qX5S6Jqsf4XjUxBt(l`p?h(J6CQO@igYxqZP4R7gwY{ zchZ{m$+Iu}!IL{*=Y(&OsHUuR^e+}7JacikS$ z;+iLawKSAZpPT#A@~*wOsHx10=m3UEldY|}xMpdUz4trKd}EiXvHBl5Bd0CDY;1OY zn>BBFPusV^J-eUlsP$SM`0>SRTS)46ktun)b648z=Uq4RpUvs-bLBqnTmR;VZ1=YP z2h@}sA1rHpUN$$A>7R1SN4LxO_}|EXxbMr>!u>;YgK)!>9c*I$7oyCSJ%T4+4-TC= z<6iBYdH3W#M#ooGx%=-~qmx=}i~ELDSsDKawF`TBk3T&i^kDG;&l%r>nSW}ZcoF=iiUnTU{Qdci>>Nr(|nu@834w@UU-oXI-rHl^g6I9D2NtaUVwn zi+jXdhJCG>>tA2~lzc$*fKLMJvb~B=?3V2n&E0REQ+hsl=E)gL{wKJFX?^}&K2dCa z{vzcQhg#Xo%EhPF{th};v6nGEF0NR%A@}e++m*>$+QQXhlD5C!e7eiGRLie2_jyU! zl=I8amTP~|IJmsW!e{sYd)~`r6@IX6Qd(u{8~0+|KiQ&8}l7CH8NKHc~^eF{`gFtqlVI2$J<0jILelEe|gOGi=TgOrf*-J)}tkp z{nxGe{rmp>zrQP=zm0wVmCdP5L|x^F^}3yDzc($PSM@HQmDP8au)(Dz$6SBq#|eJ5 zN%8o=@SjDGyHhN6m2w%2m*>kbf1jwo-}C;vwDmE3&2T!_@dgJ>ewm8OfN8fU7P^gy__m6vDlB6W$3>vDg zy`HiyWG&OX<6Ev<&7E{)*}cCZI>{pCdVd5XJ%4#=DNTISI_bUT+?FHT?#;f z5+i%D;KYcqYY(i7lqFwQnZMlB<8Pq%SIJN6?vX`@WM@U{D>3A(JN4}8+w{QOW^6s) zjn)Ql`RDq1Ck20ha{N9+`G)Os->x;^FDpFvBlp}gH6_D`Ut_tOSy>w{H|%bhEqlfz zX$JS{0>PNDh1c0rms?Hl>o_vSY<~NxXMZ-laP51dRKp=D7^Jx!nL~r@LxWnZ`sm97u zE6&c`g^$mP_ugLBq@?s0w9xB%={{xiDHGSd@A(yCvrgWi^o!-0Gxv`6tZ8oFAL7!s zcUhl>Ty(h{XwD{>cgBouze1i&XmUMjw1?$)2p404w4Gh`E8!GXbL&}iJ1kz`Tw5F& zxo?C261fw{wph>c@=S{U{(61zOFa#Sy4%ht*ID+Zs3>hr_OEq}P?3#z;G$(@QX)Qe zO-Zz6YH24xQh1!oyrSJ3Zn_s!w&h^3D?z z1a!2P-DSAL9KswhW#`n*$MVbcbOk#(mp^;|@Yl@q6XtzTDqt^|ds)*nhkNewBuO@L zADijM-1hHcyp)8R|H)6uaF4KDbYT&b!$$TU{2#0)^miPY)b&iH?CP${!r#6#w%vbO zqVnylzSgut?#z#3nuToQzEQ`1@SI&BD%mL)zrRB_bn~vhX^htsZ&lCr@l1+;(NlGL z2V=#Iwr`wM%=@0N>=nOsX{EZ@#EEIqXJ>#`g(?>y;*g(Q(&&lSDTa*ocdaS(@$>u{dI|w(WNEF-J^Vyov(bJps2oQ#UI9u7nVjF zPWlFd0>e1A}}N@O`jbCYxEd*Q0~OxofxRbLKRY$$}GS2r=yAQeEq(uH@YQ{K9gtQ!j0nORl%J zta{ne@%Ys(p@`xI6KZ?eZm)7r+;slsl#~}8f0iUk>OBZQAX^bLcaHVL+;duYD}iOW8gq`~SF!I0FI>ujRru1mdu5BLCaZg-r`6V~;g@*jv z?_4T-AUsax%P`YB#Cx#6hpM%D_uUvc@c+$gVjN+#`KTGj4+9Ffsu`$($(azKDkjc8a4;L$}wOci_v!gif);|{S)Ax>VF`X09cQWzW z$`Wlq=6~u^Cp$cRGMM)gF0tgR%f)p@}bkC){7Mp^3@h`ox$N59^>n z&-datW5qM)vkFR{%DLSk(A!@nXY@pN!b$6-Z7!aQnd88Q=VtU!Jt^`3dJPU1d&- z=8AH?c&l1L&wI-K62cP~W|&X;bK#{*N``e&qrqFT1=%bfh3o|f7o@2uUA+9ReDkV3 z0`UiY(;f+*DY8Yq}p%4cHgA7vR*zx$yN7mn6CAAWSqfv z=S7H>k&R4kVB=<|z9{S9h<*8w4lGkv3Jkt#q~#QnFaM-P#yjxlZT(AE1nnZdT-v(+ zvA*}<4reu+uCbtG4g2i*kGG%R&fGhr?EiK_rQ|dZZ~cl0H?t2cA>vFMR+p)!k`)9&SoT7JnGUr=IXq%KO!7&$UiVeB zo-nj%R6N>{n!?1mul615j-GDNn6ISHd&iT9{nQl?U+)y1DtB~o=J&rH%g(X5sc+*s z!0Vc_AZN{)hevatKiX`YV1MYk)%y}FRmpv9%T`1jD{staG{`+uWoPx;R_SepuF}QO ztCNnr533Q0S6Ju&<@Ahi=VecOwrzd0N3XlpR+ z?0cf5e5g}=s)z9MZDIa$4ZpiibiVpft?Z(`XkL4d1an}>HRi?%9_{vjW>4&}NOU^J z7}K`jKgIfkdi$n{f)9>#cV)h3s`I#i$jH9_Ea&}j7r#4i=KMW#`nS~wjSmb5-!^5- zp7Uzk$SC!fHR4#!1EH8>+BL7|TsG{HWG+q?v{WE=}d%yf@8ir)KD!@GYFv7usJ@YF@iix$pS3xySzhIA66z z;@Smcb*~bGXO$f-rh%?cOI(gzooNq}Vc^i>Z`1;v%CVChMZ~3J?OZU4_K=jJDa}NGF!xzb`cEo~1qj$Ui`UTe?D`ZF6 zMvLEJR^7C6wSn)Ou2cML;u+qm?x|xp4!X4?_hhxssjU99?c9c}nh#nR-)=hH&ij4g z>ie^%P7)9{T`qJ|y5P}QYlasRXC6-V-`0QeUI<5_;i*}l4s&rGa9;LA>Bxi|BBINu zvFLDi^8S(uF*(^~ps08C=es!?7f;Q2u6RUaqo&rbPe#8IPb7NnTE|g%GR?~BuoBmg zsgf%>40Xy5#~;i6dGW#Om*3Q`on6`c@Hw~P)|?aTmntNi7qDfp<++EypEYNyM}c9? zUselK?gIV`N1TstU7}hqz2T@HqvA3KR_E_Ocn^GEcqBc`&Z$S}_9CHo%}1>ZOKm-l zJBVFBZ+|G%@{)~5$3~VZ$Fi?xuguX*nzgq7$`kjU`@g%VEmu8~@k~^7`7%a%=F`m^ zvp@3}c`wY-RCF=fzdFu2^75>}iFQ5gGEWaC8D<_S@>9K2+M}nz;4XFT;@fSrC-(_V zo?)M`aFuS&_lF@0w|h!jB)Vt1E*1LF?o!jJ67~Di8Bg~P&o!rWk4tZiT*Cf1FTTU` z@Sa7BR&zVNsQ6$Kz1=2N-$f+yGTV&Vfns8R^>#@asLCrIOL#Vy>p=5?*aNc<^hZwG z%=?0E!THHKNpVgy)~_`0JvA+c$%}bbqn_~$ zGc{)JX;0sGiKTg#(PCF-%$+7+xVRx)YyHwyxvXB19^1Yd+ZQv}UsLOjII<-D+gz_D z*H?90-VStehU9ukIM@d{biiIS?JLspM8s% zW-BYn&x@D+ZPH?J^7vWr#V+YbZ1@%R4yNd6>ASnU340l%F65q7lt1M~vEg~=4sU~> zU0v(y`2VmUJ7Lt&ztr-nTAGSWPON#k{;V+jFRR2WIAZtar+GQWtT|~OXn$sj+R zoa_BJY;ud1>Q6s4t>)U3t44SA%Jq}7G;(zoY)TbmmE>Ks^O5tVxBbqZ>VCPR51hhf z)0S%-IXY{PtLhzo+53x%Kg4rtXp5aaKWk6_j?%)`o0*)2k#SaWKBc$29=uk0tzU6u z`{g|?Ejw%`=l{so5og=y-GA6xw||i zISX$-TD(Fc`q^{0Bi_>7$@6;z9xqu`88_vHWXV<8&oM0$>K_9`N<v&-o6%Kk zto@ZI z)06+glgQexb>zv1%gN?J*G;Q-FJv&_jy<{VPLfw=zva}87F+*JXkxl>Y5H-+o7z4; zO6s?Z4{>ox)PFadHL*`XSaV-D*B9osf)_<*n}1u$Vc51N^KalHy$5q6mMa}`>3+W` z$>i5BErUxdPOQ3Wtp7RZ!`3b8VjHi$-4=W+qTzPFP59KeD^!netG*&Bdmw!2!D%zP z9@YD?9#|>L5Z!3=Ao9yuv01V(V3jdbjUhj)K8guV`ppwAi}5A;0xVUc`>+ub<5`Qdcy5 zDx0hEpjY_z;YIliR?9AXqTIsysQSn2%dX#+SlkLoagtLCl*x^eQ`OpS*U@4$wfj`I z;KVH}YPDJ<>FK!Mfn8%^m;av*WX-G%+c^UEk`F(HRl)jj3H}QSq|V$Lf@< zj(VKjp|qFXJ?KZk%ea!Q(uyuIxwZCoB~Op9yxVti`y;gjO=myx8U-^Q=zX&;>iExh zmJwSRyf^t5US8yX#y4Wdv$>Z~YvjiC-hQ5tmZco8SJhqe+j~c?KeJTgN zeQ&n!DUXgF6FLsZFKpxHatO{($^UR!_S1(bC99kJG?bowTRL+>r$C|V$F}`;vAHfs zo^Ma;S&@CEJUyVO%#>@!)LZ9xxwSnvo!E4-;_7qHXHWgtE#A1Cq5iie zpip;}+cv)*o+F&YbYI_}m0F{@_{b z7FqUx&$@p3^-RC4BL45Of5j~O>L#td_)qx)a|mm^Wb2cdH9?|DS`#{dbuV4*^$T*Zke^n&UP*SDGwoD- zu6J(LqkT#<@AS6TlTtsb}Lhs|=m7}2sc_FYmpZ4a(Idw7QZYWHxv7J=!m zZTs!CV?%}amCsl>^}`~g2i~0j{y6@vS#?Y7(sNH`{k@HEyH9&;JZYaaeRb`DgX*B|6;Uet$%25zbm+`dzTO6(vOoDm$Pwm9eBy@eKVBvgG9R3J4U{qU5{cP zbZ_(x>NuiQuJzb8y#C0_wM_30|A^x+tbZ@h@S`==j#2bi?DrkUE8m}5qHy>|@td{5 z+8Hlq_L@&PvT5e>C2v1!)LZPF)b&j152N(WzO=G+RkKBA_v>w+>o{Ne(Vtbtbl^nqYCIiyncJ{=2L=EtDTIisr_tIuzd*@n0Rd7 z&MW2TAKepWSJ%5~@$q)QdC{WUCBFH^`F8qYIS=&LSI+tN@AH9Nhi@yi?;L197{05B zIo0q~SVxPxtEw3v?%-J5PDPbklsvv0y#>vXdV?>!GsymR{Q>F*P5&q{dZygc1&v47ugNv}AQUHh|d z8<>^O>D?&vBm2dx!yVZz0)~pNs$wNi+2>enecs^oKxJ1JuN?o1?~T$<>puQuFZ}Jb z@itfG+E-?NeNjiBywZ8{%=P^y#rDmc%W-6(soBmOVzx4-)juZ+C#WA=p2%%_|}Zy!nsw2at3!MXJHi?1mOTYp4M zE1sjTXWL|&6Tc~M``j%l{9?I(rgQvY7Q4kRlj8rH|7Q&AlsU1d*uP4D`0+Mk3q$rN zyGPfKK4qA*Yl6IvhH_=v$Mfv-oWh$cw)Pu*yQ9Uz*0{Xk_%Yjh#Unc=EHaXmDA%oT z3f5-2)RF>Hn4_da`Cp>;UE%Zsc$>zGgjWOR2 z>~ylT**{C}JI|!Gd0lDK3vW;Q)M3L`W45ffaQfnga|cC?-n{ErRI(zE@ptS|o*zLQ zv+Tm+15f38_f+->=Wf37ewSTEoH@3ASq=)L{7ordLU;c40*SFd-EDcn=Z_WJph z%kR%7?q4m@f4?H_*yHWROA?v6(@Zw!EZZ1*vU;nxMy}4H+jCo$SGI4hT$&RZAY8LP z+4tug+hCvd>XTKv+ZWw2+Gh}Aa<1I}`P<9ptmnUKOS?;7-(<17PxYqyimchbI~q29 zSpDh0Q}}=H?r+5k@;59>zGxJrPkFyA|IB+|4#Uh7#abU7!j~SgTe~ HDWM4fU58%G literal 0 HcmV?d00001 diff --git a/doc/html/img/algorithms/buffer_multi_polygon.png b/doc/html/img/algorithms/buffer_multi_polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c94a1403b91fa4218d77e4f16901bfed206ac0 GIT binary patch literal 29751 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 ogH4zBwDcWLV8 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 literal 0 HcmV?d00001 diff --git a/doc/html/svg_buffer_linestring.png b/doc/html/svg_buffer_linestring.png deleted file mode 100644 index 4c42c7ec2b59fa976012fbd403497e0367e7c5d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15155 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 diff --git a/doc/html/svg_buffer_multi_polygon.png b/doc/html/svg_buffer_multi_polygon.png deleted file mode 100644 index 8bf482d1dca2d7b4a8d582c0f3040b4d70eaeb30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19624 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 Xzr1u~jnPU51_lOCS3j3^P6w44 diff --git a/doc/reference/algorithms/buffer_with_strategies.qbk b/doc/reference/algorithms/buffer_with_strategies.qbk index 0ca3c7f9a..09096e51c 100644 --- a/doc/reference/algorithms/buffer_with_strategies.qbk +++ b/doc/reference/algorithms/buffer_with_strategies.qbk @@ -1,9 +1,7 @@ [/============================================================================ Boost.Geometry (aka GGL, Generic Geometry Library) - Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. - Copyright (c) 2009-2012 Mateusz Loskot, London, UK. - Copyright (c) 2009-2012 Bruno Lalande, Paris, France. + Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -17,12 +15,12 @@ [heading Examples] [buffer_with_strategies] -[heading Output] -The linestring case -[$svg_buffer_linestring.png] -The multi_point case -[$svg_buffer_multi_point.png] +[heading The linestring case] +[$img/algorithms/buffer_linestring.png] -The multi_polygon case -[$svg_buffer_multi_polygon.png] +[heading The multi_point case] +[$img/algorithms/buffer_multi_point.png] + +[heading The multi_polygon case] +[$img/algorithms/buffer_multi_polygon.png] diff --git a/doc/src/examples/algorithms/buffer_with_strategies.cpp b/doc/src/examples/algorithms/buffer_with_strategies.cpp index 2f47cee17..db2264bfd 100644 --- a/doc/src/examples/algorithms/buffer_with_strategies.cpp +++ b/doc/src/examples/algorithms/buffer_with_strategies.cpp @@ -13,7 +13,7 @@ #include #include #include -/*<-*/ #include "create_svg_two.hpp" /*->*/ +/*<-*/ #include "../examples_utils/create_svg_buffer.hpp" /*->*/ int main() { @@ -41,9 +41,9 @@ int main() boost::geometry::buffer(ls, result, distance_strategy, side_strategy, join_strategy, end_strategy, circle_strategy); - /*<-*/ create_svg("buffer_linestring.svg", ls, result); /*->*/ + /*<-*/ create_svg_buffer("buffer_linestring.svg", ls, result); /*->*/ - // Declare/fill of a multi point + // Declare/fill a multi point boost::geometry::model::multi_point mp; boost::geometry::read_wkt("MULTIPOINT((3 3),(4 4))", mp); @@ -51,17 +51,17 @@ int main() boost::geometry::buffer(mp, result, distance_strategy, side_strategy, join_strategy, end_strategy, circle_strategy); - /*<-*/ create_svg("buffer_multi_point.svg", mp, result); /*->*/ + /*<-*/ create_svg_buffer("buffer_multi_point.svg", mp, result); /*->*/ - // Declare/fill of a multi_polygon + // Declare/fill a multi_polygon boost::geometry::model::multi_polygon mpol; boost::geometry::read_wkt("MULTIPOLYGON(((0 1,2 5,5 3,0 1)),((1 1,5 2,5 0,1 1)))", mpol); - // Create the buffer of a polygon + // Create the buffer of a multi polygon boost::geometry::buffer(mpol, result, distance_strategy, side_strategy, join_strategy, end_strategy, circle_strategy); - /*<-*/ create_svg("buffer_multi_polygon.svg", mpol, result); /*->*/ + /*<-*/ create_svg_buffer("buffer_multi_polygon.svg", mpol, result); /*->*/ return 0; } diff --git a/doc/src/examples/examples_utils/create_svg_buffer.hpp b/doc/src/examples/examples_utils/create_svg_buffer.hpp new file mode 100644 index 000000000..09ed307c1 --- /dev/null +++ b/doc/src/examples/examples_utils/create_svg_buffer.hpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Code to create SVG for examples + +#ifndef CREATE_SVG_BUFFER_HPP +#define CREATE_SVG_BUFFER_HPP + +#include +#include + +#if defined(HAVE_SVG) +# include +#endif + +template +void create_svg_buffer(std::string const& filename, Geometry1 const& original, Geometry2 const& buffer) +{ +#if defined(HAVE_SVG) + std::cout << std::endl << "[$img/algorithms/" << boost::replace_all_copy(filename, ".svg", ".png") << "]" << std::endl << std::endl; + + typedef typename boost::geometry::point_type::type point_type; + std::ofstream svg(filename.c_str()); + + boost::geometry::svg_mapper mapper(svg, 400, 400); + mapper.add(original); + mapper.add(buffer); + + // Draw buffer below + mapper.map(buffer, "fill-opacity:0.6;fill:rgb(255,255,64);stroke:rgb(255,128,0);stroke-width:5;stroke-dasharray:1,7;stroke-linecap:round"); + + // Draw original on top + mapper.map(original, "fill-opacity:0.6;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3"); + +#else + boost::ignore_unused_variable_warning(filename); + boost::ignore_unused_variable_warning(original); + boost::ignore_unused_variable_warning(buffer); +#endif +} + +// NOTE: convert manually from svg to png using Inkscape ctrl-shift-E +// and copy png to html/img/algorithms/ + + +#endif // CREATE_SVG_BUFFER_HPP + From cebad2e20c1606bb6598e304c9d18f537a5cd0ee Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 18 Jul 2014 22:49:48 +0200 Subject: [PATCH 36/37] [buffer][doc] small changes in outputted text/comments --- doc/src/examples/examples_utils/create_svg_buffer.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/src/examples/examples_utils/create_svg_buffer.hpp b/doc/src/examples/examples_utils/create_svg_buffer.hpp index 09ed307c1..b69d281bb 100644 --- a/doc/src/examples/examples_utils/create_svg_buffer.hpp +++ b/doc/src/examples/examples_utils/create_svg_buffer.hpp @@ -6,13 +6,12 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// Code to create SVG for examples +// Code to create SVG for buffer examples #ifndef CREATE_SVG_BUFFER_HPP #define CREATE_SVG_BUFFER_HPP #include -#include #if defined(HAVE_SVG) # include @@ -22,8 +21,6 @@ template void create_svg_buffer(std::string const& filename, Geometry1 const& original, Geometry2 const& buffer) { #if defined(HAVE_SVG) - std::cout << std::endl << "[$img/algorithms/" << boost::replace_all_copy(filename, ".svg", ".png") << "]" << std::endl << std::endl; - typedef typename boost::geometry::point_type::type point_type; std::ofstream svg(filename.c_str()); @@ -31,7 +28,7 @@ void create_svg_buffer(std::string const& filename, Geometry1 const& original, G mapper.add(original); mapper.add(buffer); - // Draw buffer below + // Draw buffer at bottom mapper.map(buffer, "fill-opacity:0.6;fill:rgb(255,255,64);stroke:rgb(255,128,0);stroke-width:5;stroke-dasharray:1,7;stroke-linecap:round"); // Draw original on top @@ -45,7 +42,7 @@ void create_svg_buffer(std::string const& filename, Geometry1 const& original, G } // NOTE: convert manually from svg to png using Inkscape ctrl-shift-E -// and copy png to html/img/algorithms/ +// and copy png to html/img/... #endif // CREATE_SVG_BUFFER_HPP From 46068123b9cf93b68e3484c276eb3fb6c6841d01 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 19 Jul 2014 14:36:39 +0200 Subject: [PATCH 37/37] [buffer] create documentation about PointStrategy (buffer_circle) add buffer_square as alternative --- doc/html/img/strategies/buffer_circle.png | Bin 0 -> 14517 bytes doc/html/img/strategies/buffer_square.png | Bin 0 -> 3768 bytes doc/imports.qbk | 3 + doc/make_qbk.py | 1 + doc/reference.qbk | 2 + .../algorithms/buffer_with_strategies.qbk | 5 +- doc/src/examples/Jamfile.v2 | 1 + doc/src/examples/strategies/Jamfile.v2 | 15 +++ doc/src/examples/strategies/buffer_circle.cpp | 53 +++++++++ doc/src/examples/strategies/buffer_square.cpp | 53 +++++++++ .../strategies/cartesian/buffer_circle.hpp | 26 ++++- .../strategies/cartesian/buffer_square.hpp | 107 ++++++++++++++++++ .../boost/geometry/strategies/strategies.hpp | 1 + 13 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 doc/html/img/strategies/buffer_circle.png create mode 100644 doc/html/img/strategies/buffer_square.png create mode 100644 doc/src/examples/strategies/Jamfile.v2 create mode 100644 doc/src/examples/strategies/buffer_circle.cpp create mode 100644 doc/src/examples/strategies/buffer_square.cpp create mode 100644 include/boost/geometry/strategies/cartesian/buffer_square.hpp diff --git a/doc/html/img/strategies/buffer_circle.png b/doc/html/img/strategies/buffer_circle.png new file mode 100644 index 0000000000000000000000000000000000000000..c48369ea123c5105a9c3347f68405696729727b4 GIT binary patch literal 14517 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 NgQu&X%Q~loCIIP&CO!ZF literal 0 HcmV?d00001 diff --git a/doc/html/img/strategies/buffer_square.png b/doc/html/img/strategies/buffer_square.png new file mode 100644 index 0000000000000000000000000000000000000000..d03500eecf168ec2c58549c00704fce17d75c1ae GIT binary patch literal 3768 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 literal 0 HcmV?d00001 diff --git a/doc/imports.qbk b/doc/imports.qbk index f490a0ab0..4314a783a 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -114,5 +114,8 @@ [import src/examples/io/wkt.cpp] [import src/examples/io/read_wkt.cpp] +[import src/examples/strategies/buffer_circle.cpp] +[import src/examples/strategies/buffer_square.cpp] + [import src/examples/views/box_view.cpp] [import src/examples/views/segment_view.cpp] diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 333cf3d5c..6cd47f83c 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -115,6 +115,7 @@ strategies = ["distance::pythagoras", "distance::pythagoras_box_box" , "distance::cross_track", "distance::projected_point" , "within::winding", "within::franklin", "within::crossings_multiply" , "area::surveyor", "area::huiller" + , "buffer::buffer_circle", "buffer::buffer_square" , "centroid::bashein_detmer", "centroid::average" , "convex_hull::graham_andrew" , "simplify::douglas_peucker" diff --git a/doc/reference.qbk b/doc/reference.qbk index ffbc95f40..020bffa18 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -300,6 +300,8 @@ [include generated/distance_cross_track.qbk] [include generated/area_surveyor.qbk] [include generated/area_huiller.qbk] +[include generated/buffer_buffer_circle.qbk] +[include generated/buffer_buffer_square.qbk] [include generated/centroid_average.qbk] [include generated/centroid_bashein_detmer.qbk] [include generated/convex_hull_graham_andrew.qbk] diff --git a/doc/reference/algorithms/buffer_with_strategies.qbk b/doc/reference/algorithms/buffer_with_strategies.qbk index 09096e51c..197ab3ace 100644 --- a/doc/reference/algorithms/buffer_with_strategies.qbk +++ b/doc/reference/algorithms/buffer_with_strategies.qbk @@ -15,7 +15,6 @@ [heading Examples] [buffer_with_strategies] - [heading The linestring case] [$img/algorithms/buffer_linestring.png] @@ -24,3 +23,7 @@ [heading The multi_polygon case] [$img/algorithms/buffer_multi_polygon.png] + +[heading Available Strategies] +* PointStrategy: [link geometry.reference.strategies.strategy_buffer_buffer_circle Circle (cartesian)] +* PointStrategy: [link geometry.reference.strategies.strategy_buffer_buffer_square Square (cartesian)] diff --git a/doc/src/examples/Jamfile.v2 b/doc/src/examples/Jamfile.v2 index 90c5337d2..fbc49fe39 100644 --- a/doc/src/examples/Jamfile.v2 +++ b/doc/src/examples/Jamfile.v2 @@ -19,4 +19,5 @@ build-project algorithms ; build-project core ; build-project geometries ; build-project io ; +build-project strategies ; build-project views ; diff --git a/doc/src/examples/strategies/Jamfile.v2 b/doc/src/examples/strategies/Jamfile.v2 new file mode 100644 index 000000000..fe25d740b --- /dev/null +++ b/doc/src/examples/strategies/Jamfile.v2 @@ -0,0 +1,15 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. + +# Use, modification and distribution is subject to the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + + +project boost-geometry-doc-example-strategies + : # requirements + ; + +exe buffer_circle : buffer_circle.cpp ; +exe buffer_square : buffer_square.cpp ; diff --git a/doc/src/examples/strategies/buffer_circle.cpp b/doc/src/examples/strategies/buffer_circle.cpp new file mode 100644 index 000000000..237824a85 --- /dev/null +++ b/doc/src/examples/strategies/buffer_circle.cpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[buffer_circle +//` Shows how the buffer_circle strategy can be used as a PointStrategy to create circular buffers around points + +#include +#include +#include +/*<-*/ #include "../examples_utils/create_svg_buffer.hpp" /*->*/ + +int main() +{ + typedef double coordinate_type; + typedef boost::geometry::model::d2::point_xy point; + typedef boost::geometry::model::polygon polygon; + + // Declare the buffer_circle strategy + const int points_per_circle = 360; + + boost::geometry::strategy::buffer::buffer_circle circle_strategy(points_per_circle); + + // Declare other strategies + const double buffer_distance = 0.7; + boost::geometry::strategy::buffer::distance_symmetric distance_strategy(buffer_distance); + boost::geometry::strategy::buffer::join_round join_strategy(points_per_circle); + boost::geometry::strategy::buffer::end_round end_strategy(points_per_circle); + boost::geometry::strategy::buffer::buffer_side side_strategy; + + // Declare output + boost::geometry::model::multi_polygon result; + + // Declare/fill of a multi point + boost::geometry::model::multi_point mp; + boost::geometry::read_wkt("MULTIPOINT((3 3),(3 4),(4 4),(7 3))", mp); + + // Create the buffer of a multi point + boost::geometry::buffer(mp, result, + distance_strategy, side_strategy, + join_strategy, end_strategy, circle_strategy); + /*<-*/ create_svg_buffer("buffer_circle.svg", mp, result); /*->*/ + + return 0; +} + +//] + diff --git a/doc/src/examples/strategies/buffer_square.cpp b/doc/src/examples/strategies/buffer_square.cpp new file mode 100644 index 000000000..ea38be9b5 --- /dev/null +++ b/doc/src/examples/strategies/buffer_square.cpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[buffer_square +//` Shows how the buffer_square strategy can be used as a PointStrategy to create square buffers where the original point lies in the center + + +#include +#include +#include +/*<-*/ #include "../examples_utils/create_svg_buffer.hpp" /*->*/ + +int main() +{ + typedef double coordinate_type; + typedef boost::geometry::model::d2::point_xy point; + typedef boost::geometry::model::polygon polygon; + + // Declare the buffer_square strategy + boost::geometry::strategy::buffer::buffer_square square_strategy; + + // Declare other strategies + const int points_per_circle = 36; + const double buffer_distance = 0.5; + boost::geometry::strategy::buffer::distance_symmetric distance_strategy(buffer_distance); + boost::geometry::strategy::buffer::join_round join_strategy(points_per_circle); + boost::geometry::strategy::buffer::end_round end_strategy(points_per_circle); + boost::geometry::strategy::buffer::buffer_side side_strategy; + + // Declare output + boost::geometry::model::multi_polygon result; + + // Declare/fill of a multi point + boost::geometry::model::multi_point mp; + boost::geometry::read_wkt("MULTIPOINT((3 3),(3 4),(4 4),(7 3))", mp); + + // Create the buffer of a multi point + boost::geometry::buffer(mp, result, + distance_strategy, side_strategy, + join_strategy, end_strategy, square_strategy); + /*<-*/ create_svg_buffer("buffer_square.svg", mp, result); /*->*/ + + return 0; +} + +//] + diff --git a/include/boost/geometry/strategies/cartesian/buffer_circle.hpp b/include/boost/geometry/strategies/cartesian/buffer_circle.hpp index e5a12dd1c..5ff3d30e6 100644 --- a/include/boost/geometry/strategies/cartesian/buffer_circle.hpp +++ b/include/boost/geometry/strategies/cartesian/buffer_circle.hpp @@ -22,14 +22,38 @@ namespace boost { namespace geometry namespace strategy { namespace buffer { -// Strategy to create a buffer around a point using a specified amount of points +/*! +\brief Create a circular buffer around a point +\ingroup strategies +\details This strategy can be used as PointStrategy for the buffer algorithm. + It creates a circular buffer around a point. It can be applied + for points and multi_points, but also for a linestring (if it is degenerate, + so consisting of only one point) and for polygons (if it is degenerate). + This strategy is only applicable for Cartesian coordinate systems. + +\qbk{ +[heading Example] +[buffer_circle] +[heading Output] +[$img/strategies/buffer_circle.png] +[heading See also] +\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)] +} + */ class buffer_circle { public : + //! Constructs the strategy with default number of points (90) + buffer_circle() + : m_count(90) + {} + + //! Constructs the strategy specifying the nuber of points explicit buffer_circle(std::size_t count) : m_count(count) {} + //! Fills output_range with a circle around point using distance_strategy template < typename Point, diff --git a/include/boost/geometry/strategies/cartesian/buffer_square.hpp b/include/boost/geometry/strategies/cartesian/buffer_square.hpp new file mode 100644 index 000000000..5c4fd7586 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/buffer_square.hpp @@ -0,0 +1,107 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SQUARE_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SQUARE_HPP + +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace buffer +{ + +/*! +\brief Create a squared form buffer around a point +\ingroup strategies +\details This strategy can be used as PointStrategy for the buffer algorithm. + It creates a square from each point, where the point lies in the center. + It can be applied for points and multi_points, but also for a linestring (if it is degenerate, + so consisting of only one point) and for polygons (if it is degenerate). + This strategy is only applicable for Cartesian coordinate systems. + +\qbk{ +[heading Example] +[buffer_square] +[heading Output] +[$img/strategies/buffer_square.png] +[heading See also] +\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)] +} + */ +class buffer_square +{ +private : + template + < + typename Point, + typename DistanceType, + typename OutputRange + > + inline void add_point(Point const& point, + DistanceType const& distance, + DistanceType const& x, + DistanceType const& y, + OutputRange& output_range) const + { + typename boost::range_value::type p; + set<0>(p, get<0>(point) + x * distance); + set<1>(p, get<1>(point) + y * distance); + output_range.push_back(p); + } + + template + < + typename Point, + typename DistanceType, + typename OutputRange + > + inline void add_points(Point const& point, + DistanceType const& distance, + OutputRange& output_range) const + { + add_point(point, distance, -1.0, -1.0, output_range); + add_point(point, distance, -1.0, +1.0, output_range); + add_point(point, distance, +1.0, +1.0, output_range); + add_point(point, distance, +1.0, -1.0, output_range); + + // Close it: + output_range.push_back(output_range.front()); + } + +public : + + //! Fills output_range with a square around point using distance_strategy + template + < + typename Point, + typename DistanceStrategy, + typename OutputRange + > + inline void apply(Point const& point, + DistanceStrategy const& distance_strategy, + OutputRange& output_range) const + { + add_points(point, distance_strategy.apply(point, point, + strategy::buffer::buffer_side_left), output_range); + } + +}; + + +}} // namespace strategy::buffer + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SQUARE_HPP diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index eea784e4f..37327eed9 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include