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;
}
對於文獻《基於時空特性的GPS軌跡數據壓縮算法_張達夫》
首先,“一次性”壓縮,可以考慮以下幾種

其中,均勻采樣算法最簡單,這個就是每n個點取一個采樣點,不多說。第二個的道格拉斯-普克算法已經實現過了,也不多說。第三個是把DP算法中的誤差指標替換成了“同步歐式距離”,就是結合時間和空間因素來計算距離,摒棄之前只使用空間距離的方法。第四個是采用另外的體系,是采用“速度差”來衡量誤差,在老師給的GPS.log數據文件中GPS坐標后面的那個數據應該就是速度數據,可以使用這個速度數據來重新編寫誤差指標函數。第五個,是空間距離度量的變種,是一種在線的算法。
對於文獻《自適應參數的軌跡壓縮算法_龍浩_張書奎_孫鵬輝》
本文獻中另外提供了利用設定壓縮比來“自適應設定誤差指標”的兩種算法。其實我覺得可以是五種,因為自適應就是“把程序加個循環的變一種說法”。上面第一段那個圖中五種算法,都可以加入循環來重復計算,從而選取恰好滿足壓縮比而誤差指標取到最大的值---的情況。
上面這兩段是對軌跡壓縮問題中的“線段簡化壓縮方法”介紹。
此外還想進階的話,可以看看,“基於路網結構的壓縮方法”和“基於語義的壓縮方法”。貌似這個“基於路網的壓縮方法”使用的還比較普遍。
