douglas peucker递归分治

来源:互联网 发布:淘宝添加到桌面没有了 编辑:程序博客网 时间:2024/05/01 15:07

vs2015 c++11 standard or later


1. geometry.h

#ifndef GEOMERTY_H_#define GEOMETRY_H_#include <deque>union Point{struct{float x, y;};float compo[2];};typedef std::deque<Point> PointList;#endif // !GEOMERTY_H_


2. dauglas_peucker.hpp

#ifndef DOUGLAS_PEUCKER_HPP_#define DOUGLAS_PEUCKER_HPP_#include "geometry.h"#include <vector>#include <math.h>#include <algorithm>struct _Simple_Point// 递归函数中使用的点结构{float x, y;unsigned i;// 递归后顺序被打乱,故保存序号};typedef std::vector<_Simple_Point> _Point_List;void _douglas_peucker(_Point_List & output, float limit, _Point_List::const_iterator left, _Point_List::const_iterator right){if (output.empty())// 先加入首尾两点{output.push_back(*left);output.push_back(*right);}if (right - left <= 1)// 已相邻{return;}float c2 = (right->x - left->x) * (right->x - left->x) + (right->y - left->y) * (right->y - left->y);bool all_in_limit = true;float max_h = 0.0f;_Point_List::const_iterator max_val_iter;for (_Point_List::const_iterator iter = left + 1; iter < right; ++iter){float a2 = (iter->x - right->x) * (iter->x - right->x) + (iter->y - right->y) * (iter->y - right->y);float b2 = (iter->x - left->x) * (iter->x - left->x) + (iter->y - left->y) * (iter->y - left->y);float cosine = (b2 + c2 - a2) / (2.0f * sqrtf(b2) * sqrtf(c2));float sine = sqrtf(1.0f - cosine * cosine);float h = sqrtf(b2) * sine;if (h > limit && h > max_h){max_h = h;max_val_iter = iter;if (all_in_limit)all_in_limit = false;}}if (all_in_limit){return;}else{output.push_back(*max_val_iter);}// 分治_douglas_peucker(output, limit, left, max_val_iter);_douglas_peucker(output, limit, max_val_iter, right);}PointList DouglasPeucker(const PointList & input, float limit){if (input.size() < 2){return input;}_Point_List list(input.size());for (size_t i = 0; i < input.size(); i++){list[i].x = input[i].x;list[i].y = input[i].y;list[i].i = i;}_Point_List outlist;_douglas_peucker(outlist, limit, list.cbegin(), list.cend() - 1);std::sort(outlist.begin(), outlist.end(), [](const _Simple_Point & p1, const _Simple_Point & p2) ->bool {return p1.i < p2.i; });// sort()不能cbegin(), cend()PointList pointlist(outlist.size());for (size_t i = 0; i < pointlist.size(); i++){pointlist[i].x = outlist[i].x;pointlist[i].y = outlist[i].y;}return pointlist;}#endif // !DOUGLAS_PEUCKER_HPP_


2. test_main.cpp

#include "douglas_peucker.hpp"#include <stdio.h>int main(){PointList pointlist ={{ 0, 0 },{ 1, 1 },{ 2, 10 },{ 3, 5 },{ 4, 2 },{ 5, 1 },{ 6, 2 },{ 7, 8 },{ 8, 11 },{ 9, 0 }};PointList outlist = DouglasPeucker(pointlist, 2.0f);for (auto point : outlist){printf("{%f, %f}\n", point.x, point.y);}getchar();return 0;}

0 0