热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

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

这篇文章主要介绍了Java编程实现轨迹压缩算法开放窗口实例代码,具有一定借鉴价值,需要的朋友可以参考下。

轨迹压缩算法

场景描述

给定一个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 ENPList = new ArrayList();
		//源数据文件的地址 建立文件对象
		//这里是需要更改的地方 改你源文件的存放地址 记住如果地址中含"\",记得再加一个"\",原因"\"是转义符号 
		//这里可以写成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 rePointList = new ArrayList();
		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 getENPointFromFile(File fGPS)throws Exception{
		ArrayList pGPSArray = new ArrayList();
		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 openWindowTra(ArrayList sourceList,double maxDis){
		ArrayList targetList = new ArrayList();
		//定义初始点位置 最开始初始点位置为0 
		int startPoint = 0;
		//定义浮动点位置 最开始初始点位置2
		int floatPoint = 2;
		//定义当前轨迹点位置 最开始初始点位置为1
		int nowPoint = 1;
		int len = sourceList.size();
		//存放所有窗口内的点的信息集合 
		ArrayList listPoint = new ArrayList();
		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 pGPSPointFilter)throws Exception{
		Iterator 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 pGPSArray,ArrayList pGPSArrayRe){
		double sumDist = 0.0;
		for (int i=1;i
import java.text.DecimalFormat;
			public class ENPoint implements Comparable{
			 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.idother.id) return 1; else
				  return 0;
			}
		}

总结

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


推荐阅读
  • 如何为PDF文档添加水印?简单步骤实现
    为了增强PDF文档的安全性和版权保护,添加水印是一个有效的方法。本文将介绍如何通过专业软件或在线工具轻松为PDF文档添加水印,确保您的文档在共享时仍能保持其独特性和安全性。 ... [详细]
  • 本文汇集了作者在准备研究生入学考试过程中的心得体会,包括备考策略、复习重点及应对考试的心理调适技巧,旨在为即将参加考研的学生提供实用建议。 ... [详细]
  • 分布式计算助力链力实现毫秒级安全响应,确保100%数据准确性
    随着分布式计算技术的发展,其在数据存储、文件传输、在线视频、社交平台及去中心化金融等多个领域的应用日益广泛。国际知名企业如Firefox、Google、Opera、Netflix、OpenBazaar等均已采用该技术,推动了技术创新和服务升级。 ... [详细]
  • 垂直泊车路径设计
    本文探讨了垂直泊车路径的设计原理与实现方法。垂直泊车是指汽车从特定位置出发,经过一系列横向和纵向移动,最终达到与车位垂直停放的状态。路径设计旨在确保泊车过程既高效又安全。 ... [详细]
  • 本文探讨了在不同场景下如何高效且安全地存储Token,包括使用定时器刷新、数据库存储等方法,并针对个人开发者与第三方服务平台的不同需求提供了具体建议。 ... [详细]
  • 深入理解MongoDB的SCRAM-SHA-1认证流程
    本文详细解析了MongoDB的SCRAM-SHA-1认证机制的具体步骤,旨在帮助读者深入了解这一安全认证方法的工作原理及其在实际应用中的重要性。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • Java高级工程师学习路径及面试准备指南
    本文基于一位朋友的PDF面试经验整理,涵盖了Java高级工程师所需掌握的核心知识点,包括数据结构与算法、计算机网络、数据库、操作系统等多个方面,并提供了详细的参考资料和学习建议。 ... [详细]
  • 宝塔面板下启用HTTPS的详细指南
    本文提供了在宝塔面板环境中配置HTTPS的具体步骤,确保您的网站通信更加安全可靠。 ... [详细]
  • 本文探讨了在使用 MyBatis 进行批量数据处理时遇到的参数绑定异常问题,并提供了详细的解决方案。 ... [详细]
  • 本文详细介绍了如何在Windows和Linux系统上配置Openfire服务器,包括安装步骤、数据库配置及端口映射等关键环节。 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • 近期阅读了《中国云计算的十年变迁》和《阿里云背后的创新者们》两篇文章,深入了解了中国云计算的十年发展历程及阿里云的创立背景。阿里云作为中国公有云市场的先驱,其未来的竞争格局引人关注。 ... [详细]
  • 本文介绍了两种有效的方法来处理C4996编译器警告,包括替换为安全的函数以及通过预处理器指令禁用警告。 ... [详细]
author-avatar
学圆周_486
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有