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,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