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,131 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Area calculation for cartesian points
\ingroup strategies
\details Calculates area using the Surveyor's formula, a well-known
triangulation algorithm
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
}
*/
template
<
typename PointOfSegment,
typename CalculationType = void
>
class surveyor
{
public :
// If user specified a calculation type, use that type,
// whatever it is and whatever the point-type is.
// Else, use the pointtype, but at least double
typedef typename
boost::mpl::if_c
<
boost::is_void<CalculationType>::type::value,
typename select_most_precise
<
typename coordinate_type<PointOfSegment>::type,
double
>::type,
CalculationType
>::type return_type;
private :
class summation
{
friend class surveyor;
return_type sum;
public :
inline summation() : sum(return_type())
{
// Strategy supports only 2D areas
assert_dimension<PointOfSegment, 2>();
}
inline return_type area() const
{
return_type result = sum;
result /= 2;
return result;
}
};
public :
typedef summation state_type;
typedef PointOfSegment segment_point_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
summation& state)
{
// SUM += x2 * y1 - x1 * y2;
state.sum += get<0>(p2) * get<1>(p1) - get<0>(p1) * get<1>(p2);
}
static inline return_type result(summation const& state)
{
return state.area();
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point>
struct default_strategy<cartesian_tag, Point>
{
typedef strategy::area::surveyor<Point> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP

View File

@@ -0,0 +1,176 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
struct box_within_range
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min
, BoxContainedValue const& bed_max
, BoxContainingValue const& bing_min
, BoxContainingValue const& bing_max)
{
return bed_min > bing_min && bed_max < bing_max;
}
};
struct box_covered_by_range
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min
, BoxContainedValue const& bed_max
, BoxContainingValue const& bing_min
, BoxContainingValue const& bing_max)
{
return bed_min >= bing_min && bed_max <= bing_max;
}
};
template
<
typename SubStrategy,
typename Box1,
typename Box2,
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_box_box_loop
{
static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
{
assert_dimension_equal<Box1, Box2>();
if (! SubStrategy::apply(
get<min_corner, Dimension>(b_contained),
get<max_corner, Dimension>(b_contained),
get<min_corner, Dimension>(b_containing),
get<max_corner, Dimension>(b_containing)
)
)
{
return false;
}
return relate_box_box_loop
<
SubStrategy,
Box1, Box2,
Dimension + 1, DimensionCount
>::apply(b_contained, b_containing);
}
};
template
<
typename SubStrategy,
typename Box1,
typename Box2,
std::size_t DimensionCount
>
struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
{
static inline bool apply(Box1 const& , Box2 const& )
{
return true;
}
};
template
<
typename Box1,
typename Box2,
typename SubStrategy = box_within_range
>
struct box_in_box
{
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return relate_box_box_loop
<
SubStrategy,
Box1, Box2, 0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
} // namespace within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace within { namespace services
{
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
box_tag, box_tag,
box_tag, areal_tag,
cartesian_tag, cartesian_tag,
BoxContained, BoxContaining
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
};
}} // namespace within::services
namespace covered_by { namespace services
{
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
box_tag, box_tag,
box_tag, areal_tag,
cartesian_tag, cartesian_tag,
BoxContained, BoxContaining
>
{
typedef within::box_in_box
<
BoxContained, BoxContaining,
within::box_covered_by_range
> type;
};
}} // namespace covered_by::services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP

View File

@@ -0,0 +1,495 @@
// 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_STRATEGIES_CARTESIAN_INTERSECTION_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
#include <algorithm>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/concepts/segment_concept.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
// Temporary / will be Strategy as template parameter
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/side_info.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace intersection
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Segment, size_t Dimension>
struct segment_arrange
{
template <typename T>
static inline void apply(Segment const& s, T& s_1, T& s_2, bool& swapped)
{
s_1 = get<0, Dimension>(s);
s_2 = get<1, Dimension>(s);
if (s_1 > s_2)
{
std::swap(s_1, s_2);
swapped = true;
}
}
};
template <std::size_t Index, typename Segment>
inline typename geometry::point_type<Segment>::type get_from_index(
Segment const& segment)
{
typedef typename geometry::point_type<Segment>::type point_type;
point_type point;
geometry::detail::assign::assign_point_from_index
<
Segment, point_type, Index, 0, dimension<Segment>::type::value
>::apply(segment, point);
return point;
}
}
#endif
/***
template <typename T>
inline std::string rdebug(T const& value)
{
if (math::equals(value, 0)) return "'0'";
if (math::equals(value, 1)) return "'1'";
if (value < 0) return "<0";
if (value > 1) return ">1";
return "<0..1>";
}
***/
/*!
\see http://mathworld.wolfram.com/Line-LineIntersection.html
*/
template <typename Policy, typename CalculationType = void>
struct relate_cartesian_segments
{
typedef typename Policy::return_type return_type;
typedef typename Policy::segment_type1 segment_type1;
typedef typename Policy::segment_type2 segment_type2;
//typedef typename point_type<segment_type1>::type point_type;
//BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
BOOST_CONCEPT_ASSERT( (concept::ConstSegment<segment_type1>) );
BOOST_CONCEPT_ASSERT( (concept::ConstSegment<segment_type2>) );
typedef typename select_calculation_type
<segment_type1, segment_type2, CalculationType>::type coordinate_type;
/// Relate segments a and b
static inline return_type apply(segment_type1 const& a, segment_type2 const& b)
{
coordinate_type const dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
coordinate_type const dx_b = get<1, 0>(b) - get<0, 0>(b);
coordinate_type const dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir
coordinate_type const dy_b = get<1, 1>(b) - get<0, 1>(b);
return apply(a, b, dx_a, dy_a, dx_b, dy_b);
}
// Relate segments a and b using precalculated differences.
// This can save two or four subtractions in many cases
static inline return_type apply(segment_type1 const& a, segment_type2 const& b,
coordinate_type const& dx_a, coordinate_type const& dy_a,
coordinate_type const& dx_b, coordinate_type const& dy_b)
{
// 1) Handle "disjoint", probably common case.
// per dimension, 2 cases: a_1----------a_2 b_1-------b_2 or B left of A
coordinate_type ax_1, ax_2, bx_1, bx_2;
bool ax_swapped = false, bx_swapped = false;
detail::segment_arrange<segment_type1, 0>::apply(a, ax_1, ax_2, ax_swapped);
detail::segment_arrange<segment_type2, 0>::apply(b, bx_1, bx_2, bx_swapped);
if (ax_2 < bx_1 || ax_1 > bx_2)
{
return Policy::disjoint();
}
// 1b) In Y-dimension
coordinate_type ay_1, ay_2, by_1, by_2;
bool ay_swapped = false, by_swapped = false;
detail::segment_arrange<segment_type1, 1>::apply(a, ay_1, ay_2, ay_swapped);
detail::segment_arrange<segment_type2, 1>::apply(b, by_1, by_2, by_swapped);
if (ay_2 < ay_1 || ay_1 > by_2)
{
return Policy::disjoint();
}
typedef side::side_by_triangle<coordinate_type> side;
side_info sides;
// 2) Calculate sides
// Note: Do NOT yet calculate the determinant here, but use the SIDE strategy.
// Determinant calculation is not robust; side (orient) can be made robust
// (and is much robuster even without measures)
sides.set<1>
(
side::apply(detail::get_from_index<0>(a)
, detail::get_from_index<1>(a)
, detail::get_from_index<0>(b)),
side::apply(detail::get_from_index<0>(a)
, detail::get_from_index<1>(a)
, detail::get_from_index<1>(b))
);
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
// 2b) For other segment
sides.set<0>
(
side::apply(detail::get_from_index<0>(b)
, detail::get_from_index<1>(b)
, detail::get_from_index<0>(a)),
side::apply(detail::get_from_index<0>(b)
, detail::get_from_index<1>(b)
, detail::get_from_index<1>(a))
);
if (sides.same<0>())
{
return Policy::disjoint();
}
// Degenerate cases: segments of single point, lying on other segment, non disjoint
coordinate_type const zero = 0;
if (math::equals(dx_a, zero) && math::equals(dy_a, zero))
{
return Policy::degenerate(a, true);
}
if (math::equals(dx_b, zero) && math::equals(dy_b, zero))
{
return Policy::degenerate(b, false);
}
bool collinear = sides.collinear();
// 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 d = (dy_b * dx_a) - (dx_b * dy_a);
// Determinant d should be nonzero.
// If it is zero, we have an robustness issue here,
// (and besides that we cannot divide by it)
if(math::equals(d, zero) && ! collinear)
//if(! collinear && sides.as_collinear())
{
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
std::cout << "Determinant zero? Type : "
<< typeid(coordinate_type).name()
<< std::endl;
std::cout << " dx_a : " << dx_a << std::endl;
std::cout << " dy_a : " << dy_a << std::endl;
std::cout << " dx_b : " << dx_b << std::endl;
std::cout << " dy_b : " << dy_b << std::endl;
std::cout << " side a <-> b.first : " << sides.get<0,0>() << std::endl;
std::cout << " side a <-> b.second: " << sides.get<0,1>() << std::endl;
std::cout << " side b <-> a.first : " << sides.get<1,0>() << std::endl;
std::cout << " side b <-> a.second: " << sides.get<1,1>() << std::endl;
#endif
if (sides.as_collinear())
{
sides.set<0>(0,0);
sides.set<1>(0,0);
collinear = true;
}
else
{
return Policy::error("Determinant zero!");
}
}
if(collinear)
{
// Segments are collinear. We'll find out how.
if (math::equals(dx_b, zero))
{
// Vertical -> Check y-direction
return relate_collinear(a, b,
ay_1, ay_2, by_1, by_2,
ay_swapped, by_swapped);
}
else
{
// Check x-direction
return relate_collinear(a, b,
ax_1, ax_2, bx_1, bx_2,
ax_swapped, bx_swapped);
}
}
return Policy::segments_intersect(sides,
dx_a, dy_a, dx_b, dy_b,
a, b);
}
private :
/// Relate segments known collinear
static inline return_type relate_collinear(segment_type1 const& a
, segment_type2 const& b
, coordinate_type a_1, coordinate_type a_2
, coordinate_type b_1, coordinate_type b_2
, bool a_swapped, bool b_swapped)
{
// All ca. 150 lines are about collinear rays
// The intersections, if any, are always boundary points of the segments. No need to calculate anything.
// However we want to find out HOW they intersect, there are many cases.
// Most sources only provide the intersection (above) or that there is a collinearity (but not the points)
// or some spare sources give the intersection points (calculated) but not how they align.
// This source tries to give everything and still be efficient.
// It is therefore (and because of the extensive clarification comments) rather long...
// \see http://mpa.itc.it/radim/g50history/CMP/4.2.1-CERL-beta-libes/file475.txt
// \see http://docs.codehaus.org/display/GEOTDOC/Point+Set+Theory+and+the+DE-9IM+Matrix
// \see http://mathworld.wolfram.com/Line-LineIntersection.html
// Because of collinearity the case is now one-dimensional and can be checked using intervals
// This function is called either horizontally or vertically
// We get then two intervals:
// a_1-------------a_2 where a_1 < a_2
// b_1-------------b_2 where b_1 < b_2
// In all figures below a_1/a_2 denotes arranged intervals, a1-a2 or a2-a1 are still unarranged
// Handle "equal", in polygon neighbourhood comparisons a common case
// Check if segments are equal...
bool const a1_eq_b1 = math::equals(get<0, 0>(a), get<0, 0>(b))
&& math::equals(get<0, 1>(a), get<0, 1>(b));
bool const a2_eq_b2 = math::equals(get<1, 0>(a), get<1, 0>(b))
&& math::equals(get<1, 1>(a), get<1, 1>(b));
if (a1_eq_b1 && a2_eq_b2)
{
return Policy::segment_equal(a, false);
}
// ... or opposite equal
bool const a1_eq_b2 = math::equals(get<0, 0>(a), get<1, 0>(b))
&& math::equals(get<0, 1>(a), get<1, 1>(b));
bool const a2_eq_b1 = math::equals(get<1, 0>(a), get<0, 0>(b))
&& math::equals(get<1, 1>(a), get<0, 1>(b));
if (a1_eq_b2 && a2_eq_b1)
{
return Policy::segment_equal(a, true);
}
// The rest below will return one or two intersections.
// The delegated class can decide which is the intersection point, or two, build the Intersection Matrix (IM)
// For IM it is important to know which relates to which. So this information is given,
// without performance penalties to intersection calculation
bool const has_common_points = a1_eq_b1 || a1_eq_b2 || a2_eq_b1 || a2_eq_b2;
// "Touch" -> one intersection point -> one but not two common points
// --------> A (or B)
// <---------- B (or A)
// a_2==b_1 (b_2==a_1 or a_2==b1)
// The check a_2/b_1 is necessary because it excludes cases like
// ------->
// --->
// ... which are handled lateron
// Corresponds to 4 cases, of which the equal points are determined above
// #1: a1---->a2 b1--->b2 (a arrives at b's border)
// #2: a2<----a1 b2<---b1 (b arrives at a's border)
// #3: a1---->a2 b2<---b1 (both arrive at each others border)
// #4: a2<----a1 b1--->b2 (no arrival at all)
// Where the arranged forms have two forms:
// a_1-----a_2/b_1-------b_2 or reverse (B left of A)
if (has_common_points && (math::equals(a_2, b_1) || math::equals(b_2, a_1)))
{
if (a2_eq_b1) return Policy::collinear_touch(get<1, 0>(a), get<1, 1>(a), 0, -1);
if (a1_eq_b2) return Policy::collinear_touch(get<0, 0>(a), get<0, 1>(a), -1, 0);
if (a2_eq_b2) return Policy::collinear_touch(get<1, 0>(a), get<1, 1>(a), 0, 0);
if (a1_eq_b1) return Policy::collinear_touch(get<0, 0>(a), get<0, 1>(a), -1, -1);
}
// "Touch/within" -> there are common points and also an intersection of interiors:
// Corresponds to many cases:
// #1a: a1------->a2 #1b: a1-->a2
// b1--->b2 b1------->b2
// #2a: a2<-------a1 #2b: a2<--a1
// b1--->b2 b1------->b2
// #3a: a1------->a2 #3b: a1-->a2
// b2<---b1 b2<-------b1
// #4a: a2<-------a1 #4b: a2<--a1
// b2<---b1 b2<-------b1
// Note: next cases are similar and handled by the code
// #4c: a1--->a2
// b1-------->b2
// #4d: a1-------->a2
// b1-->b2
// For case 1-4: a_1 < (b_1 or b_2) < a_2, two intersections are equal to segment B
// For case 5-8: b_1 < (a_1 or a_2) < b_2, two intersections are equal to segment A
if (has_common_points)
{
// Either A is in B, or B is in A, or (in case of robustness/equals)
// both are true, see below
bool a_in_b = (b_1 < a_1 && a_1 < b_2) || (b_1 < a_2 && a_2 < b_2);
bool b_in_a = (a_1 < b_1 && b_1 < a_2) || (a_1 < b_2 && b_2 < a_2);
if (a_in_b && b_in_a)
{
// testcase "ggl_list_20110306_javier"
// In robustness it can occur that a point of A is inside B AND a point of B is inside A,
// still while has_common_points is true (so one point equals the other).
// If that is the case we select on length.
coordinate_type const length_a = geometry::math::abs(a_1 - a_2);
coordinate_type const length_b = geometry::math::abs(b_1 - b_2);
if (length_a > length_b)
{
a_in_b = false;
}
else
{
b_in_a = false;
}
}
int const arrival_a = a_in_b ? 1 : -1;
if (a2_eq_b2) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, 0, 0, false);
if (a1_eq_b2) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, arrival_a, 0, true);
if (a2_eq_b1) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, 0, -arrival_a, true);
if (a1_eq_b1) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, arrival_a, -arrival_a, false);
}
bool const opposite = a_swapped ^ b_swapped;
// "Inside", a completely within b or b completely within a
// 2 cases:
// case 1:
// a_1---a_2 -> take A's points as intersection points
// b_1------------b_2
// case 2:
// a_1------------a_2
// b_1---b_2 -> take B's points
if (a_1 > b_1 && a_2 < b_2)
{
// A within B
return Policy::collinear_a_in_b(a, opposite);
}
if (b_1 > a_1 && b_2 < a_2)
{
// B within A
return Policy::collinear_b_in_a(b, opposite);
}
/*
Now that all cases with equal,touch,inside,disjoint,
degenerate are handled the only thing left is an overlap
Either a1 is between b1,b2
or a2 is between b1,b2 (a2 arrives)
Next table gives an overview.
The IP's are ordered following the line A1->A2
| |
| a_2 in between | a_1 in between
| |
-----+---------------------------------+--------------------------
| a1--------->a2 | a1--------->a2
| b1----->b2 | b1----->b2
| (b1,a2), a arrives | (a1,b2), b arrives
| |
-----+---------------------------------+--------------------------
a sw.| a2<---------a1* | a2<---------a1*
| b1----->b2 | b1----->b2
| (a1,b1), no arrival | (b2,a2), a and b arrive
| |
-----+---------------------------------+--------------------------
| a1--------->a2 | a1--------->a2
b sw.| b2<-----b1 | b2<-----b1
| (b2,a2), a and b arrive | (a1,b1), no arrival
| |
-----+---------------------------------+--------------------------
a sw.| a2<---------a1* | a2<---------a1*
b sw.| b2<-----b1 | b2<-----b1
| (a1,b2), b arrives | (b1,a2), a arrives
| |
-----+---------------------------------+--------------------------
* Note that a_1 < a_2, and a1 <> a_1; if a is swapped,
the picture might seem wrong but it (supposed to be) is right.
*/
bool const both_swapped = a_swapped && b_swapped;
if (b_1 < a_2 && a_2 < b_2)
{
// Left column, from bottom to top
return
both_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), -1, 1, opposite)
: b_swapped ? Policy::collinear_overlaps(get<1, 0>(b), get<1, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, 1, opposite)
: a_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), -1, -1, opposite)
: Policy::collinear_overlaps(get<0, 0>(b), get<0, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, -1, opposite)
;
}
if (b_1 < a_1 && a_1 < b_2)
{
// Right column, from bottom to top
return
both_swapped ? Policy::collinear_overlaps(get<0, 0>(b), get<0, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, -1, opposite)
: b_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), -1, -1, opposite)
: a_swapped ? Policy::collinear_overlaps(get<1, 0>(b), get<1, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, 1, opposite)
: Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), -1, 1, opposite)
;
}
// Nothing should goes through. If any we have made an error
// Robustness: it can occur here...
return Policy::error("Robustness issue, non-logical behaviour");
}
};
}} // namespace strategy::intersection
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP

View File

@@ -0,0 +1,241 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
{
// Note: when calling the namespace "centroid", it sometimes,
// somehow, in gcc, gives compilation problems (confusion with function centroid).
namespace strategy { namespace centroid
{
/*!
\brief Centroid calculation using algorith Bashein / Detmer
\ingroup strategies
\details Calculates centroid using triangulation method published by
Bashein / Detmer
\tparam Point point type of centroid to calculate
\tparam PointOfSegment point type of segments, defaults to Point
\par Concepts for Point and PointOfSegment:
- specialized point_traits class
\author Adapted from "Centroid of a Polygon" by
Gerard Bashein and Paul R. Detmer<em>,
in "Graphics Gems IV", Academic Press, 1994</em>
\par Research notes
The algorithm gives the same results as Oracle and PostGIS but
differs from MySQL
(tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).
Without holes:
- this: POINT(4.06923363095238 1.65055803571429)
- geolib: POINT(4.07254 1.66819)
- MySQL: POINT(3.6636363636364 1.6272727272727)'
- PostGIS: POINT(4.06923363095238 1.65055803571429)
- Oracle: 4.06923363095238 1.65055803571429
- SQL Server: POINT(4.06923362245959 1.65055804168294)
Statements:
- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))')))
- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null,
sdo_elem_info_array(1, 1003, 1), sdo_ordinate_array(
2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3,2.6
,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3))
, mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
,mdsys.sdo_dim_element('y',0,10,.00000005)))
from dual
- \b SQL Server 2008: select geometry::STGeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))',0)
.STCentroid()
.STAsText()
With holes:
- this: POINT(4.04663 1.6349)
- geolib: POINT(4.04675 1.65735)
- MySQL: POINT(3.6090580503834 1.607573932092)
- PostGIS: POINT(4.0466265060241 1.63489959839357)
- Oracle: 4.0466265060241 1.63489959839357
- SQL Server: POINT(4.0466264962959677 1.6348996057331333)
Statements:
- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2
,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)
,(4 2,4.2 1.4,4.8 1.9,4.4 2.2,4 2))')));
- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null
, sdo_elem_info_array(1, 1003, 1, 25, 2003, 1)
, sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,
2,4.1,3,5.3,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3,4,2, 4.2,1.4,
4.8,1.9, 4.4,2.2, 4,2))
, mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
,mdsys.sdo_dim_element('y',0,10,.00000005)))
from dual
\qbk{
[heading See also]
[link geometry.reference.algorithms.centroid.centroid_3_with_strategy centroid (with strategy)]
}
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class bashein_detmer
{
private :
// If user specified a calculation type, use that type,
// whatever it is and whatever the point-type(s) are.
// Else, use the most appropriate coordinate type
// of the two points, but at least double
typedef typename
boost::mpl::if_c
<
boost::is_void<CalculationType>::type::value,
typename select_most_precise
<
typename select_coordinate_type
<
Point,
PointOfSegment
>::type,
double
>::type,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class sums
{
friend class bashein_detmer;
int count;
calculation_type sum_a2;
calculation_type sum_x;
calculation_type sum_y;
public :
inline sums()
: count(0)
, sum_a2(calculation_type())
, sum_x(calculation_type())
, sum_y(calculation_type())
{
typedef calculation_type ct;
}
};
public :
typedef sums state_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2, sums& state)
{
/* Algorithm:
For each segment:
begin
ai = x1 * y2 - x2 * y1;
sum_a2 += ai;
sum_x += ai * (x1 + x2);
sum_y += ai * (y1 + y2);
end
return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
*/
// Get coordinates and promote them to calculation_type
calculation_type const x1 = boost::numeric_cast<calculation_type>(get<0>(p1));
calculation_type const y1 = boost::numeric_cast<calculation_type>(get<1>(p1));
calculation_type const x2 = boost::numeric_cast<calculation_type>(get<0>(p2));
calculation_type const y2 = boost::numeric_cast<calculation_type>(get<1>(p2));
calculation_type const ai = x1 * y2 - x2 * y1;
state.count++;
state.sum_a2 += ai;
state.sum_x += ai * (x1 + x2);
state.sum_y += ai * (y1 + y2);
}
static inline bool result(sums const& state, Point& centroid)
{
calculation_type const zero = calculation_type();
if (state.count > 0 && state.sum_a2 != zero)
{
calculation_type const v3 = 3;
calculation_type const a3 = v3 * state.sum_a2;
typedef typename geometry::coordinate_type
<
Point
>::type coordinate_type;
set<0>(centroid,
boost::numeric_cast<coordinate_type>(state.sum_x / a3));
set<1>(centroid,
boost::numeric_cast<coordinate_type>(state.sum_y / a3));
return true;
}
return false;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// Register this strategy for rings and (multi)polygons, in two dimensions
template <typename Point, typename Geometry>
struct default_strategy<cartesian_tag, areal_tag, 2, Point, Geometry>
{
typedef bashein_detmer
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP

View File

@@ -0,0 +1,144 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// Copyright (c) 2009-2011 Barend Gehrels, Amsterdam, the Netherlands.
// 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_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
// Helper geometry
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace centroid
{
namespace detail
{
template <typename Type, std::size_t DimensionCount>
struct weighted_length_sums
{
typedef typename geometry::model::point
<
Type, DimensionCount,
cs::cartesian
> work_point;
Type length;
work_point average_sum;
inline weighted_length_sums()
: length(Type())
{
geometry::assign_zero(average_sum);
}
};
}
template
<
typename Point,
typename PointOfSegment = Point
>
class weighted_length
{
private :
typedef typename select_most_precise
<
typename default_distance_result<Point>::type,
typename default_distance_result<PointOfSegment>::type
>::type distance_type;
public :
typedef detail::weighted_length_sums
<
distance_type,
geometry::dimension<Point>::type::value
> state_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2, state_type& state)
{
distance_type const d = geometry::distance(p1, p2);
state.length += d;
typename state_type::work_point weighted_median;
geometry::assign_zero(weighted_median);
geometry::add_point(weighted_median, p1);
geometry::add_point(weighted_median, p2);
geometry::multiply_value(weighted_median, d/2);
geometry::add_point(state.average_sum, weighted_median);
}
static inline bool result(state_type const& state, Point& centroid)
{
distance_type const zero = distance_type();
if (! geometry::math::equals(state.length, zero))
{
assign_zero(centroid);
add_point(centroid, state.average_sum);
divide_value(centroid, state.length);
return true;
}
return false;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// Register this strategy for linear geometries, in all dimensions
template <std::size_t N, typename Point, typename Geometry>
struct default_strategy
<
cartesian_tag,
linear_tag,
N,
Point,
Geometry
>
{
typedef weighted_length
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP

View File

@@ -0,0 +1,315 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
// Helper geometry (projected point on line)
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy for distance point to segment
\ingroup strategies
\details Calculates distance using projected-point method, and (optionally) Pythagoras
\author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\tparam Strategy underlying point-point distance strategy
\par Concepts for Strategy:
- cartesian_distance operator(Point,Point)
\note If the Strategy is a "comparable::pythagoras", this strategy
automatically is a comparable projected_point strategy (so without sqrt)
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void,
typename Strategy = pythagoras<Point, PointOfSegment, CalculationType>
>
class projected_point
{
public :
typedef typename strategy::distance::services::return_type<Strategy>::type calculation_type;
private :
// The three typedefs below are necessary to calculate distances
// from segments defined in integer coordinates.
// Integer coordinates can still result in FP distances.
// There is a division, which must be represented in FP.
// So promote.
typedef typename promote_floating_point<calculation_type>::type fp_type;
// A projected point of points in Integer coordinates must be able to be
// represented in FP.
typedef model::point
<
fp_type,
dimension<PointOfSegment>::value,
typename coordinate_system<PointOfSegment>::type
> fp_point_type;
// For convenience
typedef fp_point_type fp_vector_type;
// We have to use a strategy using FP coordinates (fp-type) which is
// not always the same as Strategy (defined as point_strategy_type)
// So we create a "similar" one
typedef typename strategy::distance::services::similar_type
<
Strategy,
Point,
fp_point_type
>::type fp_strategy_type;
public :
inline calculation_type apply(Point const& p,
PointOfSegment const& p1, PointOfSegment const& p2) const
{
assert_dimension_equal<Point, PointOfSegment>();
/*
Algorithm [p1: (x1,y1), p2: (x2,y2), p: (px,py)]
VECTOR v(x2 - x1, y2 - y1)
VECTOR w(px - x1, py - y1)
c1 = w . v
c2 = v . v
b = c1 / c2
RETURN POINT(x1 + b * vx, y1 + b * vy)
*/
// v is multiplied below with a (possibly) FP-value, so should be in FP
// For consistency we define w also in FP
fp_vector_type v, w;
geometry::convert(p2, v);
geometry::convert(p, w);
subtract_point(v, p1);
subtract_point(w, p1);
Strategy strategy;
boost::ignore_unused_variable_warning(strategy);
calculation_type const zero = calculation_type();
fp_type const c1 = dot_product(w, v);
if (c1 <= zero)
{
return strategy.apply(p, p1);
}
fp_type const c2 = dot_product(v, v);
if (c2 <= c1)
{
return strategy.apply(p, p2);
}
// See above, c1 > 0 AND c2 > c1 so: c2 != 0
fp_type const b = c1 / c2;
fp_strategy_type fp_strategy
= strategy::distance::services::get_similar
<
Strategy, Point, fp_point_type
>::apply(strategy);
fp_point_type projected;
geometry::convert(p1, projected);
multiply_value(v, b);
add_point(projected, v);
//std::cout << "distance " << dsv(p) << " .. " << dsv(projected) << std::endl;
return fp_strategy.apply(p, projected);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct tag<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_segment type;
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct return_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef typename projected_point<Point, PointOfSegment, CalculationType, Strategy>::calculation_type type;
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct strategy_point_point<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef Strategy type;
};
template
<
typename Point,
typename PointOfSegment,
typename CalculationType,
typename Strategy,
typename P1,
typename P2
>
struct similar_type<projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2>
{
typedef projected_point<P1, P2, CalculationType, Strategy> type;
};
template
<
typename Point,
typename PointOfSegment,
typename CalculationType,
typename Strategy,
typename P1,
typename P2
>
struct get_similar<projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2>
{
static inline typename similar_type
<
projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2
>::type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& )
{
return projected_point<P1, P2, CalculationType, Strategy>();
}
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct comparable_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
{
// Define a projected_point strategy with its underlying point-point-strategy
// being comparable
typedef projected_point
<
Point,
PointOfSegment,
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct get_comparable<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef typename comparable_type
<
projected_point<Point, PointOfSegment, CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct result_from_distance<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
{
private :
typedef typename return_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >::type return_type;
public :
template <typename T>
static inline return_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& , T const& value)
{
Strategy s;
return result_from_distance<Strategy>::apply(s, value);
}
};
// Get default-strategy for point-segment distance calculation
// while still have the possibility to specify point-point distance strategy (PPS)
// It is used in algorithms/distance.hpp where users specify PPS for distance
// of point-to-segment or point-to-linestring.
// Convenient for geographic coordinate systems especially.
template <typename Point, typename PointOfSegment, typename Strategy>
struct default_strategy<segment_tag, Point, PointOfSegment, cartesian_tag, cartesian_tag, Strategy>
{
typedef strategy::distance::projected_point
<
Point,
PointOfSegment,
void,
typename boost::mpl::if_
<
boost::is_void<Strategy>,
typename default_strategy
<
point_tag, Point, PointOfSegment,
cartesian_tag, cartesian_tag
>::type,
Strategy
>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP

View File

@@ -0,0 +1,345 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Point1, typename Point2, size_t I, typename T>
struct compute_pythagoras
{
static inline T apply(Point1 const& p1, Point2 const& p2)
{
T const c1 = boost::numeric_cast<T>(get<I-1>(p2));
T const c2 = boost::numeric_cast<T>(get<I-1>(p1));
T const d = c1 - c2;
return d * d + compute_pythagoras<Point1, Point2, I-1, T>::apply(p1, p2);
}
};
template <typename Point1, typename Point2, typename T>
struct compute_pythagoras<Point1, Point2, 0, T>
{
static inline T apply(Point1 const&, Point2 const&)
{
return boost::numeric_cast<T>(0);
}
};
}
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between two points
\ingroup strategies
\tparam Point1 \tparam_first_point
\tparam Point2 \tparam_second_point
\tparam CalculationType \tparam_calculation
*/
template
<
typename Point1,
typename Point2 = Point1,
typename CalculationType = void
>
class pythagoras
{
public :
typedef typename select_calculation_type
<
Point1,
Point2,
CalculationType
>::type calculation_type;
static inline calculation_type apply(Point1 const& p1, Point2 const& p2)
{
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point1>) );
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Point1, Point2>();
return detail::compute_pythagoras
<
Point1, Point2,
dimension<Point1>::value,
calculation_type
>::apply(p1, p2);
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between two points
\ingroup strategies
\tparam Point1 \tparam_first_point
\tparam Point2 \tparam_second_point
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for points with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename Point1,
typename Point2 = Point1,
typename CalculationType = void
>
class pythagoras
{
typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
public :
typedef typename promote_floating_point
<
typename services::return_type<comparable_type>::type
>::type calculation_type;
/*!
\brief applies the distance calculation using pythagoras
\return the calculated distance (including taking the square root)
\param p1 first point
\param p2 second point
*/
static inline calculation_type apply(Point1 const& p1, Point2 const& p2)
{
calculation_type const t = comparable_type::apply(p1, p2);
return sqrt(t);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point1, typename Point2, typename CalculationType>
struct tag<pythagoras<Point1, Point2, CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct return_type<pythagoras<Point1, Point2, CalculationType> >
{
typedef typename pythagoras<Point1, Point2, CalculationType>::calculation_type type;
};
template
<
typename Point1,
typename Point2,
typename CalculationType,
typename P1,
typename P2
>
struct similar_type<pythagoras<Point1, Point2, CalculationType>, P1, P2>
{
typedef pythagoras<P1, P2, CalculationType> type;
};
template
<
typename Point1,
typename Point2,
typename CalculationType,
typename P1,
typename P2
>
struct get_similar<pythagoras<Point1, Point2, CalculationType>, P1, P2>
{
static inline typename similar_type
<
pythagoras<Point1, Point2, CalculationType>, P1, P2
>::type apply(pythagoras<Point1, Point2, CalculationType> const& )
{
return pythagoras<P1, P2, CalculationType>();
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct comparable_type<pythagoras<Point1, Point2, CalculationType> >
{
typedef comparable::pythagoras<Point1, Point2, CalculationType> type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct get_comparable<pythagoras<Point1, Point2, CalculationType> >
{
typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
public :
static inline comparable_type apply(pythagoras<Point1, Point2, CalculationType> const& input)
{
return comparable_type();
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct result_from_distance<pythagoras<Point1, Point2, CalculationType> >
{
private :
typedef typename return_type<pythagoras<Point1, Point2, CalculationType> >::type return_type;
public :
template <typename T>
static inline return_type apply(pythagoras<Point1, Point2, CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras
template <typename Point1, typename Point2, typename CalculationType>
struct tag<comparable::pythagoras<Point1, Point2, CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct return_type<comparable::pythagoras<Point1, Point2, CalculationType> >
{
typedef typename comparable::pythagoras<Point1, Point2, CalculationType>::calculation_type type;
};
template
<
typename Point1,
typename Point2,
typename CalculationType,
typename P1,
typename P2
>
struct similar_type<comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2>
{
typedef comparable::pythagoras<P1, P2, CalculationType> type;
};
template
<
typename Point1,
typename Point2,
typename CalculationType,
typename P1,
typename P2
>
struct get_similar<comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2>
{
static inline typename similar_type
<
comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2
>::type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& )
{
return comparable::pythagoras<P1, P2, CalculationType>();
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct comparable_type<comparable::pythagoras<Point1, Point2, CalculationType> >
{
typedef comparable::pythagoras<Point1, Point2, CalculationType> type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct get_comparable<comparable::pythagoras<Point1, Point2, CalculationType> >
{
typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& input)
{
return comparable_type();
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct result_from_distance<comparable::pythagoras<Point1, Point2, CalculationType> >
{
private :
typedef typename return_type<comparable::pythagoras<Point1, Point2, CalculationType> >::type return_type;
public :
template <typename T>
static inline return_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& , T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename Point1, typename Point2>
struct default_strategy<point_tag, Point1, Point2, cartesian_tag, cartesian_tag, void>
{
typedef pythagoras<Point1, Point2> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP

View File

@@ -0,0 +1,172 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
struct within_range
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
return value > min_value && value < max_value;
}
};
struct covered_by_range
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
return value >= min_value && value <= max_value;
}
};
template
<
typename SubStrategy,
typename Point,
typename Box,
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_point_box_loop
{
static inline bool apply(Point const& point, Box const& box)
{
if (! SubStrategy::apply(get<Dimension>(point),
get<min_corner, Dimension>(box),
get<max_corner, Dimension>(box))
)
{
return false;
}
return relate_point_box_loop
<
SubStrategy,
Point, Box,
Dimension + 1, DimensionCount
>::apply(point, box);
}
};
template
<
typename SubStrategy,
typename Point,
typename Box,
std::size_t DimensionCount
>
struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount>
{
static inline bool apply(Point const& , Box const& )
{
return true;
}
};
template
<
typename Point,
typename Box,
typename SubStrategy = within_range
>
struct point_in_box
{
static inline bool apply(Point const& point, Box const& box)
{
return relate_point_box_loop
<
SubStrategy,
Point, Box,
0, dimension<Point>::type::value
>::apply(point, box);
}
};
} // namespace within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace within { namespace services
{
template <typename Point, typename Box>
struct default_strategy
<
point_tag, box_tag,
point_tag, areal_tag,
cartesian_tag, cartesian_tag,
Point, Box
>
{
typedef within::point_in_box<Point, Box> type;
};
}} // namespace within::services
namespace covered_by { namespace services
{
template <typename Point, typename Box>
struct default_strategy
<
point_tag, box_tag,
point_tag, areal_tag,
cartesian_tag, cartesian_tag,
Point, Box
>
{
typedef within::point_in_box
<
Point, Box,
within::covered_by_range
> type;
};
}} // namespace covered_by::services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP

View File

@@ -0,0 +1,124 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using cross counting,
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\see http://tog.acm.org/resources/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c
\note Does NOT work correctly for point ON border
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class crossings_multiply
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
class flags
{
bool inside_flag;
bool first;
bool yflag0;
public :
friend class crossings_multiply;
inline flags()
: inside_flag(false)
, first(true)
, yflag0(false)
{}
};
public :
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef flags state_type;
static inline bool apply(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
flags& state)
{
calculation_type const tx = get<0>(point);
calculation_type const ty = get<1>(point);
calculation_type const x0 = get<0>(seg1);
calculation_type const y0 = get<1>(seg1);
calculation_type const x1 = get<0>(seg2);
calculation_type const y1 = get<1>(seg2);
if (state.first)
{
state.first = false;
state.yflag0 = y0 >= ty;
}
bool yflag1 = y1 >= ty;
if (state.yflag0 != yflag1)
{
if ( ((y1-ty) * (x0-x1) >= (x1-tx) * (y0-y1)) == yflag1 )
{
state.inside_flag = ! state.inside_flag;
}
}
state.yflag0 = yflag1;
return true;
}
static inline int result(flags const& state)
{
return state.inside_flag ? 1 : -1;
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP

View File

@@ -0,0 +1,118 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using cross counting
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author adapted from Randolph Franklin algorithm
\author Barend and Maarten, 1995
\author Revised for templatized library, Barend Gehrels, 2007
\return true if point is in ring, works for closed rings in both directions
\note Does NOT work correctly for point ON border
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class franklin
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class crossings
{
bool crosses;
public :
friend class franklin;
inline crossings()
: crosses(false)
{}
};
public :
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef crossings state_type;
static inline bool apply(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
crossings& state)
{
calculation_type const& px = get<0>(point);
calculation_type const& py = get<1>(point);
calculation_type const& x1 = get<0>(seg1);
calculation_type const& y1 = get<1>(seg1);
calculation_type const& x2 = get<0>(seg2);
calculation_type const& y2 = get<1>(seg2);
if (
( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
&& (px < (x1 - x2) * (py - y2) / (y1 - y2) + x2)
)
{
state.crosses = ! state.crosses;
}
return true;
}
static inline int result(crossings const& state)
{
return state.crosses ? 1 : -1;
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP

View File

@@ -0,0 +1,118 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
// 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_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
/*!
\brief Check at which side of a segment a point lies:
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class side_by_triangle
{
public :
// Template member function, because it is not always trivial
// or convenient to explicitly mention the typenames in the
// strategy-struct itself.
// Types can be all three different. Therefore it is
// not implemented (anymore) as "segment"
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
typedef typename boost::mpl::if_c
<
boost::is_void<CalculationType>::type::value,
typename select_most_precise
<
typename select_most_precise
<
typename coordinate_type<P1>::type,
typename coordinate_type<P2>::type
>::type,
typename coordinate_type<P>::type
>::type,
CalculationType
>::type coordinate_type;
//std::cout << "side: " << typeid(coordinate_type).name() << std::endl;
coordinate_type const x = get<0>(p);
coordinate_type const y = get<1>(p);
coordinate_type const sx1 = get<0>(p1);
coordinate_type const sy1 = get<1>(p1);
coordinate_type const sx2 = get<0>(p2);
coordinate_type const sy2 = get<1>(p2);
// Promote float->double, small int->int
typedef typename select_most_precise
<
coordinate_type,
double
>::type promoted_type;
promoted_type const dx = sx2 - sx1;
promoted_type const dy = sy2 - sy1;
promoted_type const dpx = x - sx1;
promoted_type const dpy = y - sy1;
promoted_type const s = dx * dpy - dy * dpx;
promoted_type const zero = promoted_type();
return math::equals(s, zero) ? 0
: s > zero ? 1
: -1;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef side_by_triangle<CalculationType> type;
};
}
#endif
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP