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,426 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-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_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
#include <cstddef>
#include <algorithm>
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/views/reversible_view.hpp>
// Temporary, comparing sorting, this can be removed in the end
//#define BOOST_GEOMETRY_USE_FLEX_SORT
//#define BOOST_GEOMETRY_USE_FLEX_SORT2
#if defined(BOOST_GEOMETRY_USE_FLEX_SORT)
# include <boost/algorithm/sorting/flex_sort.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace convex_hull
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename InputRange,
typename RangeIterator,
typename StrategyLess,
typename StrategyGreater
>
struct get_extremes
{
typedef typename point_type<InputRange>::type point_type;
point_type left, right;
bool first;
StrategyLess less;
StrategyGreater greater;
get_extremes()
: first(true)
{}
inline void apply(InputRange const& range)
{
// First iterate through this range
// (this two-stage approach avoids many point copies,
// because iterators are kept in memory. Because iterators are
// not persistent (in MSVC) this approach is not applicable
// for more ranges together)
RangeIterator left_it = boost::begin(range);
RangeIterator right_it = boost::begin(range);
for (RangeIterator it = boost::begin(range) + 1;
it != boost::end(range);
++it)
{
if (less(*it, *left_it))
{
left_it = it;
}
if (greater(*it, *right_it))
{
right_it = it;
}
}
// Then compare with earlier
if (first && boost::size(range) > 0)
{
// First time, assign left/right
left = *left_it;
right = *right_it;
first = false;
}
else
{
// Next time, check if this range was left/right from
// the extremes already collected
if (less(*left_it, left))
{
left = *left_it;
}
if (greater(*right_it, right))
{
right = *right_it;
}
}
}
};
template
<
typename InputRange,
typename RangeIterator,
typename Container,
typename SideStrategy
>
struct assign_range
{
Container lower_points, upper_points;
typedef typename point_type<InputRange>::type point_type;
point_type const& most_left;
point_type const& most_right;
inline assign_range(point_type const& left, point_type const& right)
: most_left(left)
, most_right(right)
{}
inline void apply(InputRange const& range)
{
typedef SideStrategy side;
// Put points in one of the two output sequences
for (RangeIterator it = boost::begin(range);
it != boost::end(range);
++it)
{
// check if it is lying most_left or most_right from the line
int dir = side::apply(most_left, most_right, *it);
switch(dir)
{
case 1 : // left side
upper_points.push_back(*it);
break;
case -1 : // right side
lower_points.push_back(*it);
break;
// 0: on line most_left-most_right,
// or most_left, or most_right,
// -> all never part of hull
}
}
}
};
template <typename Range>
static inline void sort(Range& range)
{
typedef typename boost::range_value<Range>::type point_type;
typedef geometry::less<point_type> comparator;
#if defined(GGL_USE_FLEX_SORT)
#if defined(GGL_USE_FLEX_SORT1)
typedef boost::detail::default_predicate
<
boost::sort_filter_cutoff
<
18,
boost::detail::insert_sort_core,
boost::sort_filter_ground
<
30,
boost::detail::heap_sort_core,
boost::detail::quick_sort_core
<
boost::pivot_median_of_three,
boost::default_partitionner
>
>
>,
comparator> my_sort;
my_sort sort;
#elif defined(GGL_USE_FLEX_SORT2)
// 1, 5, 9, 18, 25: 0.75
// 50: 0.81
typedef boost::detail::default_predicate<boost::sort_filter_cutoff
<
35,
boost::detail::insert_sort_core,
boost::detail::quick_sort_core<boost::pivot_middle, boost::default_partitionner>
>, comparator
> barend_sort;
barend_sort sort;
#else
#error Define sub-flex-sort
#endif
sort(boost::begin(range), boost::end(range));
#else
std::sort
(boost::begin(range), boost::end(range), comparator());
#endif
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Graham scan strategy to calculate convex hull
\ingroup strategies
\note Completely reworked version inspired on the sources listed below
\see http://www.ddj.com/architect/201806315
\see http://marknelson.us/2007/08/22/convex
*/
template <typename InputGeometry, typename OutputPoint>
class graham_andrew
{
public :
typedef OutputPoint point_type;
typedef InputGeometry geometry_type;
private:
typedef typename cs_tag<point_type>::type cs_tag;
typedef typename std::vector<point_type> container_type;
typedef typename std::vector<point_type>::const_iterator iterator;
typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
class partitions
{
friend class graham_andrew;
container_type m_lower_hull;
container_type m_upper_hull;
container_type m_copied_input;
};
public:
typedef partitions state_type;
inline void apply(InputGeometry const& geometry, partitions& state) const
{
// First pass.
// Get min/max (in most cases left / right) points
// This makes use of the geometry::less/greater predicates with the optional
// direction template parameter to indicate x direction
typedef typename geometry::detail::range_type<InputGeometry>::type range_type;
typedef typename boost::range_iterator
<
range_type const
>::type range_iterator;
detail::get_extremes
<
range_type,
range_iterator,
geometry::less<point_type, 0>,
geometry::greater<point_type, 0>
> extremes;
geometry::detail::for_each_range(geometry, extremes);
// Bounding left/right points
// Second pass, now that extremes are found, assign all points
// in either lower, either upper
detail::assign_range
<
range_type,
range_iterator,
container_type,
typename strategy::side::services::default_strategy<cs_tag>::type
> assigner(extremes.left, extremes.right);
geometry::detail::for_each_range(geometry, assigner);
// Sort both collections, first on x(, then on y)
detail::sort(assigner.lower_points);
detail::sort(assigner.upper_points);
//std::cout << boost::size(assigner.lower_points) << std::endl;
//std::cout << boost::size(assigner.upper_points) << std::endl;
// And decide which point should be in the final hull
build_half_hull<-1>(assigner.lower_points, state.m_lower_hull,
extremes.left, extremes.right);
build_half_hull<1>(assigner.upper_points, state.m_upper_hull,
extremes.left, extremes.right);
}
template <typename OutputIterator>
inline void result(partitions const& state,
OutputIterator out, bool clockwise) const
{
if (clockwise)
{
output_range<iterate_forward>(state.m_upper_hull, out, false);
output_range<iterate_reverse>(state.m_lower_hull, out, true);
}
else
{
output_range<iterate_forward>(state.m_lower_hull, out, false);
output_range<iterate_reverse>(state.m_upper_hull, out, true);
}
}
private:
template <int Factor>
static inline void build_half_hull(container_type const& input,
container_type& output,
point_type const& left, point_type const& right)
{
output.push_back(left);
for(iterator it = input.begin(); it != input.end(); ++it)
{
add_to_hull<Factor>(*it, output);
}
add_to_hull<Factor>(right, output);
}
template <int Factor>
static inline void add_to_hull(point_type const& p, container_type& output)
{
typedef typename strategy::side::services::default_strategy<cs_tag>::type side;
output.push_back(p);
register std::size_t output_size = output.size();
while (output_size >= 3)
{
rev_iterator rit = output.rbegin();
point_type const& last = *rit++;
point_type const& last2 = *rit++;
if (Factor * side::apply(*rit, last, last2) <= 0)
{
// Remove last two points from stack, and add last again
// This is much faster then erasing the one but last.
output.pop_back();
output.pop_back();
output.push_back(last);
output_size--;
}
else
{
return;
}
}
}
template <iterate_direction Direction, typename OutputIterator>
static inline void output_range(container_type const& range,
OutputIterator out, bool skip_first)
{
typedef typename reversible_view<container_type const, Direction>::type view_type;
view_type view(range);
bool first = true;
for (typename boost::range_iterator<view_type const>::type it = boost::begin(view);
it != boost::end(view); ++it)
{
if (first && skip_first)
{
first = false;
}
else
{
*out = *it;
++out;
}
}
}
};
}} // namespace strategy::convex_hull
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
template <typename InputGeometry, typename OutputPoint>
struct strategy_convex_hull<cartesian_tag, InputGeometry, OutputPoint>
{
typedef strategy::convex_hull::graham_andrew<InputGeometry, OutputPoint> type;
};
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP

View File

@@ -0,0 +1,151 @@
// 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_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
#include <boost/array.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
struct decide_within
{
static inline bool apply(int side, bool& result)
{
if (side != 1)
{
result = false;
return false;
}
return true; // continue
}
};
struct decide_covered_by
{
static inline bool apply(int side, bool& result)
{
if (side != 1)
{
result = side >= 0;
return false;
}
return true; // continue
}
};
template <typename Point, typename Box, typename Decide = decide_within>
struct point_in_box_by_side
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Box>::type
>::type side_strategy_type;
static inline bool apply(Point const& point, Box const& box)
{
// Create (counterclockwise) array of points, the fifth one closes it
// Every point should be on the LEFT side (=1), or ON the border (=0),
// So >= 1 or >= 0
boost::array<typename point_type<Box>::type, 5> bp;
geometry::detail::assign_box_corners_oriented<true>(box, bp);
bp[4] = bp[0];
bool result = true;
side_strategy_type strategy;
boost::ignore_unused_variable_warning(strategy);
for (int i = 1; i < 5; i++)
{
int const side = strategy.apply(point, bp[i - 1], bp[i]);
if (! Decide::apply(side, result))
{
return result;
}
}
return result;
}
};
} // 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,
spherical_tag, spherical_tag,
Point, Box
>
{
typedef within::point_in_box_by_side
<
Point, Box, within::decide_within
> 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,
spherical_tag, spherical_tag,
Point, Box
>
{
typedef within::point_in_box_by_side
<
Point, Box, within::decide_covered_by
> type;
};
}} // namespace covered_by::services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP

View File

@@ -0,0 +1,208 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 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_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using winding rule, but checking if enclosing ring is
counter clockwise and, if so, reverses the result
\ingroup strategies
\tparam Point \tparam_point
\tparam Reverse True if parameter should be reversed
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
\note but totally revised afterwards, especially for cases on segments
\note Only dependant on "side", -> agnostic, suitable for spherical/latlong
\qbk{
[heading See also]
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
}
*/
template
<
bool Reverse,
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class oriented_winding
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type strategy_side_type;
/*! subclass to keep state */
class counter
{
int m_count;
bool m_touches;
calculation_type m_sum_area;
inline int code() const
{
return m_touches ? 0 : m_count == 0 ? -1 : 1;
}
inline int clockwise_oriented_code() const
{
return (m_sum_area > 0) ? code() : -code();
}
inline int oriented_code() const
{
return Reverse
? -clockwise_oriented_code()
: clockwise_oriented_code();
}
public :
friend class oriented_winding;
inline counter()
: m_count(0)
, m_touches(false)
, m_sum_area(0)
{}
inline void add_to_area(calculation_type triangle)
{
m_sum_area += triangle;
}
};
template <size_t D>
static inline int check_touch(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state)
{
calculation_type const p = get<D>(point);
calculation_type const s1 = get<D>(seg1);
calculation_type const s2 = get<D>(seg2);
if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
{
state.m_touches = true;
}
return 0;
}
template <size_t D>
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state)
{
calculation_type const p = get<D>(point);
calculation_type const s1 = get<D>(seg1);
calculation_type const s2 = get<D>(seg2);
// Check if one of segment endpoints is at same level of point
bool eq1 = math::equals(s1, p);
bool eq2 = math::equals(s2, p);
if (eq1 && eq2)
{
// Both equal p -> segment is horizontal (or vertical for D=0)
// The only thing which has to be done is check if point is ON segment
return check_touch<1 - D>(point, seg1, seg2, state);
}
return
eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN
: 0;
}
public :
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
static inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state)
{
state.add_to_area(get<0>(s2) * get<1>(s1) - get<0>(s1) * get<1>(s2));
int count = check_segment<1>(point, s1, s2, state);
if (count != 0)
{
int side = strategy_side_type::apply(s1, s2, point);
if (side == 0)
{
// Point is lying on segment
state.m_touches = true;
state.m_count = 0;
return false;
}
// Side is NEG for right, POS for left.
// The count is -2 for down, 2 for up (or -1/1)
// Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE
// See accompagnying figure (TODO)
if (side * count > 0)
{
state.m_count += count;
}
}
return ! state.m_touches;
}
static inline int result(counter const& state)
{
return state.oriented_code();
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP

View File

@@ -0,0 +1,232 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-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_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using winding rule
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
\note but totally revised afterwards, especially for cases on segments
\note Only dependant on "side", -> agnostic, suitable for spherical/latlong
\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 winding
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type strategy_side_type;
/*! subclass to keep state */
class counter
{
int m_count;
bool m_touches;
inline int code() const
{
return m_touches ? 0 : m_count == 0 ? -1 : 1;
}
public :
friend class winding;
inline counter()
: m_count(0)
, m_touches(false)
{}
};
template <size_t D>
static inline int check_touch(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state)
{
calculation_type const p = get<D>(point);
calculation_type const s1 = get<D>(seg1);
calculation_type const s2 = get<D>(seg2);
if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
{
state.m_touches = true;
}
return 0;
}
template <size_t D>
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state)
{
calculation_type const p = get<D>(point);
calculation_type const s1 = get<D>(seg1);
calculation_type const s2 = get<D>(seg2);
// Check if one of segment endpoints is at same level of point
bool eq1 = math::equals(s1, p);
bool eq2 = math::equals(s2, p);
if (eq1 && eq2)
{
// Both equal p -> segment is horizontal (or vertical for D=0)
// The only thing which has to be done is check if point is ON segment
return check_touch<1 - D>(point, seg1, seg2,state);
}
return
eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN
: 0;
}
public :
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
static inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state)
{
int count = check_segment<1>(point, s1, s2, state);
if (count != 0)
{
int side = strategy_side_type::apply(s1, s2, point);
if (side == 0)
{
// Point is lying on segment
state.m_touches = true;
state.m_count = 0;
return false;
}
// Side is NEG for right, POS for left.
// The count is -2 for down, 2 for up (or -1/1)
// Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE
// See accompagnying figure (TODO)
if (side * count > 0)
{
state.m_count += count;
}
}
return ! state.m_touches;
}
static inline int result(counter const& state)
{
return state.code();
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// Register using "areal_tag" for ring, polygon, multi-polygon
template <typename AnyTag, typename Point, typename Geometry>
struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename AnyTag, typename Point, typename Geometry>
struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
// Register using "areal_tag" for ring, polygon, multi-polygon
template <typename AnyTag, typename Point, typename Geometry>
struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename AnyTag, typename Point, typename Geometry>
struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP

View File

@@ -0,0 +1,230 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 1995, 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 1995 Maarten Hilferink, 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_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
#include <cstddef>
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/distance.hpp>
//#define GL_DEBUG_DOUGLAS_PEUCKER
#ifdef GL_DEBUG_DOUGLAS_PEUCKER
#include <boost/geometry/util/write_dsv.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace simplify
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/*!
\brief Small wrapper around a point, with an extra member "included"
\details
It has a const-reference to the original point (so no copy here)
\tparam the enclosed point type
*/
template<typename Point>
struct douglas_peucker_point
{
Point const& p;
bool included;
inline douglas_peucker_point(Point const& ap)
: p(ap)
, included(false)
{}
// Necessary for proper compilation
inline douglas_peucker_point<Point> operator=(
douglas_peucker_point<Point> const& other)
{
return douglas_peucker_point<Point>(*this);
}
};
}
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Implements the simplify algorithm.
\ingroup strategies
\details The douglas_peucker strategy simplifies a linestring, ring or
vector of points using the well-known Douglas-Peucker algorithm.
For the algorithm, see for example:
\see http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
\see http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html
\tparam Point the point type
\tparam PointDistanceStrategy point-segment distance strategy to be used
\note This strategy uses itself a point-segment-distance strategy which
can be specified
\author Barend and Maarten, 1995/1996
\author Barend, revised for Generic Geometry Library, 2008
*/
template
<
typename Point,
typename PointDistanceStrategy
>
class douglas_peucker
{
public :
// See also ticket 5954 https://svn.boost.org/trac/boost/ticket/5954
// Comparable is currently not possible here because it has to be compared to the squared of max_distance, and more.
// For now we have to take the real distance.
typedef PointDistanceStrategy distance_strategy_type;
// typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type distance_strategy_type;
typedef typename strategy::distance::services::return_type<distance_strategy_type>::type return_type;
private :
typedef detail::douglas_peucker_point<Point> dp_point_type;
typedef typename std::vector<dp_point_type>::iterator iterator_type;
static inline void consider(iterator_type begin,
iterator_type end,
return_type const& max_dist, int& n,
distance_strategy_type const& ps_distance_strategy)
{
std::size_t size = end - begin;
// size must be at least 3
// because we want to consider a candidate point in between
if (size <= 2)
{
#ifdef GL_DEBUG_DOUGLAS_PEUCKER
if (begin != end)
{
std::cout << "ignore between " << dsv(begin->p)
<< " and " << dsv((end - 1)->p)
<< " size=" << size << std::endl;
}
std::cout << "return because size=" << size << std::endl;
#endif
return;
}
iterator_type last = end - 1;
#ifdef GL_DEBUG_DOUGLAS_PEUCKER
std::cout << "find between " << dsv(begin->p)
<< " and " << dsv(last->p)
<< " size=" << size << std::endl;
#endif
// Find most far point, compare to the current segment
//geometry::segment<Point const> s(begin->p, last->p);
return_type md(-1.0); // any value < 0
iterator_type candidate;
for(iterator_type it = begin + 1; it != last; ++it)
{
return_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);
#ifdef GL_DEBUG_DOUGLAS_PEUCKER
std::cout << "consider " << dsv(it->p)
<< " at " << double(dist)
<< ((dist > max_dist) ? " maybe" : " no")
<< std::endl;
#endif
if (dist > md)
{
md = dist;
candidate = it;
}
}
// If a point is found, set the include flag
// and handle segments in between recursively
if (md > max_dist)
{
#ifdef GL_DEBUG_DOUGLAS_PEUCKER
std::cout << "use " << dsv(candidate->p) << std::endl;
#endif
candidate->included = true;
n++;
consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);
consider(candidate, end, max_dist, n, ps_distance_strategy);
}
}
public :
template <typename Range, typename OutputIterator>
static inline OutputIterator apply(Range const& range,
OutputIterator out, double max_distance)
{
distance_strategy_type strategy;
// Copy coordinates, a vector of references to all points
std::vector<dp_point_type> ref_candidates(boost::begin(range),
boost::end(range));
// Include first and last point of line,
// they are always part of the line
int n = 2;
ref_candidates.front().included = true;
ref_candidates.back().included = true;
// Get points, recursively, including them if they are further away
// than the specified distance
typedef typename strategy::distance::services::return_type<distance_strategy_type>::type return_type;
consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);
// Copy included elements to the output
for(typename std::vector<dp_point_type>::const_iterator it
= boost::begin(ref_candidates);
it != boost::end(ref_candidates);
++it)
{
if (it->included)
{
// copy-coordinates does not work because OutputIterator
// does not model Point (??)
//geometry::convert(it->p, *out);
*out = it->p;
out++;
}
}
return out;
}
};
}} // namespace strategy::simplify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP

View File

@@ -0,0 +1,50 @@
// 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_AREA_HPP
#define BOOST_GEOMETRY_STRATEGIES_AREA_HPP
#include <boost/mpl/assert.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area { namespace services
{
/*!
\brief Traits class binding a default area strategy to a coordinate system
\ingroup area
\tparam Tag tag of coordinate system
\tparam PointOfSegment point-type
*/
template <typename Tag, typename PointOfSegment>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE
, (types<PointOfSegment>)
);
};
}}} // namespace strategy::area::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_AREA_HPP

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

View File

@@ -0,0 +1,72 @@
// 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_CENTROID_HPP
#define BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace centroid
{
struct not_applicable_strategy
{
};
namespace services
{
/*!
\brief Traits class binding a centroid calculation strategy to a coordinate system
\ingroup centroid
\tparam CsTag tag of coordinate system, for specialization
\tparam GeometryTag tag of geometry, for specialization
\tparam Dimension dimension of geometry, for specialization
\tparam Point point-type
\tparam Geometry
*/
template
<
typename CsTag,
typename GeometryTag,
std::size_t Dimension,
typename Point,
typename Geometry
>
struct default_strategy
{
typedef not_applicable_strategy type;
};
} // namespace services
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CENTROID_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_COMPARE_HPP
#define BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
#include <cstddef>
#include <functional>
#include <boost/mpl/if.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
/*!
\brief Traits class binding a comparing strategy to a coordinate system
\ingroup util
\tparam Tag tag of coordinate system of point-type
\tparam Direction direction to compare on: 1 for less (-> ascending order)
and -1 for greater (-> descending order)
\tparam Point point-type
\tparam CoordinateSystem coordinate sytem of point
\tparam Dimension: the dimension to compare on
*/
template
<
typename Tag,
int Direction,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare
{
typedef strategy::not_implemented type;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
// For compare we add defaults specializations,
// because they defaultly redirect to std::less / greater / equal_to
template
<
typename Tag,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare<Tag, 1, Point, CoordinateSystem, Dimension>
{
typedef std::less<typename coordinate_type<Point>::type> type;
};
template
<
typename Tag,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare<Tag, -1, Point, CoordinateSystem, Dimension>
{
typedef std::greater<typename coordinate_type<Point>::type> type;
};
template
<
typename Tag,
typename Point,
typename CoordinateSystem,
std::size_t Dimension
>
struct strategy_compare<Tag, 0, Point, CoordinateSystem, Dimension>
{
typedef std::equal_to<typename coordinate_type<Point>::type> type;
};
#endif
namespace strategy { namespace compare
{
/*!
\brief Default strategy, indicates the default strategy for comparisons
\details The default strategy for comparisons defer in most cases
to std::less (for ascending) and std::greater (for descending).
However, if a spherical coordinate system is used, and comparison
is done on longitude, it will take another strategy handling circular
*/
struct default_strategy {};
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Type>
struct is_default : boost::false_type
{};
template <>
struct is_default<default_strategy> : boost::true_type
{};
/*!
\brief Meta-function to select strategy
\details If "default_strategy" is specified, it will take the
traits-registered class for the specified coordinate system.
If another strategy is explicitly specified, it takes that one.
*/
template
<
typename Strategy,
int Direction,
typename Point,
std::size_t Dimension
>
struct select_strategy
{
typedef typename
boost::mpl::if_
<
is_default<Strategy>,
typename strategy_compare
<
typename cs_tag<Point>::type,
Direction,
Point,
typename coordinate_system<Point>::type,
Dimension
>::type,
Strategy
>::type type;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace strategy::compare
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP

View File

@@ -0,0 +1,75 @@
// 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_CONCEPTS_AREA_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
#include <boost/concept_check.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for area
\ingroup area
*/
template <typename Strategy>
class AreaStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type,
typedef typename Strategy::state_type state_type;
// 2) must define return_type,
typedef typename Strategy::return_type return_type;
// 3) must define point_type, of polygon (segments)
typedef typename Strategy::segment_point_type spoint_type;
struct check_methods
{
static void apply()
{
Strategy const* str;
state_type *st;
// 4) must implement a method apply with the following signature
spoint_type const* sp;
str->apply(*sp, *sp, *st);
// 5) must implement a static method result with the following signature
return_type r = str->result(*st);
boost::ignore_unused_variable_warning(r);
boost::ignore_unused_variable_warning(str);
}
};
public :
BOOST_CONCEPT_USAGE(AreaStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP

View File

@@ -0,0 +1,78 @@
// 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_CONCEPTS_CENTROID_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
#include <boost/concept_check.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for centroid
\ingroup centroid
*/
template <typename Strategy>
class CentroidStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type,
typedef typename Strategy::state_type state_type;
// 2) must define point_type,
typedef typename Strategy::point_type point_type;
// 3) must define point_type, of polygon (segments)
typedef typename Strategy::segment_point_type spoint_type;
struct check_methods
{
static void apply()
{
Strategy *str;
state_type *st;
// 4) must implement a static method apply,
// getting two segment-points
spoint_type const* sp;
str->apply(*sp, *sp, *st);
// 5) must implement a static method result
// getting the centroid
point_type *c;
bool r = str->result(*st, *c);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(r);
}
};
public :
BOOST_CONCEPT_USAGE(CentroidStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP

View File

@@ -0,0 +1,75 @@
// 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_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
#include <vector>
#include <boost/concept_check.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for convex_hull
\ingroup convex_hull
*/
template <typename Strategy>
class ConvexHullStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type
typedef typename Strategy::state_type state_type;
// 2) must define point_type
typedef typename Strategy::point_type point_type;
// 3) must define geometry_type
typedef typename Strategy::geometry_type geometry_type;
struct check_methods
{
static void apply()
{
Strategy const* str;
state_type* st;
geometry_type* sp;
std::vector<point_type> *v;
// 4) must implement a method apply, iterating over a range
str->apply(*sp, *st);
// 5) must implement a method result, with an output iterator
str->result(*st, std::back_inserter(*v), true);
}
};
public :
BOOST_CONCEPT_USAGE(ConvexHullStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP

View File

@@ -0,0 +1,206 @@
// 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_CONCEPTS_DISTANCE_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
#include <vector>
#include <iterator>
#include <boost/concept_check.hpp>
#include <boost/geometry/util/parameter_type_of.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/segment.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for point-segment-distance
\ingroup distance
*/
template <typename Strategy>
struct PointDistanceStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
// 1: inspect and define both arguments of apply
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type ptype1;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type ptype2;
// 2) check if apply-arguments fulfill point concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<ptype1>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<ptype2>)
);
// 3) must define meta-function return_type
typedef typename strategy::distance::services::return_type<Strategy>::type rtype;
// 4) must define meta-function "similar_type"
typedef typename strategy::distance::services::similar_type
<
Strategy, ptype2, ptype1
>::type stype;
// 5) must define meta-function "comparable_type"
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type ctype;
// 6) must define meta-function "tag"
typedef typename strategy::distance::services::tag
<
Strategy
>::type tag;
// 7) must implement apply with arguments
Strategy* str;
ptype1 *p1;
ptype2 *p2;
rtype r = str->apply(*p1, *p2);
// 8) must define (meta)struct "get_similar" with apply
stype s = strategy::distance::services::get_similar
<
Strategy,
ptype2, ptype1
>::apply(*str);
// 9) must define (meta)struct "get_comparable" with apply
ctype c = strategy::distance::services::get_comparable
<
Strategy
>::apply(*str);
// 10) must define (meta)struct "result_from_distance" with apply
r = strategy::distance::services::result_from_distance
<
Strategy
>::apply(*str, 1.0);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(s);
boost::ignore_unused_variable_warning(c);
boost::ignore_unused_variable_warning(r);
}
};
public :
BOOST_CONCEPT_USAGE(PointDistanceStrategy)
{
checker::apply(&Strategy::apply);
}
#endif
};
/*!
\brief Checks strategy for point-segment-distance
\ingroup strategy_concepts
*/
template <typename Strategy>
struct PointSegmentDistanceStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type ptype;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type sptype;
// 2) check if apply-arguments fulfill point concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<ptype>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<sptype>)
);
// 3) must define meta-function return_type
typedef typename strategy::distance::services::return_type<Strategy>::type rtype;
// 4) must define underlying point-distance-strategy
typedef typename strategy::distance::services::strategy_point_point<Strategy>::type stype;
BOOST_CONCEPT_ASSERT
(
(concept::PointDistanceStrategy<stype>)
);
Strategy *str;
ptype *p;
sptype *sp1;
sptype *sp2;
rtype r = str->apply(*p, *sp1, *sp2);
boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(r);
}
};
public :
BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)
{
checker::apply(&Strategy::apply);
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP

View File

@@ -0,0 +1,78 @@
// 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_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
//NOT FINISHED!
#include <boost/concept_check.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for segment intersection
\ingroup segment_intersection
*/
template <typename Strategy>
class SegmentIntersectStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define return_type
typedef typename Strategy::return_type return_type;
// 2) must define point_type (of segment points)
//typedef typename Strategy::point_type point_type;
// 3) must define segment_type 1 and 2 (of segment points)
typedef typename Strategy::segment_type1 segment_type1;
typedef typename Strategy::segment_type2 segment_type2;
struct check_methods
{
static void apply()
{
Strategy const* str;
return_type* rt;
//point_type const* p;
segment_type1 const* s1;
segment_type2 const* s2;
// 4) must implement a method apply
// having two segments
*rt = str->apply(*s1, *s2);
}
};
public :
BOOST_CONCEPT_USAGE(SegmentIntersectStrategy)
{
check_methods::apply();
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP

View File

@@ -0,0 +1,109 @@
// 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_CONCEPTS_SIMPLIFY_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
#include <vector>
#include <iterator>
#include <boost/concept_check.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for simplify
\ingroup simplify
*/
template <typename Strategy>
struct SimplifyStrategy
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
private :
// 1) must define distance_strategy_type,
// defining point-segment distance strategy (to be checked)
typedef typename Strategy::distance_strategy_type ds_type;
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
namespace ft = boost::function_types;
typedef typename ft::parameter_types
<
ApplyMethod
>::type parameter_types;
typedef typename boost::mpl::if_
<
ft::is_member_function_pointer<ApplyMethod>,
boost::mpl::int_<1>,
boost::mpl::int_<0>
>::type base_index;
// 1: inspect and define both arguments of apply
typedef typename boost::remove_const
<
typename boost::remove_reference
<
typename boost::mpl::at
<
parameter_types,
base_index
>::type
>::type
>::type point_type;
BOOST_CONCEPT_ASSERT
(
(concept::PointSegmentDistanceStrategy<ds_type>)
);
Strategy *str;
std::vector<point_type> const* v1;
std::vector<point_type> * v2;
// 2) must implement method apply with arguments
// - Range
// - OutputIterator
// - floating point value
str->apply(*v1, std::back_inserter(*v2), 1.0);
boost::ignore_unused_variable_warning(str);
}
};
public :
BOOST_CONCEPT_USAGE(SimplifyStrategy)
{
checker::apply(&ds_type::apply);
}
#endif
};
}}} // namespace boost::geometry::concept
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP

View File

@@ -0,0 +1,291 @@
// 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_CONCEPTS_WITHIN_CONCEPT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
#include <boost/concept_check.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/geometry/util/parameter_type_of.hpp>
namespace boost { namespace geometry { namespace concept
{
/*!
\brief Checks strategy for within (point-in-polygon)
\ingroup within
*/
template <typename Strategy>
class WithinStrategyPolygonal
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
// 1) must define state_type
typedef typename Strategy::state_type state_type;
struct checker
{
template <typename ApplyMethod, typename ResultMethod>
static void apply(ApplyMethod const&, ResultMethod const& )
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type point_type;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type segment_point_type;
// CHECK: apply-arguments should both fulfill point concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<point_type>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<segment_point_type>)
);
// CHECK: return types (result: int, apply: bool)
BOOST_MPL_ASSERT_MSG
(
(boost::is_same
<
bool, typename boost::function_types::result_type<ApplyMethod>::type
>::type::value),
WRONG_RETURN_TYPE_OF_APPLY
, (bool)
);
BOOST_MPL_ASSERT_MSG
(
(boost::is_same
<
int, typename boost::function_types::result_type<ResultMethod>::type
>::type::value),
WRONG_RETURN_TYPE_OF_RESULT
, (int)
);
// CHECK: calling method apply and result
Strategy const* str;
state_type* st;
point_type const* p;
segment_point_type const* sp;
bool b = str->apply(*p, *sp, *sp, *st);
int r = str->result(*st);
boost::ignore_unused_variable_warning(r);
boost::ignore_unused_variable_warning(b);
boost::ignore_unused_variable_warning(str);
}
};
public :
BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)
{
checker::apply(&Strategy::apply, &Strategy::result);
}
#endif
};
template <typename Strategy>
class WithinStrategyPointBox
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type point_type;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type box_type;
// CHECK: apply-arguments should fulfill point/box concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstPoint<point_type>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstBox<box_type>)
);
// CHECK: return types (apply: bool)
BOOST_MPL_ASSERT_MSG
(
(boost::is_same
<
bool,
typename boost::function_types::result_type<ApplyMethod>::type
>::type::value),
WRONG_RETURN_TYPE
, (bool)
);
// CHECK: calling method apply
Strategy const* str;
point_type const* p;
box_type const* bx;
bool b = str->apply(*p, *bx);
boost::ignore_unused_variable_warning(b);
boost::ignore_unused_variable_warning(str);
}
};
public :
BOOST_CONCEPT_USAGE(WithinStrategyPointBox)
{
checker::apply(&Strategy::apply);
}
#endif
};
template <typename Strategy>
class WithinStrategyBoxBox
{
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
{
typedef typename parameter_type_of
<
ApplyMethod, 0
>::type box_type1;
typedef typename parameter_type_of
<
ApplyMethod, 1
>::type box_type2;
// CHECK: apply-arguments should both fulfill box concept
BOOST_CONCEPT_ASSERT
(
(concept::ConstBox<box_type1>)
);
BOOST_CONCEPT_ASSERT
(
(concept::ConstBox<box_type2>)
);
// CHECK: return types (apply: bool)
BOOST_MPL_ASSERT_MSG
(
(boost::is_same
<
bool,
typename boost::function_types::result_type<ApplyMethod>::type
>::type::value),
WRONG_RETURN_TYPE
, (bool)
);
// CHECK: calling method apply
Strategy const* str;
box_type1 const* b1;
box_type2 const* b2;
bool b = str->apply(*b1, *b2);
boost::ignore_unused_variable_warning(b);
boost::ignore_unused_variable_warning(str);
}
};
public :
BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)
{
checker::apply(&Strategy::apply);
}
#endif
};
// So now: boost::geometry::concept::within
namespace within
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
struct check_within
{};
template <typename AnyTag, typename Strategy>
struct check_within<point_tag, AnyTag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) );
};
template <typename Strategy>
struct check_within<point_tag, box_tag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Strategy>) );
};
template <typename Strategy>
struct check_within<box_tag, box_tag, areal_tag, Strategy>
{
BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) );
};
} // namespace dispatch
#endif
/*!
\brief Checks, in compile-time, the concept of any within-strategy
\ingroup concepts
*/
template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
inline void check()
{
dispatch::check_within<FirstTag, SecondTag, CastedTag, Strategy> c;
boost::ignore_unused_variable_warning(c);
}
}}}} // namespace boost::geometry::concept::within
#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP

View File

@@ -0,0 +1,42 @@
// 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_CONVEX_HULL_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
/*!
\brief Traits class binding a convex hull calculation strategy to a coordinate system
\ingroup convex_hull
\tparam Tag tag of coordinate system
\tparam Geometry the geometry type (hull operates internally per hull over geometry)
\tparam Point point-type of output points
*/
template <typename Tag, typename Geometry, typename Point>
struct strategy_convex_hull
{
typedef strategy::not_implemented type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP

View File

@@ -0,0 +1,72 @@
// 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_COVERED_BY_HPP
#define BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace covered_by
{
namespace services
{
/*!
\brief Traits class binding a covered_by determination strategy to a coordinate system
\ingroup covered_by
\tparam TagContained tag (possibly casted) of point-type
\tparam TagContained tag (possibly casted) of (possibly) containing type
\tparam CsTagContained tag of coordinate system of point-type
\tparam CsTagContaining tag of coordinate system of (possibly) containing type
\tparam Geometry geometry-type of input (often point, or box)
\tparam GeometryContaining geometry-type of input (possibly) containing type
*/
template
<
typename TagContained,
typename TagContaining,
typename CastedTagContained,
typename CastedTagContaining,
typename CsTagContained,
typename CsTagContaining,
typename GeometryContained,
typename GeometryContaining
>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPES
, (types<GeometryContained, GeometryContaining>)
);
};
} // namespace services
}} // namespace strategy::covered_by
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP

View File

@@ -0,0 +1,51 @@
// 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_DEFAULT_AREA_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function defining return type of area function, using the default strategy
\ingroup area
\note The strategy defines the return-type (so this situation is different
from length, where distance is sqr/sqrt, but length always squared)
*/
template <typename Geometry>
struct default_area_result
{
typedef typename point_type<Geometry>::type point_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type,
point_type
>::type strategy_type;
typedef typename strategy_type::return_type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP

View File

@@ -0,0 +1,50 @@
// 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_DEFAULT_DISTANCE_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function defining return type of distance function
\ingroup distance
\note The strategy defines the return-type (so this situation is different
from length, where distance is sqr/sqrt, but length always squared)
*/
template <typename Geometry1, typename Geometry2 = Geometry1>
struct default_distance_result
{
typedef typename strategy::distance::services::return_type
<
typename strategy::distance::services::default_strategy
<
point_tag,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP

View File

@@ -0,0 +1,46 @@
// 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_DEFAULT_LENGTH_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function defining return type of length function
\ingroup length
\note Length of a line of integer coordinates can be double.
So we take at least a double. If Big Number types are used,
we take that type.
*/
template <typename Geometry>
struct default_length_result
{
typedef typename select_most_precise
<
typename coordinate_type<Geometry>::type,
long double
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP

View File

@@ -0,0 +1,135 @@
// 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_DISTANCE_HPP
#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance { namespace services
{
template <typename Strategy> struct tag {};
template <typename Strategy> struct return_type
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)
);
};
/*!
\brief Metafunction delivering a similar strategy with other input point types
*/
template
<
typename Strategy,
typename Point1,
typename Point2
>
struct similar_type
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY
, (types<Strategy, Point1, Point2>)
);
};
template
<
typename Strategy,
typename Point1,
typename Point2
>
struct get_similar
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY
, (types<Strategy, Point1, Point2>)
);
};
template <typename Strategy> struct comparable_type
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)
);
};
template <typename Strategy> struct get_comparable
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)
);
};
template <typename Strategy> struct result_from_distance {};
// For point-segment only:
template <typename Strategy> struct strategy_point_point {};
// Default strategy
/*!
\brief Traits class binding a default strategy for distance
to one (or possibly two) coordinate system(s)
\ingroup distance
\tparam GeometryTag tag (point/segment) for which this strategy is the default
\tparam Point1 first point-type
\tparam Point2 second point-type
\tparam CsTag1 tag of coordinate system of first point type
\tparam CsTag2 tag of coordinate system of second point type
*/
template
<
typename GeometryTag,
typename Point1,
typename Point2 = Point1,
typename CsTag1 = typename cs_tag<Point1>::type,
typename CsTag2 = typename cs_tag<Point2>::type,
typename UnderlyingStrategy = void
>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE_COMBINATION
, (types<Point1, Point2, CsTag1, CsTag2>)
);
};
}}} // namespace strategy::distance::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP

View File

@@ -0,0 +1,93 @@
// 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_INTERSECTION_HPP
#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/policies/relate/intersection_points.hpp>
#include <boost/geometry/policies/relate/direction.hpp>
#include <boost/geometry/policies/relate/tupled.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
namespace boost { namespace geometry
{
// The intersection strategy is a "compound strategy",
// it contains a segment-intersection-strategy
// and a side-strategy
/*!
\tparam CalculationType \tparam_calculation
*/
template
<
typename Tag,
typename Geometry1,
typename Geometry2,
typename IntersectionPoint,
typename CalculationType = void
>
struct strategy_intersection
{
private :
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
typedef typename model::referring_segment<point1_type const> segment1_type;
typedef typename model::referring_segment<point2_type const> segment2_type;
typedef segment_intersection_points
<
IntersectionPoint
> ip_type;
public:
typedef strategy::intersection::relate_cartesian_segments
<
policies::relate::segments_tupled
<
policies::relate::segments_intersection_points
<
segment1_type,
segment2_type,
ip_type,
CalculationType
> ,
policies::relate::segments_direction
<
segment1_type,
segment2_type,
CalculationType
>,
CalculationType
>,
CalculationType
> segment_intersection_strategy_type;
typedef typename strategy::side::services::default_strategy
<
Tag,
CalculationType
>::type side_strategy_type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP

View File

@@ -0,0 +1,174 @@
// 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_INTERSECTION_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
#if defined(HAVE_MATRIX_AS_STRING)
#include <string>
#endif
#include <cstddef>
namespace boost { namespace geometry
{
/*!
\brief Dimensionally Extended 9 Intersection Matrix
\details
\ingroup overlay
\see http://gis.hsr.ch/wiki/images/3/3d/9dem_springer.pdf
*/
struct de9im
{
int ii, ib, ie,
bi, bb, be,
ei, eb, ee;
inline de9im()
: ii(-1), ib(-1), ie(-1)
, bi(-1), bb(-1), be(-1)
, ei(-1), eb(-1), ee(-1)
{
}
inline de9im(int ii0, int ib0, int ie0,
int bi0, int bb0, int be0,
int ei0, int eb0, int ee0)
: ii(ii0), ib(ib0), ie(ie0)
, bi(bi0), bb(bb0), be(be0)
, ei(ei0), eb(eb0), ee(ee0)
{}
inline bool equals() const
{
return ii >= 0 && ie < 0 && be < 0 && ei < 0 && eb < 0;
}
inline bool disjoint() const
{
return ii < 0 && ib < 0 && bi < 0 && bb < 0;
}
inline bool intersects() const
{
return ii >= 0 || bb >= 0 || bi >= 0 || ib >= 0;
}
inline bool touches() const
{
return ii < 0 && (bb >= 0 || bi >= 0 || ib >= 0);
}
inline bool crosses() const
{
return (ii >= 0 && ie >= 0) || (ii == 0);
}
inline bool overlaps() const
{
return ii >= 0 && ie >= 0 && ei >= 0;
}
inline bool within() const
{
return ii >= 0 && ie < 0 && be < 0;
}
inline bool contains() const
{
return ii >= 0 && ei < 0 && eb < 0;
}
static inline char as_char(int v)
{
return v >= 0 && v < 10 ? ('0' + char(v)) : '-';
}
#if defined(HAVE_MATRIX_AS_STRING)
inline std::string matrix_as_string(std::string const& tab, std::string const& nl) const
{
std::string ret;
ret.reserve(9 + tab.length() * 3 + nl.length() * 3);
ret += tab; ret += as_char(ii); ret += as_char(ib); ret += as_char(ie); ret += nl;
ret += tab; ret += as_char(bi); ret += as_char(bb); ret += as_char(be); ret += nl;
ret += tab; ret += as_char(ei); ret += as_char(eb); ret += as_char(ee);
return ret;
}
inline std::string matrix_as_string() const
{
return matrix_as_string("", "");
}
#endif
};
struct de9im_segment : public de9im
{
bool collinear; // true if segments are aligned (for equal,overlap,touch)
bool opposite; // true if direction is reversed (for equal,overlap,touch)
bool parallel; // true if disjoint but parallel
bool degenerate; // true for segment(s) of zero length
double ra, rb; // temp
inline de9im_segment()
: de9im()
, collinear(false)
, opposite(false)
, parallel(false)
, degenerate(false)
{}
inline de9im_segment(double a, double b,
int ii0, int ib0, int ie0,
int bi0, int bb0, int be0,
int ei0, int eb0, int ee0,
bool c = false, bool o = false, bool p = false, bool d = false)
: de9im(ii0, ib0, ie0, bi0, bb0, be0, ei0, eb0, ee0)
, collinear(c)
, opposite(o)
, parallel(p)
, degenerate(d)
, ra(a), rb(b)
{}
#if defined(HAVE_MATRIX_AS_STRING)
inline std::string as_string() const
{
std::string ret = matrix_as_string();
ret += collinear ? "c" : "-";
ret += opposite ? "o" : "-";
return ret;
}
#endif
};
template <typename Point>
struct segment_intersection_points
{
std::size_t count;
Point intersections[2];
typedef Point point_type;
segment_intersection_points()
: count(0)
{}
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP

View File

@@ -0,0 +1,55 @@
// 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_SIDE_HPP
#define BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
namespace services
{
/*!
\brief Traits class binding a side determination strategy to a coordinate system
\ingroup util
\tparam Tag tag of coordinate system of point-type
\tparam CalculationType \tparam_calculation
*/
template <typename Tag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPE
, (types<Tag>)
);
};
} // namespace services
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_HPP

View File

@@ -0,0 +1,93 @@
// 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_SIDE_INFO_HPP
#define BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
#include <utility>
namespace boost { namespace geometry
{
/*!
\brief Class side_info: small class wrapping for sides (-1,0,1)
*/
class side_info
{
public :
inline side_info(int side_a1 = 0, int side_a2 = 0,
int side_b1 = 0, int side_b2 = 0)
{
sides[0].first = side_a1;
sides[0].second = side_a2;
sides[1].first = side_b1;
sides[1].second = side_b2;
}
template <int Which>
inline void set(int first, int second)
{
sides[Which].first = first;
sides[Which].second = second;
}
template <int Which, int Index>
inline int get() const
{
return Index == 0 ? sides[Which].first : sides[Which].second;
}
// Returns true if both lying on the same side WRT the other
// (so either 1,1 or -1-1)
template <int Which>
inline bool same() const
{
return sides[Which].first * sides[Which].second == 1;
}
inline bool collinear() const
{
return sides[0].first == 0
&& sides[0].second == 0
&& sides[1].first == 0
&& sides[1].second == 0;
}
// If one of the segments is collinear, the other must be as well.
// So handle it as collinear.
// (In floating point margins it can occur that one of them is 1!)
inline bool as_collinear() const
{
return sides[0].first * sides[0].second == 0
|| sides[1].first * sides[1].second == 0;
}
inline void reverse()
{
std::swap(sides[0], sides[1]);
}
private :
std::pair<int, int> sides[2];
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP

View File

@@ -0,0 +1,202 @@
// 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_SPHERICAL_AREA_HUILLER_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Area calculation by spherical excess / Huiller's formula
\ingroup strategies
\tparam PointOfSegment point type of segments of rings/polygons
\tparam CalculationType \tparam_calculation
\author Barend Gehrels. Adapted from:
- http://www.soe.ucsc.edu/~pang/160/f98/Gems/GemsIV/sph_poly.c
- http://williams.best.vwh.net/avform.htm
\note The version in Gems didn't account for polygons crossing the 180 meridian.
\note This version works for convex and non-convex polygons, for 180 meridian
crossing polygons and for polygons with holes. However, some cases (especially
180 meridian cases) must still be checked.
\note The version which sums angles, which is often seen, doesn't handle non-convex
polygons correctly.
\note The version which sums longitudes, see
http://trs-new.jpl.nasa.gov/dspace/bitstream/2014/40409/1/07-03.pdf, is simple
and works well in most cases but not in 180 meridian crossing cases. This probably
could be solved.
\note This version is made for spherical equatorial coordinate systems
\qbk{
[heading Example]
[area_with_strategy]
[area_with_strategy_output]
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
}
*/
template
<
typename PointOfSegment,
typename CalculationType = void
>
class huiller
{
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 calculation_type;
protected :
struct excess_sum
{
calculation_type sum;
// Distances are calculated on unit sphere here
strategy::distance::haversine<PointOfSegment, PointOfSegment>
distance_over_unit_sphere;
inline excess_sum()
: sum(0)
, distance_over_unit_sphere(1)
{}
inline calculation_type area(calculation_type radius) const
{
return - sum * radius * radius;
}
};
public :
typedef calculation_type return_type;
typedef PointOfSegment segment_point_type;
typedef excess_sum state_type;
inline huiller(calculation_type radius = 1.0)
: m_radius(radius)
{}
inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
excess_sum& state) const
{
if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
{
calculation_type const half = 0.5;
calculation_type const two = 2.0;
calculation_type const four = 4.0;
calculation_type const two_pi = two * geometry::math::pi<calculation_type>();
calculation_type const half_pi = half * geometry::math::pi<calculation_type>();
// Distance p1 p2
calculation_type a = state.distance_over_unit_sphere.apply(p1, p2);
// Sides on unit sphere to south pole
calculation_type b = half_pi - geometry::get_as_radian<1>(p2);
calculation_type c = half_pi - geometry::get_as_radian<1>(p1);
// Semi parameter
calculation_type s = half * (a + b + c);
// E: spherical excess, using l'Huiller's formula
// [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2]
calculation_type E = four * atan(sqrt(geometry::math::abs(tan(s / two)
* tan((s - a) / two)
* tan((s - b) / two)
* tan((s - c) / two))));
E = geometry::math::abs(E);
// In right direction: positive, add area. In left direction: negative, subtract area.
// Longitude comparisons are not so obvious. If one is negative, other is positive,
// we have to take the dateline into account.
// TODO: check this / enhance this, should be more robust. See also the "grow" for ll
// TODO: use minmax or "smaller"/"compare" strategy for this
calculation_type lon1 = geometry::get_as_radian<0>(p1) < 0
? geometry::get_as_radian<0>(p1) + two_pi
: geometry::get_as_radian<0>(p1);
calculation_type lon2 = geometry::get_as_radian<0>(p2) < 0
? geometry::get_as_radian<0>(p2) + two_pi
: geometry::get_as_radian<0>(p2);
if (lon2 < lon1)
{
E = -E;
}
state.sum += E;
}
}
inline return_type result(excess_sum const& state) const
{
return state.area(m_radius);
}
private :
/// Radius of the sphere
calculation_type m_radius;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point>
struct default_strategy<spherical_equatorial_tag, Point>
{
typedef strategy::area::huiller<Point> type;
};
// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
/***template <typename Point>
struct default_strategy<spherical_polar_tag, Point>
{
typedef strategy::area::huiller<Point> type;
};***/
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP

View File

@@ -0,0 +1,152 @@
// 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_SPHERICAL_COMPARE_SPHERICAL_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
#include <boost/math/constants/constants.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace compare
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Units>
struct shift
{
};
template <>
struct shift<degree>
{
static inline double full() { return 360.0; }
static inline double half() { return 180.0; }
};
template <>
struct shift<radian>
{
static inline double full() { return 2.0 * boost::math::constants::pi<double>(); }
static inline double half() { return boost::math::constants::pi<double>(); }
};
} // namespace detail
#endif
/*!
\brief Compare (in one direction) strategy for spherical coordinates
\ingroup strategies
\tparam Point point-type
\tparam Dimension dimension
*/
template <typename CoordinateType, typename Units, typename Compare>
struct circular_comparator
{
static inline CoordinateType put_in_range(CoordinateType const& c,
double min_border, double max_border)
{
CoordinateType value = c;
while (value < min_border)
{
value += detail::shift<Units>::full();
}
while (value > max_border)
{
value -= detail::shift<Units>::full();
}
return value;
}
inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const
{
Compare compare;
// Check situation that one of them is e.g. std::numeric_limits.
static const double full = detail::shift<Units>::full();
double mx = 10.0 * full;
if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)
{
// do normal comparison, using circular is not useful
return compare(c1, c2);
}
static const double half = full / 2.0;
CoordinateType v1 = put_in_range(c1, -half, half);
CoordinateType v2 = put_in_range(c2, -half, half);
// Two coordinates on a circle are
// at max <= half a circle away from each other.
// So if it is more, shift origin.
CoordinateType diff = geometry::math::abs(v1 - v2);
if (diff > half)
{
v1 = put_in_range(v1, 0, full);
v2 = put_in_range(v2, 0, full);
}
return compare(v1, v2);
}
};
}} // namespace strategy::compare
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
// Specialize for the longitude (dim 0)
template
<
typename Point,
template<typename> class CoordinateSystem,
typename Units
>
struct strategy_compare<spherical_polar_tag, 1, Point, CoordinateSystem<Units>, 0>
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef strategy::compare::circular_comparator
<
coordinate_type,
Units,
std::less<coordinate_type>
> type;
};
template
<
typename Point,
template<typename> class CoordinateSystem,
typename Units
>
struct strategy_compare<spherical_polar_tag, -1, Point, CoordinateSystem<Units>, 0>
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef strategy::compare::circular_comparator
<
coordinate_type,
Units,
std::greater<coordinate_type>
> type;
};
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP

View File

@@ -0,0 +1,349 @@
// 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_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/math.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
# include <boost/geometry/util/write_dsv.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy functor for distance point to segment calculation
\ingroup strategies
\details Class which calculates the distance of a point to a segment, using latlong points
\see http://williams.best.vwh.net/avform.htm
\tparam Point point type
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\tparam Strategy underlying point-point distance strategy, defaults to haversine
\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 = typename services::default_strategy<point_tag, Point>::type
>
class cross_track
{
public :
typedef typename promote_floating_point
<
typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type
>::type return_type;
inline cross_track()
{
m_strategy = Strategy();
m_radius = m_strategy.radius();
}
inline cross_track(return_type const& r)
: m_radius(r)
, m_strategy(r)
{}
inline cross_track(Strategy const& s)
: m_strategy(s)
{
m_radius = m_strategy.radius();
}
// It might be useful in the future
// to overload constructor with strategy info.
// crosstrack(...) {}
inline return_type apply(Point const& p,
PointOfSegment const& sp1, PointOfSegment const& sp2) const
{
// http://williams.best.vwh.net/avform.htm#XTE
return_type d1 = m_strategy.apply(sp1, p);
// Actually, calculation of d2 not necessary if we know that the projected point is on the great circle...
return_type d2 = m_strategy.apply(sp2, p);
return_type crs_AD = course(sp1, p);
return_type crs_AB = course(sp1, sp2);
return_type XTD = m_radius * geometry::math::abs(asin(sin(d1 / m_radius) * sin(crs_AD - crs_AB)));
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl;
std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl;
std::cout << "XTD: " << XTD << " d1: " << d1 << " d2: " << d2 << std::endl;
#endif
// Return shortest distance, either to projected point on segment sp1-sp2, or to sp1, or to sp2
return return_type((std::min)((std::min)(d1, d2), XTD));
}
inline return_type radius() const { return m_radius; }
private :
BOOST_CONCEPT_ASSERT
(
(geometry::concept::PointDistanceStrategy<Strategy >)
);
return_type m_radius;
// Point-point distances are calculated in radians, on the unit sphere
Strategy m_strategy;
/// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
inline return_type course(Point const& p1, Point const& p2) const
{
// http://williams.best.vwh.net/avform.htm#Crs
return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
return_type cos_p2lat = cos(get_as_radian<1>(p2));
// "An alternative formula, not requiring the pre-computation of d"
return atan2(sin(dlon) * cos_p2lat,
cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct tag<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_segment type;
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct return_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type type;
};
template
<
typename Point,
typename PointOfSegment,
typename CalculationType,
typename Strategy,
typename P,
typename PS
>
struct similar_type<cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS>
{
typedef cross_track<Point, PointOfSegment, CalculationType, Strategy> type;
};
template
<
typename Point,
typename PointOfSegment,
typename CalculationType,
typename Strategy,
typename P,
typename PS
>
struct get_similar<cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS>
{
static inline typename similar_type
<
cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS
>::type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy)
{
return cross_track<P, PS, CalculationType, Strategy>(strategy.radius());
}
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
struct comparable_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
{
// Comparable type is here just the strategy
typedef typename similar_type
<
cross_track
<
Point, PointOfSegment, CalculationType, Strategy
>, Point, PointOfSegment
>::type type;
};
template
<
typename Point, typename PointOfSegment,
typename CalculationType,
typename Strategy
>
struct get_comparable<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef typename comparable_type
<
cross_track<Point, PointOfSegment, CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy)
{
return comparable_type(strategy.radius());
}
};
template
<
typename Point, typename PointOfSegment,
typename CalculationType,
typename Strategy
>
struct result_from_distance<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
{
private :
typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type return_type;
public :
template <typename T>
static inline return_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& , T const& distance)
{
return distance;
}
};
template
<
typename Point, typename PointOfSegment,
typename CalculationType,
typename Strategy
>
struct strategy_point_point<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
{
typedef Strategy type;
};
/*
TODO: spherical polar coordinate system requires "get_as_radian_equatorial<>"
template <typename Point, typename PointOfSegment, typename Strategy>
struct default_strategy
<
segment_tag, Point, PointOfSegment,
spherical_polar_tag, spherical_polar_tag,
Strategy
>
{
typedef cross_track
<
Point,
PointOfSegment,
void,
typename boost::mpl::if_
<
boost::is_void<Strategy>,
typename default_strategy
<
point_tag, Point, PointOfSegment,
spherical_polar_tag, spherical_polar_tag
>::type,
Strategy
>::type
> type;
};
*/
template <typename Point, typename PointOfSegment, typename Strategy>
struct default_strategy
<
segment_tag, Point, PointOfSegment,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
>
{
typedef cross_track
<
Point,
PointOfSegment,
void,
typename boost::mpl::if_
<
boost::is_void<Strategy>,
typename default_strategy
<
point_tag, Point, PointOfSegment,
spherical_equatorial_tag, spherical_equatorial_tag
>::type,
Strategy
>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP

View File

@@ -0,0 +1,330 @@
// 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_SPHERICAL_DISTANCE_HAVERSINE_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/strategies/distance.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
namespace comparable
{
// Comparable haversine.
// To compare distances, we can avoid:
// - multiplication with radius and 2.0
// - applying sqrt
// - applying asin (which is strictly (monotone) increasing)
template
<
typename Point1,
typename Point2 = Point1,
typename CalculationType = void
>
class haversine
{
public :
typedef typename promote_floating_point
<
typename select_calculation_type
<
Point1,
Point2,
CalculationType
>::type
>::type calculation_type;
inline haversine(calculation_type const& r = 1.0)
: m_radius(r)
{}
static inline calculation_type apply(Point1 const& p1, Point2 const& p2)
{
return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
get_as_radian<0>(p2), get_as_radian<1>(p2));
}
inline calculation_type radius() const
{
return m_radius;
}
private :
static inline calculation_type calculate(calculation_type const& lon1,
calculation_type const& lat1,
calculation_type const& lon2,
calculation_type const& lat2)
{
return math::hav(lat2 - lat1)
+ cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
}
calculation_type m_radius;
};
} // namespace comparable
/*!
\brief Distance calculation for spherical coordinates
on a perfect sphere using haversine
\ingroup strategies
\tparam Point1 \tparam_first_point
\tparam Point2 \tparam_second_point
\tparam CalculationType \tparam_calculation
\author Adapted from: http://williams.best.vwh.net/avform.htm
\see http://en.wikipedia.org/wiki/Great-circle_distance
\note It says: <em>The great circle distance d between two
points with coordinates {lat1,lon1} and {lat2,lon2} is given by:
d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))
A mathematically equivalent formula, which is less subject
to rounding error for short distances is:
d=2*asin(sqrt((sin((lat1-lat2)/2))^2
+ cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2))
</em>
\qbk{
[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 haversine
{
typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type;
public :
typedef typename services::return_type<comparable_type>::type calculation_type;
/*!
\brief Constructor
\param radius radius of the sphere, defaults to 1.0 for the unit sphere
*/
inline haversine(calculation_type const& radius = 1.0)
: m_radius(radius)
{}
/*!
\brief applies the distance calculation
\return the calculated distance (including multiplying with radius)
\param p1 first point
\param p2 second point
*/
inline calculation_type apply(Point1 const& p1, Point2 const& p2) const
{
calculation_type const a = comparable_type::apply(p1, p2);
calculation_type const c = calculation_type(2.0) * asin(sqrt(a));
return m_radius * c;
}
/*!
\brief access to radius value
\return the radius
*/
inline calculation_type radius() const
{
return m_radius;
}
private :
calculation_type m_radius;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point1, typename Point2, typename CalculationType>
struct tag<haversine<Point1, Point2, CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct return_type<haversine<Point1, Point2, CalculationType> >
{
typedef typename haversine<Point1, Point2, CalculationType>::calculation_type type;
};
template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
struct similar_type<haversine<Point1, Point2, CalculationType>, P1, P2>
{
typedef haversine<P1, P2, CalculationType> type;
};
template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
struct get_similar<haversine<Point1, Point2, CalculationType>, P1, P2>
{
private :
typedef haversine<Point1, Point2, CalculationType> this_type;
public :
static inline typename similar_type<this_type, P1, P2>::type apply(this_type const& input)
{
return haversine<P1, P2, CalculationType>(input.radius());
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct comparable_type<haversine<Point1, Point2, CalculationType> >
{
typedef comparable::haversine<Point1, Point2, CalculationType> type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct get_comparable<haversine<Point1, Point2, CalculationType> >
{
private :
typedef haversine<Point1, Point2, CalculationType> this_type;
typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type;
public :
static inline comparable_type apply(this_type const& input)
{
return comparable_type(input.radius());
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct result_from_distance<haversine<Point1, Point2, CalculationType> >
{
private :
typedef haversine<Point1, Point2, CalculationType> this_type;
typedef typename return_type<this_type>::type return_type;
public :
template <typename T>
static inline return_type apply(this_type const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::haversine
template <typename Point1, typename Point2, typename CalculationType>
struct tag<comparable::haversine<Point1, Point2, CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct return_type<comparable::haversine<Point1, Point2, CalculationType> >
{
typedef typename comparable::haversine<Point1, Point2, CalculationType>::calculation_type type;
};
template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
struct similar_type<comparable::haversine<Point1, Point2, CalculationType>, P1, P2>
{
typedef comparable::haversine<P1, P2, CalculationType> type;
};
template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
struct get_similar<comparable::haversine<Point1, Point2, CalculationType>, P1, P2>
{
private :
typedef comparable::haversine<Point1, Point2, CalculationType> this_type;
public :
static inline typename similar_type<this_type, P1, P2>::type apply(this_type const& input)
{
return comparable::haversine<P1, P2, CalculationType>(input.radius());
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct comparable_type<comparable::haversine<Point1, Point2, CalculationType> >
{
typedef comparable::haversine<Point1, Point2, CalculationType> type;
};
template <typename Point1, typename Point2, typename CalculationType>
struct get_comparable<comparable::haversine<Point1, Point2, CalculationType> >
{
private :
typedef comparable::haversine<Point1, Point2, CalculationType> this_type;
public :
static inline this_type apply(this_type const& input)
{
return input;
}
};
template <typename Point1, typename Point2, typename CalculationType>
struct result_from_distance<comparable::haversine<Point1, Point2, CalculationType> >
{
private :
typedef comparable::haversine<Point1, Point2, CalculationType> strategy_type;
typedef typename return_type<strategy_type>::type return_type;
public :
template <typename T>
static inline return_type apply(strategy_type const& strategy, T const& distance)
{
return_type const s = sin((distance / strategy.radius()) / return_type(2));
return s * s;
}
};
// Register it as the default for point-types
// in a spherical equatorial coordinate system
template <typename Point1, typename Point2>
struct default_strategy<point_tag, Point1, Point2, spherical_equatorial_tag, spherical_equatorial_tag>
{
typedef strategy::distance::haversine<Point1, Point2> type;
};
// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP

View File

@@ -0,0 +1,100 @@
// 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_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/side.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
template <typename Point>
static inline double course(Point const& p1, Point const& p2)
{
// http://williams.best.vwh.net/avform.htm#Crs
double dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
double cos_p2lat = cos(get_as_radian<1>(p2));
// "An alternative formula, not requiring the pre-computation of d"
return atan2(sin(dlon) * cos_p2lat,
cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
}
}
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Check at which side of a Great Circle 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_cross_track
{
public :
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;
double d1 = 0.001; // m_strategy.apply(sp1, p);
double crs_AD = detail::course(p1, p);
double crs_AB = detail::course(p1, p2);
double XTD = asin(sin(d1) * sin(crs_AD - crs_AB));
return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;
}
};
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP

View File

@@ -0,0 +1,136 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 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_SPHERICAL_SSF_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/side.hpp>
//#include <boost/geometry/strategies/concepts/side_concept.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
/*!
\brief Check at which side of a Great Circle 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 spherical_side_formula
{
public :
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,
// Select at least a double...
typename select_most_precise
<
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,
double
>::type,
CalculationType
>::type coordinate_type;
// Convenient shortcuts
typedef coordinate_type ct;
ct const lambda1 = get_as_radian<0>(p1);
ct const delta1 = get_as_radian<1>(p1);
ct const lambda2 = get_as_radian<0>(p2);
ct const delta2 = get_as_radian<1>(p2);
ct const lambda = get_as_radian<0>(p);
ct const delta = get_as_radian<1>(p);
// Create temporary points (vectors) on unit a sphere
ct const cos_delta1 = cos(delta1);
ct const c1x = cos_delta1 * cos(lambda1);
ct const c1y = cos_delta1 * sin(lambda1);
ct const c1z = sin(delta1);
ct const cos_delta2 = cos(delta2);
ct const c2x = cos_delta2 * cos(lambda2);
ct const c2y = cos_delta2 * sin(lambda2);
ct const c2z = sin(delta2);
// (Third point is converted directly)
ct const cos_delta = cos(delta);
// Apply the "Spherical Side Formula" as presented on my blog
ct const dist
= (c1y * c2z - c1z * c2y) * cos_delta * cos(lambda)
+ (c1z * c2x - c1x * c2z) * cos_delta * sin(lambda)
+ (c1x * c2y - c1y * c2x) * sin(delta);
ct zero = ct();
return dist > zero ? 1
: dist < zero ? -1
: 0;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
/*template <typename CalculationType>
struct default_strategy<spherical_polar_tag, CalculationType>
{
typedef spherical_side_formula<CalculationType> type;
};*/
template <typename CalculationType>
struct default_strategy<spherical_equatorial_tag, CalculationType>
{
typedef spherical_side_formula<CalculationType> type;
};
template <typename CalculationType>
struct default_strategy<geographic_tag, CalculationType>
{
typedef spherical_side_formula<CalculationType> type;
};
}
#endif
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP

View File

@@ -0,0 +1,59 @@
// 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_STRATEGIES_HPP
#define BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/transform.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/area_huiller.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/compare_circular.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/agnostic/hull_graham_andrew.hpp>
#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
#include <boost/geometry/strategies/transform/map_transformer.hpp>
#include <boost/geometry/strategies/transform/inverse_transformer.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP

View File

@@ -0,0 +1,470 @@
// 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_STRATEGY_TRANSFORM_HPP
#define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
#include <cstddef>
#include <cmath>
#include <functional>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace transform
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Src, typename Dst,
std::size_t D, std::size_t N,
template <typename> class F
>
struct transform_coordinates
{
template <typename T>
static inline void transform(Src const& source, Dst& dest, T value)
{
typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;
F<coordinate_type> function;
set<D>(dest, boost::numeric_cast<coordinate_type>(function(get<D>(source), value)));
transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);
}
};
template
<
typename Src, typename Dst,
std::size_t N,
template <typename> class F
>
struct transform_coordinates<Src, Dst, N, N, F>
{
template <typename T>
static inline void transform(Src const& source, Dst& dest, T value)
{
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Transformation strategy to copy one point to another using assignment operator
\ingroup transform
\tparam P point type
*/
template <typename P>
struct copy_direct
{
inline bool apply(P const& p1, P& p2) const
{
p2 = p1;
return true;
}
};
/*!
\brief Transformation strategy to do copy a point, copying per coordinate.
\ingroup transform
\tparam P1 first point type
\tparam P2 second point type
*/
template <typename P1, typename P2>
struct copy_per_coordinate
{
inline bool apply(P1 const& p1, P2& p2) const
{
// Defensive check, dimensions are equal, selected by specialization
assert_dimension_equal<P1, P2>();
geometry::convert(p1, p2);
return true;
}
};
/*!
\brief Transformation strategy to go from degree to radian and back
\ingroup transform
\tparam P1 first point type
\tparam P2 second point type
\tparam F additional functor to divide or multiply with d2r
*/
template <typename P1, typename P2, template <typename> class F>
struct degree_radian_vv
{
inline bool apply(P1 const& p1, P2& p2) const
{
// Spherical coordinates always have 2 coordinates measured in angles
// The optional third one is distance/height, provided in another strategy
// Polar coordinates having one angle, will be also in another strategy
assert_dimension<P1, 2>();
assert_dimension<P2, 2>();
detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
return true;
}
};
template <typename P1, typename P2, template <typename> class F>
struct degree_radian_vv_3
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 3>();
assert_dimension<P2, 3>();
detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
// Copy height or other third dimension
set<2>(p2, get<2>(p1));
return true;
}
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/// Helper function for conversion, phi/theta are in radians
template <typename P, typename T, typename R>
inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p)
{
assert_dimension<P, 3>();
// http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates
// http://www.vias.org/comp_geometry/math_coord_convert_3d.htm
// https://moodle.polymtl.ca/file.php/1183/Autres_Documents/Derivation_for_Spherical_Co-ordinates.pdf
// http://en.citizendium.org/wiki/Spherical_polar_coordinates
// Phi = first, theta is second, r is third, see documentation on cs::spherical
// (calculations are splitted to implement ttmath)
T r_sin_theta = r;
T r_cos_theta = r;
r_sin_theta *= sin(theta);
r_cos_theta *= cos(theta);
set<0>(p, r_sin_theta * cos(phi));
set<1>(p, r_sin_theta * sin(phi));
set<2>(p, r_cos_theta);
}
/// Helper function for conversion, lambda/delta (lon lat) are in radians
template <typename P, typename T, typename R>
inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p)
{
assert_dimension<P, 3>();
// http://mathworld.wolfram.com/GreatCircle.html
// http://www.spenvis.oma.be/help/background/coortran/coortran.html WRONG
T r_cos_delta = r;
T r_sin_delta = r;
r_cos_delta *= cos(delta);
r_sin_delta *= sin(delta);
set<0>(p, r_cos_delta * cos(lambda));
set<1>(p, r_cos_delta * sin(lambda));
set<2>(p, r_sin_delta);
}
/// Helper function for conversion
template <typename P, typename T>
inline bool cartesian_to_spherical2(T x, T y, T z, P& p)
{
assert_dimension<P, 2>();
// http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
#if defined(BOOST_GEOMETRY_TRANSFORM_CHECK_UNIT_SPHERE)
// TODO: MAYBE ONLY IF TO BE CHECKED?
T const r = /*sqrt not necessary, sqrt(1)=1*/ (x * x + y * y + z * z);
// Unit sphere, so r should be 1
if (geometry::math::abs(r - 1.0) > T(1e-6))
{
return false;
}
// end todo
#endif
set_from_radian<0>(p, atan2(y, x));
set_from_radian<1>(p, acos(z));
return true;
}
template <typename P, typename T>
inline bool cartesian_to_spherical_equatorial2(T x, T y, T z, P& p)
{
assert_dimension<P, 2>();
set_from_radian<0>(p, atan2(y, x));
set_from_radian<1>(p, asin(z));
return true;
}
template <typename P, typename T>
inline bool cartesian_to_spherical3(T x, T y, T z, P& p)
{
assert_dimension<P, 3>();
// http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
T const r = sqrt(x * x + y * y + z * z);
set<2>(p, r);
set_from_radian<0>(p, atan2(y, x));
if (r > 0.0)
{
set_from_radian<1>(p, acos(z / r));
return true;
}
return false;
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Transformation strategy for 2D spherical (phi,theta) to 3D cartesian (x,y,z)
\details on Unit sphere
\ingroup transform
\tparam P1 first point type
\tparam P2 second point type
*/
template <typename P1, typename P2>
struct from_spherical_polar_2_to_cartesian_3
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 2>();
detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
return true;
}
};
template <typename P1, typename P2>
struct from_spherical_equatorial_2_to_cartesian_3
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 2>();
detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
return true;
}
};
/*!
\brief Transformation strategy for 3D spherical (phi,theta,r) to 3D cartesian (x,y,z)
\ingroup transform
\tparam P1 first point type
\tparam P2 second point type
*/
template <typename P1, typename P2>
struct from_spherical_polar_3_to_cartesian_3
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 3>();
detail::spherical_polar_to_cartesian(
get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
return true;
}
};
template <typename P1, typename P2>
struct from_spherical_equatorial_3_to_cartesian_3
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 3>();
detail::spherical_equatorial_to_cartesian(
get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
return true;
}
};
/*!
\brief Transformation strategy for 3D cartesian (x,y,z) to 2D spherical (phi,theta)
\details on Unit sphere
\ingroup transform
\tparam P1 first point type
\tparam P2 second point type
\note If x,y,z point is not lying on unit sphere, transformation will return false
*/
template <typename P1, typename P2>
struct from_cartesian_3_to_spherical_polar_2
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 3>();
return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
}
};
template <typename P1, typename P2>
struct from_cartesian_3_to_spherical_equatorial_2
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 3>();
return detail::cartesian_to_spherical_equatorial2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
}
};
/*!
\brief Transformation strategy for 3D cartesian (x,y,z) to 3D spherical (phi,theta,r)
\ingroup transform
\tparam P1 first point type
\tparam P2 second point type
*/
template <typename P1, typename P2>
struct from_cartesian_3_to_spherical_polar_3
{
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension<P1, 3>();
return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
/// Specialization for same coordinate system family, same system, same dimension, same point type, can be copied
template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>
struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>
{
typedef copy_direct<P> type;
};
/// Specialization for same coordinate system family and system, same dimension, different point type, copy per coordinate
template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>
struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>
{
typedef copy_per_coordinate<P1, P2> type;
};
/// Specialization to transform from degree to radian for any coordinate system / point type combination
template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>
{
typedef degree_radian_vv<P1, P2, std::multiplies> type;
};
/// Specialization to transform from radian to degree for any coordinate system / point type combination
template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>
{
typedef degree_radian_vv<P1, P2, std::divides> type;
};
/// Specialization degree->radian in 3D
template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>
{
typedef degree_radian_vv_3<P1, P2, std::multiplies> type;
};
/// Specialization radian->degree in 3D
template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>
{
typedef degree_radian_vv_3<P1, P2, std::divides> type;
};
/// Specialization to transform from unit sphere(phi,theta) to XYZ
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
{
typedef from_spherical_polar_2_to_cartesian_3<P1, P2> type;
};
/// Specialization to transform from sphere(phi,theta,r) to XYZ
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
{
typedef from_spherical_polar_3_to_cartesian_3<P1, P2> type;
};
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
{
typedef from_spherical_equatorial_2_to_cartesian_3<P1, P2> type;
};
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
{
typedef from_spherical_equatorial_3_to_cartesian_3<P1, P2> type;
};
/// Specialization to transform from XYZ to unit sphere(phi,theta)
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
{
typedef from_cartesian_3_to_spherical_polar_2<P1, P2> type;
};
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
{
typedef from_cartesian_3_to_spherical_equatorial_2<P1, P2> type;
};
/// Specialization to transform from XYZ to sphere(phi,theta,r)
template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
{
typedef from_cartesian_3_to_spherical_polar_3<P1, P2> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::transform
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP

View File

@@ -0,0 +1,41 @@
// 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_TAGS_HPP
#define BOOST_GEOMETRY_STRATEGIES_TAGS_HPP
namespace boost { namespace geometry
{
namespace strategy
{
/*!
\brief Indicate compiler/library user that strategy is not implemented.
\details Strategies are defined for point types or for point type
combinations. If there is no implementation for that specific point type, or point type
combination, the calculation cannot be done. To indicate this, this not_implemented
class is used as a typedef stub.
*/
struct not_implemented {};
}
struct strategy_tag_distance_point_point {};
struct strategy_tag_distance_point_segment {};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_TAGS_HPP

View File

@@ -0,0 +1,63 @@
// 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_TRANSFORM_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace transform { namespace services
{
/*!
\brief Traits class binding a transformation strategy to a coordinate system
\ingroup transform
\details Can be specialized
- per coordinate system family (tag)
- per coordinate system (or groups of them)
- per dimension
- per point type
\tparam CoordinateSystemTag 1,2 coordinate system tags
\tparam CoordinateSystem 1,2 coordinate system
\tparam D 1, 2 dimension
\tparam Point 1, 2 point type
*/
template
<
typename CoordinateSystemTag1, typename CoordinateSystemTag2,
typename CoordinateSystem1, typename CoordinateSystem2,
std::size_t Dimension1, std::size_t Dimension2,
typename Point1, typename Point2
>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPES
, (types<Point1, Point2>)
);
};
}}} // namespace strategy::transform::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP

View File

@@ -0,0 +1,78 @@
// 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_TRANSFORM_INVERSE_TRANSFORMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
// Remove the ublas checking, otherwise the inverse might fail
// (while nothing seems to be wrong)
#define BOOST_UBLAS_TYPE_CHECK 0
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace transform
{
/*!
\brief Transformation strategy to do an inverse ransformation in Cartesian system
\ingroup strategies
\tparam P1 first point type
\tparam P2 second point type
*/
template <typename P1, typename P2>
class inverse_transformer
: public ublas_transformer<P1, P2, dimension<P1>::type::value, dimension<P2>::type::value>
{
typedef typename select_coordinate_type<P1, P2>::type T;
public :
template <typename Transformer>
inline inverse_transformer(Transformer const& input)
{
typedef boost::numeric::ublas::matrix<T> matrix_type;
// create a working copy of the input
matrix_type copy(input.matrix());
// create a permutation matrix for the LU-factorization
typedef boost::numeric::ublas::permutation_matrix<> permutation_matrix;
permutation_matrix pm(copy.size1());
// perform LU-factorization
int res = boost::numeric::ublas::lu_factorize<matrix_type>(copy, pm);
if( res == 0 )
{
// create identity matrix
this->m_matrix.assign(boost::numeric::ublas::identity_matrix<T>(copy.size1()));
// backsubstitute to get the inverse
boost::numeric::ublas::lu_substitute(copy, pm, this->m_matrix);
}
}
};
}} // namespace strategy::transform
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP

View File

@@ -0,0 +1,165 @@
// 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_TRANSFORM_MAP_TRANSFORMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
#include <cstddef>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace transform
{
/*!
\brief Transformation strategy to do map from one to another Cartesian system
\ingroup strategies
\tparam P1 first point type
\tparam P2 second point type
\tparam Mirror if true map is mirrored upside-down (in most cases pixels
are from top to bottom, while map is from bottom to top)
*/
template
<
typename P1, typename P2,
bool Mirror = false, bool SameScale = true,
std::size_t Dimension1 = dimension<P1>::type::value,
std::size_t Dimension2 = dimension<P2>::type::value
>
class map_transformer
: public ublas_transformer<P1, P2, Dimension1, Dimension2>
{
typedef typename select_coordinate_type<P1, P2>::type T;
typedef boost::numeric::ublas::matrix<T> M;
public :
template <typename B, typename D>
explicit inline map_transformer(B const& box, D const& width, D const& height)
{
set_transformation(
get<min_corner, 0>(box), get<min_corner, 1>(box),
get<max_corner, 0>(box), get<max_corner, 1>(box),
width, height);
}
template <typename W, typename D>
explicit inline map_transformer(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
D const& width, D const& height)
{
set_transformation(wx1, wy1, wx2, wy2, width, height);
}
private :
template <typename W, typename P, typename S>
inline void set_transformation_point(W const& wx, W const& wy,
P const& px, P const& py,
S const& scalex, S const& scaley)
{
// Translate to a coordinate system centered on world coordinates (-wx, -wy)
M t1(3,3);
t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx;
t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy;
t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1;
// Scale the map
M s(3,3);
s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0;
s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0;
s(2,0) = 0; s(2,1) = 0; s(2,2) = 1;
// Translate to a coordinate system centered on the specified pixels (+px, +py)
M t2(3, 3);
t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px;
t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py;
t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1;
// Calculate combination matrix in two steps
this->m_matrix = boost::numeric::ublas::prod(s, t1);
this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix);
}
template <typename W, typename D>
void set_transformation(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
D const& width, D const& height)
{
D px1 = 0;
D py1 = 0;
D px2 = width;
D py2 = height;
// Get the same type, but at least a double
typedef typename select_most_precise<D, double>::type type;
// Calculate appropriate scale, take min because whole box must fit
// Scale is in PIXELS/MAPUNITS (meters)
W wdx = wx2 - wx1;
W wdy = wy2 - wy1;
type sx = (px2 - px1) / boost::numeric_cast<type>(wdx);
type sy = (py2 - py1) / boost::numeric_cast<type>(wdy);
if (SameScale)
{
type scale = (std::min)(sx, sy);
sx = scale;
sy = scale;
}
// Calculate centerpoints
W wtx = wx1 + wx2;
W wty = wy1 + wy2;
W two = 2;
W wmx = wtx / two;
W wmy = wty / two;
type pmx = (px1 + px2) / 2.0;
type pmy = (py1 + py2) / 2.0;
set_transformation_point(wmx, wmy, pmx, pmy, sx, sy);
if (Mirror)
{
// Mirror in y-direction
M m(3,3);
m(0,0) = 1; m(0,1) = 0; m(0,2) = 0;
m(1,0) = 0; m(1,1) = -1; m(1,2) = 0;
m(2,0) = 0; m(2,1) = 0; m(2,2) = 1;
// Translate in y-direction such that it fits again
M y(3, 3);
y(0,0) = 1; y(0,1) = 0; y(0,2) = 0;
y(1,0) = 0; y(1,1) = 1; y(1,2) = height;
y(2,0) = 0; y(2,1) = 0; y(2,2) = 1;
// Calculate combination matrix in two steps
this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix);
this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix);
}
}
};
}} // namespace strategy::transform
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP

View File

@@ -0,0 +1,422 @@
// 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_TRANSFORM_MATRIX_TRANSFORMERS_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
#include <cstddef>
// Remove the ublas checking, otherwise the inverse might fail
// (while nothing seems to be wrong)
#define BOOST_UBLAS_TYPE_CHECK 0
#include <boost/numeric/conversion/cast.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace transform
{
/*!
\brief Affine transformation strategy in Cartesian system.
\details The strategy serves as a generic definition of affine transformation matrix
and procedure of application it to given point.
\see http://en.wikipedia.org/wiki/Affine_transformation
and http://www.devmaster.net/wiki/Transformation_matrices
\ingroup strategies
\tparam P1 first point type (source)
\tparam P2 second point type (target)
\tparam Dimension1 number of dimensions to transform from first point
\tparam Dimension1 number of dimensions to transform to second point
*/
template
<
typename P1, typename P2,
std::size_t Dimension1,
std::size_t Dimension2
>
class ublas_transformer
{
};
template <typename P1, typename P2>
class ublas_transformer<P1, P2, 2, 2>
{
protected :
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
typedef coordinate_type ct; // Abbreviation
typedef boost::numeric::ublas::matrix<coordinate_type> matrix_type;
matrix_type m_matrix;
public :
inline ublas_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
: m_matrix(3, 3)
{
m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;
m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;
m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;
}
inline ublas_transformer(matrix_type const& matrix)
: m_matrix(matrix)
{}
inline ublas_transformer() : m_matrix(3, 3) {}
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal<P1, 2>();
assert_dimension_greater_equal<P2, 2>();
coordinate_type const& c1 = get<0>(p1);
coordinate_type const& c2 = get<1>(p1);
coordinate_type p2x = c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2);
coordinate_type p2y = c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2);
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(p2x));
set<1>(p2, boost::numeric_cast<ct2>(p2y));
return true;
}
matrix_type const& matrix() const { return m_matrix; }
};
// It IS possible to go from 3 to 2 coordinates
template <typename P1, typename P2>
class ublas_transformer<P1, P2, 3, 2> : public ublas_transformer<P1, P2, 2, 2>
{
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
typedef coordinate_type ct; // Abbreviation
public :
inline ublas_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
: ublas_transformer<P1, P2, 2, 2>(
m_0_0, m_0_1, m_0_2,
m_1_0, m_1_1, m_1_2,
m_2_0, m_2_1, m_2_2)
{}
inline ublas_transformer()
: ublas_transformer<P1, P2, 2, 2>()
{}
};
template <typename P1, typename P2>
class ublas_transformer<P1, P2, 3, 3>
{
protected :
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
typedef coordinate_type ct; // Abbreviation
typedef boost::numeric::ublas::matrix<coordinate_type> matrix_type;
matrix_type m_matrix;
inline ublas_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
)
: m_matrix(4, 4)
{
m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;
m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;
m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;
m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;
}
inline ublas_transformer() : m_matrix(4, 4) {}
public :
inline bool apply(P1 const& p1, P2& p2) const
{
coordinate_type const& c1 = get<0>(p1);
coordinate_type const& c2 = get<1>(p1);
coordinate_type const& c3 = get<2>(p1);
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(
c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + c3 * m_matrix(0,2) + m_matrix(0,3)));
set<1>(p2, boost::numeric_cast<ct2>(
c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + c3 * m_matrix(1,2) + m_matrix(1,3)));
set<2>(p2, boost::numeric_cast<ct2>(
c1 * m_matrix(2,0) + c2 * m_matrix(2,1) + c3 * m_matrix(2,2) + m_matrix(2,3)));
return true;
}
matrix_type const& matrix() const { return m_matrix; }
};
/*!
\brief Strategy of translate transformation in Cartesian system.
\details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
\see http://en.wikipedia.org/wiki/Translation_%28geometry%29
\ingroup strategies
\tparam P1 first point type
\tparam P2 second point type
\tparam Dimension1 number of dimensions to transform from first point
\tparam Dimension1 number of dimensions to transform to second point
*/
template
<
typename P1, typename P2,
std::size_t Dimension1 = geometry::dimension<P1>::type::value,
std::size_t Dimension2 = geometry::dimension<P2>::type::value
>
class translate_transformer
{
};
template <typename P1, typename P2>
class translate_transformer<P1, P2, 2, 2> : public ublas_transformer<P1, P2, 2, 2>
{
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
public :
// To have translate transformers compatible for 2/3 dimensions, the
// constructor takes an optional third argument doing nothing.
inline translate_transformer(coordinate_type const& translate_x,
coordinate_type const& translate_y,
coordinate_type const& dummy = 0)
: ublas_transformer<P1, P2, 2, 2>(
1, 0, translate_x,
0, 1, translate_y,
0, 0, 1)
{}
};
template <typename P1, typename P2>
class translate_transformer<P1, P2, 3, 3> : public ublas_transformer<P1, P2, 3, 3>
{
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
public :
inline translate_transformer(coordinate_type const& translate_x,
coordinate_type const& translate_y,
coordinate_type const& translate_z)
: ublas_transformer<P1, P2, 3, 3>(
1, 0, 0, translate_x,
0, 1, 0, translate_y,
0, 0, 1, translate_z,
0, 0, 0, 1)
{}
};
/*!
\brief Strategy of scale transformation in Cartesian system.
\details Scale scales a geometry up or down in all its dimensions.
\see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
\ingroup strategies
\tparam P1 first point type
\tparam P2 second point type
\tparam Dimension1 number of dimensions to transform from first point
\tparam Dimension1 number of dimensions to transform to second point
*/
template
<
typename P1, typename P2 = P1,
std::size_t Dimension1 = geometry::dimension<P1>::type::value,
std::size_t Dimension2 = geometry::dimension<P2>::type::value
>
class scale_transformer
{
};
template <typename P1, typename P2>
class scale_transformer<P1, P2, 2, 2> : public ublas_transformer<P1, P2, 2, 2>
{
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
public :
inline scale_transformer(coordinate_type const& scale_x,
coordinate_type const& scale_y,
coordinate_type const& dummy = 0)
: ublas_transformer<P1, P2, 2, 2>(
scale_x, 0, 0,
0, scale_y, 0,
0, 0, 1)
{}
inline scale_transformer(coordinate_type const& scale)
: ublas_transformer<P1, P2, 2, 2>(
scale, 0, 0,
0, scale, 0,
0, 0, 1)
{}
};
template <typename P1, typename P2>
class scale_transformer<P1, P2, 3, 3> : public ublas_transformer<P1, P2, 3, 3>
{
typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
inline scale_transformer(coordinate_type const& scale_x,
coordinate_type const& scale_y,
coordinate_type const& scale_z)
: ublas_transformer<P1, P2, 3, 3>(
scale_x, 0, 0, 0,
0, scale_y, 0, 0,
0, 0, scale_z, 0,
0, 0, 0, 1)
{}
inline scale_transformer(coordinate_type const& scale)
: ublas_transformer<P1, P2, 3, 3>(
scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, scale, 0,
0, 0, 0, 1)
{}
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename DegreeOrRadian>
struct as_radian
{};
template <>
struct as_radian<radian>
{
template <typename T>
static inline T get(T const& value)
{
return value;
}
};
template <>
struct as_radian<degree>
{
template <typename T>
static inline T get(T const& value)
{
return value * math::d2r;
}
};
template
<
typename P1, typename P2,
std::size_t Dimension1 = geometry::dimension<P1>::type::value,
std::size_t Dimension2 = geometry::dimension<P2>::type::value
>
class rad_rotate_transformer
: public ublas_transformer<P1, P2, Dimension1, Dimension2>
{
// Angle has type of coordinate type, but at least a double
typedef typename select_most_precise
<
typename select_coordinate_type<P1, P2>::type,
double
>::type angle_type;
public :
inline rad_rotate_transformer(angle_type const& angle)
: ublas_transformer<P1, P2, Dimension1, Dimension2>(
cos(angle), sin(angle), 0,
-sin(angle), cos(angle), 0,
0, 0, 1)
{}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Strategy of rotate transformation in Cartesian system.
\details Rotate rotates a geometry of specified angle about a fixed point (e.g. origin).
\see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
\ingroup strategies
\tparam P1 first point type
\tparam P2 second point type
\tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
\note A single angle is needed to specify a rotation in 2D.
Not yet in 3D, the 3D version requires special things to allow
for rotation around X, Y, Z or arbitrary axis.
\todo The 3D version will not compile.
*/
template <typename P1, typename P2, typename DegreeOrRadian>
class rotate_transformer : public detail::rad_rotate_transformer<P1, P2>
{
// Angle has type of coordinate type, but at least a double
typedef typename select_most_precise
<
typename select_coordinate_type<P1, P2>::type,
double
>::type angle_type;
public :
inline rotate_transformer(angle_type const& angle)
: detail::rad_rotate_transformer
<
P1, P2
>(detail::as_radian<DegreeOrRadian>::get(angle))
{}
};
}} // namespace strategy::transform
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP

View File

@@ -0,0 +1,71 @@
// 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_WITHIN_HPP
#define BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
namespace services
{
/*!
\brief Traits class binding a within determination strategy to a coordinate system
\ingroup within
\tparam TagContained tag (possibly casted) of point-type
\tparam TagContained tag (possibly casted) of (possibly) containing type
\tparam CsTagContained tag of coordinate system of point-type
\tparam CsTagContaining tag of coordinate system of (possibly) containing type
\tparam Geometry geometry-type of input (often point, or box)
\tparam GeometryContaining geometry-type of input (possibly) containing type
*/
template
<
typename TagContained,
typename TagContaining,
typename CastedTagContained,
typename CastedTagContaining,
typename CsTagContained,
typename CsTagContaining,
typename GeometryContained,
typename GeometryContaining
>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPES
, (types<GeometryContained, GeometryContaining>)
);
};
} // namespace services
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP