mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-29 07:32:17 +00:00
[simplify] Correctly propagate strategies to area() and perimeter().
Also made the algorithm more robust by checking the iterator before using it.
This commit is contained in:
@@ -120,8 +120,8 @@ class douglas_peucker
|
||||
PSDistanceStrategy const& ps_distance_strategy)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type::point_type point_type;
|
||||
using distance_type = decltype(ps_distance_strategy.apply(
|
||||
std::declval<point_type>(), std::declval<point_type>(), std::declval<point_type>()));
|
||||
typedef decltype(ps_distance_strategy.apply(std::declval<point_type>(),
|
||||
std::declval<point_type>(), std::declval<point_type>())) distance_type;
|
||||
|
||||
std::size_t size = end - begin;
|
||||
|
||||
@@ -153,7 +153,7 @@ class douglas_peucker
|
||||
// Find most far point, compare to the current segment
|
||||
//geometry::segment<Point const> s(begin->p, last->p);
|
||||
distance_type md(-1.0); // any value < 0
|
||||
Iterator candidate;
|
||||
Iterator candidate = end;
|
||||
for (Iterator it = begin + 1; it != last; ++it)
|
||||
{
|
||||
distance_type dist = ps_distance_strategy.apply(*(it->p), *(begin->p), *(last->p));
|
||||
@@ -174,7 +174,7 @@ class douglas_peucker
|
||||
|
||||
// If a point is found, set the include flag
|
||||
// and handle segments in between recursively
|
||||
if (max_dist < md)
|
||||
if (max_dist < md && candidate != end)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
|
||||
std::cout << "use " << dsv(candidate->p) << std::endl;
|
||||
@@ -411,10 +411,9 @@ public :
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use calculate_point_order
|
||||
// TODO: pass strategies
|
||||
// TODO: instead of area() use calculate_point_order() ?
|
||||
|
||||
int const input_sign = area_sign(geometry::area(ring));
|
||||
int const input_sign = area_sign(geometry::area(ring, strategies));
|
||||
|
||||
std::set<std::size_t> visited_indexes;
|
||||
|
||||
@@ -464,12 +463,11 @@ public :
|
||||
|
||||
simplify_range<0>::apply(rotated, out, max_distance, impl, strategies);
|
||||
|
||||
// TODO: use calculate_point_order
|
||||
// TODO: pass strategies
|
||||
// TODO: instead of area() use calculate_point_order() ?
|
||||
|
||||
// Verify that what was positive, stays positive (or goes to 0)
|
||||
// and what was negative stays negative (or goes to 0)
|
||||
int const output_sign = area_sign(geometry::area(out));
|
||||
int const output_sign = area_sign(geometry::area(out, strategies));
|
||||
if (output_sign == input_sign)
|
||||
{
|
||||
// Result is considered as satisfactory (usually this is the
|
||||
@@ -482,10 +480,8 @@ public :
|
||||
// when another starting point is used
|
||||
geometry::clear(out);
|
||||
|
||||
// TODO: pass strategies
|
||||
|
||||
if (iteration == 0
|
||||
&& geometry::perimeter(ring) < 3 * max_distance)
|
||||
&& geometry::perimeter(ring, strategies) < 3 * max_distance)
|
||||
{
|
||||
// Check if it is useful to iterate. A minimal triangle has a
|
||||
// perimeter of a bit more than 3 times the simplify distance
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/simplify/services.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/area.hpp>
|
||||
|
||||
#include <boost/geometry/util/type_traits.hpp>
|
||||
|
||||
|
||||
@@ -32,6 +34,26 @@ template <typename CalculationType = void>
|
||||
struct cartesian
|
||||
: public strategies::detail::cartesian_base
|
||||
{
|
||||
// TODO: Replace this if calculate_point_order() is used in simplify
|
||||
template <typename Geometry>
|
||||
static auto area(Geometry const&)
|
||||
{
|
||||
return strategy::area::cartesian<CalculationType>();
|
||||
}
|
||||
|
||||
// For perimeter()
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static auto distance(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
<
|
||||
util::is_pointlike<Geometry1>::value
|
||||
&& util::is_pointlike<Geometry2>::value
|
||||
> * = nullptr)
|
||||
{
|
||||
return strategy::distance::pythagoras<CalculationType>();
|
||||
}
|
||||
|
||||
// For douglas_peucker
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static auto distance(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
@@ -51,6 +73,7 @@ struct cartesian
|
||||
>();
|
||||
}
|
||||
|
||||
// For equals()
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static auto relate(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
|
||||
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/geographic/area.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -43,6 +45,35 @@ public:
|
||||
: base_t(spheroid)
|
||||
{}
|
||||
|
||||
// TODO: Replace this if calculate_point_order() is used in simplify
|
||||
template <typename Geometry>
|
||||
auto area(Geometry const&) const
|
||||
{
|
||||
return strategy::area::geographic
|
||||
<
|
||||
FormulaPolicy,
|
||||
strategy::default_order<FormulaPolicy>::value,
|
||||
Spheroid,
|
||||
CalculationType
|
||||
>(base_t::m_spheroid);
|
||||
}
|
||||
|
||||
// For perimeter()
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
auto distance(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
<
|
||||
util::is_pointlike<Geometry1>::value
|
||||
&& util::is_pointlike<Geometry2>::value
|
||||
> * = nullptr) const
|
||||
{
|
||||
return strategy::distance::geographic
|
||||
<
|
||||
FormulaPolicy, Spheroid, CalculationType
|
||||
>(base_t::m_spheroid);
|
||||
}
|
||||
|
||||
// For douglas_peucker
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
auto distance(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
@@ -61,6 +92,7 @@ public:
|
||||
>(base_t::m_spheroid);
|
||||
}
|
||||
|
||||
// For equals()
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static auto relate(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
|
||||
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/spherical/area.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -44,6 +46,32 @@ public:
|
||||
: base_t(radius_or_sphere)
|
||||
{}
|
||||
|
||||
// TODO: Replace this if calculate_point_order() is used in simplify
|
||||
template <typename Geometry>
|
||||
auto area(Geometry const&) const
|
||||
{
|
||||
return strategy::area::spherical
|
||||
<
|
||||
typename base_t::radius_type, CalculationType
|
||||
>(base_t::radius());
|
||||
}
|
||||
|
||||
// For perimeter()
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
auto distance(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
<
|
||||
util::is_pointlike<Geometry1>::value
|
||||
&& util::is_pointlike<Geometry2>::value
|
||||
> * = nullptr) const
|
||||
{
|
||||
return strategy::distance::haversine
|
||||
<
|
||||
typename base_t::radius_type, CalculationType
|
||||
>(base_t::radius());
|
||||
}
|
||||
|
||||
// For douglas_peucker
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
auto distance(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
@@ -63,6 +91,7 @@ public:
|
||||
>(base_t::radius());
|
||||
}
|
||||
|
||||
// For equals()
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static auto relate(Geometry1 const&, Geometry2 const&,
|
||||
std::enable_if_t
|
||||
|
||||
Reference in New Issue
Block a user