2016-05-17 03:04:11 +12:00
|
|
|
#pragma once
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
#ifndef TCG_POLYLINE_OPS
|
|
|
|
#define TCG_POLYLINE_OPS
|
|
|
|
|
|
|
|
// tcg includes
|
|
|
|
#include "traits.h"
|
|
|
|
#include "containers_reader.h"
|
|
|
|
#include "point.h"
|
|
|
|
#include "point_ops.h"
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
namespace tcg {
|
|
|
|
namespace polyline_ops {
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//**************************************************************************************
|
|
|
|
// Polyline Basic Operations
|
|
|
|
//**************************************************************************************
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Computes the length of the polyline between the specified point iterators.
|
|
|
|
\return The input polyline's length
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename ForIt>
|
2016-06-15 18:43:10 +12:00
|
|
|
double length(ForIt begin, ForIt end) {
|
|
|
|
typedef typename std::iterator_traits<ForIt>::value_type point_type;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
double result = 0.0;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
for (ForIt jt = begin, it = ++jt; jt != end; it = jt, ++jt)
|
|
|
|
result += tcg::point_ops::dist(*it, *jt);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
return result;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Computes the area enclosed by the input polyline's \a closure.
|
|
|
|
|
|
|
|
\note The input polyline is implicitly \a connected at the endpoints
|
|
|
|
with a straight segment. This has obviously makes no difference
|
|
|
|
if the supplied polyline already had coincident endpoints.
|
|
|
|
|
|
|
|
\return The area enclosed by the polyline's \a closure.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename ForIt>
|
2016-06-15 18:43:10 +12:00
|
|
|
double area(ForIt begin, ForIt end) {
|
|
|
|
typedef typename std::iterator_traits<ForIt>::value_type point_type;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
double result = 0.0;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
if (begin != end) {
|
|
|
|
ForIt jt = begin, it = jt++;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
for (; jt != end; it = jt++)
|
|
|
|
result += 0.5 * (tcg::point_traits<point_type>::y(*jt) +
|
|
|
|
tcg::point_traits<point_type>::y(*it)) *
|
|
|
|
(tcg::point_traits<point_type>::x(*jt) -
|
|
|
|
tcg::point_traits<point_type>::x(*it));
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
result += 0.5 * (tcg::point_traits<point_type>::y(*begin) +
|
|
|
|
tcg::point_traits<point_type>::y(*it)) *
|
|
|
|
(tcg::point_traits<point_type>::x(*begin) -
|
|
|
|
tcg::point_traits<point_type>::x(*it));
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
return result;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************************
|
|
|
|
// Quadratic Conversions
|
|
|
|
//**************************************************************************************
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Standard direct conversion function used in polyline-to-quadratics conversion.
|
|
|
|
|
|
|
|
Point a has already been inserted in the output; this function must add the
|
2016-06-15 18:43:10 +12:00
|
|
|
remaining part of a sequence of quadratics approximating the triplet (a, *bt,
|
|
|
|
c).
|
2016-03-19 06:57:51 +13:00
|
|
|
*/
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
// Note: typename iter_type::value_type == point_type
|
2016-03-19 06:57:51 +13:00
|
|
|
template <typename point_type, typename iter_type>
|
2016-06-15 18:43:10 +12:00
|
|
|
void tripletToQuadratics(
|
|
|
|
const point_type &a, const iter_type &bt, const point_type &c,
|
|
|
|
tcg::sequential_reader<std::vector<point_type>> &output) {
|
|
|
|
// Direct conversion
|
|
|
|
output.addElement(*bt);
|
|
|
|
output.addElement(c);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2016-06-15 18:43:10 +12:00
|
|
|
Performs a conversion of the specified polyline into a sequence of quadratics,
|
|
|
|
then
|
2016-03-19 06:57:51 +13:00
|
|
|
applies a quadratics sub-sequence optimal merging algorithm.
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
A user-made local triplet-to-quadratics conversion can be supplied to
|
|
|
|
recognize corners
|
2016-03-19 06:57:51 +13:00
|
|
|
or supply a tight starting approximation.
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
\warning Passed polylines with equal endpoints are interpreted as closed
|
|
|
|
(circular) polylines;
|
|
|
|
in this case, the resulting endpoints of the quadratic sequence will be
|
|
|
|
displaced to
|
2016-03-19 06:57:51 +13:00
|
|
|
the first segment mid-point.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename iter_type, typename containers_reader, typename toQuadsFunc>
|
2016-06-15 18:43:10 +12:00
|
|
|
void toQuadratics(
|
|
|
|
iter_type begin, iter_type end, containers_reader &output,
|
|
|
|
toQuadsFunc &toQuads =
|
|
|
|
&tripletToQuadratics<typename iter_type::value_type, iter_type>,
|
|
|
|
double mergeTol = 1.0);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//**************************************************************************************
|
|
|
|
// Standard Polyline Evaluators
|
|
|
|
//**************************************************************************************
|
|
|
|
|
|
|
|
/*!
|
2016-06-15 18:43:10 +12:00
|
|
|
Calculates the (weighted) standard deviation of a polyline's sub-paths with
|
|
|
|
respect
|
2016-03-19 06:57:51 +13:00
|
|
|
to the segment connecting the endpoints.
|
|
|
|
|
|
|
|
\warning For efficiency reasons, the returned value is the actual standard
|
|
|
|
deviation, times the endpoints-segment length.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename RanIt>
|
2016-06-15 18:43:10 +12:00
|
|
|
class StandardDeviationEvaluator {
|
2016-03-19 06:57:51 +13:00
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
typedef RanIt iterator_type;
|
|
|
|
typedef typename std::iterator_traits<RanIt>::difference_type diff_type;
|
|
|
|
typedef typename std::iterator_traits<RanIt>::value_type point_type;
|
|
|
|
typedef typename tcg::point_traits<point_type>::value_type value_type;
|
|
|
|
typedef double penalty_type;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
protected:
|
2016-06-15 18:43:10 +12:00
|
|
|
iterator_type m_begin, m_end;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
std::vector<double> m_sums_x, m_sums_y; //!< Sums of the points coordinates
|
|
|
|
std::vector<double> m_sums2_x,
|
|
|
|
m_sums2_y; //!< Sums of the points coordinates' squares
|
|
|
|
std::vector<double> m_sums_xy; //!< Sums of the coordinates products
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
StandardDeviationEvaluator(const iterator_type &begin,
|
|
|
|
const iterator_type &end);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
penalty_type penalty(const iterator_type &a, const iterator_type &b);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
const iterator_type &begin() const { return m_begin; }
|
|
|
|
const iterator_type &end() const { return m_end; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
const std::vector<double> &sums_x() const { return m_sums_x; }
|
|
|
|
const std::vector<double> &sums_y() const { return m_sums_y; }
|
|
|
|
const std::vector<double> &sums2_x() const { return m_sums2_x; }
|
|
|
|
const std::vector<double> &sums2_y() const { return m_sums2_y; }
|
|
|
|
const std::vector<double> &sums_xy() const { return m_sums_xy; }
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
} // namespace tcg::polyline_ops
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
#ifdef INCLUDE_HPP
|
|
|
|
#include "hpp/polyline_ops.hpp"
|
|
|
|
#endif
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
#endif // TCG_POLYLINE_OPS
|