SDT旋转门压缩算法MFC图形测试

SDT旋转门压缩算法通过上门和下门的概念,利用斜率变化来压缩慢变化曲线数据。当上门斜率大于等于下门斜率时找到数据段终点,实现数据的离散表示,从而减少数据量。算法效果受数据类型影响,正弦波数据压缩效果好。在MFC环境中,通过调整压缩精度m_Acc来平衡压缩率和解压误差。提供了解压过程的线性插值方法,并附带了VS2010的C++实现代码。

算法原理:


详细的解释:首先两扇门(由t0上的固定点,分别取上方和下方距该点E的距离取两个点形成的线段,看作上门和下门)处于关闭状态,也就是两扇门形成一条线与横向方向(t0->t8)垂直。现在加入新的点进来,上方点与新点形成新的直线斜率、下方点与新点也形成新的直线斜率。而核心就是:上门的斜率只能变大、下门的斜率只能变小,当新的点加入时,上门的斜率和下门的斜率均在变化,只能够朝一个方向变化。如果有一个新的点使得上门的斜率大于等于下门的斜率,即临界条件为双线平行时,那么这个新的点的上一个点为这一段数据表示的终点,即初始点和该点形成的线段可以粗略的标示该段区域内其它点的值(只要给出横向的数值,类同于y = kx + b),这在数学上称为离散分布,即真实的数据分布在线段区域的周围。因而,只需要两个点就可以大致的表示出这一区域所有的点,因而对于这种慢变化的曲线数据可以大大的减少实际数据量的大小,这就是整个算法的核心。


说明:该算法的压缩效果和数据有很大关系,一般测试时用正弦波数据,压缩效果很好,如果用随机数,基本不会压缩。

程序说明:

 1、m_Acc(压缩精度)的值要根据待压缩的数值来定,如果m_Acc的值太小,解压误差会很小,但压缩率低。

 2、如果m_Acc的值太大,压缩比非常高,100MB的文件可能就只有几M,但解压误差非常大。所以m_Acc要多试几次取一个比较合理的值。

 3、解压过程:(线性插值)有起点和终点坐标可以求出线段的公式,然后根据某点x轴坐标求出其对应的y的值,也就是实际的值。


下面给出VS2010测试该算法的完整C++实现代码:(作为该算法的核心模块)

1、sdt.cpp

#pragma once
#include "StdAfx.h"
#include <vector>

struct point {
<span style="white-space:pre">	</span>int time;
    double y;
	point(int new_time = 0, double new_y = 0.0) : time(new_time), y(new_y) {}
};

class sdt {
	double m_Acc;	//压缩精度

public:
	sdt(double m_Acc = 0) : m_Acc(m_Acc) {};

void compress(std::vector<point>& undeal, std::vector<point>& comp) {
		//上门和下门,初始时门是关着的
		const double MAX_DOUBLE = 1.79769e+308;
		double slope1 = -MAX_DOUBLE;
		double slope2 = MAX_DOUBLE;
      
		//当前数据的上斜率和下斜率
		double now_slope1, now_slope2;
      
		double data;               //当前的数据
		double last_stored_data = undeal[0].y;   //最近保存的点
		double last_read_data = last_stored_data;<span style="white-space:pre">	</span>//当前数据的前一个数据
  
		//save the first data
		comp.push_back(undeal[0]);
      
		int last_stored_time = undeal[0].time;  //最近保存数据的时间
      
		//循环处理数据
		int t;
		int size = undeal.size(), i;
		for( i = 1; i < size; ++i ) {
			t = undeal[i].time;
			data = undeal[i].y;
			now_slope1 = double(data - last_stored_data - m_Acc) / (t - last_stored_time);
			if(now_slope1 > slope1)	//	上门的斜率只能变大
				slope1 = now_slope1;
  
			now_slope2 = double(data - last_stored_data + m_Acc) / (t - last_stored_time);
			if(now_slope2 < slope2)	//	下门的斜率只能变小
				slope2 = now_slope2;
  
			if(slope1 >= slope2) {	//当上门的斜率大于或等于下门的斜率时,即两门的夹角大于或等于180度
				//保存前一个点
				comp.push_back(undeal[i - 1]);
              
				last_stored_time = undeal[i - 1].time; //修改最近保存数据时间点
				last_stored_data = unde
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值