Distance strategies no longer need to be parameterized with the point type(s).

[SVN r85040]
This commit is contained in:
Bruno Lalande 2013-07-14 22:54:43 +00:00
parent 23612b0b6b
commit 4246ea4217
22 changed files with 460 additions and 791 deletions

View File

@ -40,7 +40,8 @@ struct enrichment_info
point_tag, point_tag,
P P
>::type >::type
>::type >::type,
P, P
>::type distance_type; >::type distance_type;
inline enrichment_info() inline enrichment_info()

View File

@ -53,8 +53,8 @@ using strategy::distance::services::return_type;
template <typename P1, typename P2, typename Strategy> template <typename P1, typename P2, typename Strategy>
struct point_to_point struct point_to_point
{ {
static inline typename return_type<Strategy>::type apply(P1 const& p1, static inline typename return_type<Strategy, P1, P2>::type
P2 const& p2, Strategy const& strategy) apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
{ {
boost::ignore_unused_variable_warning(strategy); boost::ignore_unused_variable_warning(strategy);
return strategy.apply(p1, p2); return strategy.apply(p1, p2);
@ -65,8 +65,8 @@ struct point_to_point
template<typename Point, typename Segment, typename Strategy> template<typename Point, typename Segment, typename Strategy>
struct point_to_segment struct point_to_segment
{ {
static inline typename return_type<Strategy>::type apply(Point const& point, static inline typename return_type<Strategy, Point, typename point_type<Segment>::type>::type
Segment const& segment, Strategy const& ) apply(Point const& point, Segment const& segment, Strategy const& )
{ {
typename strategy::distance::services::default_strategy typename strategy::distance::services::default_strategy
< <
@ -96,7 +96,7 @@ template
> >
struct point_to_range struct point_to_range
{ {
typedef typename return_type<PSStrategy>::type return_type; typedef typename return_type<PSStrategy, Point, typename point_type<Range>::type>::type return_type;
static inline return_type apply(Point const& point, Range const& range, static inline return_type apply(Point const& point, Range const& range,
PPStrategy const& pp_strategy, PSStrategy const& ps_strategy) PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
@ -161,7 +161,7 @@ struct point_to_ring
{ {
typedef std::pair typedef std::pair
< <
typename return_type<PPStrategy>::type, bool typename return_type<PPStrategy, Point, typename point_type<Ring>::type>::type, bool
> distance_containment; > distance_containment;
static inline distance_containment apply(Point const& point, static inline distance_containment apply(Point const& point,
@ -195,7 +195,7 @@ template
> >
struct point_to_polygon struct point_to_polygon
{ {
typedef typename return_type<PPStrategy>::type return_type; typedef typename return_type<PPStrategy, Point, typename point_type<Polygon>::type>::type return_type;
typedef std::pair<return_type, bool> distance_containment; typedef std::pair<return_type, bool> distance_containment;
static inline distance_containment apply(Point const& point, static inline distance_containment apply(Point const& point,
@ -288,7 +288,14 @@ struct distance
> >
: distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false> : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
{ {
static inline typename return_type<Strategy>::type apply( typedef typename return_type
<
Strategy,
typename point_type<Geometry2>::type,
typename point_type<Geometry1>::type
>::type return_type;
static inline return_type apply(
Geometry1 const& g1, Geometry1 const& g1,
Geometry2 const& g2, Geometry2 const& g2,
Strategy const& strategy) Strategy const& strategy)
@ -302,44 +309,6 @@ struct distance
} }
}; };
// If reversal is needed and we got the strategy by default, invert it before
// proceeding to the reversal.
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2, typename StrategyTag
>
struct distance
<
Geometry1, Geometry2,
typename detail::distance::default_strategy<Geometry1, Geometry2>::type,
Tag1, Tag2, StrategyTag,
true
>
: distance
<
Geometry2, Geometry1,
typename detail::distance::default_strategy<Geometry2, Geometry1>::type,
Tag2, Tag1, StrategyTag,
false
>
{
typedef typename detail::distance::default_strategy<Geometry2, Geometry1>::type reversed_strategy;
static inline typename strategy::distance::services::return_type<reversed_strategy>::type apply(
Geometry1 const& g1,
Geometry2 const& g2,
typename detail::distance::default_strategy<Geometry1, Geometry2>::type const&)
{
return distance
<
Geometry2, Geometry1, reversed_strategy,
Tag2, Tag1, StrategyTag,
false
>::apply(g2, g1, reversed_strategy());
}
};
// Point-point // Point-point
template <typename P1, typename P2, typename Strategy> template <typename P1, typename P2, typename Strategy>
@ -363,9 +332,10 @@ struct distance
> >
{ {
static inline typename return_type<Strategy>::type apply(Point const& point, static inline typename return_type<Strategy, Point, typename point_type<Linestring>::type>::type
Linestring const& linestring, apply(Point const& point,
Strategy const& strategy) Linestring const& linestring,
Strategy const& strategy)
{ {
typedef typename strategy::distance::services::default_strategy typedef typename strategy::distance::services::default_strategy
< <
@ -394,9 +364,10 @@ struct distance
false false
> >
{ {
static inline typename return_type<Strategy>::type apply(Point const& point, static inline typename return_type<Strategy, Point, typename point_type<Linestring>::type>::type
Linestring const& linestring, apply(Point const& point,
Strategy const& strategy) Linestring const& linestring,
Strategy const& strategy)
{ {
typedef typename Strategy::point_strategy_type pp_strategy_type; typedef typename Strategy::point_strategy_type pp_strategy_type;
return detail::distance::point_to_range return detail::distance::point_to_range
@ -415,7 +386,7 @@ struct distance
false false
> >
{ {
typedef typename return_type<Strategy>::type return_type; typedef typename return_type<Strategy, Point, typename point_type<Ring>::type>::type return_type;
static inline return_type apply(Point const& point, static inline return_type apply(Point const& point,
Ring const& ring, Ring const& ring,
@ -450,7 +421,7 @@ struct distance
false false
> >
{ {
typedef typename return_type<Strategy>::type return_type; typedef typename return_type<Strategy, Point, typename point_type<Polygon>::type>::type return_type;
static inline return_type apply(Point const& point, static inline return_type apply(Point const& point,
Polygon const& polygon, Polygon const& polygon,
@ -496,8 +467,10 @@ struct distance
false false
> >
{ {
static inline typename return_type<Strategy>::type apply(Point const& point, static inline typename return_type<Strategy, Point, typename point_type<Segment>::type>::type
Segment const& segment, Strategy const& strategy) apply(Point const& point,
Segment const& segment,
Strategy const& strategy)
{ {
typename point_type<Segment>::type p[2]; typename point_type<Segment>::type p[2];
@ -549,9 +522,15 @@ for distance, it is probably so that there is no specialization
for return_type<...> for your strategy. for return_type<...> for your strategy.
*/ */
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2, typename Strategy>
inline typename strategy::distance::services::return_type<Strategy>::type distance( inline typename strategy::distance::services::return_type
Geometry1 const& geometry1, Geometry2 const& geometry2, <
Strategy const& strategy) Strategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type
distance(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{ {
concept::check<Geometry1 const>(); concept::check<Geometry1 const>();
concept::check<Geometry2 const>(); concept::check<Geometry2 const>();

View File

@ -252,7 +252,9 @@ inline void simplify(Geometry const& geometry, Geometry& out,
{ {
concept::check<Geometry>(); concept::check<Geometry>();
BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) ); BOOST_CONCEPT_ASSERT(
(concept::SimplifyStrategy<Strategy, typename point_type<Geometry>::type>)
);
geometry::clear(out); geometry::clear(out);
@ -322,7 +324,9 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out,
Distance const& max_distance, Strategy const& strategy) Distance const& max_distance, Strategy const& strategy)
{ {
concept::check<Geometry const>(); concept::check<Geometry const>();
BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) ); BOOST_CONCEPT_ASSERT(
(concept::SimplifyStrategy<Strategy, typename point_type<Geometry>::type>)
);
dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy); dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy);
} }

View File

@ -45,7 +45,12 @@ struct distance_single_to_multi
Strategy Strategy
> >
{ {
typedef typename strategy::distance::services::return_type<Strategy>::type return_type; typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry>::type,
typename point_type<MultiGeometry>::type
>::type return_type;
static inline return_type apply(Geometry const& geometry, static inline return_type apply(Geometry const& geometry,
MultiGeometry const& multi, MultiGeometry const& multi,
@ -84,7 +89,12 @@ struct distance_multi_to_multi
Strategy Strategy
> >
{ {
typedef typename strategy::distance::services::return_type<Strategy>::type return_type; typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Multi1>::type,
typename point_type<Multi2>::type
>::type return_type;
static inline return_type apply(Multi1 const& multi1, static inline return_type apply(Multi1 const& multi1,
Multi2 const& multi2, Strategy const& strategy) Multi2 const& multi2, Strategy const& strategy)

View File

@ -99,7 +99,11 @@ public :
typedef PointDistanceStrategy distance_strategy_type; typedef PointDistanceStrategy distance_strategy_type;
// typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type 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; typedef typename strategy::distance::services::return_type
<
distance_strategy_type,
Point, Point
>::type return_type;
private : private :
typedef detail::douglas_peucker_point<Point> dp_point_type; typedef detail::douglas_peucker_point<Point> dp_point_type;
@ -197,7 +201,11 @@ public :
// Get points, recursively, including them if they are further away // Get points, recursively, including them if they are further away
// than the specified distance // than the specified distance
typedef typename strategy::distance::services::return_type<distance_strategy_type>::type return_type; typedef typename strategy::distance::services::return_type
<
distance_strategy_type,
dp_point_type, dp_point_type
>::type return_type;
consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy); consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);
@ -224,6 +232,17 @@ public :
}} // namespace strategy::simplify }} // namespace strategy::simplify
namespace traits {
template <typename P>
struct point_type<strategy::simplify::detail::douglas_peucker_point<P> >
{
typedef P type;
};
} // namespace traits
}} // namespace boost::geometry }} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP #endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP

View File

@ -67,10 +67,8 @@ namespace strategy { namespace distance
*/ */
template template
< <
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void, typename CalculationType = void,
typename Strategy = pythagoras<Point, PointOfSegment, CalculationType> typename Strategy = pythagoras<CalculationType>
> >
class projected_point class projected_point
{ {
@ -81,45 +79,41 @@ public :
// Integer coordinates can still result in FP distances. // Integer coordinates can still result in FP distances.
// There is a division, which must be represented in FP. // There is a division, which must be represented in FP.
// So promote. // So promote.
typedef typename promote_floating_point template <typename Point, typename PointOfSegment>
< struct calculation_type
typename strategy::distance::services::return_type : promote_floating_point
< <
Strategy typename strategy::distance::services::return_type
>::type <
>::type calculation_type; Strategy,
Point,
private : PointOfSegment
>::type
// A projected point of points in Integer coordinates must be able to be >
// represented in FP. {};
typedef model::point
<
calculation_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 : public :
inline calculation_type apply(Point const& p, template <typename Point, typename PointOfSegment>
PointOfSegment const& p1, PointOfSegment const& p2) const inline typename calculation_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
{ {
assert_dimension_equal<Point, PointOfSegment>(); assert_dimension_equal<Point, PointOfSegment>();
typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
// A projected point of points in Integer coordinates must be able to be
// represented in FP.
typedef model::point
<
calculation_type,
dimension<PointOfSegment>::value,
typename coordinate_system<PointOfSegment>::type
> fp_point_type;
// For convenience
typedef fp_point_type fp_vector_type;
/* /*
Algorithm [p1: (x1,y1), p2: (x2,y2), p: (px,py)] Algorithm [p1: (x1,y1), p2: (x2,y2), p: (px,py)]
VECTOR v(x2 - x1, y2 - y1) VECTOR v(x2 - x1, y2 - y1)
@ -157,21 +151,12 @@ public :
// See above, c1 > 0 AND c2 > c1 so: c2 != 0 // See above, c1 > 0 AND c2 > c1 so: c2 != 0
calculation_type const b = c1 / c2; calculation_type const b = c1 / c2;
fp_strategy_type fp_strategy
= strategy::distance::services::get_similar
<
Strategy, Point, fp_point_type
>::apply(strategy);
boost::ignore_unused_variable_warning(fp_strategy);
fp_point_type projected; fp_point_type projected;
geometry::convert(p1, projected); geometry::convert(p1, projected);
multiply_value(v, b); multiply_value(v, b);
add_point(projected, v); add_point(projected, v);
//std::cout << "distance " << dsv(p) << " .. " << dsv(projected) << std::endl; return strategy.apply(p, projected);
return fp_strategy.apply(p, projected);
} }
}; };
@ -179,103 +164,64 @@ public :
namespace services namespace services
{ {
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy>
struct tag<projected_point<Point, PointOfSegment, CalculationType, Strategy> > struct tag<projected_point<CalculationType, Strategy> >
{ {
typedef strategy_tag_distance_point_segment type; typedef strategy_tag_distance_point_segment type;
}; };
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy, typename P, typename PS>
struct return_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> > struct return_type<projected_point<CalculationType, Strategy>, P, PS>
{ : projected_point<CalculationType, Strategy>::template calculation_type<P, PS>
typedef typename projected_point<Point, PointOfSegment, CalculationType, Strategy>::calculation_type type; {};
};
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy>
struct strategy_point_point<projected_point<Point, PointOfSegment, CalculationType, Strategy> > struct strategy_point_point<projected_point<CalculationType, Strategy> >
{ {
typedef Strategy type; typedef Strategy type;
}; };
template template <typename CalculationType, typename Strategy>
< struct comparable_type<projected_point<CalculationType, Strategy> >
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 // Define a projected_point strategy with its underlying point-point-strategy
// being comparable // being comparable
typedef projected_point typedef projected_point
< <
Point,
PointOfSegment,
CalculationType, CalculationType,
typename comparable_type<Strategy>::type typename comparable_type<Strategy>::type
> type; > type;
}; };
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy>
struct get_comparable<projected_point<Point, PointOfSegment, CalculationType, Strategy> > struct get_comparable<projected_point<CalculationType, Strategy> >
{ {
typedef typename comparable_type typedef typename comparable_type
< <
projected_point<Point, PointOfSegment, CalculationType, Strategy> projected_point<CalculationType, Strategy>
>::type comparable_type; >::type comparable_type;
public : public :
static inline comparable_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& ) static inline comparable_type apply(projected_point<CalculationType, Strategy> const& )
{ {
return comparable_type(); return comparable_type();
} }
}; };
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy, typename P, typename PS>
struct result_from_distance<projected_point<Point, PointOfSegment, CalculationType, Strategy> > struct result_from_distance<projected_point<CalculationType, Strategy>, P, PS>
{ {
private : private :
typedef typename return_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >::type return_type; typedef typename return_type<projected_point<CalculationType, Strategy>, P, PS>::type return_type;
public : public :
template <typename T> template <typename T>
static inline return_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& , T const& value) static inline return_type apply(projected_point<CalculationType, Strategy> const& , T const& value)
{ {
Strategy s; Strategy s;
return result_from_distance<Strategy>::apply(s, value); return result_from_distance<Strategy, P, PS>::apply(s, value);
} }
}; };
@ -290,8 +236,6 @@ struct default_strategy<segment_tag, Point, PointOfSegment, cartesian_tag, carte
{ {
typedef strategy::distance::projected_point typedef strategy::distance::projected_point
< <
Point,
PointOfSegment,
void, void,
typename boost::mpl::if_ typename boost::mpl::if_
< <

View File

@ -37,21 +37,23 @@ namespace strategy { namespace distance
namespace detail namespace detail
{ {
template <typename Point1, typename Point2, size_t I, typename T> template <size_t I, typename T>
struct compute_pythagoras struct compute_pythagoras
{ {
template <typename Point1, typename Point2>
static inline T apply(Point1 const& p1, Point2 const& p2) static inline T apply(Point1 const& p1, Point2 const& p2)
{ {
T const c1 = boost::numeric_cast<T>(get<I-1>(p1)); T const c1 = boost::numeric_cast<T>(get<I-1>(p1));
T const c2 = boost::numeric_cast<T>(get<I-1>(p2)); T const c2 = boost::numeric_cast<T>(get<I-1>(p2));
T const d = c1 - c2; T const d = c1 - c2;
return d * d + compute_pythagoras<Point1, Point2, I-1, T>::apply(p1, p2); return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);
} }
}; };
template <typename Point1, typename Point2, typename T> template <typename T>
struct compute_pythagoras<Point1, Point2, 0, T> struct compute_pythagoras<0, T>
{ {
template <typename Point1, typename Point2>
static inline T apply(Point1 const&, Point2 const&) static inline T apply(Point1 const&, Point2 const&)
{ {
return boost::numeric_cast<T>(0); return boost::numeric_cast<T>(0);
@ -72,24 +74,24 @@ namespace comparable
\tparam Point2 \tparam_second_point \tparam Point2 \tparam_second_point
\tparam CalculationType \tparam_calculation \tparam CalculationType \tparam_calculation
*/ */
template template <typename CalculationType = void>
<
typename Point1,
typename Point2 = Point1,
typename CalculationType = void
>
class pythagoras class pythagoras
{ {
public : public :
typedef typename util::calculation_type::geometric::binary template <typename Point1, typename Point2>
< struct calculation_type
Point1, : util::calculation_type::geometric::binary
Point2, <
CalculationType Point1,
>::type calculation_type; Point2,
CalculationType
>
{};
static inline calculation_type apply(Point1 const& p1, Point2 const& p2) template <typename Point1, typename Point2>
static inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& p1, Point2 const& p2)
{ {
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point1>) ); BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point1>) );
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) ); BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
@ -101,9 +103,8 @@ public :
return detail::compute_pythagoras return detail::compute_pythagoras
< <
Point1, Point2,
dimension<Point1>::value, dimension<Point1>::value,
calculation_type typename calculation_type<Point1, Point2>::type
>::apply(p1, p2); >::apply(p1, p2);
} }
}; };
@ -128,22 +129,21 @@ public :
*/ */
template template
< <
typename Point1,
typename Point2 = Point1,
typename CalculationType = void typename CalculationType = void
> >
class pythagoras struct pythagoras
{ {
typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type; template <typename P1, typename P2>
public : struct calculation_type
typedef typename util::calculation_type::geometric::binary : util::calculation_type::geometric::binary
< <
Point1, P1,
Point2, P2,
CalculationType, CalculationType,
double, double,
double // promote integer to double double // promote integer to double
>::type calculation_type; >
{};
/*! /*!
\brief applies the distance calculation using pythagoras \brief applies the distance calculation using pythagoras
@ -151,10 +151,11 @@ public :
\param p1 first point \param p1 first point
\param p2 second point \param p2 second point
*/ */
static inline calculation_type apply(Point1 const& p1, Point2 const& p2) template <typename P1, typename P2>
static inline typename calculation_type<P1, P2>::type
apply(P1 const& p1, P2 const& p2)
{ {
calculation_type const t = comparable_type::apply(p1, p2); return sqrt(comparable::pythagoras<CalculationType>::apply(p1, p2));
return sqrt(t);
} }
}; };
@ -163,81 +164,46 @@ public :
namespace services namespace services
{ {
template <typename Point1, typename Point2, typename CalculationType> template <typename CalculationType>
struct tag<pythagoras<Point1, Point2, CalculationType> > struct tag<pythagoras<CalculationType> >
{ {
typedef strategy_tag_distance_point_point type; typedef strategy_tag_distance_point_point type;
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename CalculationType, typename P1, typename P2>
struct return_type<pythagoras<Point1, Point2, CalculationType> > struct return_type<distance::pythagoras<CalculationType>, P1, P2>
: pythagoras<CalculationType>::template calculation_type<P1, P2>
{};
template <typename CalculationType>
struct comparable_type<pythagoras<CalculationType> >
{ {
typedef typename pythagoras<Point1, Point2, CalculationType>::calculation_type type; typedef comparable::pythagoras<CalculationType> type;
}; };
template template <typename CalculationType>
< struct get_comparable<pythagoras<CalculationType> >
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; typedef comparable::pythagoras<CalculationType> comparable_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 : public :
static inline comparable_type apply(pythagoras<Point1, Point2, CalculationType> const& ) static inline comparable_type apply(pythagoras<CalculationType> const& )
{ {
return comparable_type(); return comparable_type();
} }
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename CalculationType, typename Point1, typename Point2>
struct result_from_distance<pythagoras<Point1, Point2, CalculationType> > struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>
{ {
private : private :
typedef typename return_type<pythagoras<Point1, Point2, CalculationType> >::type return_type; typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;
public : public :
template <typename T> template <typename T>
static inline return_type apply(pythagoras<Point1, Point2, CalculationType> const& , T const& value) static inline return_type apply(pythagoras<CalculationType> const& , T const& value)
{ {
return return_type(value); return return_type(value);
} }
@ -245,83 +211,48 @@ public :
// Specializations for comparable::pythagoras // Specializations for comparable::pythagoras
template <typename Point1, typename Point2, typename CalculationType> template <typename CalculationType>
struct tag<comparable::pythagoras<Point1, Point2, CalculationType> > struct tag<comparable::pythagoras<CalculationType> >
{ {
typedef strategy_tag_distance_point_point type; typedef strategy_tag_distance_point_point type;
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename CalculationType, typename P1, typename P2>
struct return_type<comparable::pythagoras<Point1, Point2, CalculationType> > struct return_type<comparable::pythagoras<CalculationType>, P1, P2>
: comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras<CalculationType> >
{ {
typedef typename comparable::pythagoras<Point1, Point2, CalculationType>::calculation_type type; typedef comparable::pythagoras<CalculationType> type;
}; };
template <typename CalculationType>
struct get_comparable<comparable::pythagoras<CalculationType> >
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; typedef comparable::pythagoras<CalculationType> comparable_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 : public :
static inline comparable_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& ) static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )
{ {
return comparable_type(); return comparable_type();
} }
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename CalculationType, typename Point1, typename Point2>
struct result_from_distance<comparable::pythagoras<Point1, Point2, CalculationType> > struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>
{ {
private : private :
typedef typename return_type<comparable::pythagoras<Point1, Point2, CalculationType> >::type return_type; typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;
public : public :
template <typename T> template <typename T>
static inline return_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& , T const& value) static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)
{ {
return_type const v = value; return_type const v = value;
return v * v; return v * v;
@ -332,7 +263,7 @@ public :
template <typename Point1, typename Point2> template <typename Point1, typename Point2>
struct default_strategy<point_tag, Point1, Point2, cartesian_tag, cartesian_tag, void> struct default_strategy<point_tag, Point1, Point2, cartesian_tag, cartesian_tag, void>
{ {
typedef pythagoras<Point1, Point2> type; typedef pythagoras<> type;
}; };

View File

@ -23,6 +23,7 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp> #include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/segment.hpp> #include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry { namespace concept namespace boost { namespace geometry { namespace concept
@ -33,7 +34,7 @@ namespace boost { namespace geometry { namespace concept
\brief Checks strategy for point-segment-distance \brief Checks strategy for point-segment-distance
\ingroup distance \ingroup distance
*/ */
template <typename Strategy> template <typename Strategy, typename Point1, typename Point2>
struct PointDistanceStrategy struct PointDistanceStrategy
{ {
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
@ -55,66 +56,44 @@ private :
ApplyMethod, 1 ApplyMethod, 1
>::type ptype2; >::type ptype2;
// 2) check if apply-arguments fulfill point concept // 2) must define meta-function return_type
BOOST_CONCEPT_ASSERT typedef typename strategy::distance::services::return_type
(
(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 Strategy, ptype1, ptype2
>::type stype; >::type rtype;
// 5) must define meta-function "comparable_type" // 3) must define meta-function "comparable_type"
typedef typename strategy::distance::services::comparable_type typedef typename strategy::distance::services::comparable_type
< <
Strategy Strategy
>::type ctype; >::type ctype;
// 6) must define meta-function "tag" // 4) must define meta-function "tag"
typedef typename strategy::distance::services::tag typedef typename strategy::distance::services::tag
< <
Strategy Strategy
>::type tag; >::type tag;
// 7) must implement apply with arguments // 5) must implement apply with arguments
Strategy* str = 0; Strategy* str = 0;
ptype1 *p1 = 0; ptype1 *p1 = 0;
ptype2 *p2 = 0; ptype2 *p2 = 0;
rtype r = str->apply(*p1, *p2); rtype r = str->apply(*p1, *p2);
// 8) must define (meta)struct "get_similar" with apply // 6) must define (meta)struct "get_comparable" 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 ctype c = strategy::distance::services::get_comparable
< <
Strategy Strategy
>::apply(*str); >::apply(*str);
// 10) must define (meta)struct "result_from_distance" with apply // 7) must define (meta)struct "result_from_distance" with apply
r = strategy::distance::services::result_from_distance r = strategy::distance::services::result_from_distance
< <
Strategy Strategy,
ptype1, ptype2
>::apply(*str, 1.0); >::apply(*str, 1.0);
boost::ignore_unused_variable_warning(str); boost::ignore_unused_variable_warning(str);
boost::ignore_unused_variable_warning(s);
boost::ignore_unused_variable_warning(c); boost::ignore_unused_variable_warning(c);
boost::ignore_unused_variable_warning(r); boost::ignore_unused_variable_warning(r);
} }
@ -125,7 +104,7 @@ private :
public : public :
BOOST_CONCEPT_USAGE(PointDistanceStrategy) BOOST_CONCEPT_USAGE(PointDistanceStrategy)
{ {
checker::apply(&Strategy::apply); checker::apply(&Strategy::template apply<Point1, Point2>);
} }
#endif #endif
}; };
@ -135,7 +114,7 @@ public :
\brief Checks strategy for point-segment-distance \brief Checks strategy for point-segment-distance
\ingroup strategy_concepts \ingroup strategy_concepts
*/ */
template <typename Strategy> template <typename Strategy, typename Point, typename PointOfSegment>
struct PointSegmentDistanceStrategy struct PointSegmentDistanceStrategy
{ {
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
@ -156,26 +135,14 @@ private :
ApplyMethod, 1 ApplyMethod, 1
>::type sptype; >::type sptype;
// 2) check if apply-arguments fulfill point concept // 1) must define meta-function return_type
BOOST_CONCEPT_ASSERT typedef typename strategy::distance::services::return_type<Strategy, ptype, sptype>::type rtype;
(
(concept::ConstPoint<ptype>)
);
BOOST_CONCEPT_ASSERT // 2) must define underlying point-distance-strategy
(
(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; typedef typename strategy::distance::services::strategy_point_point<Strategy>::type stype;
BOOST_CONCEPT_ASSERT BOOST_CONCEPT_ASSERT
( (
(concept::PointDistanceStrategy<stype>) (concept::PointDistanceStrategy<stype, Point, PointOfSegment>)
); );
@ -194,7 +161,7 @@ private :
public : public :
BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy) BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)
{ {
checker::apply(&Strategy::apply); checker::apply(&Strategy::template apply<Point, PointOfSegment>);
} }
#endif #endif
}; };

View File

@ -19,6 +19,7 @@
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp> #include <boost/geometry/strategies/concepts/distance_concept.hpp>
@ -30,7 +31,7 @@ namespace boost { namespace geometry { namespace concept
\brief Checks strategy for simplify \brief Checks strategy for simplify
\ingroup simplify \ingroup simplify
*/ */
template <typename Strategy> template <typename Strategy, typename Point>
struct SimplifyStrategy struct SimplifyStrategy
{ {
#ifndef DOXYGEN_NO_CONCEPT_MEMBERS #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
@ -59,29 +60,14 @@ private :
boost::mpl::int_<0> boost::mpl::int_<0>
>::type base_index; >::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 BOOST_CONCEPT_ASSERT
( (
(concept::PointSegmentDistanceStrategy<ds_type>) (concept::PointSegmentDistanceStrategy<ds_type, Point, Point>)
); );
Strategy *str = 0; Strategy *str = 0;
std::vector<point_type> const* v1 = 0; std::vector<Point> const* v1 = 0;
std::vector<point_type> * v2 = 0; std::vector<Point> * v2 = 0;
// 2) must implement method apply with arguments // 2) must implement method apply with arguments
// - Range // - Range
@ -96,8 +82,7 @@ private :
public : public :
BOOST_CONCEPT_USAGE(SimplifyStrategy) BOOST_CONCEPT_USAGE(SimplifyStrategy)
{ {
checker::apply(&ds_type::apply); checker::apply(&ds_type::template apply<Point, Point>);
} }
#endif #endif
}; };

View File

@ -39,7 +39,9 @@ struct default_distance_result
point_tag, point_tag,
typename point_type<Geometry1>::type, typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type typename point_type<Geometry2>::type
>::type >::type,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type type; >::type type;
}; };

View File

@ -30,48 +30,17 @@ namespace strategy { namespace distance { namespace services
template <typename Strategy> struct tag {}; template <typename Strategy> struct tag {};
template <typename Strategy> struct return_type
template <typename Strategy, typename P1, typename P2>
struct return_type
{ {
BOOST_MPL_ASSERT_MSG BOOST_MPL_ASSERT_MSG
( (
false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>) false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy, P1, P2>)
); );
}; };
/*!
\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 template <typename Strategy> struct comparable_type
{ {
BOOST_MPL_ASSERT_MSG BOOST_MPL_ASSERT_MSG
@ -88,7 +57,8 @@ template <typename Strategy> struct get_comparable
); );
}; };
template <typename Strategy> struct result_from_distance {}; template <typename Strategy, typename P1, typename P2>
struct result_from_distance {};
// For point-segment only: // For point-segment only:

View File

@ -82,8 +82,7 @@ protected :
calculation_type sum; calculation_type sum;
// Distances are calculated on unit sphere here // Distances are calculated on unit sphere here
strategy::distance::haversine<PointOfSegment, PointOfSegment> strategy::distance::haversine<calculation_type> distance_over_unit_sphere;
distance_over_unit_sphere;
inline excess_sum() inline excess_sum()

View File

@ -21,6 +21,7 @@
#include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp> #include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/util/promote_floating_point.hpp> #include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/math.hpp> #include <boost/geometry/util/math.hpp>
@ -55,40 +56,35 @@ namespace strategy { namespace distance
*/ */
template template
< <
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void, typename CalculationType = void,
typename Strategy = typename services::default_strategy<point_tag, Point>::type typename Strategy = haversine<double, CalculationType>
> >
class cross_track class cross_track
{ {
public : public :
typedef typename promote_floating_point template <typename Point, typename PointOfSegment>
< struct return_type
typename select_calculation_type : promote_floating_point
< <
Point, typename select_calculation_type
PointOfSegment, <
CalculationType Point,
>::type PointOfSegment,
>::type return_type; CalculationType
>::type
>
{};
inline cross_track() inline cross_track()
{ {}
m_strategy = Strategy();
m_radius = m_strategy.radius();
}
inline cross_track(return_type const& r) explicit inline cross_track(typename Strategy::radius_type const& r)
: m_radius(r) : m_strategy(r)
, m_strategy(r)
{} {}
inline cross_track(Strategy const& s) inline cross_track(Strategy const& s)
: m_strategy(s) : m_strategy(s)
{ {}
m_radius = m_strategy.radius();
}
// It might be useful in the future // It might be useful in the future
@ -96,9 +92,16 @@ public :
// crosstrack(...) {} // crosstrack(...) {}
inline return_type apply(Point const& p, template <typename Point, typename PointOfSegment>
PointOfSegment const& sp1, PointOfSegment const& sp2) const inline typename return_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const
{ {
BOOST_CONCEPT_ASSERT(
(concept::PointDistanceStrategy<Strategy, Point, PointOfSegment>)
);
typedef typename return_type<Point, PointOfSegment>::type return_type;
// http://williams.best.vwh.net/avform.htm#XTE // http://williams.best.vwh.net/avform.htm#XTE
return_type d1 = m_strategy.apply(sp1, p); return_type d1 = m_strategy.apply(sp1, p);
return_type d3 = m_strategy.apply(sp1, sp2); return_type d3 = m_strategy.apply(sp1, sp2);
@ -132,7 +135,7 @@ public :
if(projection1 > 0.0 && projection2 > 0.0) if(projection1 > 0.0 && projection2 > 0.0)
{ {
return_type XTD = m_radius * geometry::math::abs( asin( sin( d1 / m_radius ) * sin( d_crs1 ) )); return_type XTD = radius() * geometry::math::abs( asin( sin( d1 / radius() ) * sin( d_crs1 ) ));
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Projection ON the segment" << std::endl; std::cout << "Projection ON the segment" << std::endl;
@ -153,23 +156,20 @@ public :
} }
} }
inline return_type radius() const { return m_radius; } inline typename Strategy::radius_type radius() const
{ return m_strategy.radius(); }
private : 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; Strategy m_strategy;
/// Calculate course (bearing) between two points. Might be moved to a "course formula" ... /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
inline return_type course(Point const& p1, Point const& p2) const template <typename Point>
inline typename return_type<Point, Point>::type
course(Point const& p1, Point const& p2) const
{ {
typedef typename return_type<Point, Point>::type return_type;
// http://williams.best.vwh.net/avform.htm#Crs // http://williams.best.vwh.net/avform.htm#Crs
return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1); return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
return_type cos_p2lat = cos(get_as_radian<1>(p2)); return_type cos_p2lat = cos(get_as_radian<1>(p2));
@ -188,84 +188,32 @@ private :
namespace services namespace services
{ {
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy>
struct tag<cross_track<Point, PointOfSegment, CalculationType, Strategy> > struct tag<cross_track<CalculationType, Strategy> >
{ {
typedef strategy_tag_distance_point_segment type; typedef strategy_tag_distance_point_segment type;
}; };
template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy> template <typename CalculationType, typename Strategy, typename P, typename PS>
struct return_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> > struct return_type<cross_track<CalculationType, Strategy>, P, PS>
{ : cross_track<CalculationType, Strategy>::template return_type<P, PS>
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 template
< <
typename Point, typename PointOfSegment,
typename CalculationType, typename CalculationType,
typename Strategy typename Strategy
> >
struct get_comparable<cross_track<Point, PointOfSegment, CalculationType, Strategy> > struct get_comparable<cross_track<CalculationType, Strategy> >
{ {
typedef typename comparable_type typedef typename comparable_type
< <
cross_track<Point, PointOfSegment, CalculationType, Strategy> cross_track<CalculationType, Strategy>
>::type comparable_type; >::type comparable_type;
public : public :
static inline comparable_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy) static inline comparable_type apply(cross_track<CalculationType, Strategy> const& strategy)
{ {
return comparable_type(strategy.radius()); return comparable_type(strategy.radius());
} }
@ -274,30 +222,29 @@ public :
template template
< <
typename Point, typename PointOfSegment,
typename CalculationType, typename CalculationType,
typename Strategy typename Strategy,
typename P, typename PS
> >
struct result_from_distance<cross_track<Point, PointOfSegment, CalculationType, Strategy> > struct result_from_distance<cross_track<CalculationType, Strategy>, P, PS>
{ {
private : private :
typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type return_type; typedef typename cross_track<CalculationType, Strategy>::template return_type<P, PS> return_type;
public : public :
template <typename T> template <typename T>
static inline return_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& , T const& distance) static inline return_type apply(cross_track<CalculationType, Strategy> const& , T const& distance)
{ {
return distance; return distance;
} }
}; };
template template
< <
typename Point, typename PointOfSegment,
typename CalculationType, typename CalculationType,
typename Strategy typename Strategy
> >
struct strategy_point_point<cross_track<Point, PointOfSegment, CalculationType, Strategy> > struct strategy_point_point<cross_track<CalculationType, Strategy> >
{ {
typedef Strategy type; typedef Strategy type;
}; };
@ -318,8 +265,6 @@ struct default_strategy
{ {
typedef cross_track typedef cross_track
< <
Point,
PointOfSegment,
void, void,
typename boost::mpl::if_ typename boost::mpl::if_
< <
@ -345,8 +290,6 @@ struct default_strategy
{ {
typedef cross_track typedef cross_track
< <
Point,
PointOfSegment,
void, void,
typename boost::mpl::if_ typename boost::mpl::if_
< <

View File

@ -39,52 +39,57 @@ namespace comparable
// - applying asin (which is strictly (monotone) increasing) // - applying asin (which is strictly (monotone) increasing)
template template
< <
typename Point1, typename RadiusType,
typename Point2 = Point1,
typename CalculationType = void typename CalculationType = void
> >
class haversine class haversine
{ {
public : public :
typedef typename promote_floating_point template <typename Point1, typename Point2>
< struct calculation_type
typename select_calculation_type : promote_floating_point
< <
Point1, typename select_calculation_type
Point2, <
CalculationType Point1,
>::type Point2,
>::type calculation_type; CalculationType
>::type
>
{};
inline haversine(calculation_type const& r = 1.0) typedef RadiusType radius_type;
explicit inline haversine(RadiusType const& r = 1.0)
: m_radius(r) : m_radius(r)
{} {}
template <typename Point1, typename Point2>
static inline calculation_type apply(Point1 const& p1, Point2 const& p2) static inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& p1, Point2 const& p2)
{ {
return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1), return calculate<typename calculation_type<Point1, Point2>::type>(
get_as_radian<0>(p2), get_as_radian<1>(p2)); 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 inline RadiusType radius() const
{ {
return m_radius; return m_radius;
} }
private : private :
template <typename R, typename T1, typename T2>
static inline calculation_type calculate(calculation_type const& lon1, static inline R calculate(T1 const& lon1, T1 const& lat1,
calculation_type const& lat1, T2 const& lon2, T2 const& lat2)
calculation_type const& lon2,
calculation_type const& lat2)
{ {
return math::hav(lat2 - lat1) return math::hav(lat2 - lat1)
+ cos(lat1) * cos(lat2) * math::hav(lon2 - lon1); + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
} }
calculation_type m_radius; RadiusType m_radius;
}; };
@ -117,23 +122,26 @@ A mathematically equivalent formula, which is less subject
*/ */
template template
< <
typename Point1, typename RadiusType,
typename Point2 = Point1,
typename CalculationType = void typename CalculationType = void
> >
class haversine class haversine
{ {
typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type; typedef comparable::haversine<RadiusType, CalculationType> comparable_type;
public : public :
template <typename Point1, typename Point2>
struct calculation_type
: services::return_type<comparable_type, Point1, Point2>
{};
typedef typename services::return_type<comparable_type>::type calculation_type; typedef RadiusType radius_type;
/*! /*!
\brief Constructor \brief Constructor
\param radius radius of the sphere, defaults to 1.0 for the unit sphere \param radius radius of the sphere, defaults to 1.0 for the unit sphere
*/ */
inline haversine(calculation_type const& radius = 1.0) inline haversine(RadiusType const& radius = 1.0)
: m_radius(radius) : m_radius(radius)
{} {}
@ -143,8 +151,11 @@ public :
\param p1 first point \param p1 first point
\param p2 second point \param p2 second point
*/ */
inline calculation_type apply(Point1 const& p1, Point2 const& p2) const template <typename Point1, typename Point2>
inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& p1, Point2 const& p2) const
{ {
typedef typename calculation_type<Point1, Point2>::type calculation_type;
calculation_type const a = comparable_type::apply(p1, p2); calculation_type const a = comparable_type::apply(p1, p2);
calculation_type const c = calculation_type(2.0) * asin(sqrt(a)); calculation_type const c = calculation_type(2.0) * asin(sqrt(a));
return m_radius * c; return m_radius * c;
@ -154,13 +165,13 @@ public :
\brief access to radius value \brief access to radius value
\return the radius \return the radius
*/ */
inline calculation_type radius() const inline RadiusType radius() const
{ {
return m_radius; return m_radius;
} }
private : private :
calculation_type m_radius; RadiusType m_radius;
}; };
@ -168,52 +179,32 @@ private :
namespace services namespace services
{ {
template <typename Point1, typename Point2, typename CalculationType> template <typename RadiusType, typename CalculationType>
struct tag<haversine<Point1, Point2, CalculationType> > struct tag<haversine<RadiusType, CalculationType> >
{ {
typedef strategy_tag_distance_point_point type; typedef strategy_tag_distance_point_point type;
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename RadiusType, typename CalculationType, typename P1, typename P2>
struct return_type<haversine<Point1, Point2, CalculationType> > struct return_type<haversine<RadiusType, CalculationType>, P1, P2>
: haversine<RadiusType, CalculationType>::template calculation_type<P1, P2>
{};
template <typename RadiusType, typename CalculationType>
struct comparable_type<haversine<RadiusType, CalculationType> >
{ {
typedef typename haversine<Point1, Point2, CalculationType>::calculation_type type; typedef comparable::haversine<RadiusType, CalculationType> type;
}; };
template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2> template <typename RadiusType, typename CalculationType>
struct similar_type<haversine<Point1, Point2, CalculationType>, P1, P2> struct get_comparable<haversine<RadiusType, CalculationType> >
{
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 : private :
typedef haversine<Point1, Point2, CalculationType> this_type; typedef haversine<RadiusType, CalculationType> this_type;
public : typedef comparable::haversine<RadiusType, CalculationType> comparable_type;
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 : public :
static inline comparable_type apply(this_type const& input) static inline comparable_type apply(this_type const& input)
{ {
@ -221,12 +212,12 @@ public :
} }
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename RadiusType, typename CalculationType, typename P1, typename P2>
struct result_from_distance<haversine<Point1, Point2, CalculationType> > struct result_from_distance<haversine<RadiusType, CalculationType>, P1, P2>
{ {
private : private :
typedef haversine<Point1, Point2, CalculationType> this_type; typedef haversine<RadiusType, CalculationType> this_type;
typedef typename return_type<this_type>::type return_type; typedef typename return_type<this_type, P1, P2>::type return_type;
public : public :
template <typename T> template <typename T>
static inline return_type apply(this_type const& , T const& value) static inline return_type apply(this_type const& , T const& value)
@ -237,51 +228,31 @@ public :
// Specializations for comparable::haversine // Specializations for comparable::haversine
template <typename Point1, typename Point2, typename CalculationType> template <typename RadiusType, typename CalculationType>
struct tag<comparable::haversine<Point1, Point2, CalculationType> > struct tag<comparable::haversine<RadiusType, CalculationType> >
{ {
typedef strategy_tag_distance_point_point type; typedef strategy_tag_distance_point_point type;
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename RadiusType, typename CalculationType, typename P1, typename P2>
struct return_type<comparable::haversine<Point1, Point2, CalculationType> > struct return_type<comparable::haversine<RadiusType, CalculationType>, P1, P2>
: comparable::haversine<RadiusType, CalculationType>::template calculation_type<P1, P2>
{};
template <typename RadiusType, typename CalculationType>
struct comparable_type<comparable::haversine<RadiusType, CalculationType> >
{ {
typedef typename comparable::haversine<Point1, Point2, CalculationType>::calculation_type type; typedef comparable::haversine<RadiusType, CalculationType> type;
}; };
template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2> template <typename RadiusType, typename CalculationType>
struct similar_type<comparable::haversine<Point1, Point2, CalculationType>, P1, P2> struct get_comparable<comparable::haversine<RadiusType, CalculationType> >
{
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 : private :
typedef comparable::haversine<Point1, Point2, CalculationType> this_type; typedef comparable::haversine<RadiusType, 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 : public :
static inline this_type apply(this_type const& input) static inline this_type apply(this_type const& input)
{ {
@ -290,12 +261,12 @@ public :
}; };
template <typename Point1, typename Point2, typename CalculationType> template <typename RadiusType, typename CalculationType, typename P1, typename P2>
struct result_from_distance<comparable::haversine<Point1, Point2, CalculationType> > struct result_from_distance<comparable::haversine<RadiusType, CalculationType>, P1, P2>
{ {
private : private :
typedef comparable::haversine<Point1, Point2, CalculationType> strategy_type; typedef comparable::haversine<RadiusType, CalculationType> strategy_type;
typedef typename return_type<strategy_type>::type return_type; typedef typename return_type<strategy_type, P1, P2>::type return_type;
public : public :
template <typename T> template <typename T>
static inline return_type apply(strategy_type const& strategy, T const& distance) static inline return_type apply(strategy_type const& strategy, T const& distance)
@ -311,7 +282,7 @@ public :
template <typename Point1, typename Point2> template <typename Point1, typename Point2>
struct default_strategy<point_tag, Point1, Point2, spherical_equatorial_tag, spherical_equatorial_tag> struct default_strategy<point_tag, Point1, Point2, spherical_equatorial_tag, spherical_equatorial_tag>
{ {
typedef strategy::distance::haversine<Point1, Point2> type; typedef strategy::distance::haversine<typename select_coordinate_type<Point1, Point2>::type> type;
}; };
// Note: spherical polar coordinate system requires "get_as_radian_equatorial" // Note: spherical polar coordinate system requires "get_as_radian_equatorial"

View File

@ -71,12 +71,12 @@ void test_distance_point()
{ {
// Test custom strategy // Test custom strategy
BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<taxicab_distance<P> >) ); BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<taxicab_distance, P, P>) );
typedef typename services::return_type<taxicab_distance<P> >::type cab_return_type; typedef typename services::return_type<taxicab_distance, P, P>::type cab_return_type;
BOOST_MPL_ASSERT((boost::is_same<cab_return_type, typename bg::coordinate_type<P>::type>)); BOOST_MPL_ASSERT((boost::is_same<cab_return_type, typename bg::coordinate_type<P>::type>));
taxicab_distance<P> tcd; taxicab_distance tcd;
cab_return_type d = bg::distance(p1, p2, tcd); cab_return_type d = bg::distance(p1, p2, tcd);
BOOST_CHECK( bg::math::abs(d - cab_return_type(2)) <= cab_return_type(0.01) ); BOOST_CHECK( bg::math::abs(d - cab_return_type(2)) <= cab_return_type(0.01) );
@ -90,7 +90,7 @@ void test_distance_point()
strategy_type strategy; strategy_type strategy;
comparable_strategy_type comparable_strategy = services::get_comparable<strategy_type>::apply(strategy); comparable_strategy_type comparable_strategy = services::get_comparable<strategy_type>::apply(strategy);
return_type comparable = services::result_from_distance<comparable_strategy_type>::apply(comparable_strategy, 3); return_type comparable = services::result_from_distance<comparable_strategy_type, P, P>::apply(comparable_strategy, 3);
BOOST_CHECK_CLOSE(comparable, return_type(9), 0.001); BOOST_CHECK_CLOSE(comparable, return_type(9), 0.001);
} }
@ -145,7 +145,7 @@ void test_distance_segment()
BOOST_CHECK_CLOSE(d1, return_type(1), 0.001); BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
// 3) custom point strategy // 3) custom point strategy
taxicab_distance<P> tcd; taxicab_distance tcd;
d1 = bg::distance(p1, seg, tcd); d1 = bg::distance(p1, seg, tcd);
BOOST_CHECK_CLOSE(d1, return_type(1), 0.001); BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
} }

View File

@ -24,9 +24,9 @@
// For a point-segment-distance operation, there is some magic inside // For a point-segment-distance operation, there is some magic inside
// using another point type and casting if necessary. Therefore, // using another point type and casting if necessary. Therefore,
// two point-types are necessary. // two point-types are necessary.
template <typename P1, typename P2 = P1>
struct taxicab_distance struct taxicab_distance
{ {
template <typename P1, typename P2>
static inline typename bg::coordinate_type<P1>::type apply( static inline typename bg::coordinate_type<P1>::type apply(
P1 const& p1, P2 const& p2) P1 const& p1, P2 const& p2)
{ {
@ -42,59 +42,40 @@ struct taxicab_distance
namespace boost { namespace geometry { namespace strategy { namespace distance { namespace services namespace boost { namespace geometry { namespace strategy { namespace distance { namespace services
{ {
template <typename P1, typename P2> template <>
struct tag<taxicab_distance<P1, P2> > struct tag<taxicab_distance>
{ {
typedef strategy_tag_distance_point_point type; typedef strategy_tag_distance_point_point type;
}; };
template <typename P1, typename P2> template <typename P1, typename P2>
struct return_type<taxicab_distance<P1, P2> > struct return_type<taxicab_distance, P1, P2>
{ {
typedef typename coordinate_type<P1>::type type; typedef typename coordinate_type<P1>::type type;
}; };
template<typename P1, typename P2, typename PN1, typename PN2> template <>
struct similar_type<taxicab_distance<P1, P2>, PN1, PN2> struct comparable_type<taxicab_distance>
{ {
typedef taxicab_distance<PN1, PN2> type; typedef taxicab_distance type;
}; };
template <>
template<typename P1, typename P2, typename PN1, typename PN2> struct get_comparable<taxicab_distance>
struct get_similar<taxicab_distance<P1, P2>, PN1, PN2>
{ {
static inline typename similar_type static inline taxicab_distance apply(taxicab_distance const& input)
<
taxicab_distance<P1, P2>, PN1, PN2
>::type apply(taxicab_distance<P1, P2> const& )
{
return taxicab_distance<PN1, PN2>();
}
};
template <typename P1, typename P2>
struct comparable_type<taxicab_distance<P1, P2> >
{
typedef taxicab_distance<P1, P2> type;
};
template <typename P1, typename P2>
struct get_comparable<taxicab_distance<P1, P2> >
{
static inline taxicab_distance<P1, P2> apply(taxicab_distance<P1, P2> const& input)
{ {
return input; return input;
} }
}; };
template <typename P1, typename P2> template <typename P1, typename P2>
struct result_from_distance<taxicab_distance<P1, P2> > struct result_from_distance<taxicab_distance, P1, P2>
{ {
template <typename T> template <typename T>
static inline typename coordinate_type<P1>::type apply(taxicab_distance<P1, P2> const& , T const& value) static inline typename coordinate_type<P1>::type apply(taxicab_distance const& , T const& value)
{ {
return value; return value;
} }

View File

@ -64,18 +64,14 @@ void test_geometry(std::string const& wkt, std::string const& expected, double d
// Check using user-specified strategy // Check using user-specified strategy
typedef typename bg::point_type<Geometry>::type point_type; typedef typename bg::point_type<Geometry>::type point_type;
typedef typename bg::cs_tag<point_type>::type tag; typedef typename bg::cs_tag<point_type>::type tag;
typedef bg::strategy::distance::projected_point typedef bg::strategy::distance::projected_point<double> strategy;
<
point_type,
point_type
> strategy;
typedef bg::strategy::simplify::douglas_peucker typedef bg::strategy::simplify::douglas_peucker
< <
point_type, point_type,
strategy strategy
> simplify_strategy_type; > simplify_strategy_type;
BOOST_CONCEPT_ASSERT( (bg::concept::SimplifyStrategy<simplify_strategy_type>) ); BOOST_CONCEPT_ASSERT( (bg::concept::SimplifyStrategy<simplify_strategy_type, point_type>) );
bg::simplify(geometry, simplified, distance, simplify_strategy_type()); bg::simplify(geometry, simplified, distance, simplify_strategy_type());
{ {

View File

@ -74,7 +74,7 @@ void test_2d()
test_distance<ml, mp>("MULTILINESTRING((1 1,2 2),(1 0,2 0),(0 2,0 3))", "MULTIPOINT((0 0),(1 1))", 0.0); test_distance<ml, mp>("MULTILINESTRING((1 1,2 2),(1 0,2 0),(0 2,0 3))", "MULTIPOINT((0 0),(1 1))", 0.0);
// Test with a strategy // Test with a strategy
bg::strategy::distance::pythagoras<P, P> pyth; bg::strategy::distance::pythagoras<> pyth;
test_distance<P, P>(pyth, "POINT(0 0)", "POINT(1 1)", sqrt(2.0)); test_distance<P, P>(pyth, "POINT(0 0)", "POINT(1 1)", sqrt(2.0));
test_distance<P, mp>(pyth, "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); test_distance<P, mp>(pyth, "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0);
test_distance<mp, P>(pyth, "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); test_distance<mp, P>(pyth, "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0);
@ -116,18 +116,18 @@ void test_mixed()
// Test with a strategy // Test with a strategy
using namespace bg::strategy::distance; using namespace bg::strategy::distance;
test_distance<P1, P2>(pythagoras<P1, P2>(), "POINT(0 0)", "POINT(1 1)", sqrt(2.0)); test_distance<P1, P2>(pythagoras<>(), "POINT(0 0)", "POINT(1 1)", sqrt(2.0));
test_distance<P1, mp1>(pythagoras<P1, P1>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); test_distance<P1, mp1>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0);
test_distance<P1, mp2>(pythagoras<P1, P2>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); test_distance<P1, mp2>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0);
test_distance<P2, mp1>(pythagoras<P2, P1>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); test_distance<P2, mp1>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0);
test_distance<P2, mp2>(pythagoras<P2, P2>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); test_distance<P2, mp2>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0);
// Most interesting: reversal AND a strategy (note that the stategy must be reversed automatically // Most interesting: reversal AND a strategy (note that the stategy must be reversed automatically
test_distance<mp1, P1>(pythagoras<P1, P1>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); test_distance<mp1, P1>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0);
test_distance<mp1, P2>(pythagoras<P1, P2>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); test_distance<mp1, P2>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0);
test_distance<mp2, P1>(pythagoras<P2, P1>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); test_distance<mp2, P1>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0);
test_distance<mp2, P2>(pythagoras<P2, P2>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); test_distance<mp2, P2>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0);
} }
template <typename P> template <typename P>

View File

@ -46,18 +46,20 @@ void test_distance(
{ {
typedef bg::strategy::distance::cross_track typedef bg::strategy::distance::cross_track
< <
Point, typename bg::coordinate_type<Point>::type
Point
> strategy_type; > strategy_type;
typedef typename bg::strategy::distance::services::return_type typedef typename bg::strategy::distance::services::return_type
< <
strategy_type strategy_type,
Point,
Point
>::type return_type; >::type return_type;
BOOST_CONCEPT_ASSERT BOOST_CONCEPT_ASSERT
( (
(bg::concept::PointSegmentDistanceStrategy<strategy_type>) (bg::concept::PointSegmentDistanceStrategy<strategy_type, Point, Point>)
); );
@ -72,6 +74,10 @@ void test_distance(
BOOST_CHECK_CLOSE(radius * d, expected, tolerance); BOOST_CHECK_CLOSE(radius * d, expected, tolerance);
// The strategy should return the same result if we reverse the parameters
d = strategy.apply(p1, p3, p2);
BOOST_CHECK_CLOSE(radius * d, expected, tolerance);
// Test specifying radius explicitly // Test specifying radius explicitly
strategy_type strategy_radius(radius); strategy_type strategy_radius(radius);
d = strategy_radius.apply(p1, p2, p3); d = strategy_radius.apply(p1, p2, p3);

View File

@ -37,25 +37,17 @@ double const average_earth_radius = 6372795.0;
template <typename Point, typename LatitudePolicy> template <typename Point, typename LatitudePolicy>
struct test_distance struct test_distance
{ {
typedef bg::strategy::distance::haversine typedef bg::strategy::distance::haversine<double> haversine_type;
< typedef typename bg::strategy::distance::services::return_type<haversine_type, Point, Point>::type return_type;
Point,
Point
> haversine_type;
BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<haversine_type>) );
typedef typename bg::strategy::distance::services::return_type<haversine_type>::type return_type;
BOOST_CONCEPT_ASSERT BOOST_CONCEPT_ASSERT
( (
(bg::concept::PointDistanceStrategy<haversine_type>) (bg::concept::PointDistanceStrategy<haversine_type, Point, Point>)
); );
static void test(double lon1, double lat1, double lon2, double lat2, static void test(double lon1, double lat1, double lon2, double lat2,
double radius, return_type expected, double tolerance) double radius, double expected, double tolerance)
{ {
haversine_type strategy(radius); haversine_type strategy(radius);
@ -117,21 +109,15 @@ void test_services()
// 1: normal, calculate distance: // 1: normal, calculate distance:
typedef bgsd::haversine<P1, P2, CalculationType> strategy_type; typedef bgsd::haversine<double, CalculationType> strategy_type;
typedef typename bgsd::services::return_type<strategy_type>::type return_type; typedef typename bgsd::services::return_type<strategy_type, P1, P2>::type return_type;
strategy_type strategy(average_earth_radius); strategy_type strategy(average_earth_radius);
return_type result = strategy.apply(p1, p2); return_type result = strategy.apply(p1, p2);
BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
// 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1 // 2: the strategy should return the same result if we reverse parameters
// 2a: similar_type: result = strategy.apply(p2, p1);
typedef typename services::similar_type<strategy_type, P2, P1>::type similar_type;
// 2b: get_similar
similar_type similar = services::get_similar<strategy_type, P2, P1>::apply(strategy);
//result = similar.apply(p1, p2); // should NOT compile because p1/p2 should also be reversed here
result = similar.apply(p2, p1);
BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
@ -149,14 +135,14 @@ void test_services()
// First the result of the comparable strategy // First the result of the comparable strategy
return_type c_result = comparable.apply(p1, p2); return_type c_result = comparable.apply(p1, p2);
// Second the comparable result of the expected distance // Second the comparable result of the expected distance
return_type c_expected = services::result_from_distance<comparable_type>::apply(comparable, expected); return_type c_expected = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, expected);
// And that one should be equa. // And that one should be equa.
BOOST_CHECK_CLOSE(c_result, return_type(c_expected), 0.001); BOOST_CHECK_CLOSE(c_result, return_type(c_expected), 0.001);
// 4: the comparable_type should have a distance_strategy_constructor as well, // 4: the comparable_type should have a distance_strategy_constructor as well,
// knowing how to compare something with a fixed distance // knowing how to compare something with a fixed distance
return_type c_dist_lower = services::result_from_distance<comparable_type>::apply(comparable, expected_lower); return_type c_dist_lower = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, expected_lower);
return_type c_dist_higher = services::result_from_distance<comparable_type>::apply(comparable, expected_higher); return_type c_dist_higher = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, expected_higher);
// If this is the case: // If this is the case:
BOOST_CHECK(c_dist_lower < c_result && c_result < c_dist_higher); BOOST_CHECK(c_dist_lower < c_result && c_result < c_dist_higher);
@ -166,8 +152,8 @@ void test_services()
BOOST_CHECK_CLOSE(c_check, expected, 0.001); BOOST_CHECK_CLOSE(c_check, expected, 0.001);
// This should also be the case // This should also be the case
return_type dist_lower = services::result_from_distance<strategy_type>::apply(strategy, expected_lower); return_type dist_lower = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, expected_lower);
return_type dist_higher = services::result_from_distance<strategy_type>::apply(strategy, expected_higher); return_type dist_higher = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, expected_higher);
BOOST_CHECK(dist_lower < result && result < dist_higher); BOOST_CHECK(dist_lower < result && result < dist_higher);
} }
@ -194,8 +180,8 @@ void time_compare_s(int const n)
template <typename P> template <typename P>
void time_compare(int const n) void time_compare(int const n)
{ {
time_compare_s<P, bg::strategy::distance::haversine<P> >(n); time_compare_s<P, bg::strategy::distance::haversine<double> >(n);
time_compare_s<P, bg::strategy::distance::comparable::haversine<P> >(n); time_compare_s<P, bg::strategy::distance::comparable::haversine<double> >(n);
} }
#include <time.h> #include <time.h>

View File

@ -52,23 +52,18 @@ void test_services()
namespace services = bg::strategy::distance::services; namespace services = bg::strategy::distance::services;
// 1: normal, calculate distance: // 1: normal, calculate distance:
typedef bgsd::projected_point<P, PS, CalculationType> strategy_type; typedef bgsd::projected_point<CalculationType> strategy_type;
BOOST_CONCEPT_ASSERT( (bg::concept::PointSegmentDistanceStrategy<strategy_type>) ); BOOST_CONCEPT_ASSERT( (bg::concept::PointSegmentDistanceStrategy<strategy_type, P, PS>) );
typedef typename services::return_type<strategy_type>::type return_type; typedef typename services::return_type<strategy_type, P, PS>::type return_type;
strategy_type strategy; strategy_type strategy;
return_type result = strategy.apply(p, p1, p2); return_type result = strategy.apply(p, p1, p2);
BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
// 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1 // 2: the strategy should return the same result if we reverse parameters
// 2a: similar_type: result = strategy.apply(p, p1, p2);
typedef typename services::similar_type<strategy_type, P, PS>::type similar_type;
// 2b: get_similar
similar_type similar = services::get_similar<strategy_type, P, PS>::apply(strategy);
result = similar.apply(p, p1, p2);
BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
@ -100,19 +95,15 @@ void test_all_2d(std::string const& wkt_p,
bg::read_wkt(wkt_sp2, sp2); bg::read_wkt(wkt_sp2, sp2);
{ {
typedef bg::strategy::distance::projected_point typedef bg::strategy::distance::projected_point<> strategy_type;
<
P1,
P2
> strategy_type;
BOOST_CONCEPT_ASSERT BOOST_CONCEPT_ASSERT
( (
(bg::concept::PointSegmentDistanceStrategy<strategy_type>) (bg::concept::PointSegmentDistanceStrategy<strategy_type, P1, P2>)
); );
strategy_type strategy; strategy_type strategy;
typedef typename bg::strategy::distance::services::return_type<strategy_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<strategy_type, P1, P2>::type return_type;
return_type d = strategy.apply(p, sp1, sp2); return_type d = strategy.apply(p, sp1, sp2);
BOOST_CHECK_CLOSE(d, expected_distance, 0.001); BOOST_CHECK_CLOSE(d, expected_distance, 0.001);
} }
@ -121,13 +112,11 @@ void test_all_2d(std::string const& wkt_p,
{ {
typedef bg::strategy::distance::projected_point typedef bg::strategy::distance::projected_point
< <
P1,
P2,
void, void,
bg::strategy::distance::comparable::pythagoras<P1, P2> bg::strategy::distance::comparable::pythagoras<>
> strategy_type; > strategy_type;
strategy_type strategy; strategy_type strategy;
typedef typename bg::strategy::distance::services::return_type<strategy_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<strategy_type, P1, P2>::type return_type;
return_type d = strategy.apply(p, sp1, sp2); return_type d = strategy.apply(p, sp1, sp2);
T expected_squared_distance = expected_distance * expected_distance; T expected_squared_distance = expected_distance * expected_distance;
BOOST_CHECK_CLOSE(d, expected_squared_distance, 0.01); BOOST_CHECK_CLOSE(d, expected_squared_distance, 0.01);

View File

@ -51,8 +51,8 @@ void test_null_distance_3d()
P2 p2; P2 p2;
bg::assign_values(p2, 1, 2, 3); bg::assign_values(p2, 1, 2, 3);
typedef bg::strategy::distance::pythagoras<P1, P2> pythagoras_type; typedef bg::strategy::distance::pythagoras<> pythagoras_type;
typedef typename bg::strategy::distance::services::return_type<pythagoras_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<pythagoras_type, P1, P2>::type return_type;
pythagoras_type pythagoras; pythagoras_type pythagoras;
return_type result = pythagoras.apply(p1, p2); return_type result = pythagoras.apply(p1, p2);
@ -68,8 +68,8 @@ void test_axis_3d()
P2 p2; P2 p2;
bg::assign_values(p2, 1, 0, 0); bg::assign_values(p2, 1, 0, 0);
typedef bg::strategy::distance::pythagoras<P1, P2> pythagoras_type; typedef bg::strategy::distance::pythagoras<> pythagoras_type;
typedef typename bg::strategy::distance::services::return_type<pythagoras_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<pythagoras_type, P1, P2>::type return_type;
pythagoras_type pythagoras; pythagoras_type pythagoras;
@ -94,8 +94,8 @@ void test_arbitrary_3d()
bg::assign_values(p2, 9, 8, 7); bg::assign_values(p2, 9, 8, 7);
{ {
typedef bg::strategy::distance::pythagoras<P1, P2> strategy_type; typedef bg::strategy::distance::pythagoras<> strategy_type;
typedef typename bg::strategy::distance::services::return_type<strategy_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<strategy_type, P1, P2>::type return_type;
strategy_type strategy; strategy_type strategy;
return_type result = strategy.apply(p1, p2); return_type result = strategy.apply(p1, p2);
@ -104,8 +104,8 @@ void test_arbitrary_3d()
{ {
// Check comparable distance // Check comparable distance
typedef bg::strategy::distance::comparable::pythagoras<P1, P2> strategy_type; typedef bg::strategy::distance::comparable::pythagoras<> strategy_type;
typedef typename bg::strategy::distance::services::return_type<strategy_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<strategy_type, P1, P2>::type return_type;
strategy_type strategy; strategy_type strategy;
return_type result = strategy.apply(p1, p2); return_type result = strategy.apply(p1, p2);
@ -137,24 +137,18 @@ void test_services()
// 1: normal, calculate distance: // 1: normal, calculate distance:
typedef bgsd::pythagoras<P1, P2, CalculationType> strategy_type; typedef bgsd::pythagoras<CalculationType> strategy_type;
BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<strategy_type>) ); BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<strategy_type, P1, P2>) );
typedef typename bgsd::services::return_type<strategy_type>::type return_type; typedef typename bgsd::services::return_type<strategy_type, P1, P2>::type return_type;
strategy_type strategy; strategy_type strategy;
return_type result = strategy.apply(p1, p2); return_type result = strategy.apply(p1, p2);
BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
// 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1 // 2: the strategy should return the same result if we reverse parameters
// 2a: similar_type: result = strategy.apply(p2, p1);
typedef typename services::similar_type<strategy_type, P2, P1>::type similar_type;
// 2b: get_similar
similar_type similar = services::get_similar<strategy_type, P2, P1>::apply(strategy);
//result = similar.apply(p1, p2); // should NOT compile because p1/p2 should also be reversed here
result = similar.apply(p2, p1);
BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
@ -173,15 +167,15 @@ void test_services()
// 4: the comparable_type should have a distance_strategy_constructor as well, // 4: the comparable_type should have a distance_strategy_constructor as well,
// knowing how to compare something with a fixed distance // knowing how to compare something with a fixed distance
return_type c_dist5 = services::result_from_distance<comparable_type>::apply(comparable, 5.0); return_type c_dist5 = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, 5.0);
return_type c_dist6 = services::result_from_distance<comparable_type>::apply(comparable, 6.0); return_type c_dist6 = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, 6.0);
// If this is the case: // If this is the case:
BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6); BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6);
// This should also be the case // This should also be the case
return_type dist5 = services::result_from_distance<strategy_type>::apply(strategy, 5.0); return_type dist5 = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, 5.0);
return_type dist6 = services::result_from_distance<strategy_type>::apply(strategy, 6.0); return_type dist6 = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, 6.0);
BOOST_CHECK(dist5 < result && result < dist6); BOOST_CHECK(dist5 < result && result < dist6);
} }
@ -191,15 +185,10 @@ void test_big_2d_with(AssignType const& x1, AssignType const& y1,
AssignType const& x2, AssignType const& y2) AssignType const& x2, AssignType const& y2)
{ {
typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type;
typedef bg::strategy::distance::pythagoras typedef bg::strategy::distance::pythagoras<CalculationType> pythagoras_type;
<
point_type,
point_type,
CalculationType
> pythagoras_type;
pythagoras_type pythagoras; pythagoras_type pythagoras;
typedef typename bg::strategy::distance::services::return_type<pythagoras_type>::type return_type; typedef typename bg::strategy::distance::services::return_type<pythagoras_type, point_type, point_type>::type return_type;
point_type p1, p2; point_type p1, p2;
@ -242,10 +231,7 @@ void test_integer(bool check_types)
bg::assign_values(p1, 12345678, 23456789); bg::assign_values(p1, 12345678, 23456789);
bg::assign_values(p2, 98765432, 87654321); bg::assign_values(p2, 98765432, 87654321);
typedef bg::strategy::distance::pythagoras typedef bg::strategy::distance::pythagoras<> pythagoras_type;
<
point_type
> pythagoras_type;
pythagoras_type pythagoras; pythagoras_type pythagoras;
BOOST_AUTO(distance, pythagoras.apply(p1, p2)); BOOST_AUTO(distance, pythagoras.apply(p1, p2));
BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001); BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001);
@ -300,7 +286,7 @@ void time_compare_s(int const n)
bg::assign_values(p1, 1, 1); bg::assign_values(p1, 1, 1);
bg::assign_values(p2, 2, 2); bg::assign_values(p2, 2, 2);
Strategy strategy; Strategy strategy;
typename bg::strategy::distance::services::return_type<Strategy>::type s = 0; typename bg::strategy::distance::services::return_type<Strategy, P, P>::type s = 0;
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
for (int j = 0; j < n; j++) for (int j = 0; j < n; j++)
@ -315,8 +301,8 @@ void time_compare_s(int const n)
template <typename P> template <typename P>
void time_compare(int const n) void time_compare(int const n)
{ {
time_compare_s<P, bg::strategy::distance::pythagoras<P> >(n); time_compare_s<P, bg::strategy::distance::pythagoras<> >(n);
time_compare_s<P, bg::strategy::distance::comparable::pythagoras<P> >(n); time_compare_s<P, bg::strategy::distance::comparable::pythagoras<> >(n);
} }
int test_main(int, char* []) int test_main(int, char* [])