$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r76767 - in trunk: boost/geometry/extensions/algorithms boost/geometry/extensions/strategies libs/geometry/test_extensions/algorithms libs/geometry/test_extensions/algorithms/buffer
From: barend.gehrels_at_[hidden]
Date: 2012-01-28 16:13:41
Author: barendgehrels
Date: 2012-01-28 16:13:39 EST (Sat, 28 Jan 2012)
New Revision: 76767
URL: http://svn.boost.org/trac/boost/changeset/76767
Log:
Harmonized offset with buffer, using range_buffer, and making hooklets vary on parameter.
This repairs offset (broken few days)
Added:
   trunk/boost/geometry/extensions/algorithms/offset_appender.hpp   (contents, props changed)
Text files modified: 
   trunk/boost/geometry/extensions/algorithms/offset.hpp                 |   114 ++++++++++----------------------------- 
   trunk/boost/geometry/extensions/strategies/buffer.hpp                 |    35 ++++++++---                             
   trunk/libs/geometry/test_extensions/algorithms/buffer/test_buffer.hpp |     6 +                                       
   trunk/libs/geometry/test_extensions/algorithms/offset.cpp             |    29 ++++-----                               
   4 files changed, 71 insertions(+), 113 deletions(-)
Modified: trunk/boost/geometry/extensions/algorithms/offset.hpp
==============================================================================
--- trunk/boost/geometry/extensions/algorithms/offset.hpp	(original)
+++ trunk/boost/geometry/extensions/algorithms/offset.hpp	2012-01-28 16:13:39 EST (Sat, 28 Jan 2012)
@@ -11,20 +11,12 @@
 
 #include <boost/config.hpp>
 
-#if defined(BOOST_MSVC_FULL_VER)
-#pragma message ("WARNING: offset might give wrong results, will be harmonized with range_buffer")
-#else
-#warning "WARNING: offset might give wrong results, will be harmonized with range_buffer"
-#endif
-
-
-
 #include <boost/range/functions.hpp>
-#include <boost/range/metafunctions.hpp>
 
 #include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/extensions/algorithms/buffer/buffer_appender.hpp>
 #include <boost/geometry/extensions/algorithms/buffer/line_line_intersection.hpp>
+#include <boost/geometry/extensions/algorithms/buffer/range_buffer.hpp>
+#include <boost/geometry/extensions/algorithms/offset_appender.hpp>
 #include <boost/geometry/algorithms/detail/disjoint.hpp>
 #include <boost/geometry/geometries/concepts/check.hpp>
 
@@ -44,81 +36,26 @@
     typename Range,
     typename RangeOut,
     typename JoinStrategy,
-    typename Distance
+    typename DistanceStrategy
 >
 struct offset_range
+    : public geometry::detail::buffer::range_buffer
+        <
+            RangeOut, 
+            DistanceStrategy, 
+            JoinStrategy,
+            linestring_tag
+        >
 {
-    typedef typename coordinate_type<RangeOut>::type coordinate_type;
-    typedef typename point_type<RangeOut>::type output_point_type;
-    typedef model::referring_segment<output_point_type const> segment_type;
-    typedef typename boost::range_iterator<Range const>::type iterator_type;
-
     template <typename Appender>
     static inline void apply(Range const& range,
                 Appender& appender,
-                JoinStrategy const& join,
-                Distance const& distance)
+                DistanceStrategy const& distance,
+                JoinStrategy const& join)
     {
-        output_point_type previous_p1, previous_p2;
-        output_point_type first_p1, first_p2;
-
-        bool first = true;
-
-        iterator_type it = boost::begin(range);
-        for (iterator_type prev = it++; it != boost::end(range); ++it)
-        {
-            if (! detail::equals::equals_point_point(*prev, *it))
-            {
-                // Simulate a vector d (dx,dy)
-                coordinate_type dx = get<0>(*it) - get<0>(*prev);
-                coordinate_type dy = get<1>(*it) - get<1>(*prev);
-
-                // For normalization [0,1] (=dot product d.d, sqrt)
-                coordinate_type length = sqrt(dx * dx + dy * dy);
-
-                // Because coordinates are not equal, length should not be zero
-                BOOST_ASSERT((! geometry::math::equals(length, 0)));
-
-                // Generate the normalized perpendicular p, to the left (ccw)
-                coordinate_type px = -dy / length;
-                coordinate_type py = dx / length;
-
-                output_point_type p1, p2;
-
-                set<0>(p2, get<0>(*it) + px * distance);
-                set<1>(p2, get<1>(*it) + py * distance);
-
-                set<0>(p1, get<0>(*prev) + px * distance);
-                set<1>(p1, get<1>(*prev) + py * distance);
-
-                if (! first)
-                {
-                    output_point_type p;
-                    segment_type s1(p1, p2);
-                    segment_type s2(previous_p1, previous_p2);
-                    if (detail::buffer::line_line_intersection<output_point_type, segment_type>::apply(s1, s2, p))
-                    {
-                        join.apply(p, *prev, previous_p2, p1, distance, appender);
-                    }
-                }
-                else
-                {
-                    first = false;
-                    first_p1 = p1;
-                    first_p2 = p2;
-
-                    appender.append(p1);
-                }
-
-                previous_p1 = p1;
-                previous_p2 = p2;
-                prev = it;
-            }
-        }
-
-        // Last one
-        appender.append(previous_p2);
-
+        iterate(appender, boost::begin(range), boost::end(range), 
+            buffer_side_left,
+            distance, join);
     }
 };
 
@@ -138,7 +75,7 @@
     typename Geometry,
     typename GeometryOut,
     typename JoinStrategy,
-    typename Distance
+    typename DistanceStrategy
 >
 struct offset
 {};
@@ -149,7 +86,7 @@
     typename Geometry,
     typename GeometryOut,
     typename JoinStrategy,
-    typename Distance
+    typename DistanceStrategy
 >
 struct offset
     <
@@ -158,14 +95,14 @@
         Geometry,
         GeometryOut,
         JoinStrategy,
-        Distance
+        DistanceStrategy
     >
     : detail::offset::offset_range
         <
             Geometry,
             GeometryOut,
             JoinStrategy,
-            Distance
+            DistanceStrategy
         >
 {};
 
@@ -188,7 +125,14 @@
     concept::check<Geometry const>();
     concept::check<GeometryOut>();
 
-    typedef detail::buffer::buffer_appender
+    typedef strategy::buffer::distance_assymetric
+        <
+            typename geometry::coordinate_type<Geometry>::type
+        > distance_strategy_type;
+    distance_strategy_type distance_strategy(distance, distance);
+
+
+    typedef detail::offset::offset_appender
         <
             GeometryOut
         > appender_type;
@@ -202,8 +146,8 @@
         Geometry,
         GeometryOut,
         JoinStrategy,
-        Distance
-    >::apply(geometry, appender, join, distance);
+        distance_strategy_type
+    >::apply(geometry, appender, distance_strategy, join);
 }
 
 
Added: trunk/boost/geometry/extensions/algorithms/offset_appender.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/geometry/extensions/algorithms/offset_appender.hpp	2012-01-28 16:13:39 EST (Sat, 28 Jan 2012)
@@ -0,0 +1,96 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 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_ALGORITHMS_DETAIL_OFFSET_APPENDER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OFFSET_APPENDER_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace offset
+{
+
+// Appends points to an output range (linestring/ring).
+template
+    <
+        typename Range
+#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
+        , typename Mapper
+#endif
+    >
+struct offset_appender
+{
+    typedef Range range_type;
+
+    typedef typename geometry::point_type<Range>::type point_type;
+
+#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
+    Mapper const& m_mapper;
+    inline offset_appender(Range& r, Mapper const& mapper)
+        : m_range(r)
+        , m_mapper(mapper)
+#else
+    inline offset_appender(Range& r)
+        : m_range(r)
+#endif
+
+    {}
+
+    inline void append(point_type const& point)
+    {
+        do_append(point);
+    }
+
+    inline void append_begin_join(point_type const& point)
+    {
+        do_append(point);
+    }
+
+    inline void append_end_join(point_type const& point)
+    {
+        do_append(point);
+    }
+
+    inline void append_begin_hooklet(point_type const& point)
+    {
+        do_append(point);
+    }
+
+    inline void append_end_hooklet(point_type const& point)
+    {
+        do_append(point);
+    }
+
+
+private :
+
+    Range& m_range;
+
+    inline void do_append(point_type const& point)
+    {
+        m_range.push_back(point);
+    }
+};
+
+
+}} // namespace detail::offset
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OFFSET_APPENDER_HPP
Modified: trunk/boost/geometry/extensions/strategies/buffer.hpp
==============================================================================
--- trunk/boost/geometry/extensions/strategies/buffer.hpp	(original)
+++ trunk/boost/geometry/extensions/strategies/buffer.hpp	2012-01-28 16:13:39 EST (Sat, 28 Jan 2012)
@@ -92,7 +92,7 @@
 
 #ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
 // Forget this, it will go
-template<typename PointIn, typename PointOut, typename Mapper>
+template<typename PointIn, typename PointOut, bool AddHooklets, typename Mapper>
 struct join_miter : public join_mapper<PointIn, Mapper>
 {
     join_miter(Mapper const& mapper) : join_mapper(mapper) {}
@@ -102,7 +102,8 @@
 template
 <
     typename PointIn,
-    typename PointOut
+    typename PointOut,
+    bool AddHooklets = true
 >
 struct join_miter
 {
@@ -125,11 +126,15 @@
 
         if (side::apply(perp1, ip, perp2) == signum)
         {
-            // If it is concave (corner to left), add helperline
-            // The helper-line IS essential for buffering holes. Without,
-            // holes might be generated, while they should NOT be there.
-            appender.append_begin_hooklet(perp1);
-            appender.append_end_hooklet(perp2);
+            if (AddHooklets)
+            {
+                appender.append_begin_hooklet(perp1);
+                appender.append_end_hooklet(perp2);
+            }
+            else
+            {
+                appender.append(ip);
+            }
         }
         else
         {
@@ -210,7 +215,7 @@
 
 #ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
 // Forget this, it will go
-template<typename PointIn, typename PointOut, typename Mapper>
+template<typename PointIn, typename PointOut, bool Hooklets, typename Mapper>
 struct join_round : public join_mapper<PointIn, Mapper>
 {
     join_round(Mapper const& mapper, int max_level = 4)
@@ -223,7 +228,8 @@
 template
 <
     typename PointIn,
-    typename PointOut
+    typename PointOut,
+    bool AddHooklets = true
 >
 struct join_round
 {
@@ -291,8 +297,15 @@
         if (side::apply(perp1, ip, perp2) == signum)
         {
             // If it is concave (corner to left), add helperline
-            appender.append_begin_hooklet(perp1);
-            appender.append_end_hooklet(perp2);
+            if (AddHooklets)
+            {
+                appender.append_begin_hooklet(perp1);
+                appender.append_end_hooklet(perp2);
+            }
+            else
+            {
+                appender.append(ip);
+            }
         }
         else
         {
Modified: trunk/libs/geometry/test_extensions/algorithms/buffer/test_buffer.hpp
==============================================================================
--- trunk/libs/geometry/test_extensions/algorithms/buffer/test_buffer.hpp	(original)
+++ trunk/libs/geometry/test_extensions/algorithms/buffer/test_buffer.hpp	2012-01-28 16:13:39 EST (Sat, 28 Jan 2012)
@@ -85,6 +85,7 @@
         <
             typename
             , typename
+            , bool
 #if defined(BOOST_GEOMETRY_DEBUG_WITH_MAPPER)
             , typename
 #endif
@@ -136,7 +137,8 @@
     typedef JoinStrategy
         <
             point_type,
-            typename bg::point_type<GeometryOut>::type
+            typename bg::point_type<GeometryOut>::type,
+            true
 #ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
             , bg::svg_mapper<point_type>
 #endif
@@ -253,6 +255,7 @@
         <
             typename
             , typename
+            , bool
 #if defined(BOOST_GEOMETRY_DEBUG_WITH_MAPPER)
             , typename
 #endif
@@ -294,6 +297,7 @@
         <
             typename
             , typename
+            , bool
 #if defined(BOOST_GEOMETRY_DEBUG_WITH_MAPPER)
             , typename
 #endif
Modified: trunk/libs/geometry/test_extensions/algorithms/offset.cpp
==============================================================================
--- trunk/libs/geometry/test_extensions/algorithms/offset.cpp	(original)
+++ trunk/libs/geometry/test_extensions/algorithms/offset.cpp	2012-01-28 16:13:39 EST (Sat, 28 Jan 2012)
@@ -35,7 +35,7 @@
 
 
 template <typename GeometryOut, typename Geometry>
-void test_offset(bool check, std::string const& caseid, Geometry const& geometry,
+void test_offset(std::string const& caseid, Geometry const& geometry,
         double distance,
         double expected_length, double percentage)
 {
@@ -45,7 +45,8 @@
     typedef bg::strategy::buffer::join_round
         <
             point_type,
-            point_type
+            point_type,
+            false
         > join_strategy;
 
     GeometryOut moved_by_offset;
@@ -66,11 +67,7 @@
 
 
     //BOOST_CHECK_EQUAL(holes, expected_hole_count);
-    if (check)
-    {
-        BOOST_CHECK_CLOSE(length, expected_length, percentage);
-    }
-
+    BOOST_CHECK_CLOSE(length, expected_length, percentage);
 
 #if defined(TEST_WITH_SVG)
     {
@@ -97,14 +94,14 @@
 
 
 template <typename Geometry>
-void test_one(bool check, std::string const& caseid, std::string const& wkt, double distance,
+void test_one(std::string const& caseid, std::string const& wkt, double distance,
         double expected_length_plus, double expected_length_minus, double percentage = 0.001)
 {
     Geometry geometry;
     bg::read_wkt(wkt, geometry);
 
-    test_offset<Geometry>(check, caseid + "_a", geometry, distance, expected_length_plus, percentage);
-    test_offset<Geometry>(check, caseid + "_b", geometry, -distance, expected_length_minus, percentage);
+    test_offset<Geometry>(caseid + "_a", geometry, distance, expected_length_plus, percentage);
+    test_offset<Geometry>(caseid + "_b", geometry, -distance, expected_length_minus, percentage);
 }
 
 
@@ -123,12 +120,12 @@
     static std::string const curve = "LINESTRING(2 7,3 5,5 4,7 5,8 7)";
     static std::string const reallife1 = "LINESTRING(76396.40464822574 410095.6795147947,76397.85016212701 410095.211865792,76401.30666443033 410095.0466387949,76405.05892643372 410096.1007777959,76409.45103273794 410098.257640797,76412.96309264141 410101.6522238015)";
 
-    test_one<linestring>(true, "ls_simplex", simplex, 0.5, std::sqrt(2.0), std::sqrt(2.0));
-    test_one<linestring>(false, "one_bend", one_bend, 0.5, 10.17328, 8.8681);
-    test_one<linestring>(false, "two_bends", two_bends, 0.5, 13.2898, 12.92811);
-    test_one<linestring>(false, "overlapping", overlapping, 0.5, 27.1466, 22.0596);
-    test_one<linestring>(false, "curve", curve, 0.5, 7.7776,  10.0507);
-    test_one<linestring>(false, "reallife1", reallife1, 16.5, 5.4654, 36.4943);
+    test_one<linestring>("ls_simplex", simplex, 0.5, std::sqrt(2.0), std::sqrt(2.0));
+    test_one<linestring>("one_bend", one_bend, 0.5, 10.17328, 8.8681);
+    test_one<linestring>("two_bends", two_bends, 0.5, 13.2898, 12.92811);
+    test_one<linestring>("overlapping", overlapping, 0.5, 27.1466, 22.0596);
+    test_one<linestring>("curve", curve, 0.5, 7.7776,  10.0507);
+    test_one<linestring>("reallife1", reallife1, 16.5, 5.4654, 36.4943);
 }