Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86368 - in trunk: boost/geometry/algorithms/detail/overlay boost/geometry/strategies boost/geometry/strategies/cartesian libs/geometry/doc libs/geometry/extensions/test/algorithms/buffer libs/geometry/test/algorithms libs/geometry/test/algorithms/overlay libs/geometry/test/algorithms/overlay/robustness
From: barend.gehrels_at_[hidden]
Date: 2013-10-20 11:30:21


Author: barendgehrels
Date: 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013)
New Revision: 86368
URL: http://svn.boost.org/trac/boost/changeset/86368

Log:
[geometry] revised solution for robustness, we don't go to integer which was shortly done. This is partly a revert of r85867, where we scaled to integer. Now we make side information consistent by iteratively selecting a larger epsilon. This will be moved into a separate class. All tests pass now, also the complete ticket_9081 test which failed before

Text files modified:
   trunk/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp | 143 ++++++++------
   trunk/boost/geometry/strategies/cartesian/cart_intersect.hpp | 389 ++++++++++++++++++++++++++++++++++-----
   trunk/boost/geometry/strategies/cartesian/side_by_triangle.hpp | 39 +++
   trunk/boost/geometry/strategies/side_info.hpp | 15
   trunk/libs/geometry/doc/release_notes.qbk | 1
   trunk/libs/geometry/extensions/test/algorithms/buffer/multi_point_buffer.cpp | 4
   trunk/libs/geometry/test/algorithms/difference.cpp | 11
   trunk/libs/geometry/test/algorithms/intersection.cpp | 11 -
   trunk/libs/geometry/test/algorithms/overlay/get_turn_info.cpp | 5
   trunk/libs/geometry/test/algorithms/overlay/robustness/ticket_9081.cpp | 64 +++--
   trunk/libs/geometry/test/algorithms/test_union.hpp | 43 ++-
   trunk/libs/geometry/test/algorithms/union.cpp | 31 +-
   12 files changed, 546 insertions(+), 210 deletions(-)

Modified: trunk/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
==============================================================================
--- trunk/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -16,16 +16,14 @@
 
 #include <boost/geometry/algorithms/convert.hpp>
 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-#include <boost/geometry/algorithms/detail/zoom_to_robust.hpp>
 
-#include <boost/geometry/geometries/point.hpp>
 #include <boost/geometry/geometries/segment.hpp>
 
 
 // Silence warning C4127: conditional expression is constant
 #if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4127)
+#pragma warning(push)
+#pragma warning(disable : 4127)
 #endif
 
 
@@ -39,7 +37,7 @@
 public:
 
     // NOTE: "char" will be replaced by enum in future version
- inline turn_info_exception(char const method)
+ inline turn_info_exception(char const method)
     {
         message = "Boost.Geometry Turn exception: ";
         message += method;
@@ -288,8 +286,14 @@
             int const side_pk_p = side.pk_wrt_p1();
             int const side_qk_q = side.qk_wrt_q1();
 
+ bool const both_continue = side_pk_p == 0 && side_qk_q == 0;
+ bool const robustness_issue_in_continue = both_continue && side_pk_q2 != 0;
+
             bool const q_turns_left = side_qk_q == 1;
- bool const block_q = side_qk_p1 == 0 && ! same(side_qi_p1, side_qk_q);
+ bool const block_q = side_qk_p1 == 0
+ && ! same(side_qi_p1, side_qk_q)
+ && ! robustness_issue_in_continue
+ ;
 
             // If Pk at same side as Qi/Qk
             // (the "or" is for collinear case)
@@ -479,20 +483,6 @@
         // oppositely
         if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
         {
- // After fixing robustness with integer: if they both continue collinearly,
- // we might miss next intersection point because other rounding factor...
- // Therefore we also look at the real-side (FP side)
- typedef typename geometry::coordinate_type<Point1>::type coordinate_type;
- if (boost::is_floating_point<coordinate_type>::value)
- {
- coordinate_type sv_pk_p = strategy::side::side_by_triangle<>::side_value<coordinate_type, coordinate_type>(pi, pj, pk);
- coordinate_type sv_qk_p = strategy::side::side_by_triangle<>::side_value<coordinate_type, coordinate_type>(pi, pj, qk);
- if (sv_pk_p != sv_qk_p)
- {
- ui_else_iu(sv_pk_p > sv_qk_p, ti);
- return;
- }
- }
             both(ti, operation_continue);
 
             return;
@@ -587,6 +577,12 @@
          - if Q arrives and Q turns left: union for Q (=intersection for P)
          - if Q arrives and Q turns right: intersection for Q (=union for P)
 
+ ROBUSTNESS: p and q are collinear, so you would expect
+ that side qk//p1 == pk//q1. But that is not always the case
+ in near-epsilon ranges. Then decision logic is different.
+ If p arrives, q is further, so the angle qk//p1 is (normally)
+ more precise than pk//p1
+
     */
     template
     <
@@ -620,6 +616,9 @@
             : side_q
             ;
 
+ int const side_pk = side.pk_wrt_q1();
+ int const side_qk = side.qk_wrt_p1();
+
         // See comments above,
         // resulting in a strange sort of mathematic rule here:
         // The arrival-info multiplied by the relevant side
@@ -627,22 +626,15 @@
 
         int const product = arrival * side_p_or_q;
 
- if (product == 0 && (side_p != 0 || side_q != 0))
+ // Robustness: side_p is supposed to be equal to side_pk (because p/q are collinear)
+ // and side_q to side_qk
+ bool const robustness_issue = side_pk != side_p || side_qk != side_q;
+
+ if (robustness_issue)
         {
- // If q is collinear, p turns left
- if (side_p != 0 && side_q == 0)
- {
- ui_else_iu(side_p == 1, ti);
- return;
- }
- if (side_q != 0 && side_p == 0)
- {
- ui_else_iu(side_q == -1, ti);
- return;
- }
+ handle_robustness(ti, arrival, side_p, side_q, side_pk, side_qk);
         }
-
- if(product == 0)
+ else if(product == 0)
         {
             both(ti, operation_continue);
         }
@@ -652,6 +644,37 @@
         }
     }
 
+ static inline void handle_robustness(TurnInfo& ti, int arrival,
+ int side_p, int side_q, int side_pk, int side_qk)
+ {
+ // We take the longer one, i.e. if q arrives in p (arrival == -1),
+ // then p exceeds q and we should take p for a union...
+
+ bool use_p_for_union = arrival == -1;
+
+ // ... unless one of the sides consistently directs to the other side
+ int const consistent_side_p = side_p == side_pk ? side_p : 0;
+ int const consistent_side_q = side_q == side_qk ? side_q : 0;
+ if (arrival == -1 && (consistent_side_p == -1 || consistent_side_q == 1))
+ {
+ use_p_for_union = false;
+ }
+ if (arrival == 1 && (consistent_side_p == 1 || consistent_side_q == -1))
+ {
+ use_p_for_union = true;
+ }
+
+ //std::cout << "ROBUSTNESS -> Collinear "
+ // << " arr: " << arrival
+ // << " dir: " << side_p << " " << side_q
+ // << " rev: " << side_pk << " " << side_qk
+ // << " cst: " << cside_p << " " << cside_q
+ // << std::boolalpha << " " << use_p_for_union
+ // << std::endl;
+
+ ui_else_iu(use_p_for_union, ti);
+ }
+
 };
 
 template
@@ -693,9 +716,22 @@
         typename IntersectionInfo
>
     static inline bool set_tp(Point const& ri, Point const& rj, Point const& rk, int side_rk_r,
- Point const& si, Point const& sj,
+ bool const handle_robustness, Point const& si, Point const& sj, int side_rk_s,
                 TurnInfo& tp, IntersectionInfo const& intersection_info)
     {
+ if (handle_robustness)
+ {
+ // For Robustness: also calculate rk w.r.t. the other line. Because they are collinear opposite, that direction should be the reverse of the first direction.
+ // If this is not the case, we make it all-collinear, so zero
+ if (side_rk_r != 0 && side_rk_r != -side_rk_s)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ROBUSTNESS
+ std::cout << "Robustness correction: " << side_rk_r << " / " << side_rk_s << std::endl;
+#endif
+ side_rk_r = 0;
+ }
+ }
+
         operation_type blocked = operation_blocked;
         switch(side_rk_r)
         {
@@ -764,7 +800,7 @@
 
         // If P arrives within Q, there is a turn dependent on P
         if (dir_info.arrival[0] == 1
- && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), qi, qj, tp, intersection_info))
+ && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, intersection_info))
         {
             AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
             *out++ = tp;
@@ -772,7 +808,7 @@
 
         // If Q arrives within P, there is a turn dependent on Q
         if (dir_info.arrival[1] == 1
- && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), pi, pj, tp, intersection_info))
+ && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, intersection_info))
         {
             AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
             *out++ = tp;
@@ -861,7 +897,7 @@
     static bool const include_degenerate = false;
     static bool const include_opposite = false;
 
- template
+ template
     <
         typename Info,
         typename Point1,
@@ -920,35 +956,12 @@
     {
         typedef model::referring_segment<Point1 const> segment_type1;
         typedef model::referring_segment<Point2 const> segment_type2;
-
- typedef typename select_coordinate_type<Point1, Point2>::type coordinate_type;
-
- typedef model::point
- <
- typename geometry::robust_type<coordinate_type>::type,
- geometry::dimension<Point1>::value,
- typename geometry::coordinate_system<Point1>::type
- > robust_point_type;
-
- robust_point_type pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob;
- geometry::zoom_to_robust(pi, pj, pk, qi, qj, qk, pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob);
-
- typedef geometry::strategy::side::side_by_triangle<> side;
- side_info robust_sides;
- robust_sides.set<0>(side::apply(qi_rob, qj_rob, pi_rob),
- side::apply(qi_rob, qj_rob, pj_rob));
- robust_sides.set<1>(side::apply(pi_rob, pj_rob, qi_rob),
- side::apply(pi_rob, pj_rob, qj_rob));
-
- bool const p_equals = detail::equals::equals_point_point(pi_rob, pj_rob);
- bool const q_equals = detail::equals::equals_point_point(qi_rob, qj_rob);
-
         segment_type1 p1(pi, pj), p2(pj, pk);
         segment_type2 q1(qi, qj), q2(qj, qk);
 
- side_calculator<robust_point_type, robust_point_type> side_calc(pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob);
+ side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
 
- typename strategy::return_type result = strategy::apply(p1, q1, robust_sides, p_equals, q_equals);
+ typename strategy::return_type result = strategy::apply(p1, q1);
 
         char const method = result.template get<1>().how;
 
@@ -991,7 +1004,7 @@
                 else
                 {
                     // Swap p/q
- side_calculator<robust_point_type, robust_point_type> swapped_side_calc(qi_rob, qj_rob, qk_rob, pi_rob, pj_rob, pk_rob);
+ side_calculator<Point1, Point2> swapped_side_calc(qi, qj, qk, pi, pj, pk);
                     policy::template apply<1>(qi, qj, qk, pi, pj, pk,
                                 tp, result.template get<0>(), result.template get<1>(),
                                 swapped_side_calc);
@@ -1110,7 +1123,7 @@
 
 
 #if defined(_MSC_VER)
-#pragma warning(pop)
+#pragma warning(pop)
 #endif
 
 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP

Modified: trunk/boost/geometry/strategies/cartesian/cart_intersect.hpp
==============================================================================
--- trunk/boost/geometry/strategies/cartesian/cart_intersect.hpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/boost/geometry/strategies/cartesian/cart_intersect.hpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -29,6 +29,10 @@
 
 #include <boost/geometry/strategies/side_info.hpp>
 
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+# include <boost/geometry/io/wkt/write.hpp>
+#endif
+
 
 namespace boost { namespace geometry
 {
@@ -70,18 +74,6 @@
 }
 #endif
 
-/***
-template <typename T>
-inline std::string rdebug(T const& value)
-{
- if (math::equals(value, 0)) return "'0'";
- if (math::equals(value, 1)) return "'1'";
- if (value < 0) return "<0";
- if (value > 1) return ">1";
- return "<0..1>";
-}
-***/
-
 /*!
     \see http://mathworld.wolfram.com/Line-LineIntersection.html
  */
@@ -105,7 +97,7 @@
     static inline void debug_segments(std::string const& header, segment_type1 const& a, segment_type2 const& b)
     {
         std::cout << "Robustness issue: " << header << std::endl;
- std::cout
+ std::cout
             << "A: " << wkt(a) << std::endl
             << "B: " << wkt(b) << std::endl
             ;
@@ -129,13 +121,26 @@
             coordinate_type const& dx_b, coordinate_type const& dy_b)
     {
         typedef side::side_by_triangle<coordinate_type> side;
+ side_info sides;
 
         coordinate_type const zero = 0;
         bool const a_is_point = math::equals(dx_a, zero) && math::equals(dy_a, zero);
         bool const b_is_point = math::equals(dx_b, zero) && math::equals(dy_b, zero);
 
- // Get sides of a relative to b, and b relative to a
- side_info sides;
+ if(a_is_point && b_is_point)
+ {
+ if(math::equals(get<1,0>(a), get<1,0>(b)) && math::equals(get<1,1>(a), get<1,1>(b)))
+ {
+ Policy::degenerate(a, true);
+ }
+ else
+ {
+ return Policy::disjoint();
+ }
+ }
+
+ bool collinear_use_first = math::abs(dx_a) + math::abs(dx_b) >= math::abs(dy_a) + math::abs(dy_b);
+
         sides.set<0>
             (
                 side::apply(detail::get_from_index<0>(b)
@@ -154,42 +159,19 @@
                     , detail::get_from_index<1>(a)
                     , detail::get_from_index<1>(b))
             );
- return apply(a, b, dx_a, dy_a, dx_b, dy_b, sides, a_is_point, b_is_point);
- }
-
- static inline return_type apply(segment_type1 const& a, segment_type2 const& b,
- side_info& sides, bool a_is_point, bool b_is_point)
- {
- coordinate_type const dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
- coordinate_type const dx_b = get<1, 0>(b) - get<0, 0>(b);
- coordinate_type const dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir
- coordinate_type const dy_b = get<1, 1>(b) - get<0, 1>(b);
- return apply(a, b, dx_a, dy_a, dx_b, dy_b, sides, a_is_point, b_is_point);
- }
-
- static inline return_type apply(segment_type1 const& a, segment_type2 const& b,
- coordinate_type const& dx_a, coordinate_type const& dy_a,
- coordinate_type const& dx_b, coordinate_type const& dy_b,
- side_info& sides, bool a_is_point, bool b_is_point)
- {
- if(a_is_point && b_is_point)
- {
- if(math::equals(get<1,0>(a), get<1,0>(b)) && math::equals(get<1,1>(a), get<1,1>(b)))
- {
- Policy::degenerate(a, true);
- }
- else
- {
- return Policy::disjoint();
- }
- }
 
         bool collinear = sides.collinear();
 
+ robustness_verify_collinear(a, b, a_is_point, b_is_point, sides, collinear);
+ robustness_verify_meeting(a, b, sides, collinear, collinear_use_first);
+
         if (sides.same<0>() || sides.same<1>())
         {
             // Both points are at same side of other segment, we can leave
- return Policy::disjoint();
+ if (robustness_verify_same_side(a, b, sides))
+ {
+ return Policy::disjoint();
+ }
         }
 
         // Degenerate cases: segments of single point, lying on other segment, are not disjoint
@@ -235,13 +217,18 @@
                 {
                     return Policy::disjoint();
                 }
+
+ if (robustness_verify_disjoint_at_one_collinear(a, b, sides))
+ {
+ return Policy::disjoint();
+ }
+
             }
         }
 
         if(collinear)
         {
- // Use dimension 0 for collinear cases if differences in x exceeds differences in y
- if (math::abs(dx_a) + math::abs(dx_b) >= math::abs(dy_a) + math::abs(dy_b))
+ if (collinear_use_first)
             {
                 return relate_collinear<0>(a, b);
             }
@@ -318,6 +305,312 @@
     }
 
     template <std::size_t Dimension>
+ static inline bool analyse_equal(segment_type1 const& a, segment_type2 const& b)
+ {
+ coordinate_type const a_1 = geometry::get<0, Dimension>(a);
+ coordinate_type const a_2 = geometry::get<1, Dimension>(a);
+ coordinate_type const b_1 = geometry::get<0, Dimension>(b);
+ coordinate_type const b_2 = geometry::get<1, Dimension>(b);
+ return math::equals(a_1, b_1)
+ || math::equals(a_2, b_1)
+ || math::equals(a_1, b_2)
+ || math::equals(a_2, b_2)
+ ;
+ }
+
+ static inline void robustness_verify_collinear(
+ segment_type1 const& a, segment_type2 const& b,
+ bool a_is_point, bool b_is_point,
+ side_info& sides,
+ bool& collinear)
+ {
+ bool only_0_collinear = sides.zero<0>() && ! b_is_point && ! sides.zero<1>();
+ bool only_1_collinear = sides.zero<1>() && ! a_is_point && ! sides.zero<0>();
+ if (only_0_collinear || only_1_collinear)
+ {
+ typename geometry::point_type<segment_type1>::type a0 = detail::get_from_index<0>(a);
+ typename geometry::point_type<segment_type1>::type a1 = detail::get_from_index<1>(a);
+ typename geometry::point_type<segment_type2>::type b0 = detail::get_from_index<0>(b);
+ typename geometry::point_type<segment_type2>::type b1 = detail::get_from_index<1>(b);
+ bool ae = false, be = false;
+
+ // If one of the segments is collinear, the other is probably so too.
+ side_info check;
+ coordinate_type factor = 1;
+ int iteration = 0;
+ bool collinear_consistent = false;
+ do
+ {
+ typedef side::side_by_triangle<coordinate_type> side;
+
+ // We have a robustness issue. We keep increasing epsilon until we have a consistent set
+ coordinate_type const two = 2;
+ factor *= two;
+ coordinate_type epsilon = math::relaxed_epsilon<coordinate_type>(factor);
+ check.set<0>
+ (
+ side::apply_with_epsilon(b0, b1, a0, epsilon),
+ side::apply_with_epsilon(b0, b1, a1, epsilon)
+ );
+ check.set<1>
+ (
+ side::apply_with_epsilon(a0, a1, b0, epsilon),
+ side::apply_with_epsilon(a0, a1, b1, epsilon)
+ );
+ ae = point_equals_with_epsilon(a0, a1, epsilon);
+ be = point_equals_with_epsilon(b0, b1, epsilon);
+
+ collinear_consistent = true;
+ if ( (check.zero<0>() && ! be && ! check.zero<1>())
+ || (check.zero<1>() && ! ae && ! check.zero<0>())
+ )
+ {
+ collinear_consistent = false;
+ }
+
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout
+ << "*** collinear_consistent: "
+ << iteration << std::boolalpha
+ << " consistent: " << collinear_consistent
+ << " equals: " << ae << "," << be
+ << " epsilon: " << epsilon
+ << " ";
+ check.debug();
+#endif
+
+
+ } while (! collinear_consistent && iteration++ < 10);
+
+ sides = check;
+ collinear = sides.collinear();
+ }
+ }
+
+ static inline void robustness_verify_meeting(
+ segment_type1 const& a, segment_type2 const& b,
+ side_info& sides,
+ bool& collinear, bool& collinear_use_first)
+ {
+ if (sides.meeting())
+ {
+ // If two segments meet each other at their segment-points, two sides are zero,
+ // the other two are not (unless collinear but we don't mean those here).
+ // However, in near-epsilon ranges it can happen that two sides are zero
+ // but they do not meet at their segment-points.
+ // In that case they are nearly collinear and handled as such.
+
+ if (! point_equals
+ (
+ select(sides.zero_index<0>(), a),
+ select(sides.zero_index<1>(), b)
+ )
+ )
+ {
+
+ typename geometry::point_type<segment_type1>::type a0 = detail::get_from_index<0>(a);
+ typename geometry::point_type<segment_type1>::type a1 = detail::get_from_index<1>(a);
+ typename geometry::point_type<segment_type2>::type b0 = detail::get_from_index<0>(b);
+ typename geometry::point_type<segment_type2>::type b1 = detail::get_from_index<1>(b);
+
+ side_info check;
+ coordinate_type factor = 1;
+ coordinate_type epsilon = math::relaxed_epsilon<coordinate_type>(factor);
+ int iteration = 1;
+ bool points_meet = false;
+ bool meeting_consistent = false;
+ do
+ {
+ typedef side::side_by_triangle<coordinate_type> side;
+
+ // We have a robustness issue. We keep increasing epsilon until we have a consistent set
+ coordinate_type const two = 2;
+ factor *= two;
+ epsilon = math::relaxed_epsilon<coordinate_type>(factor);
+ check.set<0>
+ (
+ side::apply_with_epsilon(b0, b1, a0, epsilon),
+ side::apply_with_epsilon(b0, b1, a1, epsilon)
+ );
+ check.set<1>
+ (
+ side::apply_with_epsilon(a0, a1, b0, epsilon),
+ side::apply_with_epsilon(a0, a1, b1, epsilon)
+ );
+
+ meeting_consistent = true;
+ if (check.meeting())
+ {
+ points_meet = point_equals_with_epsilon
+ (
+ select(check.zero_index<0>(), a),
+ select(check.zero_index<1>(), b),
+ epsilon
+ );
+ if (! points_meet)
+ {
+ meeting_consistent = false;
+
+ }
+ }
+
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout
+ << "*** meeting_consistent: "
+ << iteration << std::boolalpha
+ << " consistent: " << meeting_consistent
+ << " epsilon: " << epsilon
+ << " ";
+ check.debug();
+#endif
+
+
+ } while (! meeting_consistent && iteration++ < 10);
+
+
+ sides = check;
+
+ if (! sides.meeting()
+ && ((sides.zero<0>() && !sides.zero<1>())
+ || (! sides.zero<0>() && sides.zero<1>())
+ )
+ )
+ {
+ // Set sides to zero
+ sides.set<0>(0,0);
+ sides.set<1>(0,0);
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "ADAPTED New side info: " << std::endl;
+ sides.debug();
+#endif
+ }
+
+ collinear = sides.collinear();
+
+ if (collinear_use_first && analyse_equal<0>(a, b))
+ {
+ collinear_use_first = false;
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "Use [1] to check collinearity" << std::endl;
+#endif
+ }
+ else if (! collinear_use_first && analyse_equal<1>(a, b))
+ {
+ collinear_use_first = true;
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "Use [0] to check collinearity" << std::endl;
+#endif
+ }
+ }
+ }
+ }
+
+ // Verifies and if necessary correct missed touch because of robustness
+ // This is the case at multi_polygon_buffer unittest #rt_m
+ static inline bool robustness_verify_same_side(
+ segment_type1 const& a, segment_type2 const& b,
+ side_info& sides)
+ {
+ int corrected = 0;
+ if (sides.one_touching<0>())
+ {
+ if (point_equals(
+ select(sides.zero_index<0>(), a),
+ select(0, b)
+ ))
+ {
+ sides.correct_to_zero<1, 0>();
+ corrected = 1;
+ }
+ if (point_equals
+ (
+ select(sides.zero_index<0>(), a),
+ select(1, b)
+ ))
+ {
+ sides.correct_to_zero<1, 1>();
+ corrected = 2;
+ }
+ }
+ else if (sides.one_touching<1>())
+ {
+ if (point_equals(
+ select(sides.zero_index<1>(), b),
+ select(0, a)
+ ))
+ {
+ sides.correct_to_zero<0, 0>();
+ corrected = 3;
+ }
+ if (point_equals
+ (
+ select(sides.zero_index<1>(), b),
+ select(1, a)
+ ))
+ {
+ sides.correct_to_zero<0, 1>();
+ corrected = 4;
+ }
+ }
+
+ return corrected == 0;
+ }
+
+ static inline bool robustness_verify_disjoint_at_one_collinear(
+ segment_type1 const& a, segment_type2 const& b,
+ side_info const& sides)
+ {
+ if (sides.one_of_all_zero())
+ {
+ if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename Segment>
+ static inline typename point_type<Segment>::type select(int index, Segment const& segment)
+ {
+ return index == 0
+ ? detail::get_from_index<0>(segment)
+ : detail::get_from_index<1>(segment)
+ ;
+ }
+
+ // We cannot use geometry::equals here. Besides that this will be changed
+ // to compare segment-coordinate-values directly (not necessary to retrieve point first)
+ template <typename Point1, typename Point2>
+ static inline bool point_equals(Point1 const& point1, Point2 const& point2)
+ {
+ return math::equals(get<0>(point1), get<0>(point2))
+ && math::equals(get<1>(point1), get<1>(point2))
+ ;
+ }
+
+ template <typename Point1, typename Point2, typename T>
+ static inline bool point_equals_with_epsilon(Point1 const& point1, Point2 const& point2, T const& epsilon)
+ {
+ // Check if difference is within espilon range (epsilon can be 0 for integer)
+ return math::abs(geometry::get<0>(point1) - geometry::get<0>(point2)) <= epsilon
+ && math::abs(geometry::get<1>(point1) - geometry::get<1>(point2)) <= epsilon
+ ;
+ }
+
+
+ // We cannot use geometry::equals here. Besides that this will be changed
+ // to compare segment-coordinate-values directly (not necessary to retrieve point first)
+ template <typename Point1, typename Point2>
+ static inline bool point_equality(Point1 const& point1, Point2 const& point2,
+ bool& equals_0, bool& equals_1)
+ {
+ equals_0 = math::equals(get<0>(point1), get<0>(point2));
+ equals_1 = math::equals(get<1>(point1), get<1>(point2));
+ return equals_0 && equals_1;
+ }
+
+ template <std::size_t Dimension>
     static inline bool verify_disjoint(segment_type1 const& a,
                     segment_type2 const& b)
     {
@@ -336,8 +629,6 @@
         bool a_swapped = false, b_swapped = false;
         detail::segment_arrange<Dimension>(a, a_1, a_2, a_swapped);
         detail::segment_arrange<Dimension>(b, b_1, b_2, b_swapped);
-
- // TODO: these should be passed as integer too -> normal comparisons possible
         if (math::smaller(a_2, b_1) || math::larger(a_1, b_2))
         //if (a_2 < b_1 || a_1 > b_2)
         {

Modified: trunk/boost/geometry/strategies/cartesian/side_by_triangle.hpp
==============================================================================
--- trunk/boost/geometry/strategies/cartesian/side_by_triangle.hpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/boost/geometry/strategies/cartesian/side_by_triangle.hpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -65,7 +65,7 @@
 
         return geometry::detail::determinant<promoted_type>
                 (
- dx, dy,
+ dx, dy,
                     dpx, dpy
                 );
 
@@ -99,8 +99,41 @@
         promoted_type const s = side_value<coordinate_type, promoted_type>(p1, p2, p);
         promoted_type const zero = promoted_type();
 
- return math::equals(s, zero) ? 0
- : s > zero ? 1
+ return math::equals(s, zero) ? 0
+ : s > zero ? 1
+ : -1;
+ }
+
+ template <typename P1, typename P2, typename P, typename T>
+ static inline int apply_with_epsilon(P1 const& p1, P2 const& p2, P const& p, T const& epsilon)
+ {
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<P1>::type,
+ typename coordinate_type<P2>::type
+ >::type,
+ typename coordinate_type<P>::type
+ >::type,
+ CalculationType
+ >::type coordinate_type;
+
+ // Promote float->double, small int->int
+ typedef typename select_most_precise
+ <
+ coordinate_type,
+ double
+ >::type promoted_type;
+
+ promoted_type const s = side_value<coordinate_type, promoted_type>(p1, p2, p);
+ promoted_type const zero = promoted_type();
+
+ return math::abs(s - zero) < epsilon ? 0
+ : s > zero ? 1
             : -1;
     }
 };

Modified: trunk/boost/geometry/strategies/side_info.hpp
==============================================================================
--- trunk/boost/geometry/strategies/side_info.hpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/boost/geometry/strategies/side_info.hpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -16,8 +16,9 @@
 
 #include <cmath>
 #include <utility>
-#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
-#include <iostream>
+
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+# include <iostream>
 #endif
 
 namespace boost { namespace geometry
@@ -25,8 +26,8 @@
 
 // Silence warning C4127: conditional expression is constant
 #if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4127)
+#pragma warning(push)
+#pragma warning(disable : 4127)
 #endif
 
 /*!
@@ -145,13 +146,13 @@
         return sides[Which].first == 0 ? 0 : 1;
     }
 
-#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
     inline void debug() const
     {
         std::cout << sides[0].first << " "
             << sides[0].second << " "
             << sides[1].first << " "
- << sides[1].second
+ << sides[1].second
             << std::endl;
     }
 #endif
@@ -167,7 +168,7 @@
 };
 
 #if defined(_MSC_VER)
-#pragma warning(pop)
+#pragma warning(pop)
 #endif
 
 }} // namespace boost::geometry

Modified: trunk/libs/geometry/doc/release_notes.qbk
==============================================================================
--- trunk/libs/geometry/doc/release_notes.qbk Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/doc/release_notes.qbk 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -20,6 +20,7 @@
 [*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
 
 [/=================]
 [heading Boost 1.55]

Modified: trunk/libs/geometry/extensions/test/algorithms/buffer/multi_point_buffer.cpp
==============================================================================
--- trunk/libs/geometry/extensions/test/algorithms/buffer/multi_point_buffer.cpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/extensions/test/algorithms/buffer/multi_point_buffer.cpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -201,8 +201,8 @@
     //test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
     test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
 
-#ifdef NDEBUG
- // only in release mode
+
+#ifdef BOOST_GEOMETRY_BUFFER_TEST_GROWTH
     for (int i = 5; i <= 50; i++)
     {
         test_growth<bg::model::point<double, 2, bg::cs::cartesian> >(i, 20);

Modified: trunk/libs/geometry/test/algorithms/difference.cpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/difference.cpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/test/algorithms/difference.cpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -258,24 +258,19 @@
         1, 0, 13);
     ***/
 
-#ifdef _MSC_VER
-#ifdef TEST_ISOVIST
     test_one<polygon, polygon, polygon>("isovist",
         isovist1[0], isovist1[1],
- if_typed_tt<ct>(4, 2), 0, 0.279121891701124,
- if_typed_tt<ct>(4, 3), 0, if_typed_tt<ct>(224.889211358929, 223.777),
- if_typed_tt<ct>(0.001, 0.2));
+ if_typed_tt<ct>(4, 2), -1, 0.279121,
+ 4, -1, 224.8892,
+ if_typed_tt<ct>(0.001, 0.1));
 
     // SQL Server gives: 0.279121891701124 and 224.889211358929
     // PostGIS gives: 0.279121991127244 and 224.889205853156
 
-#endif
-
     test_one<polygon, polygon, polygon>("ggl_list_20110306_javier",
         ggl_list_20110306_javier[0], ggl_list_20110306_javier[1],
         1, -1, 71495.3331,
         2, -1, 8960.49049);
-#endif
         
     test_one<polygon, polygon, polygon>("ggl_list_20110307_javier",
         ggl_list_20110307_javier[0], ggl_list_20110307_javier[1],

Modified: trunk/libs/geometry/test/algorithms/intersection.cpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/intersection.cpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/test/algorithms/intersection.cpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -15,8 +15,6 @@
 #include <iostream>
 #include <string>
 
-#define TEST_ISOVIST
-
 #include <boost/geometry/geometries/point_xy.hpp>
 #include <boost/geometry/geometries/register/linestring.hpp>
 
@@ -161,21 +159,14 @@
     bool const open = bg::closure<Polygon>::value == bg::open;
 
 
-#ifdef TEST_ISOVIST
-#ifdef _MSC_VER
     test_one<Polygon, Polygon, Polygon>("isovist",
         isovist1[0], isovist1[1],
- 1, if_typed<ct, double>(18, 20), 88.19203,
+ 1, 19, 88.19203,
         if_typed_tt<ct>(0.01, 0.1));
 
     // SQL Server gives: 88.1920416352664
     // PostGIS gives: 88.19203677911
 
-#endif
-#endif
-
- //std::cout << typeid(ct).name() << std::endl;
-
     if (! ccw && open)
     {
         // Pointcount for ttmath/double (both 5) or float (4)

Modified: trunk/libs/geometry/test/algorithms/overlay/get_turn_info.cpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/overlay/get_turn_info.cpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/test/algorithms/overlay/get_turn_info.cpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -323,14 +323,15 @@
             method_collinear, 5, 5, "ui");
 
     // The next two cases are changed (BSG 2013-09-24), they contain turn info (#buffer_rt_g)
+ // In new approach they are changed back (BSG 2013-10-20)
     test_both<P, double>("ccx1",
             5, 1, 5, 6, 5, 8, // p
             5, 5, 5, 7, 3, 8, // q
- method_collinear, 5, 6, "iu"); // "cc");
+ method_collinear, 5, 6, "cc"); // "iu");
     test_both<P, double>("cxc1",
             5, 1, 5, 6, 7, 8, // p
             5, 3, 5, 5, 5, 7, // q
- method_collinear, 5, 5, "iu"); // "cc");
+ method_collinear, 5, 5, "cc"); // "iu");
 
     // Bug in case #54 of "overlay_cases.hpp"
     test_both<P, double>("c_bug1",

Modified: trunk/libs/geometry/test/algorithms/overlay/robustness/ticket_9081.cpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/overlay/robustness/ticket_9081.cpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/test/algorithms/overlay/robustness/ticket_9081.cpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -9,10 +9,7 @@
 
 // Adapted from: the attachment of ticket 9081
 
-#define BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
-#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
-//#define BOOST_GEOMETRY_DEBUG_INTERSECTION
-//#define CHECK_SELF_INTERSECTIONS
+#define CHECK_SELF_INTERSECTIONS
 
  #include <iomanip>
  #include <iostream>
@@ -78,14 +75,16 @@
 
 int main()
 {
- int num_orig=50;
- int num_rounds=20000;
- //int num_rounds=16000;
+ int num_orig = 50;
+ int num_rounds = 20000;
     srand(1234);
- std::cout<<std::setprecision(16);
+ std::cout << std::setprecision(16);
     std::map<int, std::string> genesis;
     int pj;
 
+
+ std::string wkt1, wkt2, operation;
+
     try
     {
 
@@ -116,13 +115,22 @@
 
     for(int j=0;j<num_rounds;j++)
     {
- std::cout << " " << j;
+ if (j % 100 == 0) { std::cout << " " << j; }
         pj = j;
         int a = rand() % poly_list.size();
         int b = rand() % poly_list.size();
- multi_polygon mp_i,mp_d,mp_e;
+
         //debug_with_svg(j, 'i', poly_list[a], poly_list[b], genesis[a], genesis[b]);
+
+ { std::ostringstream out; out << boost::geometry::wkt(poly_list[a]); wkt1 = out.str(); }
+ { std::ostringstream out; out << boost::geometry::wkt(poly_list[b]); wkt2 = out.str(); }
+
+ multi_polygon mp_i, mp_u, mp_d, mp_e;
+ operation = "intersection";
         boost::geometry::intersection(poly_list[a],poly_list[b],mp_i);
+ operation = "intersection";
+ boost::geometry::union_(poly_list[a],poly_list[b],mp_u);
+ operation = "difference";
         boost::geometry::difference(poly_list[a],poly_list[b],mp_d);
         boost::geometry::difference(poly_list[b],poly_list[a],mp_e);
 #ifdef CHECK_SELF_INTERSECTIONS
@@ -132,10 +140,10 @@
         }
         catch(...)
         {
- std::cout<<"FAILED TO INTERSECT " << j << std::endl;
- std::cout<<boost::geometry::wkt(poly_list[a])<<std::endl;
- std::cout<<boost::geometry::wkt(poly_list[b])<<std::endl;
- std::cout<<boost::geometry::wkt(mp_i)<<std::endl;
+ std::cout << "FAILED TO INTERSECT " << j << std::endl;
+ std::cout << boost::geometry::wkt(poly_list[a]) << std::endl;
+ std::cout << boost::geometry::wkt(poly_list[b]) << std::endl;
+ std::cout << boost::geometry::wkt(mp_i) << std::endl;
             try
             {
                 boost::geometry::detail::overlay::has_self_intersections(mp_i);
@@ -152,10 +160,10 @@
         }
         catch(...)
         {
- std::cout<<"FAILED TO SUBTRACT " << j << std::endl;
- std::cout<<boost::geometry::wkt(poly_list[a])<<std::endl;
- std::cout<<boost::geometry::wkt(poly_list[b])<<std::endl;
- std::cout<<boost::geometry::wkt(mp_d)<<std::endl;
+ std::cout << "FAILED TO SUBTRACT " << j << std::endl;
+ std::cout << boost::geometry::wkt(poly_list[a]) << std::endl;
+ std::cout << boost::geometry::wkt(poly_list[b]) << std::endl;
+ std::cout << boost::geometry::wkt(mp_d) << std::endl;
             break;
         }
         try
@@ -164,29 +172,29 @@
         }
         catch(...)
         {
- std::cout<<"FAILED TO SUBTRACT " << j << std::endl;
- std::cout<<boost::geometry::wkt(poly_list[b])<<std::endl;
- std::cout<<boost::geometry::wkt(poly_list[a])<<std::endl;
- std::cout<<boost::geometry::wkt(mp_e)<<std::endl;
+ std::cout << "FAILED TO SUBTRACT " << j << std::endl;
+ std::cout << boost::geometry::wkt(poly_list[b]) << std::endl;
+ std::cout << boost::geometry::wkt(poly_list[a]) << std::endl;
+ std::cout << boost::geometry::wkt(mp_e) << std::endl;
             break;
         }
 #endif
         
- if(boost::geometry::area(mp_i)>0)
+ if(boost::geometry::area(mp_i) > 0)
         {
             std::ostringstream out;
             out << "intersection(" << genesis[a] << " , " << genesis[b] << ")";
             genesis[poly_list.size()] = out.str();
             poly_list.push_back(mp_i);
         }
- if(boost::geometry::area(mp_d)>0)
+ if(boost::geometry::area(mp_d) > 0)
         {
             std::ostringstream out;
             out << "difference(" << genesis[a] << " - " << genesis[b] << ")";
             genesis[poly_list.size()] = out.str();
             poly_list.push_back(mp_d);
         }
- if(boost::geometry::area(mp_e)>0)
+ if(boost::geometry::area(mp_e) > 0)
         {
             std::ostringstream out;
             out << "difference(" << genesis[b] << ", " << genesis[a] << ")";
@@ -200,7 +208,11 @@
     }
     catch(std::exception const& e)
     {
- std::cout << e.what() << " at " << pj << std::endl;
+ std::cout << e.what()
+ << " in " << operation << " at " << pj << std::endl
+ << wkt1 << std::endl
+ << wkt2 << std::endl
+ << std::endl;
     }
     catch(...)
     {

Modified: trunk/libs/geometry/test/algorithms/test_union.hpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/test_union.hpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/test/algorithms/test_union.hpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -1,4 +1,4 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Boost.Geometry (aka GGL, Generic Geometry Library)
 // Unit Test
 
 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
@@ -37,16 +37,21 @@
 
 template <typename OutputType, typename G1, typename G2>
 void test_union(std::string const& caseid, G1 const& g1, G2 const& g2,
- std::size_t expected_count, int expected_hole_count,
+ int expected_count, int expected_hole_count,
         int expected_point_count, double expected_area,
         double percentage)
 {
     typedef typename bg::coordinate_type<G1>::type coordinate_type;
     std::vector<OutputType> clip;
+
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "*** UNION " << caseid << std::endl;
+#endif
+
     bg::union_(g1, g2, clip);
 
     typename bg::default_area_result<G1>::type area = 0;
- int n = 0;
+ std::size_t n = 0;
     std::size_t holes = 0;
     for (typename std::vector<OutputType>::iterator it = clip.begin();
             it != clip.end(); ++it)
@@ -56,6 +61,7 @@
         n += bg::num_points(*it, true);
     }
 
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
     {
         // Test inserter functionality
         // Test if inserter returns output-iterator (using Boost.Range copy)
@@ -78,35 +84,34 @@
         BOOST_CHECK_EQUAL(boost::size(clip), boost::size(inserted) - 1);
         BOOST_CHECK_CLOSE(area_inserted, expected_area, percentage);
     }
+#endif
 
 
 
- /***
- std::cout << "case: " << caseid
- << " n: " << n
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "*** case: " << caseid
         << " area: " << area
+ << " points: " << n
         << " polygons: " << boost::size(clip)
         << " holes: " << holes
         << std::endl;
- ***/
+#endif
 
- if (expected_point_count >= 0)
- {
- BOOST_CHECK_MESSAGE(bg::math::abs(n - expected_point_count) < 3,
- "union: " << caseid
- << " #points expected: " << expected_point_count
- << " detected: " << n
- << " type: " << (type_for_assert_message<G1, G2>())
- );
- }
+ BOOST_CHECK_MESSAGE(expected_point_count < 0 || std::abs(int(n) - expected_point_count) < 3,
+ "union: " << caseid
+ << " #points expected: " << expected_point_count
+ << " detected: " << n
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
 
- BOOST_CHECK_MESSAGE(clip.size() == expected_count,
+ BOOST_CHECK_MESSAGE(expected_count < 0 || int(clip.size()) == expected_count,
             "union: " << caseid
             << " #clips expected: " << expected_count
             << " detected: " << clip.size()
             << " type: " << (type_for_assert_message<G1, G2>())
             );
- BOOST_CHECK_MESSAGE(expected_hole_count < 0 || holes == std::size_t(expected_hole_count),
+
+ BOOST_CHECK_MESSAGE(expected_hole_count < 0 || int(holes) == expected_hole_count,
             "union: " << caseid
             << " #holes expected: " << expected_hole_count
             << " detected: " << holes
@@ -161,7 +166,7 @@
 
 template <typename OutputType, typename G1, typename G2>
 void test_one(std::string const& caseid, std::string const& wkt1, std::string const& wkt2,
- std::size_t expected_count, std::size_t expected_hole_count,
+ int expected_count, int expected_hole_count,
         int expected_point_count, double expected_area,
         double percentage = 0.001)
 {

Modified: trunk/libs/geometry/test/algorithms/union.cpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/union.cpp Sun Oct 20 09:54:27 2013 (r86367)
+++ trunk/libs/geometry/test/algorithms/union.cpp 2013-10-20 11:30:21 EDT (Sun, 20 Oct 2013) (r86368)
@@ -15,8 +15,6 @@
 #include <iostream>
 #include <string>
 
-#define TEST_ISOVIST
-
 #include <algorithms/test_union.hpp>
 #include <algorithms/test_overlay.hpp>
 
@@ -216,48 +214,43 @@
     test_one<Polygon, Polygon, Polygon>("ggl_list_20110306_javier",
         ggl_list_20110306_javier[0], ggl_list_20110306_javier[1],
         1, 1, 16, 80456.4904910401);
-
+
     test_one<Polygon, Polygon, Polygon>("ggl_list_20110307_javier",
         ggl_list_20110307_javier[0], ggl_list_20110307_javier[1],
         1, 1, 13, 20016.4);
 
     test_one<Polygon, Polygon, Polygon>("ggl_list_20110627_phillip",
         ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1],
- 1, 0,
- if_typed<ct, double>(5, if_typed_tt<ct>(8, 8)),
+ 1, 0,
+ if_typed<ct, double>(5, if_typed_tt<ct>(8, 8)),
         14729.07145);
-
+
 
     // FP might return different amount of points
     test_one<Polygon, Polygon, Polygon>("ggl_list_20110716_enrico",
         ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
         1, 1,
- if_typed<ct, double>(18, if_typed<ct, float>(-1, 17)),
+ if_typed<ct, double>(18, if_typed<ct, float>(-1, 17)),
         129904.197692871);
 
- test_one<Polygon, Polygon, Polygon>("ggl_list_20110820_christophe",
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110820_christophe",
         ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
- 2, // Previously it was 1 for double. The intersections are missed now, they fall in eps margins, arbitrary to generate them...
- 0,
- if_typed_tt<ct>(9, 8),
+ -1, // Either 1 or 2, depending if the intersection/turn point (eps.region) is missed
+ 0,
+ if_typed_tt<ct>(9, 8),
         67.3550722317627);
 
 
-#ifdef TEST_ISOVIST
-#ifdef _MSC_VER
     test_one<Polygon, Polygon, Polygon>("isovist",
         isovist1[0], isovist1[1],
         1,
         0,
- if_typed<ct, float>(72, if_typed<ct, double>(67, 73)),
- 313.36036462, 0.1);
+ -1,
+ 313.36036462, 0.01);
 
     // SQL Server gives: 313.360374193241
     // PostGIS gives: 313.360364623393
 
-#endif
-#endif
-
     // Ticket 5103 https://svn.boost.org/trac/boost/ticket/5103
     // This ticket was actually reported for Boost.Polygon
     // We check it for Boost.Geometry as well.
@@ -301,7 +294,7 @@
     if (test_rt_i_rev)
     {
         test_one<Polygon, Polygon, Polygon>("buffer_rt_i_rev", buffer_rt_i[1], buffer_rt_i[0],
- 1, 0, 13, 13.6569);
+ 1, 0, 13, 13.6569);
     }
 
     test_one<Polygon, Polygon, Polygon>("buffer_rt_j", buffer_rt_j[0], buffer_rt_j[1],


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