92 #ifndef PSIMPL_GENERIC 93 #define PSIMPL_GENERIC 118 template <
typename T>
131 return array [offset];
135 return array [offset];
191 template <
unsigned DIM,
class InputIterator>
196 for (
unsigned d = 0; d < DIM; ++d) {
214 template <
unsigned DIM,
class InputIterator,
class OutputIterator>
218 OutputIterator result)
220 for (
unsigned d = 0; d < DIM; ++d) {
236 template <
unsigned DIM,
class InputIterator>
237 inline typename std::iterator_traits <InputIterator>::value_type
dot (
241 typename std::iterator_traits <InputIterator>::value_type result = 0;
242 for (
unsigned d = 0; d < DIM; ++d) {
243 result += (*v1) * (*v2);
259 template <
unsigned DIM,
class InputIterator,
class OutputIterator>
264 OutputIterator result)
266 typedef typename std::iterator_traits <InputIterator>::value_type value_type;
268 for (
unsigned d = 0; d < DIM; ++d) {
269 *result = *p1 + static_cast <value_type> (fraction * (*p2 - *p1));
284 template <
unsigned DIM,
class InputIterator1,
class InputIterator2>
289 typename std::iterator_traits <InputIterator1>::value_type result = 0;
290 for (
unsigned d = 0; d < DIM; ++d) {
291 result += (*p1 - *p2) * (*p1 - *p2);
306 template <
unsigned DIM,
class InputIterator>
307 inline typename std::iterator_traits <InputIterator>::value_type
line_distance2 (
312 typedef typename std::iterator_traits <InputIterator>::value_type value_type;
317 make_vector <DIM> (l1, l2, v);
318 make_vector <DIM> (l1,
p, w);
320 value_type cv = dot <DIM> (v, v);
321 value_type cw = dot <DIM> (w, v);
324 float fraction = cv == 0 ? 0 : static_cast <
float> (cw) / static_cast <float> (cv);
326 value_type proj [DIM];
327 interpolate <DIM> (l1, l2, fraction, proj);
329 return point_distance2 <DIM> (
p, proj);
340 template <
unsigned DIM,
class InputIterator>
346 typedef typename std::iterator_traits <InputIterator>::value_type value_type;
351 make_vector <DIM> (s1, s2, v);
352 make_vector <DIM> (s1,
p, w);
354 value_type cw = dot <DIM> (w, v);
357 return point_distance2 <DIM> (
p, s1);
360 value_type cv = dot <DIM> (v, v);
363 return point_distance2 <DIM> (
p, s2);
367 float fraction = cv == 0 ? 0 : static_cast <
float> (cw) / static_cast <float> (cv);
369 value_type proj [DIM];
370 interpolate <DIM> (s1, s2, fraction, proj);
372 return point_distance2 <DIM> (
p, proj);
383 template <
unsigned DIM,
class InputIterator>
384 inline typename std::iterator_traits <InputIterator>::value_type
ray_distance2 (
389 typedef typename std::iterator_traits <InputIterator>::value_type value_type;
394 make_vector <DIM> (r1, r2, v);
395 make_vector <DIM> (r1,
p, w);
397 value_type cv = dot <DIM> (v, v);
398 value_type cw = dot <DIM> (w, v);
402 return point_distance2 <DIM> (
p, r1);
406 float fraction = cv == 0 ? 0 : static_cast <
float> (cw) / static_cast <float> (cv);
408 value_type proj [DIM];
409 interpolate <DIM> (r1, r2, fraction, proj);
411 return point_distance2 <DIM> (
p, proj);
421 template <
class InputIterator>
426 typedef typename std::iterator_traits <InputIterator>::value_type value_type;
427 typedef typename std::iterator_traits <InputIterator>::difference_type diff_type;
431 diff_type count = std::distance (first, last);
437 stats.
max = static_cast <
double> (*std::max_element (first, last));
438 stats.
sum = static_cast <
double> (std::accumulate (first, last, init));
439 stats.
mean = stats.
sum / count;
440 std::transform (first, last, first, std::bind2nd (std::minus <value_type> (), stats.
mean));
441 stats.
std = std::sqrt (static_cast <double> (std::inner_product (first, last, first, init)) / count);
453 template <
unsigned DIM,
class InputIterator,
class OutputIterator>
456 typedef typename std::iterator_traits <InputIterator>::difference_type
diff_type;
457 typedef typename std::iterator_traits <InputIterator>::value_type
value_type;
458 typedef typename std::iterator_traits <const value_type*>::difference_type
ptr_diff_type;
496 OutputIterator result)
498 diff_type coordCount = std::distance (first, last);
499 diff_type pointCount = DIM
504 if (coordCount % DIM || pointCount < 3 || n < 2) {
505 return std::copy (first, last, result);
508 unsigned remaining = pointCount - 1;
509 InputIterator key =
first;
512 CopyKey (key, result);
515 while (Forward (key, n, remaining)) {
516 CopyKey (key, result);
558 OutputIterator result)
560 diff_type coordCount = std::distance (first, last);
561 diff_type pointCount = DIM
564 value_type tol2 = tol * tol;
567 if (coordCount % DIM || pointCount < 3 || tol2 == 0) {
568 return std::copy (first, last, result);
571 InputIterator current =
first;
572 InputIterator next =
first;
575 CopyKeyAdvance (next, result);
578 for (diff_type index = 1; index < pointCount - 1; ++index) {
579 if (math::point_distance2 <DIM> (current, next) < tol2) {
584 CopyKeyAdvance (next, result);
587 CopyKeyAdvance (next, result);
613 OutputIterator result)
617 return PerpendicularDistance (first, last, tol, result);
621 return std::copy (first, last, result);
623 diff_type coordCount = std::distance (first, last);
628 diff_type tempCoordCount = std::distance (tempPoly.
get (),
632 if (coordCount == tempCoordCount) {
633 return std::copy (tempPoly.
get (), tempPoly.
get () + coordCount, result);
644 tempCoordCount = std::distance (tempResult.
get (),
646 tempPoly.
get (), tempPoly.
get () + coordCount, tol, tempResult.
get ()));
649 if (coordCount == tempCoordCount) {
650 return std::copy (tempPoly.
get (), tempPoly.
get () + coordCount, result);
660 tempPoly.
get (), tempPoly.
get () + coordCount, tol, result);
701 OutputIterator result)
703 diff_type coordCount = std::distance (first, last);
704 diff_type pointCount = DIM
707 value_type tol2 = tol * tol;
710 if (coordCount % DIM || pointCount < 3 || tol2 == 0) {
711 return std::copy (first, last, result);
714 InputIterator p0 =
first;
715 InputIterator p1 = AdvanceCopy(p0);
716 InputIterator p2 = AdvanceCopy(p1);
719 CopyKey (p0, result);
723 if (math::segment_distance2 <DIM> (p0, p2, p1) < tol2) {
724 CopyKey (p2, result);
735 CopyKey (p1, result);
744 CopyKey (p1, result);
787 OutputIterator result)
789 diff_type coordCount = std::distance (first, last);
790 diff_type pointCount = DIM
793 value_type tol2 = tol * tol;
796 if (coordCount % DIM || pointCount < 3 || tol2 == 0) {
797 return std::copy (first, last, result);
801 InputIterator p0 =
first;
802 InputIterator p1 = AdvanceCopy (first);
805 InputIterator pi = p1;
806 InputIterator pj = p1;
809 CopyKey (p0, result);
812 for (diff_type j = 2; j < pointCount; ++j) {
816 if (math::line_distance2 <DIM> (p0, p1, pj) < tol2) {
820 CopyKey (pi, result);
826 CopyKey (pj, result);
877 OutputIterator result)
879 diff_type coordCount = std::distance (first, last);
880 diff_type pointCount = DIM
883 value_type min_tol2 = min_tol * min_tol;
884 value_type max_tol2 = max_tol * max_tol;
887 if (coordCount % DIM || pointCount < 3 || min_tol2 == 0 || max_tol2 == 0) {
888 return std::copy (first, last, result);
892 InputIterator r0 =
first;
893 InputIterator r1 =
first;
894 bool rayDefined =
false;
897 InputIterator pi = r0;
902 CopyKey (r0, result);
904 for (diff_type j = 2; j < pointCount; ++j) {
910 if (math::point_distance2 <DIM> (r0, pj) < min_tol2) {
919 if (math::point_distance2 <DIM> (r0, pj) < max_tol2 &&
920 math::ray_distance2 <DIM> (r0, r1, pj) < min_tol2)
925 CopyKey (pi, result);
931 CopyKey (pj, result);
983 OutputIterator result)
985 diff_type coordCount = std::distance (first, last);
986 diff_type pointCount = DIM
989 value_type tol2 = tol * tol;
992 if (coordCount % DIM || pointCount < 3 || look_ahead < 2 || tol2 == 0) {
993 return std::copy (first, last, result);
996 InputIterator current =
first;
997 InputIterator next =
first;
999 unsigned remaining = pointCount - 1;
1000 unsigned moved = Forward (next, look_ahead, remaining);
1003 CopyKey (current, result);
1007 InputIterator
p = AdvanceCopy (current);
1010 d2 = std::max (d2, math::segment_distance2 <DIM> (current, next, p));
1018 CopyKey (current, result);
1019 moved = Forward (next, look_ahead, remaining);
1022 Backward (next, remaining);
1071 InputIterator
first,
1074 OutputIterator result)
1076 diff_type coordCount = std::distance (first, last);
1077 diff_type pointCount = DIM
1081 if (coordCount % DIM || pointCount < 3 || tol == 0) {
1082 return std::copy (first, last, result);
1087 ptr_diff_type reducedCoordCount = std::distance (reduced.
get (),
1089 ptr_diff_type reducedPointCount = reducedCoordCount / DIM;
1093 DPHelper::Approximate (reduced.
get (), reducedCoordCount, tol, keys.
get ());
1096 const value_type* current = reduced.
get ();
1097 for (ptr_diff_type
p=0;
p<reducedPointCount; ++
p, current += DIM) {
1099 for (
unsigned d = 0; d < DIM; ++d) {
1100 *result = current [d];
1148 InputIterator
first,
1151 OutputIterator result)
1153 diff_type coordCount = std::distance (first, last);
1154 diff_type pointCount = DIM
1158 if (coordCount % DIM || pointCount <= static_cast <diff_type> (count) || count < 2) {
1159 return std::copy (first, last, result);
1164 for (ptr_diff_type c=0; c<coordCount; ++c) {
1165 coords [c] = *
first;
1171 DPHelper::ApproximateN (coords.
get (), coordCount, count, keys.
get ());
1174 const value_type* current = coords.
get ();
1175 for (ptr_diff_type
p=0;
p<pointCount; ++
p, current += DIM) {
1177 for (
unsigned d = 0; d < DIM; ++d) {
1178 *result = current [d];
1225 InputIterator original_first,
1226 InputIterator original_last,
1227 InputIterator simplified_first,
1228 InputIterator simplified_last,
1229 OutputIterator result,
1232 diff_type original_coordCount = std::distance (original_first, original_last);
1233 diff_type original_pointCount = DIM
1234 ? original_coordCount / DIM
1237 diff_type simplified_coordCount = std::distance (simplified_first, simplified_last);
1238 diff_type simplified_pointCount = DIM
1239 ? simplified_coordCount / DIM
1243 if (original_coordCount % DIM || original_pointCount < 2 ||
1244 simplified_coordCount % DIM || simplified_pointCount < 2 ||
1245 original_pointCount < simplified_pointCount ||
1246 !math::equal <DIM> (original_first, simplified_first))
1255 InputIterator simplified_prev = simplified_first;
1256 std::advance (simplified_first, DIM);
1259 while (simplified_first != simplified_last) {
1261 while (original_first != original_last &&
1262 !math::equal <DIM> (original_first, simplified_first))
1264 *result = math::segment_distance2 <DIM> (simplified_prev, simplified_first,
1267 std::advance (original_first, DIM);
1270 simplified_prev = simplified_first;
1271 std::advance (simplified_first, DIM);
1274 if (original_first != original_last) {
1280 *valid = original_first != original_last;
1318 InputIterator original_first,
1319 InputIterator original_last,
1320 InputIterator simplified_first,
1321 InputIterator simplified_last,
1324 diff_type pointCount = std::distance (original_first, original_last) / DIM;
1328 diff_type errorCount =
1332 simplified_first, simplified_last,
1333 errors.
get (), valid));
1337 std::ptr_fun <double, double> (std::sqrt));
1353 OutputIterator& result)
1355 for (
unsigned d = 0; d < DIM; ++d) {
1372 OutputIterator& result)
1374 CopyKeyAdvance (key, result);
1389 std::advance (it, n * static_cast <diff_type> (DIM));
1425 unsigned& remaining)
1427 n = std::min (n, remaining);
1443 unsigned& remaining)
1470 KeyInfo (ptr_diff_type index=0, value_type dist2=0) :
1471 index (index), dist2 (dist2) {}
1501 const value_type* coords,
1502 ptr_diff_type coordCount,
1504 unsigned char* keys)
1506 value_type tol2 = tol * tol;
1507 ptr_diff_type pointCount = coordCount / DIM;
1509 std::fill_n (keys, pointCount, 0);
1511 keys [pointCount - 1] = 1;
1513 typedef std::stack <SubPoly> Stack;
1516 SubPoly subPoly (0, coordCount-DIM);
1517 stack.push (subPoly);
1519 while (!stack.empty ()) {
1520 subPoly = stack.top ();
1525 keys [keyInfo.
index / DIM] = 1;
1542 const value_type* coords,
1543 ptr_diff_type coordCount,
1545 unsigned char* keys)
1547 ptr_diff_type pointCount = coordCount / DIM;
1549 std::fill_n (keys, pointCount, 0);
1551 keys [pointCount - 1] = 1;
1552 unsigned keyCount = 2;
1554 if (countTol == 2) {
1558 typedef std::priority_queue <SubPolyAlt> PriorityQueue;
1559 PriorityQueue queue;
1563 queue.push (subPoly);
1565 while (!queue.empty ()) {
1566 subPoly = queue.top ();
1572 if (keyCount == countTol) {
1603 const value_type* coords,
1604 ptr_diff_type
first,
1609 for (ptr_diff_type current = first + DIM; current < last; current += DIM) {
1610 value_type d2 = math::segment_distance2 <DIM> (coords +
first, coords + last,
1612 if (d2 < keyInfo.
dist2) {
1616 keyInfo.
index = current;
1636 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1638 ForwardIterator
first,
1639 ForwardIterator last,
1641 OutputIterator result)
1644 return ps.
NthPoint (first, last, n, result);
1659 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1661 ForwardIterator
first,
1662 ForwardIterator last,
1663 typename std::iterator_traits <ForwardIterator>::value_type tol,
1664 OutputIterator result)
1683 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1685 ForwardIterator
first,
1686 ForwardIterator last,
1687 typename std::iterator_traits <ForwardIterator>::value_type tol,
1689 OutputIterator result)
1707 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1709 ForwardIterator
first,
1710 ForwardIterator last,
1711 typename std::iterator_traits <ForwardIterator>::value_type tol,
1712 OutputIterator result)
1730 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1732 ForwardIterator
first,
1733 ForwardIterator last,
1734 typename std::iterator_traits <ForwardIterator>::value_type tol,
1735 OutputIterator result)
1754 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1756 ForwardIterator
first,
1757 ForwardIterator last,
1758 typename std::iterator_traits <ForwardIterator>::value_type min_tol,
1759 typename std::iterator_traits <ForwardIterator>::value_type max_tol,
1760 OutputIterator result)
1763 return ps.
Opheim (first, last, min_tol, max_tol, result);
1779 template <
unsigned DIM,
class B
idirectionalIterator,
class OutputIterator>
1781 BidirectionalIterator
first,
1782 BidirectionalIterator last,
1783 typename std::iterator_traits <BidirectionalIterator>::value_type tol,
1784 unsigned look_ahead,
1785 OutputIterator result)
1788 return ps.
Lang (first, last, tol, look_ahead, result);
1803 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1805 ForwardIterator
first,
1806 ForwardIterator last,
1807 typename std::iterator_traits <ForwardIterator>::value_type tol,
1808 OutputIterator result)
1826 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1828 ForwardIterator
first,
1829 ForwardIterator last,
1831 OutputIterator result)
1851 template <
unsigned DIM,
class ForwardIterator,
class OutputIterator>
1853 ForwardIterator original_first,
1854 ForwardIterator original_last,
1855 ForwardIterator simplified_first,
1856 ForwardIterator simplified_last,
1857 OutputIterator result,
1861 return ps.
ComputePositionalErrors2 (original_first, original_last, simplified_first, simplified_last, result, valid);
1877 template <
unsigned DIM,
class ForwardIterator>
1879 ForwardIterator original_first,
1880 ForwardIterator original_last,
1881 ForwardIterator simplified_first,
1882 ForwardIterator simplified_last,
1890 #endif // PSIMPL_GENERIC POD structure for storing several statistical values.
OutputIterator simplify_douglas_peucker(ForwardIterator first, ForwardIterator last, typename std::iterator_traits< ForwardIterator >::value_type tol, OutputIterator result)
Performs Douglas-Peucker polyline simplification (DP).
SubPolyAlt(ptr_diff_type first=0, ptr_diff_type last=0)
OutputIterator NthPoint(InputIterator first, InputIterator last, unsigned n, OutputIterator result)
Performs the nth point routine (NP).
SubPoly(ptr_diff_type first=0, ptr_diff_type last=0)
OutputIterator PerpendicularDistance(InputIterator first, InputIterator last, value_type tol, OutputIterator result)
Performs the perpendicular distance routine (PD).
OutputIterator Opheim(InputIterator first, InputIterator last, value_type min_tol, value_type max_tol, OutputIterator result)
Performs Opheim approximation (OP).
OutputIterator DouglasPeucker(InputIterator first, InputIterator last, value_type tol, OutputIterator result)
Performs Douglas-Peucker approximation (DP).
void CopyKeyAdvance(InputIterator &key, OutputIterator &result)
Copies the key to the output destination, and increments the iterator.
OutputIterator simplify_opheim(ForwardIterator first, ForwardIterator last, typename std::iterator_traits< ForwardIterator >::value_type min_tol, typename std::iterator_traits< ForwardIterator >::value_type max_tol, OutputIterator result)
Performs Opheim polyline simplification (OP).
InputIterator AdvanceCopy(InputIterator it, diff_type n=1)
Increments a copy of the iterator by n points.
Defines a sub polyline including its key.
Provides various simplification algorithms for n-dimensional simple polylines.
Statistics compute_statistics(InputIterator first, InputIterator last)
Computes various statistics for the range [first, last)
std::iterator_traits< const value_type * >::difference_type ptr_diff_type
math::Statistics ComputePositionalErrorStatistics(InputIterator original_first, InputIterator original_last, InputIterator simplified_first, InputIterator simplified_last, bool *valid=0)
Computes statistics for the positional errors between a polyline and its simplification.
unsigned Forward(InputIterator &it, unsigned n, unsigned &remaining)
Increments the iterator by n points if possible.
std::iterator_traits< InputIterator >::difference_type diff_type
void Advance(InputIterator &it, diff_type n=1)
Increments the iterator by n points.
OutputIterator simplify_perpendicular_distance(ForwardIterator first, ForwardIterator last, typename std::iterator_traits< ForwardIterator >::value_type tol, unsigned repeat, OutputIterator result)
Repeatedly performs the perpendicular distance routine (PD).
ptr_diff_type last
coord index of the first point
OutputIterator simplify_lang(BidirectionalIterator first, BidirectionalIterator last, typename std::iterator_traits< BidirectionalIterator >::value_type tol, unsigned look_ahead, OutputIterator result)
Performs Lang polyline simplification (LA).
std::iterator_traits< InputIterator >::value_type ray_distance2(InputIterator r1, InputIterator r2, InputIterator p)
Computes the squared distance between a ray (r1, r2) and a point p.
bool equal(InputIterator p1, InputIterator p2)
Determines if two points have the exact same coordinates.
static KeyInfo FindKey(const value_type *coords, ptr_diff_type first, ptr_diff_type last)
Finds the key for the given sub polyline.
OutputIterator make_vector(InputIterator p1, InputIterator p2, OutputIterator result)
Creates a vector from two points.
OutputIterator simplify_douglas_peucker_n(ForwardIterator first, ForwardIterator last, unsigned count, OutputIterator result)
Performs a variant of Douglas-Peucker polyline simplification (DPn).
Defines the key of a polyline.
OutputIterator ComputePositionalErrors2(InputIterator original_first, InputIterator original_last, InputIterator simplified_first, InputIterator simplified_last, OutputIterator result, bool *valid=0)
Computes the squared positional error between a polyline and its simplification.
OutputIterator simplify_nth_point(ForwardIterator first, ForwardIterator last, unsigned n, OutputIterator result)
Performs the nth point routine (NP).
scoped_array & operator=(const scoped_array &)
OutputIterator compute_positional_errors2(ForwardIterator original_first, ForwardIterator original_last, ForwardIterator simplified_first, ForwardIterator simplified_last, OutputIterator result, bool *valid=0)
Computes the squared positional error between a polyline and its simplification.
KeyInfo(ptr_diff_type index=0, value_type dist2=0)
std::iterator_traits< InputIterator >::value_type segment_distance2(InputIterator s1, InputIterator s2, InputIterator p)
Computes the squared distance between a line segment (s1, s2) and a point p.
OutputIterator ReumannWitkam(InputIterator first, InputIterator last, value_type tol, OutputIterator result)
Performs Reumann-Witkam approximation (RW).
OutputIterator RadialDistance(InputIterator first, InputIterator last, value_type tol, OutputIterator result)
Performs the (radial) distance between points routine (RD).
void CopyKey(InputIterator key, OutputIterator &result)
Copies the key to the output destination.
OutputIterator simplify_reumann_witkam(ForwardIterator first, ForwardIterator last, typename std::iterator_traits< ForwardIterator >::value_type tol, OutputIterator result)
Performs Reumann-Witkam polyline simplification (RW).
std::iterator_traits< InputIterator >::value_type dot(InputIterator v1, InputIterator v2)
Computes the dot product of two vectors.
T & operator[](int offset)
Douglas-Peucker approximation helper class.
std::iterator_traits< InputIterator1 >::value_type point_distance2(InputIterator1 p1, InputIterator2 p2)
Computes the squared distance of two points.
OutputIterator interpolate(InputIterator p1, InputIterator p2, float fraction, OutputIterator result)
Peforms linear interpolation between two points.
value_type dist2
coord index of the key
std::iterator_traits< InputIterator >::value_type value_type
static void Approximate(const value_type *coords, ptr_diff_type coordCount, value_type tol, unsigned char *keys)
Performs Douglas-Peucker approximation.
void Backward(InputIterator &it, unsigned &remaining)
Decrements the iterator by 1 point.
void swap(scoped_array &b)
OutputIterator Lang(InputIterator first, InputIterator last, value_type tol, unsigned look_ahead, OutputIterator result)
Performs Lang approximation (LA).
OutputIterator DouglasPeuckerN(InputIterator first, InputIterator last, unsigned count, OutputIterator result)
Performs a Douglas-Peucker approximation variant (DPn).
void swap(scoped_array< T > &a, scoped_array< T > &b)
math::Statistics compute_positional_error_statistics(ForwardIterator original_first, ForwardIterator original_last, ForwardIterator simplified_first, ForwardIterator simplified_last, bool *valid=0)
Computes statistics for the positional errors between a polyline and its simplification.
OutputIterator simplify_radial_distance(ForwardIterator first, ForwardIterator last, typename std::iterator_traits< ForwardIterator >::value_type tol, OutputIterator result)
Performs the (radial) distance between points routine (RD).
std::iterator_traits< InputIterator >::value_type line_distance2(InputIterator l1, InputIterator l2, InputIterator p)
Computes the squared distance between an infinite line (l1, l2) and a point p.
KeyInfo keyInfo
coord index of the last point
Root namespace of the polyline simplification library.
OutputIterator PerpendicularDistance(InputIterator first, InputIterator last, value_type tol, unsigned repeat, OutputIterator result)
Repeatedly performs the perpendicular distance routine (PD).
ptr_diff_type last
coord index of the first point
A smart pointer for holding a dynamically allocated array.
PointBufferPtr transform(PointBufferPtr pc_in, const Transformd &T)
static void ApproximateN(const value_type *coords, ptr_diff_type coordCount, unsigned countTol, unsigned char *keys)
Performs Douglas-Peucker approximation.