算法简介
道格拉斯—普克算法(Douglas—Peucker)也称,线简化算法。作用在于,删除冗余数据,减少数据的存贮量,节省存贮空间,加快后继处理的速度。
格拉斯—普克算法(Douglas—Peucker)的核心思想:
- 对每一条曲线的首末端点连一条线,求所有点到该直线的距离,并找出最大距离值Dmax,用与阈值限差D相比:
- 若Dmax<D,这条曲线上的中间点全部舍去;
- 若Dmax ≥ D,保留对应的坐标点(X’, Y’)
- 以新的点为断点,把曲线分为两部分,对这两部分从第一步开始重复
程序实现
主函数
/*Author: Chuqiao Yi && Xiaoqing Shen*/
#include<stdio.h>
#include<math.h>
#include "simplify.h"
#include<malloc.h>
#include "geom.h"
void main() {
int all_x[10] = { -4,-3,-2,-1,1,3,4,5,6,7 };
int all_y[10] = { 1,-1,0,-1,1,-3,1,2,3,5 };
int len = sizeof(struct point_2d_struct);
struct point_2d_struct* head_point, * new_point, * current_point, * end_point, * tmp_point; //头结点,新开辟的结点,临时结点
head_point = NULL; new_point = NULL;
for (int i = 0; i < 10; i++) {
current_point = (struct point_2d_struct*)malloc(len); //开辟新的结点
if (head_point == NULL)
head_point = current_point;
else
new_point->next = current_point;
current_point->x = all_x[i];
current_point->y = all_y[i];
new_point = current_point;
current_point->next = NULL;
}
end_point = current_point; //记录尾结点
simplify(head_point, end_point, 1);//进行简化
tmp_point = head_point;
while (tmp_point!= NULL) {
printf("x=%d,x=%d\n", tmp_point->x, tmp_point->y); //输出被简化的节点横纵坐标
tmp_point = tmp_point->next;
}
tmp_point = head_point;
while (tmp_point != NULL) {
tmp_point = head_point;
head_point = tmp_point->next;
free(tmp_point);
}
printf("Bye!\n");
}
线简化函数(simplify.c)
/**
* C implementation of Ramer-Douglas-Peucker algorithm.
*
* @author Bruno Vandekerkhove
* @version 1.0
*/
#include <stdlib.h>
#include <math.h>
#include "simplify.h"
void simplify(point_2d* start_point, point_2d* end_point, double epsilon) {
if (start_point == end_point || start_point == NULL || end_point == NULL || start_point->next == NULL)
return; // 达到终止条件之后退出
// 计算首尾点的坐标差
int dx = end_point->x - start_point->x;
int dy = end_point->y - start_point->y;
// 通过迭代计算记录距离首尾连线最远的点
double d, dmax = 0.0; // Maximum distance of point from line through endpoints so far
point_2d* furthest_point = start_point;
// Loop through points between endpoints
double norm = sqrt(dx * dx + dy * dy);
point_2d* current_point = start_point->next;
while (current_point != end_point) {
// 计算当前点到首尾连线的距离
d = abs(dx * (start_point->y - current_point->y)
- dy * (start_point->x - current_point->x)) / norm;
// 对距离的最大值进行更新
if (d > dmax) {
furthest_point = current_point;
dmax = d;
}
current_point = current_point->next;
}
// 如果距离大于预设值,那么对两个线段进行递归计算
if (dmax > epsilon) {
simplify(start_point, furthest_point, epsilon);
simplify(furthest_point, end_point, epsilon);
}
else { // 如果距离不大于预设值,那么对当前线段进行简化处理(删除,释放首尾节点之间的所有点)
point_2d* current_point = start_point->next, * previous_point;
while (current_point != end_point) {
previous_point = current_point;
current_point = current_point->next;
free(previous_point);
}
// 使得第一个点的next指向最末尾的点
start_point->next = end_point;
}
}
对应的两个头函数(simplify.h geom.h)
#include "geom.h"
/*
* Simplify the given linked list of points assuming given epsilon.
*
* @param start_point
* The starting point of the linked list of points to simplify.
* @param end_point
* The end point of the linked list of points to simplify.
* @param epsilon
* The maximum distance for points to be used when simplifying.
*/
void simplify(point_2d* start_point, point_2d* end_point, double epsilon);
#pragma once
#pragma once
/**
* Geometry tools.
*
* @author Bruno Vandekerkhove
* @version 1.0
*/
#ifndef _GEOM_
#define _GEOM_
/*
* 2D point referring to image location.
*/
typedef struct point_struct {
int x; // Column
int y; // Row
} point;
/*
* 2D point referring to image location (to be used in linked list).
*/
typedef struct point_2d_struct {
int x; // Column
int y; // Row
struct point_2d_struct* next;
} point_2d;
/*
* 2D line referring to image locations.
*/
typedef struct line_struct {
int x1;
int y1;
int x2;
int y2;
} line;
/*
* 2D line referring to image locations (to be used in linked list).
*/
typedef struct line_2d_struct {
int x1;
int y1;
int x2;
int y2;
struct line_2d_struct* next;
} line_2d;
/*
* 2D rectangle referring to image locations.
*/
typedef struct rectangle_struct {
int min_x;
int min_y;
int max_x;
int max_y;
} rectangle;
#endif
参考
PS.原创代码,转载请获得作者同意