blob: c8f567398f476dcad501e58f3a4b75d4e27a2e7e [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-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_TEST_DISTANCE_HPP
#define BOOST_GEOMETRY_TEST_DISTANCE_HPP
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/domains/gis/io/wkt/read_wkt.hpp>
#include <boost/geometry/strategies/strategies.hpp>
// Define a custom distance strategy
// For this one, the "taxicab" distance,
// see http://en.wikipedia.org/wiki/Taxicab_geometry
// For a point-point-distance operation, one typename Point is enough.
// For a point-segment-distance operation, there is some magic inside
// using another point type and casting if necessary. Therefore,
// two point-types are necessary.
template <typename P1, typename P2 = P1>
struct taxicab_distance
{
static inline typename bg::coordinate_type<P1>::type apply(
P1 const& p1, P2 const& p2)
{
using bg::get;
using bg::math::abs;
return abs(get<0>(p1) - get<1>(p2))
+ abs(get<1>(p1) - get<1>(p2));
}
};
namespace boost { namespace geometry { namespace strategy { namespace distance { namespace services
{
template <typename P1, typename P2>
struct tag<taxicab_distance<P1, P2> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename P1, typename P2>
struct return_type<taxicab_distance<P1, P2> >
{
typedef typename coordinate_type<P1>::type type;
};
template<typename P1, typename P2, typename PN1, typename PN2>
struct similar_type<taxicab_distance<P1, P2>, PN1, PN2>
{
typedef taxicab_distance<PN1, PN2> type;
};
template<typename P1, typename P2, typename PN1, typename PN2>
struct get_similar<taxicab_distance<P1, P2>, PN1, PN2>
{
static inline typename similar_type
<
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;
}
};
template <typename P1, typename P2>
struct result_from_distance<taxicab_distance<P1, P2> >
{
template <typename T>
static inline typename coordinate_type<P1>::type apply(taxicab_distance<P1, P2> const& , T const& value)
{
return value;
}
};
}}}}} // namespace bg::strategy::distance::services
template <typename Geometry1, typename Geometry2>
void test_distance(Geometry1 const& geometry1,
Geometry2 const& geometry2,
long double expected_distance)
{
typename bg::default_distance_result<Geometry1>::type distance = bg::distance(geometry1, geometry2);
#ifdef GEOMETRY_TEST_DEBUG
std::ostringstream out;
out << typeid(typename bg::coordinate_type<Geometry1>::type).name()
<< std::endl
<< typeid(typename bg::default_distance_result<Geometry1>::type).name()
<< std::endl
<< "distance : " << bg::distance(geometry1, geometry2)
<< std::endl;
std::cout << out.str();
#endif
BOOST_CHECK_CLOSE(distance, expected_distance, 0.0001);
}
template <typename Geometry1, typename Geometry2>
void test_geometry(std::string const& wkt1, std::string const& wkt2, double expected_distance)
{
Geometry1 geometry1;
bg::read_wkt(wkt1, geometry1);
Geometry2 geometry2;
bg::read_wkt(wkt2, geometry2);
test_distance(geometry1, geometry2, expected_distance);
}
#endif