轨迹压缩之Douglas-Peucker算法之C++实现

http://www.cnblogs.com/xdlwd086/p/5100425.html

这位学长编了java版本的,于是在借鉴学长的思路的基础上,做出了C++的实现,以此分享。

#include <stdio.h>     //定义输入/输出函数
#include <stdlib.h>    //定义杂项函数及内存分配函数
#include <ctime>
#include <cstdlib>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
using namespace std;
#define M_PI 3.14159265358979323846
#define DMax 30.0

long double gps[3150][2];
int gps_visit[3150] = {0};

/*	The code of GeoDistance function:
Input: Two coordination {Latitude1, Longitude1, Latitude2, Longitude2 } (type:double)
Output: Distance(Unit: m) (type:double)
*/
long double Rad(long double d){
        return d * M_PI / 180.0;
}
//经度 longitude        纬度latitude
long double Geodist(long double  lon1, long double lat1, long double lon2, long double lat2){
        long double radLat1 = Rad(lat1);
        long double radLat2 = Rad(lat2);
        long double delta_lon = Rad(lon2 - lon1);
        long double top_1 = cos(radLat2) * sin(delta_lon);
        long double top_2 = cos(radLat1) * sin(radLat2) - sin(radLat1) * cos(radLat2) * cos(delta_lon);
        long double top = sqrt(top_1 * top_1 + top_2 * top_2);
        long double bottom = sin(radLat1) * sin(radLat2) +cos(radLat1) * cos(radLat2) * cos(delta_lon);
        long double delta_sigma = atan2(top, bottom);
        long double distance = delta_sigma * 6378137.0;
        return distance;
}

//将2007-10-14-GPS.log文件中的GPS数据提取出来,转换之后另存起来
void init1(){
    ifstream in1;
    ofstream out1;
	in1.open("F:\\研一上\\滴滴算法竞赛\\城市计算\\Task\\Data\\task 1-compression\\2007-10-14-GPS.log");
	out1.open("F:\\研一上\\滴滴算法竞赛\\城市计算\\Task\\Data\\task 1-compression\\GPS.txt");

	for(int i=0;i<3150;i++){
        string temp;
        getline(in1, temp);
        string gps_E = temp.substr(20,10);
        string gps_N = temp.substr(33,9);
        out1<<gps_E<<" "<<gps_N<<endl;
	}
    out1.close();
    in1.close();
}

void init2(){
    ifstream in2;
    ofstream out2;
    in2.open("F:\\研一上\\滴滴算法竞赛\\城市计算\\Task\\Data\\task 1-compression\\GPS.txt");
    out2.open("F:\\研一上\\滴滴算法竞赛\\城市计算\\Task\\Data\\task 1-compression\\realGPS1.txt");
    for(int i=0;i<3150;i++){
        long double gps_E,gps_N;
        in2>>gps_E>>gps_N;
        gps_E = (gps_E - 11600.0)*1.0/60+116.0;
        gps_N = (gps_N - 3900)*1.0/60+39.0;
        out2 <<setiosflags(ios::fixed)<<setprecision(6)<<gps_E<<" "<<gps_N<<" "<<i+1<< endl;
        gps[i][0] = gps_E;
        gps[i][1] = gps_N;
    }
    out2.close();
    in2.close();
}

long double get_d(int point_A,int point_B,int point_C ){
    long double a  = abs( Geodist(gps[point_B][0],gps[point_B][1],gps[point_C][0],gps[point_C][1] )  );
    long double b  = abs( Geodist(gps[point_A][0],gps[point_A][1],gps[point_C][0],gps[point_C][1] )  );
    long double c  = abs( Geodist(gps[point_A][0],gps[point_A][1],gps[point_B][0],gps[point_B][1] )  );
    long double p = (a+b+c)/2.0;
    long double s = sqrtl( abs( p*(p-a)*(p-b)*(p-c)  )  );
    long double d = s*2.0/c;
    return d;
}

void dp_gps(int point_start,int point_end){
    if(point_start<point_end){  //递归进行条件
        long double maxDist = 0;  //最大距离
        int mid = 0;              //最大距离对应的下标
        for(int i=point_start+1;i<point_end;i++){
            long double temp = get_d(point_start,point_end,i);
            if(temp>maxDist){
                maxDist = temp;
                mid = i;
            }//求出最大距离及最大距离对应点的下标
        }
        if(maxDist>=DMax){
            gps_visit[mid] = 1; //记录当前点加入
            //将原来的线段以当前点为中心拆成两段,分别进行递归处理
            dp_gps(point_start,mid);
            dp_gps(mid,point_end);
        }
    }
}

int main(){
    int count = 0;  //记录输出点的个数
    long double Mean_distance_error;  //平均距离误差
    long double Compression_rate;     //压缩率
    init1();
    init2();
    gps_visit[0] = 1;
    gps_visit[3149] = 1;
    dp_gps(0,3149);

    ofstream out3;
    out3.open("F:\\研一上\\滴滴算法竞赛\\城市计算\\Task\\Data\\task 1-compression\\pointID.txt");
    for(int i=0;i<3150;i++ ){
        if(gps_visit[i]==1){
            out3<<i+1<<endl;
            count++;
        }
    }
    out3.close();

    long double sum_notVisit_d = 0;
    int start = 0,end;
    for(int i=0;i<3150;){
        if(start == 3149) break;     //如果开始点是尾点,那就结束
        for(int j=start+1;j<3150;j++){   //找出下一个压缩节点
            if(gps_visit[j]==1){
                end = j;
                break;
            }
        }
        for(int k=start+1;k<end;k++ ){
            if(gps_visit[k]==0){
                sum_notVisit_d+= get_d( start,end,k );
            }
        }
        start = end;
    }
    Mean_distance_error = sum_notVisit_d/3150.0;
    Compression_rate = count/3150.0;

    cout<<count<<endl;  //输出压缩后点的个数
    cout<<setiosflags(ios::fixed)<<setprecision(6)<<Mean_distance_error <<endl;
    cout<<setiosflags(ios::fixed)<<setprecision(4)<<Compression_rate*100<<"%"<<endl;

    system("pause");
    return 0;
}

  

时间: 2024-08-30 16:44:22

轨迹压缩之Douglas-Peucker算法之C++实现的相关文章

轨迹压缩之Douglas-Peucker算法之Java实现

第一部分 问题描述 1.1 具体任务 本次作业任务是轨迹压缩,给定一个GPS数据记录文件,每条记录包含经度和维度两个坐标字段,所有记录的经纬度坐标构成一条轨迹,要求采用合适的压缩算法,使得压缩后轨迹的距离误差小于30m. 1.2 程序输入 本程序输入是一个GPS数据记录文件. 1.3 数据输出 输出形式是文件,包括三部分,压缩后点的ID序列及坐标.点的个数.平均距离误差.压缩率 第二部分 问题解答 根据问题描述,我们对问题进行求解,问题求解分为以下几步: 2.1 数据预处理 本次程序输入为GPS

基于encoder-decoder和DCGAN的轨迹压缩研究

目录 基于encoder-decoder和DCGAN的轨迹压缩研究 内容介绍 问题介绍 本文思路 网络模型 代价函数 梯度下降 可视化 完整代码如下: 基于encoder-decoder和DCGAN的轨迹压缩研究 内容介绍 首先,本文的实验结果为:失败. 本文仅实现了程序编码和结果可视化,但是没实现的本文的目标. 理论可行的一个课题研究,但是经过初步尝试,似乎不可行,我也不知道哪些地方错了,或者需要加入那些数据处理步骤,或者程序本身就那里逻辑错了. 本文给出了完整的程序和实验思路,用来交流. 由

稀疏矩阵的压缩存储及转置算法

矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合. 稀疏矩阵:有效数据远少于无效数据. eg:规定无效数据为 0 1 0 0 0 0 0 0 0 0 2 0 3 0 0 0 4 0 0 0 0 上述矩阵则可称为一个稀疏矩阵 我们在学习C语言的时候已经见过并使用过矩阵,其实它在我们的编程语言里可以翻译成二维数组,由于稀疏矩阵的有效数据十分的少,完全存储十分耗费我们的空间,所以我们选择只存储它的有效数据位,所以我们可以直接使用一维数组将其存储起来,但是我们必须让别人在看它时还能知道它是一个

【代码】稀疏矩阵的压缩存储与转置算法

#include<iostream> #include<vector> template <class T> struct Triple { T _value; size_t _row; size_t _col; Triple(const T& t =T(),size_t row = 0 ,size_t col = 0) :_value(t) , _row(row) , _col(col) {} }; template <class T> class

倒排索引压缩:改进的PForDelta算法

由于倒排索引文件往往占用巨大的磁盘空间,我们自然想到对数据进行压缩.同时,引进压缩算法后,使得磁盘占用减少,操作系统在query processing过程中磁盘读取效率也能提升.另外,压缩算法不仅要考虑压缩效果,还要照顾到query processing过程的解压缩效率. 总的来说,好的索引压缩算法需要最大化两个方面: 1.减少磁盘资源占用 2.加快用户查询响应速度 其中,加快响应速度比减少磁盘占用更为重要.本文主要介绍PForDelta压缩算法,其简单易懂,能够提供可观的数据压缩,同时具备非常

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

1.算法描述 经典的Douglas-Peucker算法(简称DP法)描述如下: (1)在曲线首尾两点A,B之间连接一条直线AB,该直线为曲线的弦: (2)得到曲线上离该直线段距离最大的点C,计算其与AB的距离d: (3)比较该距离与预先给定的阈值threshold的大小,如果小于threshold,则该直线段作为曲线的近似,该段曲线处理完毕. (4)如果距离大于阈值,则用C将曲线分为两段AC和BC,并分别对两段取信进行1~3的处理. (5)当所有曲线都处理完毕时,依次连接各个分割点形成的折线,即

Hadoop序列化与压缩

传统的的计算机系统通过I/O操作与外界交流,,Hadoop的I/O由传统的I/O系统发展而来,但是又有些不同,Hadoop需要处理P.T级别的数据,所以在org.apache.hadoop.io包中包含了一些面向海量数据处理的基本输入输出工具,本文会对其中的序列化和压缩进行研究. 1 序列化 对象的序列化用于将对象编码成一个字节流,以及从字节流中重新构建对象.将一个对象编码成一个字节流称为序列化对象(Serializing),相反的处理过程称为反序列化. 序列化有三种主要的用途: A.作为一种持

普林斯顿大学公开课 算法1-10:并检查集合-高速整合方法优化

本节介绍了高速综合优化算法. 重量的概念,每次操作的时候将重量小的部件挂在重量大的部件之下. 这样就避免了树形结构太高的问题. 下图展示了优化前后的树形结构深度的对照. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2FpcGVpY2hhbzI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > 证明 能够证明每一个节点的深度最大为lgN. 由于

linux学习笔记——打包、压缩、远程文件传输

############打包.压缩########################## 1.打包 (打包表示把一堆文件变成一个)tar            ##打包工具        -f        ##指定生成包的名字        -c        ##创建包        -v        ##显示创建过程        -t        ##查看包中内容        -x        ##解包        -r        ##追加文件到包中        -C