summaryrefslogtreecommitdiff
path: root/boost/geometry/policies
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
committerChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
commit08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch)
tree7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/geometry/policies
parentbb4dd8289b351fae6b55e303f189127a394a1edd (diff)
downloadboost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/geometry/policies')
-rw-r--r--boost/geometry/policies/disjoint_interrupt_policy.hpp67
-rw-r--r--boost/geometry/policies/predicate_based_interrupt_policy.hpp101
-rw-r--r--boost/geometry/policies/relate/de9im.hpp9
-rw-r--r--boost/geometry/policies/relate/direction.hpp266
-rw-r--r--boost/geometry/policies/relate/intersection_points.hpp245
-rw-r--r--boost/geometry/policies/relate/intersection_ratios.hpp127
-rw-r--r--boost/geometry/policies/relate/tupled.hpp116
-rw-r--r--boost/geometry/policies/robustness/get_rescale_policy.hpp290
-rw-r--r--boost/geometry/policies/robustness/no_rescale_policy.hpp66
-rw-r--r--boost/geometry/policies/robustness/rescale_policy.hpp83
-rw-r--r--boost/geometry/policies/robustness/robust_point_type.hpp30
-rw-r--r--boost/geometry/policies/robustness/robust_type.hpp67
-rw-r--r--boost/geometry/policies/robustness/segment_ratio.hpp239
-rw-r--r--boost/geometry/policies/robustness/segment_ratio_type.hpp28
14 files changed, 1410 insertions, 324 deletions
diff --git a/boost/geometry/policies/disjoint_interrupt_policy.hpp b/boost/geometry/policies/disjoint_interrupt_policy.hpp
new file mode 100644
index 0000000000..2a6e54b079
--- /dev/null
+++ b/boost/geometry/policies/disjoint_interrupt_policy.hpp
@@ -0,0 +1,67 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2013-2014.
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// 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_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP
+
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint
+{
+
+
+struct disjoint_interrupt_policy
+{
+ static bool const enabled = true;
+ bool has_intersections;
+
+ inline disjoint_interrupt_policy()
+ : has_intersections(false)
+ {}
+
+ template <typename Range>
+ inline bool apply(Range const& range)
+ {
+ // If there is any IP in the range, it is NOT disjoint
+ if (boost::size(range) > 0)
+ {
+ has_intersections = true;
+ return true;
+ }
+ return false;
+ }
+};
+
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP
diff --git a/boost/geometry/policies/predicate_based_interrupt_policy.hpp b/boost/geometry/policies/predicate_based_interrupt_policy.hpp
new file mode 100644
index 0000000000..0021b12dc6
--- /dev/null
+++ b/boost/geometry/policies/predicate_based_interrupt_policy.hpp
@@ -0,0 +1,101 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template
+<
+ typename IsAcceptableTurnPredicate,
+ bool AllowEmptyTurnRange = true // by default, allow an empty turn range
+>
+struct stateless_predicate_based_interrupt_policy
+{
+ static bool const enabled = true;
+ bool has_intersections; // set to true if there is at least one
+ // unacceptable turn
+
+ inline stateless_predicate_based_interrupt_policy()
+ : has_intersections(false)
+ {}
+
+ template <typename Range>
+ inline bool apply(Range const& range)
+ {
+ // if there is at least one unacceptable turn in the range, return false
+ has_intersections = !detail::check_iterator_range
+ <
+ IsAcceptableTurnPredicate,
+ AllowEmptyTurnRange
+ >::apply(boost::begin(range), boost::end(range));
+
+ return has_intersections;
+ }
+};
+
+
+
+
+template
+<
+ typename IsAcceptableTurnPredicate,
+ bool AllowEmptyTurnRange = true // by default, allow an empty turn range
+>
+struct predicate_based_interrupt_policy
+{
+ static bool const enabled = true;
+ bool has_intersections; // set to true if there is at least one
+ // unacceptable turn
+ IsAcceptableTurnPredicate const& m_predicate;
+
+ inline
+ predicate_based_interrupt_policy(IsAcceptableTurnPredicate const& predicate)
+ : has_intersections(false)
+ , m_predicate(predicate)
+ {}
+
+ template <typename Range>
+ inline bool apply(Range const& range)
+ {
+ // if there is at least one unacceptable turn in the range, return false
+ has_intersections = !detail::check_iterator_range
+ <
+ IsAcceptableTurnPredicate,
+ AllowEmptyTurnRange
+ >::apply(boost::begin(range), boost::end(range), m_predicate);
+
+ return has_intersections;
+ }
+};
+
+
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
diff --git a/boost/geometry/policies/relate/de9im.hpp b/boost/geometry/policies/relate/de9im.hpp
index 766d80b220..e2d6b5111c 100644
--- a/boost/geometry/policies/relate/de9im.hpp
+++ b/boost/geometry/policies/relate/de9im.hpp
@@ -158,15 +158,6 @@ struct segments_de9im
false, false, false, true);
}
- static inline return_type collinear_disjoint()
- {
- return de9im_segment(0,0,
- -1, -1, 1,
- -1, -1, 0,
- 1, 0, 2,
- true);
- }
-
};
diff --git a/boost/geometry/policies/relate/direction.hpp b/boost/geometry/policies/relate/direction.hpp
index cfbaf7dd15..02fed94b10 100644
--- a/boost/geometry/policies/relate/direction.hpp
+++ b/boost/geometry/policies/relate/direction.hpp
@@ -88,7 +88,8 @@ struct direction_type
// New information
side_info sides;
- int arrival[2]; // 1=arrival, -1departure, 0=neutral; == how_a//how_b
+ // THIS IS EQUAL TO arrival_a, arrival_b - they probably can go now we have robust fractions
+ int arrival[2]; // 1=arrival, -1=departure, 0=neutral; == how_a//how_b
// About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
@@ -110,28 +111,19 @@ struct direction_type
};
-
-template <typename S1, typename S2, typename CalculationType = void>
struct segments_direction
{
typedef direction_type return_type;
- typedef S1 segment_type1;
- typedef S2 segment_type2;
- typedef typename select_calculation_type
- <
- S1, S2, CalculationType
- >::type coordinate_type;
-
- // Get the same type, but at least a double
- typedef typename select_most_precise<coordinate_type, double>::type rtype;
-
-
- template <typename R>
- static inline return_type segments_intersect(side_info const& sides,
- R const&,
- coordinate_type const& dx1, coordinate_type const& dy1,
- coordinate_type const& dx2, coordinate_type const& dy2,
- S1 const& s1, S2 const& s2)
+
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename SegmentIntersectionInfo
+ >
+ static inline return_type segments_crosses(side_info const& sides,
+ SegmentIntersectionInfo const& ,
+ Segment1 const& , Segment2 const& )
{
bool const ra0 = sides.get<0,0>() == 0;
bool const ra1 = sides.get<0,1>() == 0;
@@ -140,95 +132,153 @@ struct segments_direction
return
// opposite and same starting point (FROM)
- ra0 && rb0 ? calculate_side<1>(sides, dx1, dy1, s1, s2, 'f', -1, -1)
+ ra0 && rb0 ? calculate_side<1>(sides, 'f', -1, -1)
// opposite and point to each other (TO)
- : ra1 && rb1 ? calculate_side<0>(sides, dx1, dy1, s1, s2, 't', 1, 1)
+ : ra1 && rb1 ? calculate_side<0>(sides, 't', 1, 1)
// not opposite, forming an angle, first a then b,
// directed either both left, or both right
// Check side of B2 from A. This is not calculated before
- : ra1 && rb0 ? angle<1>(sides, dx1, dy1, s1, s2, 'a', 1, -1)
+ : ra1 && rb0 ? angle<1>(sides, 'a', 1, -1)
// not opposite, forming a angle, first b then a,
// directed either both left, or both right
- : ra0 && rb1 ? angle<0>(sides, dx1, dy1, s1, s2, 'a', -1, 1)
+ : ra0 && rb1 ? angle<0>(sides, 'a', -1, 1)
// b starts from interior of a
- : rb0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'B', 0, -1)
+ : rb0 ? starts_from_middle(sides, 'B', 0, -1)
// a starts from interior of b (#39)
- : ra0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'A', -1, 0)
+ : ra0 ? starts_from_middle(sides, 'A', -1, 0)
// b ends at interior of a, calculate direction of A from IP
- : rb1 ? b_ends_at_middle(sides, dx2, dy2, s1, s2)
+ : rb1 ? b_ends_at_middle(sides)
// a ends at interior of b
- : ra1 ? a_ends_at_middle(sides, dx1, dy1, s1, s2)
+ : ra1 ? a_ends_at_middle(sides)
// normal intersection
- : calculate_side<1>(sides, dx1, dy1, s1, s2, 'i', -1, -1)
+ : calculate_side<1>(sides, 'i', -1, -1)
;
}
- static inline return_type collinear_touch(
- coordinate_type const& ,
- coordinate_type const& , int arrival_a, int arrival_b)
+ template <typename Ratio>
+ static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)
{
- // Though this is 'collinear', we handle it as To/From/Angle because it is the same.
- // It only does NOT have a direction.
- side_info sides;
- //int const arrive = how == 'T' ? 1 : -1;
- bool opposite = arrival_a == arrival_b;
- return
- ! opposite
- ? return_type(sides, 'a', arrival_a, arrival_b)
- : return_type(sides, arrival_a == 0 ? 't' : 'f', arrival_a, arrival_b, 0, 0, true);
+ // a1--------->a2
+ // b1----->b2
+ // a departs: -1
+
+ // a1--------->a2
+ // b1----->b2
+ // a arrives: 1
+
+ // a1--------->a2
+ // b1----->b2
+ // both arrive there -> r-to = 1/1, or 0/1 (on_segment)
+
+ // First check the TO (for arrival), then FROM (for departure)
+ return r_to.in_segment() ? 1
+ : r_to.on_segment() ? 0
+ : r_from.on_segment() ? -1
+ : -1
+ ;
}
- template <typename S>
- static inline return_type collinear_interior_boundary_intersect(S const& , bool,
- int arrival_a, int arrival_b, bool opposite)
+ template <typename Ratio>
+ static inline void analyze(Ratio const& r,
+ int& in_segment_count,
+ int& on_end_count,
+ int& outside_segment_count)
{
- return_type r('c', opposite);
- r.arrival[0] = arrival_a;
- r.arrival[1] = arrival_b;
- return r;
+ if (r.on_end())
+ {
+ on_end_count++;
+ }
+ else if (r.in_segment())
+ {
+ in_segment_count++;
+ }
+ else
+ {
+ outside_segment_count++;
+ }
}
- static inline return_type collinear_a_in_b(S1 const& , bool opposite)
- {
- return_type r('c', opposite);
- r.arrival[0] = 1;
- r.arrival[1] = -1;
- return r;
- }
- static inline return_type collinear_b_in_a(S2 const& , bool opposite)
+ template <typename Segment1, typename Segment2, typename Ratio>
+ static inline return_type segments_collinear(
+ Segment1 const& , Segment2 const&,
+ Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
+ Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
{
- return_type r('c', opposite);
- r.arrival[0] = -1;
- r.arrival[1] = 1;
- return r;
- }
+ // If segments are opposite, the ratio of the FROM w.r.t. the other
+ // is larger than the ratio of the TO w.r.t. the other
+ bool const opposite = ra_to_wrt_b < ra_from_wrt_b;
- static inline return_type collinear_overlaps(
- coordinate_type const& , coordinate_type const& ,
- coordinate_type const& , coordinate_type const& ,
- int arrival_a, int arrival_b, bool opposite)
- {
return_type r('c', opposite);
- r.arrival[0] = arrival_a;
- r.arrival[1] = arrival_b;
+
+ // IMPORTANT: the order of conditions is different as in intersection_points.hpp
+ // We assign A in 0 and B in 1
+ r.arrival[0] = arrival_value(ra_from_wrt_b, ra_to_wrt_b);
+ r.arrival[1] = arrival_value(rb_from_wrt_a, rb_to_wrt_a);
+
+ // Analyse them
+ int a_in_segment_count = 0;
+ int a_on_end_count = 0;
+ int a_outside_segment_count = 0;
+ int b_in_segment_count = 0;
+ int b_on_end_count = 0;
+ int b_outside_segment_count = 0;
+ analyze(ra_from_wrt_b,
+ a_in_segment_count, a_on_end_count, a_outside_segment_count);
+ analyze(ra_to_wrt_b,
+ a_in_segment_count, a_on_end_count, a_outside_segment_count);
+ analyze(rb_from_wrt_a,
+ b_in_segment_count, b_on_end_count, b_outside_segment_count);
+ analyze(rb_to_wrt_a,
+ b_in_segment_count, b_on_end_count, b_outside_segment_count);
+
+ if (a_on_end_count == 1
+ && b_on_end_count == 1
+ && a_outside_segment_count == 1
+ && b_outside_segment_count == 1)
+ {
+ // This is a collinear touch
+ // --------> A (or B)
+ // <---------- B (or A)
+ // We adapt the "how"
+ // TODO: how was to be refactored anyway,
+ if (! opposite)
+ {
+ r.how = 'a';
+ }
+ else
+ {
+ r.how = r.arrival[0] == 0 ? 't' : 'f';
+ }
+ }
+ else if (a_on_end_count == 2
+ && b_on_end_count == 2)
+ {
+ r.how = 'e';
+ }
+
return r;
}
- static inline return_type segment_equal(S1 const& , bool opposite)
+ template <typename Segment>
+ static inline return_type degenerate(Segment const& , bool)
{
- return return_type('e', opposite);
+ return return_type('0', false);
}
- static inline return_type degenerate(S1 const& , bool)
+ template <typename Segment, typename Ratio>
+ static inline return_type one_degenerate(Segment const& ,
+ Ratio const& ,
+ bool)
{
+ // To be decided
return return_type('0', false);
}
@@ -237,11 +287,6 @@ struct segments_direction
return return_type('d', false);
}
- static inline return_type collinear_disjoint()
- {
- return return_type('d', false);
- }
-
static inline return_type error(std::string const&)
{
// Return "E" to denote error
@@ -252,62 +297,29 @@ struct segments_direction
private :
- static inline bool is_left
- (
- coordinate_type const& ux,
- coordinate_type const& uy,
- coordinate_type const& vx,
- coordinate_type const& vy
- )
- {
- // This is a "side calculation" as in the strategies, but here terms are precalculated
- // We might merge this with side, offering a pre-calculated term (in fact already done using cross-product)
- // Waiting for implementing spherical...
-
- rtype const zero = rtype();
- return geometry::detail::determinant<rtype>(ux, uy, vx, vy) > zero;
- }
-
template <std::size_t I>
static inline return_type calculate_side(side_info const& sides,
- coordinate_type const& dx1, coordinate_type const& dy1,
- S1 const& s1, S2 const& s2,
char how, int how_a, int how_b)
{
- coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1);
- coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1);
-
- return is_left(dx1, dy1, dpx, dpy)
- ? return_type(sides, how, how_a, how_b, -1, 1)
- : return_type(sides, how, how_a, how_b, 1, -1);
+ int const dir = sides.get<1, I>() == 1 ? 1 : -1;
+ return return_type(sides, how, how_a, how_b, -dir, dir);
}
template <std::size_t I>
static inline return_type angle(side_info const& sides,
- coordinate_type const& dx1, coordinate_type const& dy1,
- S1 const& s1, S2 const& s2,
char how, int how_a, int how_b)
{
- coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1);
- coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1);
-
- return is_left(dx1, dy1, dpx, dpy)
- ? return_type(sides, how, how_a, how_b, 1, 1)
- : return_type(sides, how, how_a, how_b, -1, -1);
+ int const dir = sides.get<1, I>() == 1 ? 1 : -1;
+ return return_type(sides, how, how_a, how_b, dir, dir);
}
static inline return_type starts_from_middle(side_info const& sides,
- coordinate_type const& dx1, coordinate_type const& dy1,
- S1 const& s1, S2 const& s2,
char which,
int how_a, int how_b)
{
// Calculate ARROW of b segment w.r.t. s1
- coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1);
- coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1);
-
- int dir = is_left(dx1, dy1, dpx, dpy) ? 1 : -1;
+ int dir = sides.get<1, 1>() == 1 ? 1 : -1;
// From other perspective, then reverse
bool const is_a = which == 'A';
@@ -326,31 +338,19 @@ private :
// To be harmonized
- static inline return_type a_ends_at_middle(side_info const& sides,
- coordinate_type const& dx, coordinate_type const& dy,
- S1 const& s1, S2 const& s2)
+ static inline return_type a_ends_at_middle(side_info const& sides)
{
- coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1);
- coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1);
-
// Ending at the middle, one ARRIVES, the other one is NEUTRAL
- // (because it both "arrives" and "departs" there
- return is_left(dx, dy, dpx, dpy)
- ? return_type(sides, 'm', 1, 0, 1, 1)
- : return_type(sides, 'm', 1, 0, -1, -1);
+ // (because it both "arrives" and "departs" there)
+ int const dir = sides.get<1, 1>() == 1 ? 1 : -1;
+ return return_type(sides, 'm', 1, 0, dir, dir);
}
- static inline return_type b_ends_at_middle(side_info const& sides,
- coordinate_type const& dx, coordinate_type const& dy,
- S1 const& s1, S2 const& s2)
+ static inline return_type b_ends_at_middle(side_info const& sides)
{
- coordinate_type dpx = get<1, 0>(s1) - get<0, 0>(s2);
- coordinate_type dpy = get<1, 1>(s1) - get<0, 1>(s2);
-
- return is_left(dx, dy, dpx, dpy)
- ? return_type(sides, 'm', 0, 1, 1, 1)
- : return_type(sides, 'm', 0, 1, -1, -1);
+ int const dir = sides.get<0, 1>() == 1 ? 1 : -1;
+ return return_type(sides, 'm', 0, 1, dir, dir);
}
};
diff --git a/boost/geometry/policies/relate/intersection_points.hpp b/boost/geometry/policies/relate/intersection_points.hpp
index d7d5199051..aa2f697a2a 100644
--- a/boost/geometry/policies/relate/intersection_points.hpp
+++ b/boost/geometry/policies/relate/intersection_points.hpp
@@ -16,12 +16,12 @@
#include <boost/concept_check.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
-
+#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@@ -30,106 +30,153 @@ namespace policies { namespace relate
{
-template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
+/*!
+\brief Policy calculating the intersection points themselves
+ */
+template
+<
+ typename ReturnType
+>
struct segments_intersection_points
{
typedef ReturnType return_type;
- typedef S1 segment_type1;
- typedef S2 segment_type2;
-
- typedef typename select_calculation_type
- <
- S1, S2, CalculationType
- >::type coordinate_type;
-
- template <typename R>
- static inline return_type segments_intersect(side_info const&,
- R const& r,
- coordinate_type const& dx1, coordinate_type const& dy1,
- coordinate_type const& dx2, coordinate_type const& dy2,
- S1 const& s1, S2 const& s2)
- {
- typedef typename geometry::coordinate_type
- <
- typename return_type::point_type
- >::type return_coordinate_type;
-
- coordinate_type const s1x = get<0, 0>(s1);
- coordinate_type const s1y = get<0, 1>(s1);
-
- return_type result;
- result.count = 1;
- set<0>(result.intersections[0],
- boost::numeric_cast<return_coordinate_type>(R(s1x) + r * R(dx1)));
- set<1>(result.intersections[0],
- boost::numeric_cast<return_coordinate_type>(R(s1y) + r * R(dy1)));
- return result;
- }
-
- static inline return_type collinear_touch(coordinate_type const& x,
- coordinate_type const& y, int, int)
+ template
+ <
+ typename Point,
+ typename Segment,
+ typename SegmentRatio,
+ typename T
+ >
+ static inline void assign(Point& point,
+ Segment const& segment,
+ SegmentRatio const& ratio,
+ T const& dx, T const& dy)
{
- return_type result;
- result.count = 1;
- set<0>(result.intersections[0], x);
- set<1>(result.intersections[0], y);
- return result;
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ // Calculate the intersection point based on segment_ratio
+ // Up to now, division was postponed. Here we divide using numerator/
+ // denominator. In case of integer this results in an integer
+ // division.
+ BOOST_ASSERT(ratio.denominator() != 0);
+ set<0>(point, boost::numeric_cast<coordinate_type>(
+ get<0, 0>(segment)
+ + ratio.numerator() * dx / ratio.denominator()));
+ set<1>(point, boost::numeric_cast<coordinate_type>(
+ get<0, 1>(segment)
+ + ratio.numerator() * dy / ratio.denominator()));
}
- template <typename S>
- static inline return_type collinear_inside(S const& s, int index1 = 0, int index2 = 1)
+
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename SegmentIntersectionInfo
+ >
+ static inline return_type segments_crosses(side_info const&,
+ SegmentIntersectionInfo const& sinfo,
+ Segment1 const& s1, Segment2 const& s2)
{
return_type result;
- result.count = 2;
- set<0>(result.intersections[index1], get<0, 0>(s));
- set<1>(result.intersections[index1], get<0, 1>(s));
- set<0>(result.intersections[index2], get<1, 0>(s));
- set<1>(result.intersections[index2], get<1, 1>(s));
- return result;
- }
+ result.count = 1;
- template <typename S>
- static inline return_type collinear_interior_boundary_intersect(S const& s, bool a_in_b,
- int, int, bool opposite)
- {
- int index1 = opposite && ! a_in_b ? 1 : 0;
- return collinear_inside(s, index1, 1 - index1);
- }
+ if (sinfo.robust_ra < sinfo.robust_rb)
+ {
+ assign(result.intersections[0], s1, sinfo.robust_ra,
+ sinfo.dx_a, sinfo.dy_a);
+ }
+ else
+ {
+ assign(result.intersections[0], s2, sinfo.robust_rb,
+ sinfo.dx_b, sinfo.dy_b);
+ }
- static inline return_type collinear_a_in_b(S1 const& s, bool)
- {
- return collinear_inside(s);
- }
- static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
- {
- int index1 = opposite ? 1 : 0;
- return collinear_inside(s, index1, 1 - index1);
- }
+ result.fractions[0].assign(sinfo);
- static inline return_type collinear_overlaps(
- coordinate_type const& x1, coordinate_type const& y1,
- coordinate_type const& x2, coordinate_type const& y2,
- int, int, bool)
- {
- return_type result;
- result.count = 2;
- set<0>(result.intersections[0], x1);
- set<1>(result.intersections[0], y1);
- set<0>(result.intersections[1], x2);
- set<1>(result.intersections[1], y2);
return result;
}
- static inline return_type segment_equal(S1 const& s, bool)
+ template <typename Segment1, typename Segment2, typename Ratio>
+ static inline return_type segments_collinear(
+ Segment1 const& a, Segment2 const& b,
+ Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
+ Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
{
return_type result;
- result.count = 2;
- // TODO: order of IP's
- set<0>(result.intersections[0], get<0, 0>(s));
- set<1>(result.intersections[0], get<0, 1>(s));
- set<0>(result.intersections[1], get<1, 0>(s));
- set<1>(result.intersections[1], get<1, 1>(s));
+ int index = 0, count_a = 0, count_b = 0;
+ Ratio on_a[2];
+
+ // The conditions "index < 2" are necessary for non-robust handling,
+ // if index would be 2 this indicate an (currently uncatched) error
+
+ // IMPORTANT: the order of conditions is different as in direction.hpp
+ if (ra_from_wrt_b.on_segment()
+ && index < 2)
+ {
+ // a1--------->a2
+ // b1----->b2
+ //
+ // ra1 (relative to b) is between 0/1:
+ // -> First point of A is intersection point
+ detail::assign_point_from_index<0>(a, result.intersections[index]);
+ result.fractions[index].assign(Ratio::zero(), ra_from_wrt_b);
+ on_a[index] = Ratio::zero();
+ index++;
+ count_a++;
+ }
+ if (rb_from_wrt_a.in_segment()
+ && index < 2)
+ {
+ // We take the first intersection point of B
+ // a1--------->a2
+ // b1----->b2
+ // But only if it is not located on A
+ // a1--------->a2
+ // b1----->b2 rb_from_wrt_a == 0/1 -> a already taken
+
+ detail::assign_point_from_index<0>(b, result.intersections[index]);
+ result.fractions[index].assign(rb_from_wrt_a, Ratio::zero());
+ on_a[index] = rb_from_wrt_a;
+ index++;
+ count_b++;
+ }
+
+ if (ra_to_wrt_b.on_segment()
+ && index < 2)
+ {
+ // Similarly, second IP (here a2)
+ // a1--------->a2
+ // b1----->b2
+ detail::assign_point_from_index<1>(a, result.intersections[index]);
+ result.fractions[index].assign(Ratio::one(), ra_to_wrt_b);
+ on_a[index] = Ratio::one();
+ index++;
+ count_a++;
+ }
+ if (rb_to_wrt_a.in_segment()
+ && index < 2)
+ {
+ detail::assign_point_from_index<1>(b, result.intersections[index]);
+ result.fractions[index].assign(rb_to_wrt_a, Ratio::one());
+ on_a[index] = rb_to_wrt_a;
+ index++;
+ count_b++;
+ }
+
+ // TEMPORARY
+ // If both are from b, and b is reversed w.r.t. a, we swap IP's
+ // to align them w.r.t. a
+ // get_turn_info still relies on some order (in some collinear cases)
+ if (index == 2 && on_a[1] < on_a[0])
+ {
+ std::swap(result.fractions[0], result.fractions[1]);
+ std::swap(result.intersections[0], result.intersections[1]);
+ }
+
+ result.count = index;
+
return result;
}
@@ -142,17 +189,35 @@ struct segments_intersection_points
return return_type();
}
- static inline return_type collinear_disjoint()
+ // Both degenerate
+ template <typename Segment>
+ static inline return_type degenerate(Segment const& segment, bool)
{
- return return_type();
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], get<0, 0>(segment));
+ set<1>(result.intersections[0], get<0, 1>(segment));
+ return result;
}
- static inline return_type degenerate(S1 const& s, bool)
+ // One degenerate
+ template <typename Segment, typename Ratio>
+ static inline return_type one_degenerate(Segment const& degenerate_segment,
+ Ratio const& ratio, bool a_degenerate)
{
return_type result;
result.count = 1;
- set<0>(result.intersections[0], get<0, 0>(s));
- set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[0], get<0, 0>(degenerate_segment));
+ set<1>(result.intersections[0], get<0, 1>(degenerate_segment));
+ if (a_degenerate)
+ {
+ // IP lies on ratio w.r.t. segment b
+ result.fractions[0].assign(Ratio::zero(), ratio);
+ }
+ else
+ {
+ result.fractions[0].assign(ratio, Ratio::zero());
+ }
return result;
}
};
diff --git a/boost/geometry/policies/relate/intersection_ratios.hpp b/boost/geometry/policies/relate/intersection_ratios.hpp
new file mode 100644
index 0000000000..81ecba0b54
--- /dev/null
+++ b/boost/geometry/policies/relate/intersection_ratios.hpp
@@ -0,0 +1,127 @@
+// 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)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
+
+
+#include <algorithm>
+#include <string>
+
+#include <boost/concept_check.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate
+{
+
+
+/*!
+\brief Policy returning segment ratios
+\note Template argument FractionType should be a fraction_type<SegmentRatio>
+ */
+template
+<
+ typename FractionType
+>
+struct segments_intersection_ratios
+{
+ typedef FractionType return_type;
+
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename SegmentIntersectionInfo
+ >
+ static inline return_type segments_crosses(side_info const&,
+ SegmentIntersectionInfo const& sinfo,
+ Segment1 const& , Segment2 const& )
+ {
+ return_type result;
+ result.assign(sinfo);
+ return result;
+ }
+
+ template <typename Segment1, typename Segment2, typename Ratio>
+ static inline return_type segments_collinear(
+ Segment1 const& , Segment2 const& ,
+ Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
+ Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
+ {
+ // We have only one result, for (potentially) two IP's,
+ // so we take a first one
+ return_type result;
+
+ if (ra_from_wrt_b.on_segment())
+ {
+ result.assign(Ratio::zero(), ra_from_wrt_b);
+ }
+ else if (rb_from_wrt_a.in_segment())
+ {
+ result.assign(rb_from_wrt_a, Ratio::zero());
+ }
+ else if (ra_to_wrt_b.on_segment())
+ {
+ result.assign(Ratio::one(), ra_to_wrt_b);
+ }
+ else if (rb_to_wrt_a.in_segment())
+ {
+ result.assign(rb_to_wrt_a, Ratio::one());
+ }
+
+ return result;
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type error(std::string const&)
+ {
+ return return_type();
+ }
+
+ template <typename Segment>
+ static inline return_type degenerate(Segment const& segment, bool)
+ {
+ return return_type();
+ }
+
+ template <typename Segment, typename Ratio>
+ static inline return_type one_degenerate(Segment const& ,
+ Ratio const& ratio, bool a_degenerate)
+ {
+ return_type result;
+ if (a_degenerate)
+ {
+ // IP lies on ratio w.r.t. segment b
+ result.assign(Ratio::zero(), ratio);
+ }
+ else
+ {
+ result.assign(ratio, Ratio::zero());
+ }
+ return result;
+ }
+
+};
+
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
diff --git a/boost/geometry/policies/relate/tupled.hpp b/boost/geometry/policies/relate/tupled.hpp
index f6713c44c9..6da9095c4e 100644
--- a/boost/geometry/policies/relate/tupled.hpp
+++ b/boost/geometry/policies/relate/tupled.hpp
@@ -14,8 +14,6 @@
#include <boost/tuple/tuple.hpp>
#include <boost/geometry/strategies/side_info.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
@@ -26,7 +24,7 @@ namespace policies { namespace relate
// "tupled" to return intersection results together.
// Now with two, with some meta-programming and derivations it can also be three (or more)
-template <typename Policy1, typename Policy2, typename CalculationType = void>
+template <typename Policy1, typename Policy2>
struct segments_tupled
{
typedef boost::tuple
@@ -35,107 +33,50 @@ struct segments_tupled
typename Policy2::return_type
> return_type;
- // Take segments of first policy, they should be equal
- typedef typename Policy1::segment_type1 segment_type1;
- typedef typename Policy1::segment_type2 segment_type2;
-
- typedef typename select_calculation_type
- <
- segment_type1,
- segment_type2,
- CalculationType
- >::type coordinate_type;
-
- // Get the same type, but at least a double
- typedef typename select_most_precise<coordinate_type, double>::type rtype;
-
- template <typename R>
- static inline return_type segments_intersect(side_info const& sides,
- R const& r,
- coordinate_type const& dx1, coordinate_type const& dy1,
- coordinate_type const& dx2, coordinate_type const& dy2,
- segment_type1 const& s1, segment_type2 const& s2)
- {
- return boost::make_tuple
- (
- Policy1::segments_intersect(sides, r,
- dx1, dy1, dx2, dy2, s1, s2),
- Policy2::segments_intersect(sides, r,
- dx1, dy1, dx2, dy2, s1, s2)
- );
- }
-
- static inline return_type collinear_touch(coordinate_type const& x,
- coordinate_type const& y, int arrival_a, int arrival_b)
- {
- return boost::make_tuple
- (
- Policy1::collinear_touch(x, y, arrival_a, arrival_b),
- Policy2::collinear_touch(x, y, arrival_a, arrival_b)
- );
- }
-
- template <typename S>
- static inline return_type collinear_interior_boundary_intersect(S const& segment,
- bool a_within_b,
- int arrival_a, int arrival_b, bool opposite)
- {
- return boost::make_tuple
- (
- Policy1::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite),
- Policy2::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite)
- );
- }
-
- static inline return_type collinear_a_in_b(segment_type1 const& segment,
- bool opposite)
- {
- return boost::make_tuple
- (
- Policy1::collinear_a_in_b(segment, opposite),
- Policy2::collinear_a_in_b(segment, opposite)
- );
- }
- static inline return_type collinear_b_in_a(segment_type2 const& segment,
- bool opposite)
+ template <typename Segment1, typename Segment2, typename SegmentIntersectionInfo>
+ static inline return_type segments_crosses(side_info const& sides,
+ SegmentIntersectionInfo const& sinfo,
+ Segment1 const& s1, Segment2 const& s2)
{
return boost::make_tuple
(
- Policy1::collinear_b_in_a(segment, opposite),
- Policy2::collinear_b_in_a(segment, opposite)
+ Policy1::segments_crosses(sides, sinfo, s1, s2),
+ Policy2::segments_crosses(sides, sinfo, s1, s2)
);
}
-
- static inline return_type collinear_overlaps(
- coordinate_type const& x1, coordinate_type const& y1,
- coordinate_type const& x2, coordinate_type const& y2,
- int arrival_a, int arrival_b, bool opposite)
+ template <typename Segment1, typename Segment2, typename Ratio>
+ static inline return_type segments_collinear(
+ Segment1 const& segment1, Segment2 const& segment2,
+ Ratio const& ra1, Ratio const& ra2, Ratio const& rb1, Ratio const& rb2)
{
return boost::make_tuple
(
- Policy1::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite),
- Policy2::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite)
+ Policy1::segments_collinear(segment1, segment2, ra1, ra2, rb1, rb2),
+ Policy2::segments_collinear(segment1, segment2, ra1, ra2, rb1, rb2)
);
}
- static inline return_type segment_equal(segment_type1 const& s,
- bool opposite)
+ template <typename Segment>
+ static inline return_type degenerate(Segment const& segment,
+ bool a_degenerate)
{
return boost::make_tuple
(
- Policy1::segment_equal(s, opposite),
- Policy2::segment_equal(s, opposite)
+ Policy1::degenerate(segment, a_degenerate),
+ Policy2::degenerate(segment, a_degenerate)
);
}
- static inline return_type degenerate(segment_type1 const& segment,
- bool a_degenerate)
+ template <typename Segment, typename Ratio>
+ static inline return_type one_degenerate(Segment const& segment,
+ Ratio const& ratio,
+ bool a_degenerate)
{
return boost::make_tuple
(
- Policy1::degenerate(segment, a_degenerate),
- Policy2::degenerate(segment, a_degenerate)
+ Policy1::one_degenerate(segment, ratio, a_degenerate),
+ Policy2::one_degenerate(segment, ratio, a_degenerate)
);
}
@@ -157,15 +98,6 @@ struct segments_tupled
);
}
- static inline return_type collinear_disjoint()
- {
- return boost::make_tuple
- (
- Policy1::collinear_disjoint(),
- Policy2::collinear_disjoint()
- );
- }
-
};
}} // namespace policies::relate
diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp
new file mode 100644
index 0000000000..ed7c1eb94c
--- /dev/null
+++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp
@@ -0,0 +1,290 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2014 Mateusz Loskot, London, UK.
+// 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)
+
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
+
+
+#include <cstddef>
+
+#include <boost/type_traits.hpp>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/recalculate.hpp>
+#include <boost/geometry/algorithms/detail/get_max_size.hpp>
+#include <boost/geometry/policies/robustness/robust_type.hpp>
+
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
+#include <boost/geometry/policies/robustness/rescale_policy.hpp>
+
+#include <boost/geometry/util/promote_floating_point.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_rescale_policy
+{
+
+template <typename Point, typename RobustPoint, typename Geometry, typename Factor>
+static inline void init_rescale_policy(Geometry const& geometry,
+ Point& min_point,
+ RobustPoint& min_robust_point,
+ Factor& factor)
+{
+ // Get bounding boxes
+ model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
+
+ // Scale this to integer-range
+ typedef typename promote_floating_point
+ <
+ typename geometry::coordinate_type<Point>::type
+ >::type num_type;
+ num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(env));
+ num_type const range = 10000000.0; // Define a large range to get precise integer coordinates
+ num_type const half = 0.5;
+ factor = math::equals(diff, num_type()) ? 1
+ : boost::numeric_cast<num_type>(
+ boost::numeric_cast<boost::long_long_type>(half + range / diff));
+
+ // Assign input/output minimal points
+ detail::assign_point_from_index<0>(env, min_point);
+ num_type const two = 2;
+ boost::long_long_type const min_coordinate
+ = boost::numeric_cast<boost::long_long_type>(-range / two);
+ assign_values(min_robust_point, min_coordinate, min_coordinate);
+}
+
+template <typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, typename Factor>
+static inline void init_rescale_policy(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Point& min_point,
+ RobustPoint& min_robust_point,
+ Factor& factor)
+{
+ // Get bounding boxes
+ model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry1);
+ model::box<Point> env2 = geometry::return_envelope<model::box<Point> >(geometry2);
+ geometry::expand(env, env2);
+
+ // TODO: merge this with implementation above
+ // Scale this to integer-range
+ typedef typename promote_floating_point
+ <
+ typename geometry::coordinate_type<Point>::type
+ >::type num_type;
+ num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(env));
+ num_type const range = 10000000.0; // Define a large range to get precise integer coordinates
+ num_type const half = 0.5;
+ factor = math::equals(diff, num_type()) ? 1
+ : boost::numeric_cast<num_type>(
+ boost::numeric_cast<boost::long_long_type>(half + range / diff));
+
+ // Assign input/output minimal points
+ detail::assign_point_from_index<0>(env, min_point);
+ num_type const two = 2;
+ boost::long_long_type const min_coordinate
+ = boost::numeric_cast<boost::long_long_type>(-range / two);
+ assign_values(min_robust_point, min_coordinate, min_coordinate);
+}
+
+
+template
+<
+ typename Point,
+ bool IsFloatingPoint
+>
+struct rescale_policy_type
+{
+ typedef no_rescale_policy type;
+};
+
+// We rescale only all FP types
+template
+<
+ typename Point
+>
+struct rescale_policy_type<Point, true>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+ typedef model::point
+ <
+ typename detail::robust_type<coordinate_type>::type,
+ geometry::dimension<Point>::value,
+ typename geometry::coordinate_system<Point>::type
+ > robust_point_type;
+ typedef typename promote_floating_point<coordinate_type>::type factor_type;
+ typedef detail::robust_policy<Point, robust_point_type, factor_type> type;
+};
+
+template <typename Policy>
+struct get_rescale_policy
+{
+ template <typename Geometry>
+ static inline Policy apply(Geometry const& geometry)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
+ typedef typename promote_floating_point<coordinate_type>::type factor_type;
+ typedef model::point
+ <
+ typename detail::robust_type<coordinate_type>::type,
+ geometry::dimension<point_type>::value,
+ typename geometry::coordinate_system<point_type>::type
+ > robust_point_type;
+
+ point_type min_point;
+ robust_point_type min_robust_point;
+ factor_type factor;
+ init_rescale_policy(geometry, min_point, min_robust_point, factor);
+
+ return Policy(min_point, min_robust_point, factor);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ typedef typename point_type<Geometry1>::type point_type;
+ typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
+ typedef typename promote_floating_point<coordinate_type>::type factor_type;
+ typedef model::point
+ <
+ typename detail::robust_type<coordinate_type>::type,
+ geometry::dimension<point_type>::value,
+ typename geometry::coordinate_system<point_type>::type
+ > robust_point_type;
+
+ point_type min_point;
+ robust_point_type min_robust_point;
+ factor_type factor;
+ init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, factor);
+
+ return Policy(min_point, min_robust_point, factor);
+ }
+};
+
+// Specialization for no-rescaling
+template <>
+struct get_rescale_policy<no_rescale_policy>
+{
+ template <typename Geometry>
+ static inline no_rescale_policy apply(Geometry const& )
+ {
+ return no_rescale_policy();
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& )
+ {
+ return no_rescale_policy();
+ }
+};
+
+
+}} // namespace detail::get_rescale_policy
+#endif // DOXYGEN_NO_DETAIL
+
+template<typename Point>
+struct rescale_policy_type
+ : public detail::get_rescale_policy::rescale_policy_type
+ <
+ Point,
+#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ false
+#else
+ boost::is_floating_point
+ <
+ typename geometry::coordinate_type<Point>::type
+ >::type::value
+#endif
+ >
+{
+ static const bool is_point
+ = boost::is_same
+ <
+ typename geometry::tag<Point>::type,
+ geometry::point_tag
+ >::type::value;
+
+ BOOST_MPL_ASSERT_MSG((is_point),
+ INVALID_INPUT_GEOMETRY,
+ (typename geometry::tag<Point>::type));
+};
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag_cast
+ <
+ typename tag<Geometry1>::type,
+ box_tag,
+ pointlike_tag,
+ linear_tag,
+ areal_tag
+ >::type,
+ typename Tag2 = typename tag_cast
+ <
+ typename tag<Geometry2>::type,
+ box_tag,
+ pointlike_tag,
+ linear_tag,
+ areal_tag
+ >::type
+>
+struct rescale_overlay_policy_type
+ // Default: no rescaling
+ : public detail::get_rescale_policy::rescale_policy_type
+ <
+ typename geometry::point_type<Geometry1>::type,
+ false
+ >
+{};
+
+// Areal/areal: get rescale policy based on coordinate type
+template
+<
+ typename Geometry1,
+ typename Geometry2
+>
+struct rescale_overlay_policy_type<Geometry1, Geometry2, areal_tag, areal_tag>
+ : public rescale_policy_type
+ <
+ typename geometry::point_type<Geometry1>::type
+ >
+{};
+
+
+template <typename Policy, typename Geometry>
+inline Policy get_rescale_policy(Geometry const& geometry)
+{
+ return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry);
+}
+
+template <typename Policy, typename Geometry1, typename Geometry2>
+inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry1, geometry2);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
diff --git a/boost/geometry/policies/robustness/no_rescale_policy.hpp b/boost/geometry/policies/robustness/no_rescale_policy.hpp
new file mode 100644
index 0000000000..a7899842c1
--- /dev/null
+++ b/boost/geometry/policies/robustness/no_rescale_policy.hpp
@@ -0,0 +1,66 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2013 Bruno Lalande, Paris, France.
+// Copyright (c) 2013 Mateusz Loskot, London, UK.
+// Copyright (c) 2013 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)
+
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
+
+#include <stddef.h>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Probably this will be moved out of namespace detail
+struct no_rescale_policy
+{
+ static bool const enabled = false;
+
+ // We don't rescale but return the reference of the input
+ template <std::size_t Dimension, typename Value>
+ inline Value const& apply(Value const& value) const
+ {
+ return value;
+ }
+};
+
+} // namespace detail
+#endif
+
+
+// Implement meta-functions for this policy
+template <typename Point>
+struct robust_point_type<Point, detail::no_rescale_policy>
+{
+ // The point itself
+ typedef Point type;
+};
+
+template <typename Point>
+struct segment_ratio_type<Point, detail::no_rescale_policy>
+{
+ // Define a segment_ratio defined on coordinate type, e.g.
+ // int/int or float/float
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+ typedef segment_ratio<coordinate_type> type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
diff --git a/boost/geometry/policies/robustness/rescale_policy.hpp b/boost/geometry/policies/robustness/rescale_policy.hpp
new file mode 100644
index 0000000000..5b3b566976
--- /dev/null
+++ b/boost/geometry/policies/robustness/rescale_policy.hpp
@@ -0,0 +1,83 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2014 Mateusz Loskot, London, UK.
+// 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)
+
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename FpPoint, typename IntPoint, typename CalculationType>
+struct robust_policy
+{
+ static bool const enabled = true;
+
+ typedef typename geometry::coordinate_type<IntPoint>::type output_ct;
+
+ robust_policy(FpPoint const& fp_min, IntPoint const& int_min, CalculationType const& the_factor)
+ : m_fp_min(fp_min)
+ , m_int_min(int_min)
+ , m_multiplier(the_factor)
+ {
+ }
+
+ template <std::size_t Dimension, typename Value>
+ inline output_ct apply(Value const& value) const
+ {
+ // a + (v-b)*f
+ CalculationType const a = static_cast<CalculationType>(get<Dimension>(m_int_min));
+ CalculationType const b = static_cast<CalculationType>(get<Dimension>(m_fp_min));
+ CalculationType const result = a + (value - b) * m_multiplier;
+ return static_cast<output_ct>(result);
+ }
+
+ FpPoint m_fp_min;
+ IntPoint m_int_min;
+ CalculationType m_multiplier;
+};
+
+} // namespace detail
+#endif
+
+
+// Implement meta-functions for this policy
+
+// Define the IntPoint as a robust-point type
+template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>
+struct robust_point_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >
+{
+ typedef IntPoint type;
+};
+
+// Meta function for rescaling, if rescaling is done segment_ratio is based on long long
+template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>
+struct segment_ratio_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >
+{
+ typedef segment_ratio<boost::long_long_type> type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
diff --git a/boost/geometry/policies/robustness/robust_point_type.hpp b/boost/geometry/policies/robustness/robust_point_type.hpp
new file mode 100644
index 0000000000..25639227f0
--- /dev/null
+++ b/boost/geometry/policies/robustness/robust_point_type.hpp
@@ -0,0 +1,30 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2013 Bruno Lalande, Paris, France.
+// Copyright (c) 2013 Mateusz Loskot, London, UK.
+// Copyright (c) 2013 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)
+
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
+
+namespace boost { namespace geometry
+{
+
+// Meta-function to typedef a robust point type for a policy
+template <typename Point, typename Policy>
+struct robust_point_type
+{
+ // By default, the point itself is the robust type
+ typedef Point type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
diff --git a/boost/geometry/policies/robustness/robust_type.hpp b/boost/geometry/policies/robustness/robust_type.hpp
new file mode 100644
index 0000000000..4cfb2c4d91
--- /dev/null
+++ b/boost/geometry/policies/robustness/robust_type.hpp
@@ -0,0 +1,67 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2014 Mateusz Loskot, London, UK.
+// 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)
+
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
+
+
+#include <boost/type_traits.hpp>
+#include <boost/config.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail_dispatch
+{
+
+template <typename CoordinateType, typename IsFloatingPoint>
+struct robust_type
+{
+};
+
+template <typename CoordinateType>
+struct robust_type<CoordinateType, boost::false_type>
+{
+ typedef CoordinateType type;
+};
+
+template <typename CoordinateType>
+struct robust_type<CoordinateType, boost::true_type>
+{
+ typedef boost::long_long_type type;
+};
+
+} // namespace detail_dispatch
+
+namespace detail
+{
+
+template <typename CoordinateType>
+struct robust_type
+{
+ typedef typename detail_dispatch::robust_type
+ <
+ CoordinateType,
+ typename boost::is_floating_point<CoordinateType>::type
+ >::type type;
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
diff --git a/boost/geometry/policies/robustness/segment_ratio.hpp b/boost/geometry/policies/robustness/segment_ratio.hpp
new file mode 100644
index 0000000000..8b55605c7f
--- /dev/null
+++ b/boost/geometry/policies/robustness/segment_ratio.hpp
@@ -0,0 +1,239 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2013 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_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/rational.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace detail { namespace segment_ratio
+{
+
+template
+<
+ typename Type,
+ bool IsIntegral = boost::is_integral<Type>::type::value
+>
+struct less {};
+
+template <typename Type>
+struct less<Type, true>
+{
+ template <typename Ratio>
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)
+ {
+ return boost::rational<Type>(lhs.numerator(), lhs.denominator())
+ < boost::rational<Type>(rhs.numerator(), rhs.denominator());
+ }
+};
+
+template <typename Type>
+struct less<Type, false>
+{
+ template <typename Ratio>
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)
+ {
+ BOOST_ASSERT(lhs.denominator() != 0);
+ BOOST_ASSERT(rhs.denominator() != 0);
+ return lhs.numerator() * rhs.denominator()
+ < rhs.numerator() * lhs.denominator();
+ }
+};
+
+template
+<
+ typename Type,
+ bool IsIntegral = boost::is_integral<Type>::type::value
+>
+struct equal {};
+
+template <typename Type>
+struct equal<Type, true>
+{
+ template <typename Ratio>
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)
+ {
+ return boost::rational<Type>(lhs.numerator(), lhs.denominator())
+ == boost::rational<Type>(rhs.numerator(), rhs.denominator());
+ }
+};
+
+template <typename Type>
+struct equal<Type, false>
+{
+ template <typename Ratio>
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)
+ {
+ BOOST_ASSERT(lhs.denominator() != 0);
+ BOOST_ASSERT(rhs.denominator() != 0);
+ return geometry::math::equals
+ (
+ lhs.numerator() * rhs.denominator(),
+ rhs.numerator() * lhs.denominator()
+ );
+ }
+};
+
+}}
+
+//! Small class to keep a ratio (e.g. 1/4)
+//! Main purpose is intersections and checking on 0, 1, and smaller/larger
+//! The prototype used Boost.Rational. However, we also want to store FP ratios,
+//! (so numerator/denominator both in float)
+//! and Boost.Rational starts with GCD which we prefer to avoid if not necessary
+//! On a segment means: this ratio is between 0 and 1 (both inclusive)
+//!
+template <typename Type>
+class segment_ratio
+{
+public :
+ typedef Type numeric_type;
+
+ // Type-alias for the type itself
+ typedef segment_ratio<Type> thistype;
+
+ inline segment_ratio()
+ : m_numerator(0)
+ , m_denominator(1)
+ , m_approximation(0)
+ {}
+
+ inline segment_ratio(const Type& nominator, const Type& denominator)
+ : m_numerator(nominator)
+ , m_denominator(denominator)
+ {
+ initialize();
+ }
+
+ inline Type const& numerator() const { return m_numerator; }
+ inline Type const& denominator() const { return m_denominator; }
+
+ inline void assign(const Type& nominator, const Type& denominator)
+ {
+ m_numerator = nominator;
+ m_denominator = denominator;
+ initialize();
+ }
+
+ inline void initialize()
+ {
+ // Minimal normalization
+ // 1/-4 => -1/4, -1/-4 => 1/4
+ if (m_denominator < 0)
+ {
+ m_numerator = -m_numerator;
+ m_denominator = -m_denominator;
+ }
+
+ typedef typename promote_floating_point<Type>::type num_type;
+ static const num_type scale = 1000000.0;
+ m_approximation =
+ m_denominator == 0 ? 0
+ : boost::numeric_cast<double>
+ (
+ boost::numeric_cast<num_type>(m_numerator) * scale
+ / boost::numeric_cast<num_type>(m_denominator)
+ );
+ }
+
+ inline bool is_zero() const { return math::equals(m_numerator, 0); }
+ inline bool is_one() const { return math::equals(m_numerator, m_denominator); }
+ inline bool on_segment() const
+ {
+ // e.g. 0/4 or 4/4 or 2/4
+ return m_numerator >= 0 && m_numerator <= m_denominator;
+ }
+ inline bool in_segment() const
+ {
+ // e.g. 1/4
+ return m_numerator > 0 && m_numerator < m_denominator;
+ }
+ inline bool on_end() const
+ {
+ // e.g. 0/4 or 4/4
+ return is_zero() || is_one();
+ }
+ inline bool left() const
+ {
+ // e.g. -1/4
+ return m_numerator < 0;
+ }
+ inline bool right() const
+ {
+ // e.g. 5/4
+ return m_numerator > m_denominator;
+ }
+
+ inline bool close_to(thistype const& other) const
+ {
+ return geometry::math::abs(m_approximation - other.m_approximation) < 2;
+ }
+
+ inline bool operator< (thistype const& other) const
+ {
+ return close_to(other)
+ ? detail::segment_ratio::less<Type>::apply(*this, other)
+ : m_approximation < other.m_approximation;
+ }
+
+ inline bool operator== (thistype const& other) const
+ {
+ return close_to(other)
+ && detail::segment_ratio::equal<Type>::apply(*this, other);
+ }
+
+ static inline thistype zero()
+ {
+ static thistype result(0, 1);
+ return result;
+ }
+
+ static inline thistype one()
+ {
+ static thistype result(1, 1);
+ return result;
+ }
+
+#if defined(BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO)
+ friend std::ostream& operator<<(std::ostream &os, segment_ratio const& ratio)
+ {
+ os << ratio.m_numerator << "/" << ratio.m_denominator
+ << " (" << (static_cast<double>(ratio.m_numerator)
+ / static_cast<double>(ratio.m_denominator))
+ << ")";
+ return os;
+ }
+#endif
+
+
+
+private :
+ Type m_numerator;
+ Type m_denominator;
+
+ // Contains ratio on scale 0..1000000 (for 0..1)
+ // This is an approximation for fast and rough comparisons
+ // Boost.Rational is used if the approximations are close.
+ // Reason: performance, Boost.Rational does a GCD by default and also the
+ // comparisons contain while-loops.
+ double m_approximation;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
diff --git a/boost/geometry/policies/robustness/segment_ratio_type.hpp b/boost/geometry/policies/robustness/segment_ratio_type.hpp
new file mode 100644
index 0000000000..19e935bbb9
--- /dev/null
+++ b/boost/geometry/policies/robustness/segment_ratio_type.hpp
@@ -0,0 +1,28 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2013 Bruno Lalande, Paris, France.
+// Copyright (c) 2013 Mateusz Loskot, London, UK.
+// Copyright (c) 2013 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)
+
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+namespace boost { namespace geometry
+{
+
+// Meta-function to access segment-ratio for a policy
+template <typename Point, typename Policy>
+struct segment_ratio_type {}; // : not_implemented<> {};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP