C语言程序实现道格拉斯—普克算法(Douglas--Peucker)

算法简介

道格拉斯—普克算法(Douglas—Peucker)也称,线简化算法。作用在于,删除冗余数据,减少数据的存贮量,节省存贮空间,加快后继处理的速度。

格拉斯—普克算法(Douglas—Peucker)的核心思想:

  1. 对每一条曲线的首末端点连一条线,求所有点到该直线的距离,并找出最大距离值Dmax,用与阈值限差D相比:
  2. 若Dmax<D,这条曲线上的中间点全部舍去;
  3. 若Dmax ≥ D,保留对应的坐标点(X’, Y’)
  4. 以新的点为断点,把曲线分为两部分,对这两部分从第一步开始重复C语言程序实现道格拉斯—普克算法(Douglas--Peucker)_第1张图片

 

程序实现

主函数

/*Author: Chuqiao Yi && Xiaoqing Shen*/

#include
#include
#include "simplify.h"
#include
#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 
#include 
#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

参考

Ramer-Douglas-Peucker 

PS.原创代码,转载请获得作者同意

你可能感兴趣的:(道格拉斯—普克算法,Douglas,Peucker,C语言)