当前位置: 移动技术网 > IT编程>开发语言>Java > Java编程实现轨迹压缩算法开放窗口实例代码

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

2019年07月19日  | 移动技术网IT编程  | 我要评论

手机高清mv下载,馨宝,圣莫丽斯秘密花园

轨迹压缩算法

场景描述

给定一个gps数据记录文件,每条记录包含经度和维度两个坐标字段,根据距离阈值压缩记录,将过滤后的所有记录的经纬度坐标构成一条轨迹

算法描述

这种算法的用处还是相当广泛的。

轨迹压缩算法分为两大类,分别是无损压缩和有损压缩,无损压缩算法主要包括哈夫曼编码,有损压缩算法又分为批处理方式和在线数据压缩方式,其中批处理方式又包括dp(douglas-peucker)算法、td-tr(top-down time-ratio)算法和bellman算法,在线数据压缩方式又包括滑动窗口、开放窗口、基于安全区域的方法等。

大家也可参考这篇文章:java编程实现轨迹压缩之douglas-peucker算法详细代码

代码实现

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;
			}
		}

总结

以上就是本文关于java编程实现轨迹压缩算法开放窗口实例代码的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网