Java编程实现轨迹压缩之Douglas-Peucker算法详细代码

第一部分 问题描述

1.1 具体任务

  本次作业任务是轨迹压缩,给定一个GPS数据记录文件,每条记录包含经度和维度两个坐标字段,所有记录的经纬度坐标构成一条轨迹,要求采用合适的压缩算法,使得压缩后轨迹的距离误差小于30m。

1.2 程序输入

  本程序输入是一个GPS数据记录文件。

1.3 数据输出

  输出形式是文件,包括三部分,压缩后点的ID序列及坐标、点的个数、平均距离误差、压缩率

第二部分 问题解答

  根据问题描述,我们对问题进行求解,问题求解分为以下几步:

2.1 数据预处理

  本次程序输入为GPS数据记录文件,共有3150行记录,每行记录又分为若干个字段,根据题意,我们只需关注经度和纬度坐标字段即可,原始数据文件部分记录如图2.1所示:

图2.1 原始数据文件部分记录示意图

 如图2.1所示,原始数据文件每条记录中经纬度坐标字段数据的保存格式是典型的GPS坐标表达方式,即度分格式,形式为dddmm.mmmm,其中ddd表示度,mm.mmmm表示分,小数点前面表示分的整数部分,小数点后表示分的小数部分;本次数据预处理,为方便后面两个坐标点之间距离的计算,我们需要将度分格式的经纬度坐标数据换算成度的形式,换算方法是ddd+mm.mmmm/60,此处我们保留小数点后6位数字,换算后的形式为ddd.xxxxxx。

  我们以第一条记录中经纬度坐标(11628.2491,3955.6535)为例,换算后的结果为(116.470818,39.927558),所有记录中经纬度坐标都使用方法进行,并且可以为每一个转换后的坐标点生成一个ID,进行唯一标识,压缩后,我们只需输出所有被保留点的ID即可。

2.2 Douglas-Peucker轨迹压缩算法

  轨迹压缩算法分为两大类,分别是无损压缩和有损压缩,无损压缩算法主要包括哈夫曼编码,有损压缩算法又分为批处理方式和在线数据压缩方式,其中批处理方式又包括DP(Douglas-Peucker)算法、TD-TR(Top-Down Time-Ratio)算法和Bellman算法,在线数据压缩方式又包括滑动窗口、开放窗口、基于安全区域的方法等。

  由于时间有限,本次轨迹压缩,我们决定采用相对简单的DP算法。

  DP算法步骤如下:

  (1)在轨迹曲线在曲线首尾两点A,B之间连接一条直线AB,该直线为曲线的弦;

  (2)遍历曲线上其他所有点,求每个点到直线AB的距离,找到最大距离的点C,最大距离记为dmax;

  (3)比较该距离dmax与预先定义的阈值Dmax大小,如果dmax<Dmax,则将该直线AB作为曲线段的近似,曲线段处理完毕;

  (4)若dmax>=Dmax,则使C点将曲线AB分为AC和CB两段,并分别对这两段进行(1)~(3)步处理;

  (5)当所有曲线都处理完毕时,依次连接各个分割点形成的折线,即为原始曲线的路径。

2.3 点到直线的距离

  DP算法中需要求点到直线的距离,该距离指的是垂直欧式距离,即直线AB外的点C到直线AB的距离d,此处A、B、C三点均为经纬度坐标;我们采用三角形面积相等法求距离d,具体方法是:A、B、C三点构成三角形,该三角形的面积有两种求法,分别是普通方法(底x高/2)和海伦公式,海伦公式如下:

  假设有一个三角形,边长分别为a、b、c,三角形的面积S可由以下公式求得:

其中p为半周长:

我们通过海伦公式求得三角形面积,然后就可以求得高的大小,此处高即为距离d。要想用海伦公式,必须求出A、B、C三点两两之间的距离,该距离公式是由老师给出的,直接调用距离函数即可。

注意:求出距离后,要加上绝对值,以防止距离为负数。

2.4 平均误差求解

  平均误差指的是压缩时忽略的那些点到对应线段的距离之和除以总点数得到的数值。

2.5 压缩率求解

  压缩率的计算公式如下:

2.6 数据结果文件的生成

  经过上面的处理和计算,我们将压缩后剩余点的ID和点的个数、平均距离误差、压缩率等参数都写入最终的结果文件中,问题解答完成。

第三部分 代码实现

  本程序采用Java语言编写,开发环境为IntelliJ IDEA 14.0.2,代码共分为两个类,一个是ENPoint类,用于保存经纬度点信息,一个是TrajectoryCompressionMain类,用于编写数据处理、DP算法、点到直线距离、求平均误差等函数。

3.1 程序总流程

  整个程序流程主要包括以下几个步骤:

  (1)定义相关ArrayList数组和File对象,其中ArrayList数组对象有三个,分别是原始经纬度坐标数组pGPSArryInit、过滤后的点坐标数组pGPSArrayFilter、过滤并排序后的点坐标数组pGPSArrayFilterSort;File文件对象共有五个,分别是原始数据文件对象fGPS、压缩后的结果数据文件对象oGPS、保持转换后的原始经纬度坐标点的数据文件fInitGPSPoint、仿真测试文件fTestInitPoint和fTestFilterPoint。

  (2)获取原始点坐标并将其写入到文件中,主要包括读文件和写文件两种操作;

  (3)进行轨迹压缩;

  (4)对压缩后的经纬度点坐标进行排序;

  (5)生成仿真测试文件,并用R语言工具进行图形绘制,得到最终的结果;

  (6)求平均误差和压缩率,平均误差通过函数求得,压缩率直接计算获得;

  (7)将最终结果写入结果文件中,包括过滤后的点的ID,点的个数、平均误差和压缩率;

3.2 具体实现代码

  (1)ENPoint.java

package cc.xidian.main;
import java.text.DecimalFormat;
/**
* Created by hadoop on 2015/12/20.
*/
public class ENPoint implements Comparable<ENPoint>{
public int id;
//点ID
public double pe;
//经度
public double pn;
//维度
public ENPoint(){
}
//空构造函数
public String toString(){
	//DecimalFormat df = new DecimalFormat("0.000000");
	return this.id+"#"+this.pn+","+this.pe;
}
public String getTestString(){
	DecimalFormat df = new DecimalFormat("0.000000");
	return df.format(this.pn)+","+df.format(this.pe);
}
public String getResultString(){
	DecimalFormat df = new DecimalFormat("0.000000");
	return this.id+"#"+df.format(this.pn)+","+df.format(this.pe);
}
@Override
public int compareTo(ENPoint other) {
	if(this.id<other.id) return -1; else if(this.id>other.id) return1; else
	return0;
}
}

(2)TrajectoryCompressionMain.java

package cc.xidian.main;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.List;
/**
* Created by hadoop on 2015/12/19.
*/
public class TrajectoryCompressionMain{
	public static void main(String[] args)throws Exception{
		//-----------------------1、相关ArrayList数组和File对象的声明和定义-------------------------------------------------//
		ArrayList<ENPoint> pGPSArrayInit = new ArrayList<ENPoint>();
		//原纪录经纬度坐标数组
		ArrayList<ENPoint> pGPSArrayFilter = new ArrayList<ENPoint>();
		//过滤后的经纬度坐标数组
		ArrayList<ENPoint> pGPSArrayFilterSort = new ArrayList<ENPoint>();
		//过滤并排序后的经纬度坐标数组
		File fGPS = new File("2007-10-14-GPS.log");
		//原始数据文件对象
		File oGPS = new File("2015-12-25-GPS-Result.log");
		//过滤后的结果数据文件对象
		//保持转换成度后的原始经纬度数据文件,保持格式为“ID#经纬值,纬度值”,其中经度和维度单位为度,并保留小数点后6位数字
		File fInitGPSPoint = new File("2007-10-14-GPS-ENPoint.log");
		//保持转换后的原始经纬度坐标点的数据文件
		File fTestInitPoint = new File("2007-10-14-GPS-InitTestPoint.log");
		//用于仿真的原始经纬度坐标点数据文件
		File fTestFilterPoint = new File("2015-12-25-GPS-FilterTestPoint.log");
		//用于仿真的过滤后的经纬度坐标点数据文件
		//-------------------------2、获取原始点坐标并将其写入到文件中-------------------------------------------------------//
		pGPSArrayInit = getENPointFromFile(fGPS);
		//从原始数据文件中获取转换后的经纬度坐标点数据,存放到ArrayList数组中
		writeInitPointToFile(fInitGPSPoint, pGPSArrayInit);
		//将转换后的原始经纬度点数据写入文件中
		System.out.println(pGPSArrayInit.size());
		//输出原始经纬度点坐标的个数
		//-------------------------3、进行轨迹压缩-----------------------------------------------------------------------//
		double DMax = 30.0;
		//设定最大距离误差阈值
		pGPSArrayFilter.add(pGPSArrayInit.get(0));
		//获取第一个原始经纬度点坐标并添加到过滤后的数组中
		pGPSArrayFilter.add(pGPSArrayInit.get(pGPSArrayInit.size()-1));
		//获取最后一个原始经纬度点坐标并添加到过滤后的数组中
		ENPoint[] enpInit = new ENPoint[pGPSArrayInit.size()];
		//使用一个点数组接收所有的点坐标,用于后面的压缩
		Iterator<ENPoint> iInit = pGPSArrayInit.iterator();
		int jj=0;
		while(iInit.hasNext()){
			enpInit[jj] = iInit.next();
			jj++;
		}
		//将ArrayList中的点坐标拷贝到点数组中
		int start = 0;
		//起始下标
		int end = pGPSArrayInit.size()-1;
		//结束下标
		TrajCompressC(enpInit,pGPSArrayFilter,start,end,DMax);
		//DP压缩算法
		System.out.println(pGPSArrayFilter.size());
		//输出压缩后的点数
		//-------------------------4、对压缩后的经纬度点坐标数据按照ID从小到大排序---------------------------------------------//
		ENPoint[] enpFilter = new ENPoint[pGPSArrayFilter.size()];
		//使用一个点数组接收过滤后的点坐标,用于后面的排序
		Iterator<ENPoint> iF = pGPSArrayFilter.iterator();
		int i = 0;
		while(iF.hasNext()){
			enpFilter[i] = iF.next();
			i++;
		}
		//将ArrayList中的点坐标拷贝到点数组中
		Arrays.sort(enpFilter);
		//进行排序
		for (int j=0;j<enpFilter.length;j++){
			pGPSArrayFilterSort.add(enpFilter[j]);
			//将排序后的点坐标写到一个新的ArrayList数组中
		}
		//-------------------------5、生成仿真测试文件--------------------------------------------------------------------//
		writeTestPointToFile(fTestInitPoint,pGPSArrayInit);
		//将原始经纬度数据点写入仿真文件中,格式为“经度,维度”
		writeTestPointToFile(fTestFilterPoint, pGPSArrayFilterSort);
		//将过滤后的经纬度数据点写入仿真文件中,格式为“经度,维度”
		//-------------------------6、求平均误差-------------------------------------------------------------------------//
		double mDError = getMeanDistError(pGPSArrayInit,pGPSArrayFilterSort);
		//求平均误差
		System.out.println(mDError);
		//-------------------------7、求压缩率--------------------------------------------------------------------------//
		double cRate = (double)pGPSArrayFilter.size()/pGPSArrayInit.size()*100;
		//求压缩率
		System.out.println(cRate);
		//-------------------------8、生成最终结果文件--------------------------------------------------------------------//
		//将最终结果写入结果文件中,包括过滤后的点的ID,点的个数、平均误差和压缩率
		writeFilterPointToFile(oGPS,pGPSArrayFilterSort,mDError,cRate);
		//------------------------------------------------------------------------------------------------------------//
	}
	/**
*函数功能:从源文件中读出所以记录中的经纬度坐标,并存入到ArrayList数组中,并将其返回
* @param fGPS:源数据文件
* @return pGPSArrayInit:返回保存所有点坐标的ArrayList数组
* @throws Exception
*/
	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;
	}
	/**
* 函数功能:将过滤后的点的经纬度坐标、平均距离误差、压缩率写到结果文件中
* @param outGPSFile:结果文件
* @param pGPSPointFilter:过滤后的点
* @param mDerror:平均距离误差
* @param cRate:压缩率
* @throws Exception
*/
	public static void writeFilterPointToFile(File outGPSFile,ArrayList<ENPoint> pGPSPointFilter,
	double mDerror,double cRate)throws Exception{
		Iterator<ENPoint> iFilter = pGPSPointFilter.iterator();
		RandomAccessFile rFilter = new RandomAccessFile(outGPSFile,"rw");
		while(iFilter.hasNext()){
			ENPoint p = iFilter.next();
			String sFilter = p.getResultString()+"\n";
			byte[] bFilter = sFilter.getBytes();
			rFilter.write(bFilter);
		}
		String strmc = "#"+Integer.toString(pGPSPointFilter.size())+","+
		double.toString(mDerror)+","+double.toString(cRate)+"%"+"#"+"\n";
		byte[] bmc = strmc.getBytes();
		rFilter.write(bmc);
		rFilter.close();
	}
	/**
* 函数功能:将转换后的原始经纬度数据点存到文件中
* @param outGPSFile
* @param pGPSPointFilter
* @throws Exception
*/
	public static void writeInitPointToFile(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.toString()+"\n";
			byte[] bFilter = sFilter.getBytes();
			rFilter.write(bFilter);
		}
		rFilter.close();
	}
	/**
* 函数功能:将数组中的经纬度点坐标数据写入测试文件中,用于可视化测试
* @param outGPSFile:文件对象
* @param pGPSPointFilter:点数组
* @throws Exception
*/
	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.getTestString()+"\n";
			byte[] bFilter = sFilter.getBytes();
			rFilter.write(bFilter);
		}
		rFilter.close();
	}
	/**
* 函数功能:将原始经纬度坐标数据转换成度
* @param str:原始经纬度坐标
* @return :返回对于的度数据
*/
	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;
	}
	/**
* 函数功能:保留一个double数的小数点后六位
* @param d:原始double数
* @return 返回转换后的double数
*/
	public static double getPointSix(double d){
		DecimalFormat df = new DecimalFormat("0.000000");
		return double.parsedouble(df.format(d));
	}
	/**
* 函数功能:使用三角形面积(使用海伦公式求得)相等方法计算点pX到点pA和pB所确定的直线的距离
* @param pA:起始点
* @param pB:结束点
* @param pX:第三个点
* @return distance:点pX到pA和pB所在直线的距离
*/
	public static double distToSegment(ENPoint pA,ENPoint pB,ENPoint pX){
		double a = Math.abs(geoDist(pA, pB));
		double b = Math.abs(geoDist(pA, pX));
		double c = Math.abs(geoDist(pB, pX));
		double p = (a+b+c)/2.0;
		double s = Math.sqrt(Math.abs(p*(p-a)*(p-b)*(p-c)));
		double d = s*2.0/a;
		return d;
	}
	/**
* 函数功能:用老师给的看不懂的方法求两个经纬度点之间的距离
* @param pA:起始点
* @param pB:结束点
* @return distance:距离
*/
	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;
	}
	/**
* 函数功能:角度转弧度
* @param d:角度
* @return 返回的是弧度
*/
	public static double Rad(double d)
	{
		return d * Math.PI / 180.0;
	}
	/**
* 函数功能:根据最大距离限制,采用DP方法递归的对原始轨迹进行采样,得到压缩后的轨迹
* @param enpInit:原始经纬度坐标点数组
* @param enpArrayFilter:保持过滤后的点坐标数组
* @param start:起始下标
* @param end:终点下标
* @param DMax:预先指定好的最大距离误差
*/
	public static void TrajCompressC(ENPoint[] enpInit,ArrayList<ENPoint> enpArrayFilter,
	int start,int end,double DMax){
		if(start < end){
			//递归进行的条件
			double maxDist = 0;
			//最大距离
			int cur_pt = 0;
			//当前下标
			for (int i=start+1;i<end;i++){
				double curDist = distToSegment(enpInit[start],enpInit[end],enpInit[i]);
				//当前点到对应线段的距离
				if(curDist > maxDist){
					maxDist = curDist;
					cur_pt = i;
				}
				//求出最大距离及最大距离对应点的下标
			}
			//若当前最大距离大于最大距离误差
			if(maxDist >= DMax){
				enpArrayFilter.add(enpInit[cur_pt]);
				//将当前点加入到过滤数组中
				//将原来的线段以当前点为中心拆成两段,分别进行递归处理
				TrajCompressC(enpInit,enpArrayFilter,start,cur_pt,DMax);
				TrajCompressC(enpInit,enpArrayFilter,cur_pt,end,DMax);
			}
		}
	}
	/**
* 函数功能:求平均距离误差
* @param pGPSArrayInit:原始数据点坐标
* @param pGPSArrayFilterSort:过滤后的数据点坐标
* @return :返回平均距离
*/
	public static double getMeanDistError(
	ArrayList<ENPoint> pGPSArrayInit,ArrayList<ENPoint> pGPSArrayFilterSort){
		double sumDist = 0.0;
		for (int i=1;i<pGPSArrayFilterSort.size();i++){
			int start = pGPSArrayFilterSort.get(i-1).id;
			int end = pGPSArrayFilterSort.get(i).id;
			for (int j=start+1;j<end;j++){
				sumDist += distToSegment(
				pGPSArrayInit.get(start),pGPSArrayInit.get(end),pGPSArrayInit.get(j));
			}
		}
		double meanDist = sumDist/(pGPSArrayInit.size());
		return meanDist;
	}
}

第四部分 程序结果

4.1 程序输出结果

  压缩后的结果:

  (1)总点数:140个点;(2)平均距离误差:7.943786;(3)压缩率:4.4444%

4.2 仿真结果

  经过轨迹压缩,我们将原始经纬度坐标点转换为压缩过滤后的经纬度坐标点,我们将这两种点坐标数据分别写入两个文件中,然后根据这两个文件使用R语言进行图形绘制,分别画出压缩前和压缩后的轨迹 ,进行对比,根据对比结果就可以看出我们轨迹压缩算法是否有效,最终对比结果如图4.1所示:

第五部分 总结

  本程序编写过程中,遇到了各种各样的问题,也学到了很多编程经验,下面就遇到的问题及解决方案做一个总结,最后对程序存在的不足提出改进建议。

5.1 遇到的问题及解决方案

  问题1:经纬度坐标顺序问题

  解决:距离公式中的参数是纬度在前经度在后,需要调整下经纬度坐标点的顺序。

  问题2:距离不能为负值

  解决:保证求出的距离不能为负值,加绝对值函数即可。

  问题3:DP算法实现细节

  解决:开始使用ArrayList数组解决下标问题,递归求解时出现巨大误差,后来改用普通数组下标进行递归,结果好多了。

5.2 存在的不足与展望

  (1)进行轨迹压缩时,DP算法是最简单的一种算法,并不是最优的,可选用一些效果好的算法再次进行轨迹压缩;

  (2)本次实验数据的记录为3150条,数据量不算大,如果有10亿条数据,该怎么办呢?我们可以从硬件、分布式、数据预处理、数据切分、性能好的数据仓库等方面考虑。

以上就是本文关于Java编程实现轨迹压缩之Douglas-Peucker算法详细代码的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • Java 蒙特卡洛算法求圆周率近似值实例详解

    起源 [1946: John von Neumann, Stan Ulam, and Nick Metropolis, all at the Los Alamos Scientific Laboratory, cook up the Metropolis algorithm, also known as the Monte Carlo method.]1946年,美国拉斯阿莫斯国家实验室的三位科学家John von Neumann,Stan Ulam 和 Nick Metropolis共同发明,

  • Java实现的最大匹配分词算法详解

    本文实例讲述了Java实现的最大匹配分词算法.分享给大家供大家参考,具体如下: 全文检索有两个重要的过程: 1分词 2倒排索引 我们先看分词算法 目前对中文分词有两个方向,其中一个是利用概率的思想对文章分词. 也就是如果两个字,一起出现的频率很高的话,我们可以假设这两个字是一个词.这里可以用一个公式衡量:M(A,B)=P(AB)/P(A)P(B),其中 A表示一个字,B表示一个字,P(AB)表示AB相邻出现的概率,P(A)表示A在这篇文章中的频度,P(B)表示B在这篇文章中的频度.用概率分词的好

  • Java实现的快速查找算法示例

    本文实例讲述了Java实现的快速查找算法.分享给大家供大家参考,具体如下: 快速查找算法,可以根据想要找的是第几个大的数,每次循环都能固定下来一个数在数组完整排完序之后的位置,每次循环都能定一个数的位置,如果当前固定的数的位置和用户要找的第几个数匹配,则就直接返回.例如我要找第二大的数,如果循环一次固定的数的下标是1,那就是当前需要找的数. 代码如下: // 快速查找算法 public static int quickSelect(int[] arr, int selectIndex) { in

  • Java使用分治算法实现排序数索引功能示例【二分搜索】

    本文实例讲述了Java使用分治算法实现排序数索引功能.分享给大家供大家参考,具体如下: /** * Find the first q and return the index * First method is brutal force * Second may * be Divid and Conquer * * @author open201 * */ public class Ono { /** * f(n) = s.length = n; * * @param s * @param q

  • Java实现合并两个有序序列算法示例

    本文实例讲述了Java实现合并两个有序序列算法.分享给大家供大家参考,具体如下: 问题描述 输入:序列A<a0,a1,a2,...aq,aq+1,aq+2,...,ar>,其中a0<a1<...<aq,aq+1<aq+2<...<ar 输出:序列B<b0,b1,...,br>,其中b0<b1<...<br 算法思想 创建一个长度为r的数组R,将A中的序列看作是两个有序序列 B=A<a0,a1,a2,...,aq> C

  • Java简单实现约瑟夫环算法示例

    本文实例讲述了Java简单实现约瑟夫环算法.分享给大家供大家参考,具体如下: 1.算法背景: 罗马人攻占了乔塔帕特,41人藏在一个山洞中躲过了这场浩劫.这41个人中,包括历史学家josephus和他的一个朋友.剩余的39个人为了表示不向罗马人屈服,决定集体自杀.大家决定了一个自杀方案,所有这41人围城一个圆圈,由第一个人开始顺时针报数,没报数为3的人就立刻自杀,然后由下一个人重新开始报数 仍然是每报数为3的人就立刻自杀,......,知道所有人都自杀死亡为止. 约瑟夫和他的朋友并不想自杀,于是约

  • Java编程实现轨迹压缩之Douglas-Peucker算法详细代码

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

  • Java编程文件遍历之指定遍历的层数详细代码

    遍历就是把每个元素都访问一次.比如一个二叉树,遍历二叉树意思就是把二叉树中的每个元素都访问一次 本例演示了"文件遍历时,指定遍历的层数"的实现方式. 1.例子代码 package com.myjava.test; import java.io.File; import java.util.ArrayList; import java.util.List; public class JavaTest { /** * @param args */ public static void ma

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

    轨迹压缩算法 场景描述 给定一个GPS数据记录文件,每条记录包含经度和维度两个坐标字段,根据距离阈值压缩记录,将过滤后的所有记录的经纬度坐标构成一条轨迹 算法描述 这种算法的用处还是相当广泛的. 轨迹压缩算法分为两大类,分别是无损压缩和有损压缩,无损压缩算法主要包括哈夫曼编码,有损压缩算法又分为批处理方式和在线数据压缩方式,其中批处理方式又包括DP(Douglas-Peucker)算法.TD-TR(Top-Down Time-Ratio)算法和Bellman算法,在线数据压缩方式又包括滑动窗口.

  • Java编程一维数组转换成二维数组实例代码

    简介:由于经常在使用矩阵进行计算时,会首先将一维数组转为二维数组.因此,在这里记录一下,也希望对他人有帮助. 实例代码: package deal; public class ArryTest { public static void main(String[] args) { //创建一个一维数组 0,1,2,3...,10 double [] c= new double[10]; for (int i = 0; i < c.length; i++) { c[i]=i; } double[][

  • Java编程实现beta分布的采样或抽样实例代码

    本文研究的主要是Java编程实现beta分布的采样或抽样,具体如下. 本文将使用math3提供的工具包,对beta分布进行采样.如下程序是对alpha=81,beta=219的beta分布函数,进行抽样,共采样10000次. package function; /** * @author:合肥工业大学 管理学院 钱洋 * @email:1563178220@qq.com * @ 这里主要采用的是math3中的gamma相关函数 */ import org.apache.commons.math3

  • Java实现把文件压缩成zip文件的示例代码

    实现代码 ackage org.fh.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * 说明:java压缩成zip * 作者:FH Admin * from:fhadmin.cn */ public class Fi

  • Java实现微信公众平台朋友圈分享功能详细代码

    其实分享的方法在微信官网有较为详细的文档说明,现就其中一些比较绕的步骤进行总结,有问题随时交流哈. 首先微信其实已经自带分享到朋友圈,朋友,qq空间等功能,对于开发微信专门提供了一个接口,可以根据需要修改一些配置.例如修改要分享内容的头像,链接,描述等. 开发步骤: 1.在公众平台配置js-sdk接口 "公众号设置"--"功能设置"--"JS接口安全域名" 2.在要分享的页面引入js http://res.wx.qq.com/open/js/jw

  • Java编程细节重构之为什么if-else不是好代码详析

    前言 面向过程设计和面向对象设计的主要区别是:是否在业务逻辑层使用冗长的if else判断.如果你还在大量使用if else,当然,界面表现层除外,即使你使用Java/C#这样完全面向对象的语言,也只能说明你的思维停留在传统的面向过程语言上.本文将通过示例代码给大家介绍关于Java编程细节重构之if-else的相关内容,下面来一起看看详细的介绍吧 平时开发中if-else用的多吗? 其实这是个再正常不过的coding习惯,当我们代码量小的时候用来做条件判断是再简单不过的了. 但对于优秀程序员来说

  • 使用Java生成jpg与压缩图片为jpg文件的代码示例

    Java生成jpg格式图片: package other.pic; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.RandomAccessFile; import java.awt.imag

  • 详解Java编程规约(命名风格、常量定义、代码格式)

    命名风格 1.[强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例: _name / __name / $name / name_ / name$ / name__ 2.[强制]代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式. 说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义.注意,纯拼音命名方式更要避免采用. 正例:renminbi / alibaba / taobao / youku / hangzhou 等国际通用的名称,可视

随机推荐