mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-10 15:44:07 +00:00
[equals] use collected_vector as a type, no specialization (review result)
This commit is contained in:
parent
609196e711
commit
f46a2c261e
@ -46,25 +46,16 @@
|
|||||||
namespace boost { namespace geometry
|
namespace boost { namespace geometry
|
||||||
{
|
{
|
||||||
|
|
||||||
template
|
|
||||||
<
|
|
||||||
typename T,
|
|
||||||
typename Geometry,
|
|
||||||
typename CSTag = typename cs_tag<Geometry>::type
|
|
||||||
>
|
|
||||||
struct collected_vector
|
|
||||||
: nyi::not_implemented_tag
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename T, typename Geometry>
|
template <typename T>
|
||||||
struct collected_vector<T, Geometry, cartesian_tag>
|
struct collected_vector_cartesian
|
||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
inline collected_vector()
|
inline collected_vector_cartesian()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline collected_vector(T const& px, T const& py,
|
inline collected_vector_cartesian(T const& px, T const& py,
|
||||||
T const& pdx, T const& pdy)
|
T const& pdx, T const& pdy)
|
||||||
: x(px)
|
: x(px)
|
||||||
, y(py)
|
, y(py)
|
||||||
@ -75,7 +66,7 @@ struct collected_vector<T, Geometry, cartesian_tag>
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename Point>
|
template <typename Point>
|
||||||
inline collected_vector(Point const& p1, Point const& p2)
|
inline collected_vector_cartesian(Point const& p1, Point const& p2)
|
||||||
: x(get<0>(p1))
|
: x(get<0>(p1))
|
||||||
, y(get<1>(p1))
|
, y(get<1>(p1))
|
||||||
, dx(get<0>(p2) - x)
|
, dx(get<0>(p2) - x)
|
||||||
@ -100,7 +91,7 @@ struct collected_vector<T, Geometry, cartesian_tag>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For sorting
|
// For sorting
|
||||||
inline bool operator<(collected_vector const& other) const
|
inline bool operator<(collected_vector_cartesian const& other) const
|
||||||
{
|
{
|
||||||
if (math::equals(x, other.x))
|
if (math::equals(x, other.x))
|
||||||
{
|
{
|
||||||
@ -117,13 +108,13 @@ struct collected_vector<T, Geometry, cartesian_tag>
|
|||||||
return x < other.x;
|
return x < other.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool next_is_collinear(collected_vector const& other) const
|
inline bool next_is_collinear(collected_vector_cartesian const& other) const
|
||||||
{
|
{
|
||||||
return same_direction(other);
|
return same_direction(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For std::equals
|
// For std::equals
|
||||||
inline bool operator==(collected_vector const& other) const
|
inline bool operator==(collected_vector_cartesian const& other) const
|
||||||
{
|
{
|
||||||
return math::equals(x, other.x)
|
return math::equals(x, other.x)
|
||||||
&& math::equals(y, other.y)
|
&& math::equals(y, other.y)
|
||||||
@ -131,7 +122,7 @@ struct collected_vector<T, Geometry, cartesian_tag>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline bool same_direction(collected_vector const& other) const
|
inline bool same_direction(collected_vector_cartesian const& other) const
|
||||||
{
|
{
|
||||||
// For high precision arithmetic, we have to be
|
// For high precision arithmetic, we have to be
|
||||||
// more relaxed then using ==
|
// more relaxed then using ==
|
||||||
@ -149,35 +140,32 @@ private:
|
|||||||
// Compatible with spherical_side_formula which currently
|
// Compatible with spherical_side_formula which currently
|
||||||
// is the default spherical_equatorial and geographic strategy
|
// is the default spherical_equatorial and geographic strategy
|
||||||
// so CSTag is spherical_equatorial_tag or geographic_tag
|
// so CSTag is spherical_equatorial_tag or geographic_tag
|
||||||
template <typename T, typename Geometry>
|
template <typename T, typename Point>
|
||||||
struct collected_vector<T, Geometry, spherical_equatorial_tag>
|
struct collected_vector_spherical
|
||||||
{
|
{
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
|
||||||
typedef typename geometry::detail::cs_angular_units<Geometry>::type units_type;
|
|
||||||
typedef model::point<T, 2, cs::spherical_equatorial<units_type> > point_type;
|
|
||||||
typedef model::point<T, 3, cs::cartesian> vector_type;
|
typedef model::point<T, 3, cs::cartesian> vector_type;
|
||||||
|
|
||||||
collected_vector()
|
collected_vector_spherical()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename Point>
|
collected_vector_spherical(Point const& p1, Point const& p2)
|
||||||
collected_vector(Point const& p1, Point const& p2)
|
|
||||||
: origin(get<0>(p1), get<1>(p1))
|
: origin(get<0>(p1), get<1>(p1))
|
||||||
{
|
{
|
||||||
origin = detail::return_normalized<point_type>(
|
origin = detail::return_normalized<Point>(
|
||||||
origin,
|
origin,
|
||||||
strategy::normalize::spherical_point());
|
strategy::normalize::spherical_point());
|
||||||
|
|
||||||
using namespace geometry::formula;
|
using namespace geometry::formula;
|
||||||
prev = sph_to_cart3d<vector_type>(p1);
|
prev = sph_to_cart3d<vector_type>(p1);
|
||||||
next = sph_to_cart3d<vector_type>(p2);
|
next = sph_to_cart3d<vector_type>(p2);
|
||||||
direction = cross_product(prev, next);
|
cross = direction = cross_product(prev, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool normalize()
|
bool normalize()
|
||||||
{
|
{
|
||||||
T magnitude_sqr = dot_product(direction, direction);
|
T const magnitude_sqr = dot_product(direction, direction);
|
||||||
|
|
||||||
// NOTE: shouldn't here math::equals() be called?
|
// NOTE: shouldn't here math::equals() be called?
|
||||||
if (magnitude_sqr > 0)
|
if (magnitude_sqr > 0)
|
||||||
@ -189,7 +177,7 @@ struct collected_vector<T, Geometry, spherical_equatorial_tag>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(collected_vector const& other) const
|
bool operator<(collected_vector_spherical const& other) const
|
||||||
{
|
{
|
||||||
if (math::equals(get<0>(origin), get<0>(other.origin)))
|
if (math::equals(get<0>(origin), get<0>(other.origin)))
|
||||||
{
|
{
|
||||||
@ -213,13 +201,13 @@ struct collected_vector<T, Geometry, spherical_equatorial_tag>
|
|||||||
// For consistency with side and intersection strategies used by relops
|
// For consistency with side and intersection strategies used by relops
|
||||||
// IMPORTANT: this method should be called for previous vector
|
// IMPORTANT: this method should be called for previous vector
|
||||||
// and next vector should be passed as parameter
|
// and next vector should be passed as parameter
|
||||||
bool next_is_collinear(collected_vector const& other) const
|
bool next_is_collinear(collected_vector_spherical const& other) const
|
||||||
{
|
{
|
||||||
return formula::sph_side_value(direction, other.next) == 0;
|
return formula::sph_side_value(cross, other.next) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For std::equals
|
// For std::equals
|
||||||
bool operator==(collected_vector const& other) const
|
bool operator==(collected_vector_spherical const& other) const
|
||||||
{
|
{
|
||||||
return math::equals(get<0>(origin), get<0>(other.origin))
|
return math::equals(get<0>(origin), get<0>(other.origin))
|
||||||
&& math::equals(get<1>(origin), get<1>(other.origin))
|
&& math::equals(get<1>(origin), get<1>(other.origin))
|
||||||
@ -228,62 +216,57 @@ struct collected_vector<T, Geometry, spherical_equatorial_tag>
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// For consistency with side and intersection strategies used by relops
|
// For consistency with side and intersection strategies used by relops
|
||||||
bool is_collinear(collected_vector const& other) const
|
// NOTE: alternative would be to equal-compare direction's coordinates
|
||||||
|
// or to check if dot product of directions is equal to 1.
|
||||||
|
bool is_collinear(collected_vector_spherical const& other) const
|
||||||
{
|
{
|
||||||
return formula::sph_side_value(direction, other.prev) == 0
|
return formula::sph_side_value(cross, other.prev) == 0
|
||||||
&& formula::sph_side_value(direction, other.next) == 0;
|
&& formula::sph_side_value(cross, other.next) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bool same_direction(collected_vector const& other) const
|
Point origin; // used for sorting and equality check
|
||||||
{
|
|
||||||
return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction))
|
|
||||||
&& math::equals_with_epsilon(get<1>(direction), get<1>(other.direction))
|
|
||||||
&& math::equals_with_epsilon(get<2>(direction), get<2>(other.direction));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
point_type origin; // used for sorting and equality check
|
|
||||||
vector_type direction; // used for sorting, only in operator<
|
vector_type direction; // used for sorting, only in operator<
|
||||||
|
vector_type cross; // used for sorting, used for collinearity check
|
||||||
vector_type prev; // used for collinearity check, only in operator==
|
vector_type prev; // used for collinearity check, only in operator==
|
||||||
vector_type next; // used for collinearity check
|
vector_type next; // used for collinearity check
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for spherical polar
|
// Version for spherical polar
|
||||||
template <typename T, typename Geometry>
|
template <typename T, typename Point>
|
||||||
struct collected_vector<T, Geometry, spherical_polar_tag>
|
struct collected_vector_polar
|
||||||
: public collected_vector<T, Geometry, spherical_equatorial_tag>
|
: public collected_vector_spherical<T, Point>
|
||||||
{
|
{
|
||||||
typedef T type;
|
using type = T;
|
||||||
using base_type = collected_vector<T, Geometry, spherical_equatorial_tag>;
|
using base_point_type
|
||||||
|
= model::point<T, 2, cs::spherical_equatorial<geometry::degree>>;
|
||||||
|
using base_type = collected_vector_spherical<T, base_point_type>;
|
||||||
|
|
||||||
collected_vector() {}
|
collected_vector_polar() {}
|
||||||
|
|
||||||
template <typename Point>
|
collected_vector_polar(Point const& p1, Point const& p2)
|
||||||
collected_vector(Point const& p1, Point const& p2)
|
|
||||||
: base_type(to_equatorial(p1), to_equatorial(p2))
|
: base_type(to_equatorial(p1), to_equatorial(p2))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Point>
|
static base_point_type to_equatorial(Point const& p)
|
||||||
Point to_equatorial(Point const& p)
|
|
||||||
{
|
{
|
||||||
typedef typename coordinate_type<Point>::type coord_type;
|
using coord_type = typename coordinate_type<Point>::type;
|
||||||
|
using constants = math::detail::constants_on_spheroid
|
||||||
typedef math::detail::constants_on_spheroid
|
|
||||||
<
|
<
|
||||||
coord_type,
|
coord_type,
|
||||||
typename coordinate_system<Point>::type::units
|
typename coordinate_system<Point>::type::units
|
||||||
> constants;
|
> ;
|
||||||
|
|
||||||
coord_type const pi_2 = constants::half_period() / 2;
|
constexpr coord_type pi_2 = constants::half_period() / 2;
|
||||||
|
|
||||||
Point res = p;
|
base_point_type res;
|
||||||
|
set<0>(res, get<0>(p));
|
||||||
set<1>(res, pi_2 - get<1>(p));
|
set<1>(res, pi_2 - get<1>(p));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: implement collected_vector type for geographic
|
||||||
// TODO: specialize collected_vector for geographic_tag
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_NO_DETAIL
|
#ifndef DOXYGEN_NO_DETAIL
|
||||||
|
@ -167,6 +167,12 @@ struct equals_by_collection
|
|||||||
Geometry2 const& geometry2,
|
Geometry2 const& geometry2,
|
||||||
Strategy const& strategy)
|
Strategy const& strategy)
|
||||||
{
|
{
|
||||||
|
using cs_tag = typename Strategy::cs_tag;
|
||||||
|
|
||||||
|
static_assert(std::is_same<cs_tag, spherical_tag>::value
|
||||||
|
|| std::is_same<cs_tag, cartesian_tag>::value,
|
||||||
|
"requires a strategy for cartesian or spherical");
|
||||||
|
|
||||||
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
|
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -181,9 +187,15 @@ struct equals_by_collection
|
|||||||
double
|
double
|
||||||
>::type;
|
>::type;
|
||||||
|
|
||||||
using collected_vector_type = geometry::collected_vector
|
using collected_vector_type = std::conditional_t
|
||||||
<
|
<
|
||||||
calculation_type, Geometry1
|
std::is_same<cs_tag, spherical_tag>::value,
|
||||||
|
collected_vector_spherical
|
||||||
|
<
|
||||||
|
calculation_type,
|
||||||
|
typename geometry::point_type<Geometry1>::type
|
||||||
|
>,
|
||||||
|
collected_vector_cartesian<calculation_type>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
std::vector<collected_vector_type> c1, c2;
|
std::vector<collected_vector_type> c1, c2;
|
||||||
@ -199,7 +211,7 @@ struct equals_by_collection
|
|||||||
std::sort(c1.begin(), c1.end());
|
std::sort(c1.begin(), c1.end());
|
||||||
std::sort(c2.begin(), c2.end());
|
std::sort(c2.begin(), c2.end());
|
||||||
|
|
||||||
// Just check if these vectors are equal.
|
// Check if these vectors are equal.
|
||||||
return std::equal(c1.begin(), c1.end(), c2.begin());
|
return std::equal(c1.begin(), c1.end(), c2.begin());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -233,13 +245,6 @@ struct use_collect_vectors<strategy::side::spherical_side_formula<CV>, CsTag>
|
|||||||
static constexpr bool value = true;
|
static constexpr bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CV>
|
|
||||||
struct use_collect_vectors<strategy::side::spherical_side_formula<CV>,
|
|
||||||
geographic_tag>
|
|
||||||
{
|
|
||||||
static constexpr bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use either collect_vectors or relate
|
// Use either collect_vectors or relate
|
||||||
// NOTE: the result could be conceptually different for invalid
|
// NOTE: the result could be conceptually different for invalid
|
||||||
// geometries in different coordinate systems because collect_vectors
|
// geometries in different coordinate systems because collect_vectors
|
||||||
@ -255,8 +260,11 @@ struct equals_by_collection_or_relate
|
|||||||
using side_strategy = decltype(std::declval<Strategy>().side());
|
using side_strategy = decltype(std::declval<Strategy>().side());
|
||||||
using implementation = std::conditional_t
|
using implementation = std::conditional_t
|
||||||
<
|
<
|
||||||
use_collect_vectors<side_strategy,
|
use_collect_vectors
|
||||||
typename cs_tag<Geometry1>::type>::value,
|
<
|
||||||
|
side_strategy,
|
||||||
|
typename Strategy::cs_tag
|
||||||
|
>::value,
|
||||||
equals_by_collection<TrivialCheck>,
|
equals_by_collection<TrivialCheck>,
|
||||||
equals_by_relate<Geometry1, Geometry2>
|
equals_by_relate<Geometry1, Geometry2>
|
||||||
>;
|
>;
|
||||||
|
@ -19,4 +19,5 @@ test-suite boost-geometry-algorithms-equals
|
|||||||
[ run equals.cpp : : : : algorithms_equals ]
|
[ run equals.cpp : : : : algorithms_equals ]
|
||||||
[ run equals_multi.cpp : : : : algorithms_equals_multi ]
|
[ run equals_multi.cpp : : : : algorithms_equals_multi ]
|
||||||
[ run equals_on_spheroid.cpp : : : : algorithms_equals_on_spheroid ]
|
[ run equals_on_spheroid.cpp : : : : algorithms_equals_on_spheroid ]
|
||||||
|
[ run equals_sph.cpp : : : : algorithms_equals_sph ]
|
||||||
;
|
;
|
||||||
|
@ -234,7 +234,6 @@ BOOST_AUTO_TEST_CASE( equals_segment_segment_geo )
|
|||||||
test_segment_segment<bgm::point<long double, 2, cs_type> >("geo");
|
test_segment_segment<bgm::point<long double, 2, cs_type> >("geo");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
|
||||||
// This version uses collect_vectors (because its side
|
// This version uses collect_vectors (because its side
|
||||||
// strategy is spherical_side_formula) and fails
|
// strategy is spherical_side_formula) and fails
|
||||||
BOOST_AUTO_TEST_CASE( equals_ring_ring_se)
|
BOOST_AUTO_TEST_CASE( equals_ring_ring_se)
|
||||||
@ -247,7 +246,6 @@ BOOST_AUTO_TEST_CASE( equals_ring_ring_se)
|
|||||||
"POLYGON((10 50,10 51,11 50,10 50))",
|
"POLYGON((10 50,10 51,11 50,10 50))",
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( equals_ring_ring_geo )
|
BOOST_AUTO_TEST_CASE( equals_ring_ring_geo )
|
||||||
{
|
{
|
||||||
|
@ -147,5 +147,13 @@ int test_main( int , char* [] )
|
|||||||
{
|
{
|
||||||
test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
|
test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
|
||||||
|
|
||||||
|
// TODO: the polar version needs several traits more, for example in cs_tag,
|
||||||
|
// to compile properly.
|
||||||
|
//test_all<bg::model::point<double, 2, bg::cs::polar<bg::degree> > >();
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||||
|
test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,10 @@
|
|||||||
#include <boost/variant/variant.hpp>
|
#include <boost/variant/variant.hpp>
|
||||||
|
|
||||||
|
|
||||||
struct no_strategy {};
|
struct no_strategy
|
||||||
|
{
|
||||||
|
using cs_tag = void;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||||
bool call_equals(Geometry1 const& geometry1,
|
bool call_equals(Geometry1 const& geometry1,
|
||||||
@ -60,7 +63,9 @@ void check_geometry(Geometry1 const& geometry1,
|
|||||||
<< " equals: " << wkt1
|
<< " equals: " << wkt1
|
||||||
<< " to " << wkt2
|
<< " to " << wkt2
|
||||||
<< " -> Expected: " << expected
|
<< " -> Expected: " << expected
|
||||||
<< " detected: " << detected);
|
<< " detected: " << detected
|
||||||
|
<< " strategy: " << typeid(Strategy).name()
|
||||||
|
<< " cs: " << typeid(typename Strategy::cs_tag).name());
|
||||||
|
|
||||||
detected = call_equals(geometry2, geometry1, strategy);
|
detected = call_equals(geometry2, geometry1, strategy);
|
||||||
|
|
||||||
@ -69,7 +74,8 @@ void check_geometry(Geometry1 const& geometry1,
|
|||||||
<< " equals: " << wkt2
|
<< " equals: " << wkt2
|
||||||
<< " to " << wkt1
|
<< " to " << wkt1
|
||||||
<< " -> Expected: " << expected
|
<< " -> Expected: " << expected
|
||||||
<< " detected: " << detected);
|
<< " strategy: " << typeid(Strategy).name()
|
||||||
|
<< " cs: " << typeid(typename Strategy::cs_tag).name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user