利用道格拉斯·普客法(DP法)压缩矢量多边形(C++)

1.算法描述

经典的Douglas-Peucker算法(简称DP法)描述如下:

(1)在曲线首尾两点A,B之间连接一条直线AB,该直线为曲线的弦;

(2)得到曲线上离该直线段距离最大的点C,计算其与AB的距离d;

(3)比较该距离与预先给定的阈值threshold的大小,如果小于threshold,则该直线段作为曲线的近似,该段曲线处理完毕。

(4)如果距离大于阈值,则用C将曲线分为两段AC和BC,并分别对两段取信进行1~3的处理。

(5)当所有曲线都处理完毕时,依次连接各个分割点形成的折线,即可以作为曲线的近似

2.算法分析

①显然,整个过程是一个迭代过程,第四步时迭代,再次回到第一步。

②由于计算开方耗时,所以直接取d2作为评判值更加方便。

③DP法一般是化简一条曲线,本次化简的是多边形,实质是一条首尾相连的多边形,意味着曲线首尾两点的坐标相等。如果两点坐标相等,则第二步计算距离时会出现分母为0的问题。因此要换一个就近的点。

3.算法实现

①计算某点到已知两点的距离。

// 计算一点到一条直线(已知两点)的距离
double disP2L(CMyPoint* first, CMyPoint* last, CMyPoint* third) //first和last分别为线的两端,third是第三点
																//CMyPoint是点的类型,可以换成CPoint
{
	double x0 = first->Getx();
	double y0 = first->Gety();
	double x1 = last->Getx();
	double y1 = last->Gety();
	double x = third->Getx();
	double y = third->Gety();
	//diSquare是d2,不开方,耗时更短。
	double disSuqare = ((y0 - y1)*x + (x1 - x0)*y + (x0*y1 - x1*y0))*((y0 - y1)*x + (x1 - x0)*y + (x0*y1 - x1*y0)) / ((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0));
	return disSuqare;
}

②压缩算法

// Douglas–Peucker法,20190220,压缩,zf
void DP(vector<CMyPoint*> inputLine)        //输入是包含指针的数组,vector类型
{
	if (inputLine.size() <= 2)              //若少于两点,直接返回
		return;
	int size = inputLine.size();
	CMyPoint *first = inputLine[0];         //定义首点
	CMyPoint *last = inputLine[size - 1];   //定义尾点
	while (last->Getx() == first->Getx() && last->Gety() == first->Gety()) {//若首尾相同,则换点
		size = size - 1;
		last = inputLine[size - 1];
	}
	int flag = 0;                            //标记距离最大的点的下标
	double disSquare = 0;
	for (int i = 1; i<inputLine.size() - 1; i++) {
		double temp = disP2L(first, last, inputLine[i]);
		if (temp>disSquare) {                //记录最大距离及编号
			disSquare = temp;
			flag = i;
		}
	}
	if (disSquare<4) {                       //判断值与阈值的关系,阈值自己设定
		out_DP.push_back(first);             //如果小于阈值,则保留首尾点
		out_DP.push_back(last);              //out_DP是一个全局变量,vector<CMyPoint*> out_DP
		                                     //用于存储留下来的点,是最后的成果
	}
	else {                                   //否则分成两段
		vector<CMyPoint*> head, rear;
		for (int j = 0; j<inputLine.size(); j++) {
			if (j <= flag) head.push_back(inputLine[j]);
			if (j >= flag) rear.push_back(inputLine[j]);
		}
		DP(head);                            //迭代进行
		DP(rear);
	}
}

4.实验效果

分别是前、后

  

在保持图形和面积基本不变的前提下,多边形的点变少,压缩具有较好效果。

原文地址:https://www.cnblogs.com/fan-0802-WHU/p/10417427.html

时间: 2024-08-30 18:19:02

利用道格拉斯·普客法(DP法)压缩矢量多边形(C++)的相关文章

LightOJ - 1128 (倍增法 + dp)

唔 已经有一个多月没有写题解了, 其实这一个多月也是做了一些题目的,但是就是比较懒啊,所以都堆在一起没有写了--. 题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26842 题意: 给出一棵树(有默认根), 每个节点有一个权值,再给出q个询问,每个询问包含v k两个变量, 让你输出树根和v节点的路径上,权值大于等于k的离树根最近的节点. 思路: 算是倍增法 + dp的入门练习吧. dp[v][i] 表示节点v

2017年淘客全新玩法——代理模式

2017年必将会是淘客的一个转折年. 在这之前,他的火爆完全是在依托流量,不管是微信还是QQ群,谁的流量多,谁的收益就多就越是能脱颖而出.然而到了今年,如果还在依托固有的泛流量思维定式,90%以上的人会被淘汰出局. 当然我不是说流量不管用了,而是说在获取流量的方式上,会发生很大的变化,也就是引流.之前在松松博客上面曾经发表过一篇关于群维护的文章,可以和这篇互补来看,具体参考<听说你的淘客群又做死了?来学学群维护这几招!> 如今红包裂变是越来越难了,成本也在不断高升,那么今年的新路子会是什么?我

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

poj 3349:Snowflake Snow Snowflakes(哈希查找,求和取余法+拉链法)

Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 30529   Accepted: 8033 Description You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Y

HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由于得到每张卡片的状态不知道,所以用状态压缩,dp[i] 表示这个状态时,要全部收齐卡片的期望. 由于有可能是什么也没有,所以我们要特殊判断一下.然后就和剩下的就简单了. 另一个方法就是状态压缩+容斥,同样每个状态表示收集的状态,由于每张卡都是独立,所以,每个卡片的期望就是1.0/p,然后要做的就是要去重,既然

八皇后问题(回溯法&amp;枚举法)

作者 : 卿笃军 本文讨论了八皇后问题的三种解决方案: 一.枚举法 二.回溯法(递归版) 三.回溯法(非递归版) 本来这些代码是以前编写好的,没有发表,由于最近又学习到了八皇后问题,自己整理了一下发表了出来! 首先.说明一下何为八皇后问题,我也不去谷歌了,直接简单的说明一下: 八皇后问题,就是在一个8*8的平面棋盘上,要求你摆放8个棋子,要求:这8个棋子不能有2个在同一行,也不能有2个在同一列,同时一条斜线上面也不能有2个~~~~ 比如:4*4的棋盘,你可以这样摆放(4皇后问题): 以上图为参照

[问题2014A02] 解答二(求和法+拆分法,由张诚纯同学提供)

[问题2014A02] 解答二(求和法+拆分法,由张诚纯同学提供) 将行列式 \(D_n\) 的第二列,\(\cdots\),第 \(n\) 列全部加到第一列,可得 \[ D_n=\begin{vmatrix} \sum_{i=1}^na_i+(n-2)a_1 & a_1+a_2 & \cdots & a_1+a_{n-1} & a_1+a_n \\ \sum_{i=1}^na_i+(n-2)a_2 & 0 & \cdots & a_2+a_{n-1

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就

hdu 4352 数位dp + 状态压缩

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2265    Accepted Submission(s): 927 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful