源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Java编程实现轨迹压缩算法开放窗口实例代码

  • 时间:2020-05-11 06:55 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Java编程实现轨迹压缩算法开放窗口实例代码
轨迹压缩算法 场景描述 给定一个GPS数据记录文件,每条记录包含经度和维度两个坐标字段,根据距离阈值压缩记录,将过滤后的所有记录的经纬度坐标构成一条轨迹 算法描述 这种算法的用处还是相当广泛的。 轨迹压缩算法分为两大类,分别是无损压缩和有损压缩,无损压缩算法主要包括哈夫曼编码,有损压缩算法又分为批处理方式和在线数据压缩方式,其中批处理方式又包括DP(Douglas-Peucker)算法、TD-TR(Top-Down Time-Ratio)算法和Bellman算法,在线数据压缩方式又包括滑动窗口、开放窗口、基于安全区域的方法等。 大家也可参考这篇文章:[b]《[/b][url=http://www.1sucai.cn/article/129227.htm][b]Java编程实现轨迹压缩之Douglas-Peucker算法详细代码[/b][/url][b]》[/b] 代码实现
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TrajectoryCom {
 public static void main(String[] args) throws Exception{
  //阈值定义
  double maxDistanceError = 30;
  /*
  * 文件读取
  * */
  //存放从文件读取的位置点的信息列表
  ArrayList<enpoint> ENPList = new ArrayList<enpoint>();
  //源数据文件的地址 建立文件对象
  //这里是需要更改的地方 改你源文件的存放地址 记住如果地址中含"\",记得再加一个"\",原因"\"是转义符号 
  //这里可以写成C:/Users/Administrator/Desktop/11.6/2007-10-14-GPS.log
  File sourceFile = new File("./2007-10-14-GPS.log");
  //调用文件读取函数 读取文件数据
  ENPList = getENPointFromFile(sourceFile);
  //这里是测试 有没有读到里面 看看列表里的数据个数 交作业的时候记得注释掉
  System.out.println(ENPList.size());
  /*
  * 数据处理
  * 方法:开放窗口轨迹压缩法
  * */
  //存放目标点的集合
  ArrayList<enpoint> rePointList = new ArrayList<enpoint>();
  rePointList = openWindowTra(ENPList,maxDistanceError);
  System.out.println(rePointList.size());
  /*
  * 写入目标文件
  * */
  File targetFile = new File("./2007-10-14-GPSResult.log");
  writeTestPointToFile(targetFile,rePointList);
  /*
  * 压缩率计算
  */
  double cpL = (double)rePointList.size() / (double)ENPList.size() * 100;
  DecimalFormat df = new DecimalFormat("0.000000");
  System.out.println("压缩率:"+ df.format(cpL) + "%");
  /*
  * 计算平均距离误差
  * */
  double aveDisErr = getMeanDistError(ENPList,rePointList);
  System.out.println(aveDisErr);
  /*
  * 画线形成对比图
  * */
  //generateImage(ENPList,rePointList);
 }
 /*
 * 从提供的文件信息里提取位置点
 * 并将每个点的坐标数值调用转换函数存到列表里
 * 函数返回一个 存放所有位置点 的集合
 */
 public static ArrayList<enpoint> getENPointFromFile(File fGPS)throws Exception{
  ArrayList<enpoint> pGPSArray = new ArrayList<enpoint>();
  if(fGPS.exists()&&fGPS.isFile()){
   InputStreamReader read = new InputStreamReader(new FileInputStream(fGPS));
   //输入流初始化
   BufferedReader bReader = new BufferedReader(read);
   //缓存读取初始化
   String str;
   String[] strGPS;
   int i = 0;
   while((str = bReader.readLine())!=null){
    //每次读一行
    strGPS = str.split(" ");
    ENPoint p = new ENPoint();
    p.id = i;
    i++;
    p.pe = (dfTodu(strGPS[3]));
    p.pn = (dfTodu(strGPS[5]));
    pGPSArray.add(p);
   }
   bReader.close();
  }
  return pGPSArray;
 }
 /**
 * 函数功能:将原始经纬度坐标数据转换成度
 * 获取的经纬度数据为一个字符串
 */
 public static double dfTodu(String str){
  int indexD = str.indexOf('.');
  //获取 . 字符所在的位置
  String strM = str.substring(0,indexD-2);
  //整数部分
  String strN = str.substring(indexD-2);
  //小数部分
  double d = double.parsedouble(strM)+double.parsedouble(strN)/60;
  return d;
 }
 /*
 * 开放窗口方法实现
 * 返回一个压缩后的位置列表
 * 列表每条数据存放ID、点的坐标
 * 
 * 算法描述:
 * 初始点和浮动点计算出投影点,判断投影点和轨迹点的距离与阈值 若存在距离大于阈值 
 * 则初始点放入targetList,浮动点向前检索一点作为新的初始点,新的初始点向后检索第二个作为新的浮动点 这里存在判断 即新的初始点位置+1是不是等于列表长度 这里决定了浮动点的选取
 * 如此处理至终点
 * */
 public static ArrayList<enpoint> openWindowTra(ArrayList<enpoint> sourceList,double maxDis){
  ArrayList<enpoint> targetList = new ArrayList<enpoint>();
  //定义初始点位置 最开始初始点位置为0 
  int startPoint = 0;
  //定义浮动点位置 最开始初始点位置2
  int floatPoint = 2;
  //定义当前轨迹点位置 最开始初始点位置为1
  int nowPoint = 1;
  int len = sourceList.size();
  //存放所有窗口内的点的信息集合 
  ArrayList<enpoint> listPoint = new ArrayList<enpoint>();
  listPoint.add(sourceList.get(nowPoint));
  //浮动点位置决定循环
  while(true){
   //标志 用来控制判断是否进行窗口内轨迹点更新
   Boolean flag = false;
   //计算并判断窗口内所有点和投影点的距离是否大于阈值
   for (ENPoint point:listPoint){
    double disOfTwo = getDistance(sourceList.get(startPoint),sourceList.get(floatPoint),point);
    if(disOfTwo >= 30){
     flag = true;
     break;
    }
   }
   if(flag){
    //窗口内点距离都大于阈值
    //初始点加到目标列表
    targetList.add(sourceList.get(startPoint));
    //初始点变化
    startPoint = floatPoint - 1;
    //浮动点变化
    floatPoint += 1;
    if(floatPoint >= len){
     targetList.add(sourceList.get(floatPoint-1));
     break;
    }
    //窗口内点变化
    listPoint.clear();
    //System.out.println(listPoint.size());
    listPoint.add(sourceList.get(startPoint+1));
   } else{
    //距离小于阈值的情况
    //初始点不变
    //当前窗口集合加入当前浮动点
    listPoint.add(sourceList.get(floatPoint));
    //浮动点后移一位
    floatPoint += 1;
    //如果浮动点是终点 且当前窗口点距离都小于阈值 就直接忽略窗口点 直接将终点加入目标点集合
    if(floatPoint >= len){
     targetList.add(sourceList.get(startPoint));
     targetList.add(sourceList.get(floatPoint-1));
     break;
    }
   }
   flag = false;
  }
  return targetList;
 }
 /*计算投影点到轨迹点的距离
 * 入口是初始点A、浮动点B、当前轨迹点C
 * 三角形面积公式
 */
 public static double getDistance(ENPoint A,ENPoint B,ENPoint C){
  double distance = 0;
  double a = Math.abs(geoDist(A,B));
  double b = Math.abs(geoDist(B,C));
  double c = Math.abs(geoDist(A,C));
  double p = (a + b + c)/2.0;
  double s = Math.sqrt(p * (p-a) * (p-b) * (p-c));
  distance = s * 2.0 / a;
  return distance;
 }
 /*
 * ArrayList 拷贝函数
 * */
 /*提供的函数
 * 其中计算距离的函数 经过改造得到下面的距离计算方法
 * 具体是怎么计算距离的 我也没研究了
 * */
 public static double geoDist(ENPoint pA,ENPoint pB){
  double radLat1 = Rad(pA.pn);
  double radLat2 = Rad(pB.pn);
  double delta_lon = Rad(pB.pe - pA.pe);
  double top_1 = Math.cos(radLat2) * Math.sin(delta_lon);
  double top_2 = Math.cos(radLat1) * Math.sin(radLat2) - Math.sin(radLat1) * Math.cos(radLat2) * Math.cos(delta_lon);
  double top = Math.sqrt(top_1 * top_1 + top_2 * top_2);
  double bottom = Math.sin(radLat1) * Math.sin(radLat2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.cos(delta_lon);
  double delta_sigma = Math.atan2(top, bottom);
  double distance = delta_sigma * 6378137.0;
  return distance;
 }
 public static double Rad(double d){
  return d * Math.PI / 180.0;
 }
 /*
 * 将压缩后的位置点信息写入到文件中
 * */
 public static void writeTestPointToFile(File outGPSFile,ArrayList<enpoint> pGPSPointFilter)throws Exception{
  Iterator<enpoint> iFilter = pGPSPointFilter.iterator();
  RandomAccessFile rFilter = new RandomAccessFile(outGPSFile,"rw");
  while(iFilter.hasNext()){
   ENPoint p = iFilter.next();
   String sFilter = p.getResultString();
   byte[] bFilter = sFilter.getBytes();
   rFilter.write(bFilter);
  }
  rFilter.close();
 }
 /**
 * 函数功能:求平均距离误差
 * 返回平均距离
 */
 public static double getMeanDistError(ArrayList<enpoint> pGPSArray,ArrayList<enpoint> pGPSArrayRe){
  double sumDist = 0.0;
  for (int i=1;i<pgpsarrayre.size();i++){
   double="" end="pGPSArrayRe.get(i).id;" int="" j="start+1;j<end;j++){" meandist="sumDist/(pGPSArray.size());" pre="" return="" start="pGPSArrayRe.get(i-1).id;" sumdist=""><pre class="brush:java;">import java.text.DecimalFormat;
   public class ENPoint implements Comparable<enpoint>{
    public int id;
   //点ID
   public double pe;
   //经度
   public double pn;
   //维度
   public ENPoint(){
   }
   //空构造函数
   public String toString(){
    return this.id+"#"+this.pn+","+this.pe;
   }
   public String getResultString(){
    DecimalFormat df = new DecimalFormat("0.000000");
    return this.id+"#"+df.format(this.pe)+","+df.format(this.pn)+" \n";
   }
   @Override
    public int compareTo(ENPoint other) {
    if(this.id<other.id) else="" return="" this.id="">other.id) return 1; else
      return 0;
   }
  }
[b]总结[/b] 以上就是本文关于Java编程实现轨迹压缩算法开放窗口实例代码的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部