Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- std::vector<Point> DouglasPeucker(const std::vector<Point>& pts, const double tolerance) {
- std::vector<Point> result_pts;
- struct StackElement {
- Point pt;
- size_t idx;
- };
- {
- std::vector<StackElement> dpStack;
- result_pts.resize(0);
- // size == 8 is some arbitrary size at which simplification probably
- // isn't worth it.
- if (pts.empty() || pts.size() <= 100) {
- return std::vector<Point>(pts);
- }
- dpStack.reserve(pts.size());
- Point anchor = pts.front();
- size_t anchor_idx = 0;
- Point floater = pts.back();
- size_t floater_idx = pts.size() - 2;
- // many items submitted to this are closed loops,
- // whose first + last points are equivalent. this
- // will cause divide by zero errors when finding distance below
- if (floater == anchor) {
- floater = pts[floater_idx - 1];
- }
- result_pts.push_back(anchor);
- StackElement elem{
- floater,
- floater_idx,
- };
- dpStack.push_back(elem);
- while (!dpStack.empty()) {
- double max_distSq = 0.0;
- Point furthest = anchor;
- size_t furthest_idx = anchor_idx;
- // find point furthest from line seg created by (anchor, floater) and note it
- for (size_t i = anchor_idx + 1; i < floater_idx; ++i) {
- const double dist = static_cast<double>(GetDistSqFromLine(pts[i], pts[anchor_idx], pts[floater_idx]));
- if (dist > max_distSq) {
- max_distSq = dist;
- furthest = pts[i];
- furthest_idx = i;
- }
- }
- // remove point if less than tolerance
- if (max_distSq <= tolerance) {
- result_pts.push_back(dpStack.back().pt);
- dpStack.pop_back();
- anchor = floater;
- anchor_idx = floater_idx;
- if (!dpStack.empty()) {
- floater = dpStack.back().pt;
- floater_idx = dpStack.back().idx;
- }
- }
- else {
- floater = furthest;
- floater_idx = furthest_idx;
- elem.pt = floater;
- elem.idx = floater_idx;
- dpStack.push_back(elem);
- }
- }
- }
- return result_pts;
- }
Add Comment
Please, Sign In to add comment