Added boost header

This commit is contained in:
Christophe Riccio
2012-01-08 01:26:07 +00:00
parent 9c3faaca40
commit c7d752cdf8
8946 changed files with 1732316 additions and 0 deletions

View File

@@ -0,0 +1,242 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_COMPARE_HPP
#define BOOST_GEOMETRY_POLICIES_COMPARE_HPP
#include <cstddef>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace compare
{
template
<
int Direction,
typename Point,
typename Strategy,
std::size_t Dimension,
std::size_t DimensionCount
>
struct compare_loop
{
typedef typename strategy::compare::detail::select_strategy
<
Strategy, Direction, Point, Dimension
>::type compare_type;
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
static inline bool apply(Point const& left, Point const& right)
{
coordinate_type const& cleft = geometry::get<Dimension>(left);
coordinate_type const& cright = geometry::get<Dimension>(right);
if (geometry::math::equals(cleft, cright))
{
return compare_loop
<
Direction, Point, Strategy,
Dimension + 1, DimensionCount
>::apply(left, right);
}
else
{
compare_type compare;
return compare(cleft, cright);
}
}
};
template
<
int Direction,
typename Point,
typename Strategy,
std::size_t DimensionCount
>
struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
{
static inline bool apply(Point const&, Point const&)
{
// On coming here, points are equal. Return true if
// direction = 0 (equal), false if -1/1 (greater/less)
return Direction == 0;
}
};
template <int Direction, typename Point, typename Strategy>
struct compare_in_all_dimensions
{
inline bool operator()(Point const& left, Point const& right) const
{
return detail::compare::compare_loop
<
Direction, Point, Strategy,
0, geometry::dimension<Point>::type::value
>::apply(left, right);
}
};
template <typename Point, typename Strategy, std::size_t Dimension>
class compare_in_one_dimension
{
Strategy compare;
public :
inline bool operator()(Point const& left, Point const& right) const
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
coordinate_type const& cleft = get<Dimension>(left);
coordinate_type const& cright = get<Dimension>(right);
return compare(cleft, cright);
}
};
}} // namespace detail::compare
#endif
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
int Direction,
typename Point,
typename Strategy,
int Dimension
>
struct compare_geometries
: detail::compare::compare_in_one_dimension
<
Point,
typename strategy::compare::detail::select_strategy
<
Strategy, Direction, Point, Dimension
>::type,
Dimension
>
{};
// Specialization with -1: compare in all dimensions
template <int Direction, typename Point, typename Strategy>
struct compare_geometries<Direction, Point, Strategy, -1>
: detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
/*!
\brief Less functor, to sort points in ascending order.
\ingroup compare
\details This functor compares points and orders them on x,
then on y, then on z coordinate.
\tparam Geometry the geometry
\tparam Dimension the dimension to sort on, defaults to -1,
indicating ALL dimensions. That's to say, first on x,
on equal x-es then on y, etc.
If a dimension is specified, only that dimension is considered
\tparam Strategy underlying coordinate comparing functor,
defaults to the default comparison strategies
related to the point coordinate system. If specified, the specified
strategy is used. This can e.g. be std::less<double>.
*/
template
<
typename Point,
int Dimension = -1,
typename Strategy = strategy::compare::default_strategy
>
struct less
: dispatch::compare_geometries
<
1, // indicates ascending
Point,
Strategy,
Dimension
>
{
typedef Point first_argument_type;
typedef Point second_argument_type;
typedef bool result_type;
};
/*!
\brief Greater functor
\ingroup compare
\details Can be used to sort points in reverse order
\see Less functor
*/
template
<
typename Point,
int Dimension = -1,
typename Strategy = strategy::compare::default_strategy
>
struct greater
: dispatch::compare_geometries
<
-1, // indicates descending
Point,
Strategy,
Dimension
>
{};
/*!
\brief Equal To functor, to compare if points are equal
\ingroup compare
\tparam Geometry the geometry
\tparam Dimension the dimension to compare on, defaults to -1,
indicating ALL dimensions.
If a dimension is specified, only that dimension is considered
\tparam Strategy underlying coordinate comparing functor
*/
template
<
typename Point,
int Dimension = -1,
typename Strategy = strategy::compare::default_strategy
>
struct equal_to
: dispatch::compare_geometries
<
0,
Point,
Strategy,
Dimension
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_COMPARE_HPP

View File

@@ -0,0 +1,185 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_DE9IM_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
template <typename S1, typename S2>
struct segments_de9im
{
typedef de9im_segment return_type;
typedef S1 segment_type1;
typedef S2 segment_type2;
typedef typename select_coordinate_type<S1, S2>::type coordinate_type;
static inline return_type rays_intersect(bool on_segment,
double ra, double rb,
coordinate_type const& dx1, coordinate_type const& dy1,
coordinate_type const& dx2, coordinate_type const& dy2,
coordinate_type const& wx, coordinate_type const& wy,
S1 const& s1, S2 const& s2)
{
if(on_segment)
{
// 0 <= ra <= 1 and 0 <= rb <= 1
// Now check if one of them is 0 or 1, these are "touch" cases
bool a = math::equals(ra, 0.0) || math::equals(ra, 1.0);
bool b = math::equals(rb, 0.0) || math::equals(rb, 1.0);
if (a && b)
{
// Touch boundary/boundary: i-i == -1, i-b == -1, b-b == 0
// Opposite: if both are equal they touch in opposite direction
return de9im_segment(ra,rb,
-1, -1, 1,
-1, 0, 0,
1, 0, 2, false, math::equals(ra,rb));
}
else if (a || b)
{
// Touch boundary/interior: i-i == -1, i-b == -1 or 0, b-b == -1
int A = a ? 0 : -1;
int B = b ? 0 : -1;
return de9im_segment(ra,rb,
-1, B, 1,
A, -1, 0,
1, 0, 2);
}
// Intersects: i-i == 0, i-b == -1, i-e == 1
return de9im_segment(ra,rb,
0, -1, 1,
-1, -1, 0,
1, 0, 2);
}
// Not on segment, disjoint
return de9im_segment(ra,rb,
-1, -1, 1,
-1, -1, 0,
1, 0, 2);
}
static inline return_type collinear_touch(coordinate_type const& x,
coordinate_type const& y, bool opposite, char)
{
return de9im_segment(0,0,
-1, -1, 1,
-1, 0, 0,
1, 0, 2,
true, opposite);
}
template <typename S>
static inline return_type collinear_interior_boundary_intersect(S const& s,
bool a_within_b, bool opposite)
{
return a_within_b
? de9im_segment(0,0,
1, -1, -1,
0, 0, -1,
1, 0, 2,
true, opposite)
: de9im_segment(0,0,
1, 0, 1,
-1, 0, 0,
-1, -1, 2,
true, opposite);
}
static inline return_type collinear_a_in_b(S1 const& s, bool opposite)
{
return de9im_segment(0,0,
1, -1, -1,
0, -1, -1,
1, 0, 2,
true, opposite);
}
static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
{
return de9im_segment(0,0,
1, 0, 1,
-1, -1, 0,
-1, -1, 2,
true, opposite);
}
static inline return_type collinear_overlaps(
coordinate_type const& x1, coordinate_type const& y1,
coordinate_type const& x2, coordinate_type const& y2, bool opposite)
{
return de9im_segment(0,0,
1, 0, 1,
0, -1, 0,
1, 0, 2,
true, opposite);
}
static inline return_type segment_equal(S1 const& s, bool opposite)
{
return de9im_segment(0,0,
1, -1, -1,
-1, 0, -1,
-1, -1, 2,
true, opposite);
}
static inline return_type degenerate(S1 const& segment, bool a_degenerate)
{
return a_degenerate
? de9im_segment(0,0,
0, -1, -1,
-1, -1, -1,
1, 0, 2,
false, false, false, true)
: de9im_segment(0,0,
0, -1, 1,
-1, -1, 0,
-1, -1, 2,
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);
}
static inline return_type parallel()
{
return de9im_segment(0,0,
-1, -1, 1,
-1, -1, 0,
1, 0, 2, false, false, true);
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP

View File

@@ -0,0 +1,348 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_DIRECTION_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
#include <cstddef>
#include <string>
#include <boost/concept_check.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
struct direction_type
{
inline direction_type(side_info const& s, char h,
int ha, int hb,
int da = 0, int db = 0,
bool op = false)
: how(h)
, opposite(op)
, how_a(ha)
, how_b(hb)
, dir_a(da)
, dir_b(db)
, sides(s)
{
arrival[0] = ha;
arrival[1] = hb;
}
inline direction_type(char h, bool op, int ha = 0, int hb = 0)
: how(h)
, opposite(op)
, how_a(ha)
, how_b(hb)
, dir_a(0)
, dir_b(0)
{
arrival[0] = ha;
arrival[1] = hb;
}
// "How" is the intersection formed?
char how;
// Is it opposite (for collinear/equal cases)
bool opposite;
// Information on how A arrives at intersection, how B arrives at intersection
// 1: arrives at intersection
// -1: starts from intersection
int how_a;
int how_b;
// Direction: how is A positioned from B
// 1: points left, seen from IP
// -1: points right, seen from IP
// In case of intersection: B's TO direction
// In case that B's TO direction is at A: B's from direction
// In collinear cases: it is 0
int dir_a; // Direction of A-s TO from IP
int dir_b; // Direction of B-s TO from IP
// New information
side_info sides;
int arrival[2]; // 1=arrival, -1departure, 0=neutral; == how_a//how_b
// About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
// Arrival 1: a1--------->a2 (a arrives within b)
// b1----->b2
// Arrival 1: (a in b)
//
// Arrival -1: a1--------->a2 (a does not arrive within b)
// b1----->b2
// Arrival -1: (b in a) a_1-------------a_2
// b_1---b_2
// Arrival 0: a1------->a2 (a arrives at TO-border of b)
// b1--->b2
};
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;
static inline return_type segments_intersect(side_info const& sides,
coordinate_type const& dx1, coordinate_type const& dy1,
coordinate_type const& dx2, coordinate_type const& dy2,
S1 const& s1, S2 const& s2)
{
bool const ra0 = sides.get<0,0>() == 0;
bool const ra1 = sides.get<0,1>() == 0;
bool const rb0 = sides.get<1,0>() == 0;
bool const rb1 = sides.get<1,1>() == 0;
return
// opposite and same starting point (FROM)
ra0 && rb0 ? calculate_side<1>(sides, dx1, dy1, s1, s2, 'f', -1, -1)
// opposite and point to each other (TO)
: ra1 && rb1 ? calculate_side<0>(sides, dx1, dy1, s1, s2, '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)
// 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)
// b starts from interior of a
: rb0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'B', 0, -1)
// a starts from interior of b (#39)
: ra0 ? starts_from_middle(sides, dx1, dy1, s1, s2, '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)
// a ends at interior of b
: ra1 ? a_ends_at_middle(sides, dx1, dy1, s1, s2)
// normal intersection
: calculate_side<1>(sides, dx1, dy1, s1, s2, 'i', -1, -1)
;
}
static inline return_type collinear_touch(
coordinate_type const& ,
coordinate_type const& , int arrival_a, int arrival_b)
{
// 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);
}
template <typename S>
static inline return_type collinear_interior_boundary_intersect(S const& , bool,
int arrival_a, int arrival_b, bool opposite)
{
return_type r('c', opposite);
r.arrival[0] = arrival_a;
r.arrival[1] = arrival_b;
return r;
}
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)
{
return_type r('c', opposite);
r.arrival[0] = -1;
r.arrival[1] = 1;
return r;
}
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;
return r;
}
static inline return_type segment_equal(S1 const& , bool opposite)
{
return return_type('e', opposite);
}
static inline return_type degenerate(S1 const& , bool)
{
return return_type('0', false);
}
static inline return_type disjoint()
{
return return_type('d', false);
}
static inline return_type collinear_disjoint()
{
return return_type('d', false);
}
static inline return_type parallel()
{
return return_type('p', false);
}
static inline return_type error(std::string const& msg)
{
// msg
return return_type('d', false);
}
private :
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);
// This is a "side calculation" as in the strategies, but here two terms are precalculated
// We might merge this with side, offering a pre-calculated term
// Waiting for implementing spherical...
return dx1 * dpy - dy1 * dpx > 0
? return_type(sides, how, how_a, how_b, -1, 1)
: return_type(sides, how, how_a, how_b, 1, -1);
}
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 dx1 * dpy - dy1 * dpx > 0
? return_type(sides, how, how_a, how_b, 1, 1)
: return_type(sides, how, how_a, how_b, -1, -1);
}
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 = dx1 * dpy - dy1 * dpx > 0 ? 1 : -1;
// From other perspective, then reverse
bool const is_a = which == 'A';
if (is_a)
{
dir = -dir;
}
return return_type(sides, 's',
how_a,
how_b,
is_a ? dir : -dir,
! is_a ? dir : -dir);
}
// 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)
{
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 dx * dpy - dy * dpx > 0
? return_type(sides, 'm', 1, 0, 1, 1)
: return_type(sides, 'm', 1, 0, -1, -1);
}
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)
{
coordinate_type dpx = get<1, 0>(s1) - get<0, 0>(s2);
coordinate_type dpy = get<1, 1>(s1) - get<0, 1>(s2);
return dx * dpy - dy * dpx > 0
? return_type(sides, 'm', 0, 1, 1, 1)
: return_type(sides, 'm', 0, 1, -1, -1);
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP

View File

@@ -0,0 +1,191 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_POINTS_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
#include <algorithm>
#include <string>
#include <boost/concept_check.hpp>
#include <boost/numeric/conversion/cast.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>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
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;
// Get the same type, but at least a double
typedef typename select_most_precise<coordinate_type, double>::type rtype;
static inline return_type segments_intersect(side_info const&,
coordinate_type const& dx1, coordinate_type const& dy1,
coordinate_type const& dx2, coordinate_type const& dy2,
S1 const& s1, S2 const& s2)
{
return_type result;
typedef typename geometry::coordinate_type
<
typename return_type::point_type
>::type coordinate_type;
// Get the same type, but at least a double (also used for divisions
typedef typename select_most_precise
<
coordinate_type, double
>::type promoted_type;
promoted_type const s1x = get<0, 0>(s1);
promoted_type const s1y = get<0, 1>(s1);
// Calculate other determinants - Cramers rule
promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2);
promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2);
promoted_type const d = (dy2 * dx1) - (dx2 * dy1);
promoted_type const da = (promoted_type(dx2) * wy) - (promoted_type(dy2) * wx);
// r: ratio 0-1 where intersection divides A/B
promoted_type r = da / d;
// Handle robustness issues
if (r < 0)
{
r = 0;
}
else if (r > 1)
{
r = 1;
}
result.count = 1;
set<0>(result.intersections[0],
boost::numeric_cast<coordinate_type>(s1x + r * promoted_type(dx1)));
set<1>(result.intersections[0],
boost::numeric_cast<coordinate_type>(s1y + r * promoted_type(dy1)));
return result;
}
static inline return_type collinear_touch(coordinate_type const& x,
coordinate_type const& y, int, int)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], x);
set<1>(result.intersections[0], y);
return result;
}
template <typename S>
static inline return_type collinear_inside(S const& s, int index1 = 0, int index2 = 1)
{
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;
}
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);
}
static inline return_type collinear_a_in_b(S1 const& s, bool opposite)
{
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);
}
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 opposite)
{
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));
return result;
}
static inline return_type disjoint()
{
return return_type();
}
static inline return_type error(std::string const& msg)
{
return return_type();
}
static inline return_type collinear_disjoint()
{
return return_type();
}
static inline return_type parallel()
{
return return_type();
}
static inline return_type degenerate(S1 const& s, bool)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], get<0, 0>(s));
set<1>(result.intersections[0], get<0, 1>(s));
return result;
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP

View File

@@ -0,0 +1,176 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_POINTS_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
#include <string>
#include <boost/concept_check.hpp>
#include <boost/numeric/conversion/cast.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>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
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;
// Get the same type, but at least a double
typedef typename select_most_precise<coordinate_type, double>::type rtype;
static inline return_type segments_intersect(side_info const&,
coordinate_type const& dx1, coordinate_type const& dy1,
coordinate_type const& dx2, coordinate_type const& dy2,
S1 const& s1, S2 const& s2)
{
return_type result;
typedef typename geometry::coordinate_type
<
typename return_type::point_type
>::type coordinate_type;
// Get the same type, but at least a double (also used for divisions
typedef typename select_most_precise
<
coordinate_type, double
>::type promoted_type;
coordinate_type const s1x = get<0, 0>(s1);
coordinate_type const s1y = get<0, 1>(s1);
// Calculate other determinants - Cramers rule
promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2);
promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2);
promoted_type const d = (dy2 * dx1) - (dx2 * dy1);
promoted_type const da = (dx2 * wy) - (dy2 * wx);
// r: ratio 0-1 where intersection divides A/B
promoted_type const r = da / d;
result.count = 1;
set<0>(result.intersections[0],
boost::numeric_cast<coordinate_type>(s1x + r * dx1));
set<1>(result.intersections[0],
boost::numeric_cast<coordinate_type>(s1y + r * dy1));
return result;
}
static inline return_type collinear_touch(coordinate_type const& x,
coordinate_type const& y, bool, char)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], x);
set<1>(result.intersections[0], y);
return result;
}
template <typename S>
static inline return_type collinear_inside(S const& s)
{
return_type result;
result.count = 2;
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));
return result;
}
template <typename S>
static inline return_type collinear_interior_boundary_intersect(S const& s, bool, bool)
{
return collinear_inside(s);
}
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)
{
return collinear_inside(s);
}
static inline return_type collinear_overlaps(
coordinate_type const& x1, coordinate_type const& y1,
coordinate_type const& x2, coordinate_type const& y2, 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)
{
return_type result;
result.count = 2;
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));
return result;
}
static inline return_type disjoint()
{
return return_type();
}
static inline return_type error(std::string const& msg)
{
return return_type();
}
static inline return_type collinear_disjoint()
{
return return_type();
}
static inline return_type parallel()
{
return return_type();
}
static inline return_type degenerate(S1 const& s, bool)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], get<0, 0>(s));
set<1>(result.intersections[0], get<0, 1>(s));
return result;
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP

View File

@@ -0,0 +1,213 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_POINTS_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
#include <string>
#include <boost/concept_check.hpp>
#include <boost/numeric/conversion/cast.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>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
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;
// Get the same type, but at least a double (also used for divisions
typedef typename select_most_precise
<
coordinate_type, double
>::type promoted_type;
template <int Dimension>
static inline return_type rico(
coordinate_type const& dm1, coordinate_type const& dn1,
coordinate_type const& dm2, coordinate_type const& dn2,
S1 const& s1, S2 const& s2)
{
promoted_type const a1 = dn1 / dm1;
promoted_type const a2 = dn2 / dm2;
promoted_type const da = a1 - a2;
if (math::equals(da, 0))
{
return rico<1 - Dimension>(dn1, dm1, dn2, dm2, s1, s2);
}
promoted_type const b1 = get<0, Dimension>(s1) - a1 * get<0, 1 - Dimension>(s1);
promoted_type const b2 = get<0, Dimension>(s2) - a2 * get<0, 1 - Dimension>(s2);
promoted_type const v = (b2 - b1) / da;
return_type result;
result.count = 1;
set<1 - Dimension>(result.intersections[0],
boost::numeric_cast<coordinate_type>(v));
set<Dimension>(result.intersections[0],
boost::numeric_cast<coordinate_type>(a1 * v + b1));
return result;
}
static inline return_type cross(S1 const& s1, S2 const& s2)
{
// Take one of first segment, and one of second segment
return_type result;
result.count = 1;
set<0>(result.intersections[0], get<0, 0>(s1));
set<1>(result.intersections[0], get<0, 1>(s2));
return result;
}
static inline return_type segments_intersect(side_info const& sides,
coordinate_type const& dx1, coordinate_type const& dy1,
coordinate_type const& dx2, coordinate_type const& dy2,
S1 const& s1, S2 const& s2)
{
bool vertical1 = math::equals(dx1, 0);
bool horizontal2 = math::equals(dy2, 0);
if (vertical1 && horizontal2)
{
return cross(s1, s2);
}
bool vertical2 = math::equals(dx2, 0);
bool horizontal1 = math::equals(dy1, 0);
if (horizontal1 && vertical2)
{
return cross(s2, s1);
}
if (vertical1 || vertical2)
{
return rico<0>(dy1, dx1, dy2, dx2, s1, s2);
}
else
{
// Not crossing, take the most reasonable choice.
// We want to divide by the largest one.
//if (
return rico<1>(dx1, dy1, dx2, dy2, s1, s2);
}
}
static inline return_type collinear_touch(coordinate_type const& x,
coordinate_type const& y, bool, char)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], x);
set<1>(result.intersections[0], y);
return result;
}
template <typename S>
static inline return_type collinear_inside(S const& s)
{
return_type result;
result.count = 2;
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));
return result;
}
template <typename S>
static inline return_type collinear_interior_boundary_intersect(S const& s, bool, bool)
{
return collinear_inside(s);
}
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)
{
return collinear_inside(s);
}
static inline return_type collinear_overlaps(
coordinate_type const& x1, coordinate_type const& y1,
coordinate_type const& x2, coordinate_type const& y2, 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)
{
return_type result;
result.count = 2;
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));
return result;
}
static inline return_type disjoint()
{
return return_type();
}
static inline return_type error(std::string const& msg)
{
return return_type();
}
static inline return_type collinear_disjoint()
{
return return_type();
}
static inline return_type parallel()
{
return return_type();
}
static inline return_type degenerate(S1 const& s, bool)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], get<0, 0>(s));
set<1>(result.intersections[0], get<0, 1>(s));
return result;
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP

View File

@@ -0,0 +1,182 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 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_TUPLED_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
#include <string>
#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
{
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>
struct segments_tupled
{
typedef boost::tuple
<
typename Policy1::return_type,
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;
static inline return_type segments_intersect(side_info const& sides,
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,
dx1, dy1, dx2, dy2, s1, s2),
Policy2::segments_intersect(sides,
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)
{
return boost::make_tuple
(
Policy1::collinear_b_in_a(segment, opposite),
Policy2::collinear_b_in_a(segment, opposite)
);
}
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)
{
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)
);
}
static inline return_type segment_equal(segment_type1 const& s,
bool opposite)
{
return boost::make_tuple
(
Policy1::segment_equal(s, opposite),
Policy2::segment_equal(s, opposite)
);
}
static inline return_type degenerate(segment_type1 const& segment,
bool a_degenerate)
{
return boost::make_tuple
(
Policy1::degenerate(segment, a_degenerate),
Policy2::degenerate(segment, a_degenerate)
);
}
static inline return_type disjoint()
{
return boost::make_tuple
(
Policy1::disjoint(),
Policy2::disjoint()
);
}
static inline return_type error(std::string const& msg)
{
return boost::make_tuple
(
Policy1::error(msg),
Policy2::error(msg)
);
}
static inline return_type collinear_disjoint()
{
return boost::make_tuple
(
Policy1::collinear_disjoint(),
Policy2::collinear_disjoint()
);
}
static inline return_type parallel()
{
return boost::make_tuple
(
Policy1::parallel(),
Policy2::parallel()
);
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP