Android Studio GPX文件解析显示地图轨迹和海拔示意(模拟沿轨迹前进)
目录
1.GPX文件解析
2.地图轨迹绘制
3.海拔示意图绘制
4.行进模拟
开始(暂停):
前进实现:
计时模块:
其他参数
1.GPX文件解析
详见此博客:
Android Studio GPX文件的解析(总和)_.'~'.的博客-CSDN博客_gpx文件
2.地图轨迹绘制
轨迹绘制:
利用GPX解析得到的数据在百度地图SDK上利用折现的绘制方法,绘制出相应的地图路线图。
public void drawroad(){List<LatLng> points = new ArrayList<LatLng>();//构建折线点坐标for(int i=0;i<longitudes.size();i++){//System.out.println(longitudes.get(i) );// longitudes.size();LatLng p = new LatLng(latitudes.get(i), longitudes.get(i));points.add(p);}//设置折线的属性OverlayOptions mOverlayOptions = new PolylineOptions().width(10).color(0xAAFF0000).points(points);//在地图上绘制折线//mPloyline 折线对象Overlay mPolyline = mBaiduMap.addOverlay(mOverlayOptions);}
自身点标记:
在行进过程中始终标记自身所处位置(海拔示意图也会始终标记自身位置)。
public void drawpoint(int i){//定义Maker坐标点LatLng point = new LatLng(latitudes.get(i), longitudes.get(i));
//构建Marker图标BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.me3);
//构建MarkerOption,用于在地图上添加MarkerOverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
//在地图上添加Marker,并显示//在地图上批量添加mPolyline2 =mBaiduMap.addOverlay(option);}
3.海拔示意图绘制
将GPX文件解析得到的海拔数据,按数据的多少不同按比例进行绘制(实质为直线的绘制)
@RequiresApi(api = Build.VERSION_CODES.N)public void drawele(int me){imageView=(ImageView) findViewById(R.id.ele);//确定最高,最低海拔Double max = Collections.max(elevations);Double min = Collections.min(elevations);int max1= Math.toIntExact(Math.round(max));int min1= Math.toIntExact(Math.round(min));runOnUiThread(new Runnable() {@Overridepublic void run() {top.setText(String.valueOf(max1)+"M");low.setText(String.valueOf(min1)+"M");}});if(max1-min1>h){double y= (max-min)/h;Log.e("TAG", "drawele: "+y );yinterval= Math.toIntExact((long) Math.ceil(y)); //得到最大值和高的关系,依此比例绘制高度}else{double y= h/(max-min);Log.e("TAG", "drawele: "+y );yinterval= Math.toIntExact((long) Math.ceil(y)); //得到最大值和高的关系,依此比例绘制高度}Log.e("max min", "drawele: "+max+"__"+min+"___"+yinterval+" ++"+h );//开始绘制海拔示意图Bitmap newb = Bitmap.createBitmap(w , h, Bitmap.Config.ARGB_8888);Canvas canvasTemp = new Canvas(newb);//Canvas canvasTemp2=new Canvas(newb);canvasTemp.drawColor(Color.TRANSPARENT);Paint p = new Paint();//防锯齿p.setAntiAlias(true);p.setStyle(Paint.Style.STROKE);//STROKE,FILLp.setStrokeWidth(5);p.setColor(Color.LTGRAY);p.setTextAlign(Paint.Align.CENTER);p.setColor(Color.BLACK);p.setStyle(Paint.Style.FILL);//STROKE,FILL//判断是否为初始化,将位置置为0if(me==0){p.setColor(Color.RED);canvasTemp.drawCircle(0,(float) (h-(elevations.get(0)-min1)/(max1-min1)*h),10,p);p.setColor(Color.BLACK);}/*if(flagwidth==1){}else{drawele(me);}*///海拔示意图,公式 h-(H-min1)/(max1-min1)*h,H为当前绘制点海拔,h为屏幕高度if(elevations.size()>w) { //点多宽度少Log.e(TAG, "drawele:点多宽度少!!!!!!!!!!!!!!!!!!!! " );flagwidth=0;// /*double xinterval1=1xinterval=(float) elevations.size()/(float) w; //大于1,得到手机屏幕显示宽度和需要绘制的点个数关系,以此比例取点for(int i=1;i<=w;i++){ //i为屏幕宽度点计数, *xinterval得到按比例取得的高度点, XX数组存储每个输出的海拔点的角标(位置,第几个)// if((int)(i)*xinterval>elevations.size()/2) p.setColor(Color.RED);// canvasTemp.drawLine(0, (float)( (h-520)/yinterval),1,(float)( (h-100)/yinterval),p);canvasTemp.drawLine(i-1, (float) (h-((elevations.get((int)((i-1)*xinterval>elevations.size()-1?elevations.size()-1:(i-1)*xinterval))-min1)/(max1-min1))*h),i,(float) (h-((elevations.get((int)((i)*xinterval>elevations.size()-1?elevations.size()-1:(i)*xinterval))-min1)/(max1-min1))*h),p);//canvasTemp.drawLine(i-1, (float) (h-elevations.get((int)((i-1)*xinterval>elevations.size()-1?elevations.size()-1:(i-1)*xinterval))/yinterval),i,(float) (h-elevations.get((int)(i*xinterval>elevations.size()-1?elevations.size()-1:i*xinterval))/yinterval),p);XX[i-1]=(int)(i*xinterval>elevations.size()-1?elevations.size()-1:i*xinterval);//Log.e("000000000000000000", "drawele: "+(i-xinterval)+"__"+(float) (h-elevations.get(i-1)/yinterval) );if(XX[i-1]==me){ //计数点me 标记当前输出点的位置,等于绘制的海拔的某一点,在这个位置标记红点p.setColor(Color.RED);canvasTemp.drawCircle(i,(float) (h-((elevations.get((int)((i-1)*xinterval>elevations.size()-1?elevations.size()-1:(i-1)*xinterval))-min1)/(max1-min1))*h),10,p);//canvasTemp.drawCircle(i,(float) (h-elevations.get(XX[i-1])/yinterval),10,p);p.setColor(Color.BLACK);}}}else if(elevations.size()<w){Log.e(TAG, "drawele:未修改部分!!!!!!!!!!!!!!!!!!!! " );flagwidth=1;xinterval=(float) w/(float) elevations.size();//for(int i=1;i<elevations.size()-1;i++){canvasTemp.drawLine((i-1)*xinterval>w?w:(i-1)*xinterval, (float) (h-(elevations.get(i-1)-min1)/(max1-min1)*h),i*xinterval>w?w:i*xinterval,(float) (h-(elevations.get(i)-min1)/(max1-min1)*h),p);// canvasTemp.drawLine((i-1)*xinterval>w?w:(i-1)*xinterval, (float) (h-elevations.get(i-1)/yinterval),i*xinterval>w?w:i*xinterval,(float) (h-elevations.get(i)/yinterval),p);//Log.e("000000000000000000", "drawele: "+(i-xinterval)+"__"+(float) (h-elevations.get(i-1)/yinterval) );if(i-1==me){p.setColor(Color.RED);canvasTemp.drawCircle(i*xinterval>w?w:i*xinterval,(float) (h-(elevations.get(i)-min1)/(max1-min1)*h),10,p);//canvasTemp.drawCircle(i*xinterval>w?w:i*xinterval,(float) (h-elevations.get(i)/yinterval),10,p);p.setColor(Color.BLACK);}}}runOnUiThread(new Runnable() {@Overridepublic void run() {imageView.setImageBitmap(newb);}});}
4.行进模拟
开始(暂停):
此部分实现按钮的功能和信息展示的转换,在停止时按钮显示”开始“,点击按钮后,相应的计时模块开始进行计时,按钮信息显示为”暂停“,点击按钮,计时模块停止计时,按钮又显示为”开始“,再次点击,计时继续,按钮显示为”暂停“,如此循环。
public void startgo(View view) {if(!stop){runOnUiThread(new Runnable() {@Overridepublic void run() {startgo.setText("暂停");}});TIME2 = System.currentTimeMillis();if(Time3!=0) {Time4+=TIME2-Time3;}stop=!stop;}else{runOnUiThread(new Runnable() {@Overridepublic void run() {startgo.setText("开始");}});Time3=System.currentTimeMillis();stop=!stop;}if(!Timestart) {if(!ok){ok=!ok;}Timestart = true;TIME();}}
前进实现:
自身标记点的刷新,各项数据的刷新(重新计算)
@RequiresApi(api = Build.VERSION_CODES.N)public void StepIn() {if(true) {if (me >= latitudes.size()||me>=elevations.size()-1) {//Toast.makeText(this, "已到达终点", Toast.LENGTH_SHORT).show();Log.e(TAG, "StepIn: "+"已到达终点" );} else {cargo++;Miles += 2;runOnUiThread(new Runnable() {@Overridepublic void run() {M.setText(String.valueOf(Miles) + "m");}});if (Miles >= (distance.getDistance(latitudes.get(me), longitudes.get(me), latitudes.get(0), longitudes.get(0)))) {mPolyline2.remove();drawpoint(me);/*//移动距离计算Miles = Miles + distance.getDistance(latitudes.get(me - 1), longitudes.get(me - 1), latitudes.get(me), longitudes.get(me));M.setText(String.valueOf(Miles) + "m");*/me++;//根据flagwidth的值,选择高度示意点的刷新方式(取样,还是拉伸)//取样刷新if (flagwidth == 0 && me > XX[xx] && me <= latitudes.size()) {Log.e("me%xinterval==0", "stepin: " + me + "++++" + xinterval);drawele(XX[xx]);if (xx < w - 1) xx++;} else if (flagwidth == 1) { //拉伸刷新,所有点都输出drawele(me);}//总和所有爬升的高度if (elevations.get(me - 1) - elevations.get(me - 2) > 0) {Hight += elevations.get(me - 1) - elevations.get(me - 2);String str = String.format("%.2f", Hight);double Hight2 = Double.parseDouble(str);runOnUiThread(new Runnable() {@Overridepublic void run() {H.setText(String.valueOf(Hight2) + "m");}});}//计算坡度,坡度=(高程差/水平距离)x100%。计算下一步设计的坡度,及即将到来的路径坡度//Miles = Miles + distance.getDistance(latitudes.get(me - 1), longitudes.get(me - 1), latitudes.get(me), longitudes.get(me));gradient = ((elevations.get(me) - elevations.get(me - 1))) / distance.getDistance(latitudes.get(me - 1), longitudes.get(me - 1), latitudes.get(me), longitudes.get(me));String str3 = String.format("%.2f", gradient);//double gr = Double.parseDouble(str3);Log.e("--------------", "stepin: " + str3);runOnUiThread(new Runnable() {@Overridepublic void run() {G.setText(str3);}});}}}}
计时模块:
开始与暂停控制的就是此模块的计时功能。
private void TIME(){if(Timestart) {TIME1 = System.currentTimeMillis();new Thread(new Runnable() {SimpleDateFormat sd = new SimpleDateFormat("HH:mm:ss");@Overridepublic void run() {while (true&&Timestart) {if (stop) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}TIME2 = System.currentTimeMillis();TIME = TIME2 - TIME1-Time4;// Log.e("______", "run: "+hours+":"+minute+":"+second );sd.setTimeZone(TimeZone.getTimeZone("GMT+0"));//**TimeZone时区,加上这句话就解决啦**runOnUiThread(new Runnable() {@Overridepublic void run() {Time.setText(sd.format(TIME));}});}/*else{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}TIME2 = System.currentTimeMillis();Time4+=TIME2-Time3;}*/}runOnUiThread(new Runnable() {@Overridepublic void run() {Time.setText("骑行时间");}});}}).start();}}
其他参数
最大速度,最小速度,大致卡路里计算 :
private void bikespeed(){new Thread(new Runnable() {@Overridepublic void run() {String str1;String str2;while(true) {now = System.currentTimeMillis(); //1000=1sif(now-last>=1000){Vnow=(Miles-Mile)*1000/(now-last);str1 = String.format("%.2f",Vnow);double two = Double.parseDouble(str1);//计算卡路里if(Vnow>0){Kcal+=wight*((now-last)/120000)/(Vnow/2.22);Log.e(TAG,"run: "+Kcal+"ppp"+wight*(Miles/1000)*1.036 );}//Kcal=wight*(Miles/1000)*1.036;str2 = String.format("%.2f",Kcal);double Kcal2=Double.parseDouble(str2);//更新实时速度runOnUiThread(new Runnable() {@Overridepublic void run() {V.setText(String.valueOf(two)+"m/s");K.setText(String.valueOf(Kcal2));}});Log.e(TAG, "run:" +MINV );//更新最大速度if(two>MAXV){MAXV=two;//第一次计算速度,最大速度等于最小速度if(first==0){// first=1;//first=1之后此段代码不再执行,最小速度将始终记录最小值,去掉此段代码可实现短时间内最小速度(可能)MINV=two;runOnUiThread(new Runnable() {@Overridepublic void run() {minV.setText(String.valueOf(MINV)+"m/s");}});}runOnUiThread(new Runnable() {@Overridepublic void run() {maxV.setText(String.valueOf(MAXV)+"m/s");}});}//更新最小速度,当最小速度显示0的时候表示停止,再移动的时候最小速度不会显示0,为最小运动速度>0if(two==0){runOnUiThread(new Runnable() {@Overridepublic void run() {minV.setText(String.valueOf(two)+"m/s");}});}else if(two<MINV&&two!=0){MINV=two;runOnUiThread(new Runnable() {@Overridepublic void run() {minV.setText(String.valueOf(MINV)+"m/s");}});}else {runOnUiThread(new Runnable() {@Overridepublic void run() {minV.setText(String.valueOf(MINV)+"m/s");}});}last= System.currentTimeMillis();Mile=Miles;}}}}).start();}
Android Studio GPX文件解析显示地图轨迹和海拔示意(模拟沿轨迹前进)相关推荐
- android xml 未能解析文件,Android Studio提示“无法解析符号”,但项目已编译
我在build.gradle中使用以下内容在AndroidStudio中导入twitter4j: dependencies { compile 'com.android.support:support ...
- Android Studio - HPROF文件查看和分析工具
Android Studio - HPROF文件查看和分析工具 Android Studio 翻译的官方文章 原文链接 当你在Android Studio中使用Android Monitor里的Mem ...
- android自定义控件不显示,解决Android Studio Design界面不显示layout控件的问题
Android Studio更新到3.1.3后,发现拖到Design中的控件在预览界面中不显示: 解决办法: 在Styles.xml中的parent="..."中的Theme前添加 ...
- android studio val,导入--Android Studio突然无法解析符号
导入--Android Studio突然无法解析符号 Android Studio 0.4.2工作正常,今天我打开它,几乎所有东西都是红色,自动完成已停止工作. 我看看导入和AS似乎告诉我它突然找不到 ...
- 安卓 linux init.rc,[原创]Android init.rc文件解析过程详解(二)
Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...
- Android studio 刷新文件状态
问题 有时候Android Studio Git 文件的状态不对,比如我修改了某个文件,他并没有给我显示出来. 那怎么刷一下文件状态呢,如下图: 解决方法:
- Android init.rc文件解析过程详解(三)
Android init.rc文件解析过程详解(三) 三.相关结构体 1.listnode listnode结构体用于建立双向链表,这种结构广泛用于kernel代码中, android源代码中定义了l ...
- Android init.rc文件解析过程详解(二)
Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...
- Android init.rc文件解析过程详解(一)
Android init.rc文件解析过程详解(一) 一.init.rc文件结构介绍 init.rc文件基本组成单位是section, section分为三种类型,分别由三个关键字(所谓关键字 ...
- android studio logcat 无筛选 显示全部日志 无应用包名区分
android studio logcat 无筛选 显示全部日志 无应用包名区分 不显示所有应用 出现这个情况后很多同学无法解决,重启adb,重启studio,重启电脑,都是没用的... 其实是有个开 ...
最新文章
- 【RocketMQ工作原理】消息堆积与消费延迟
- 撒列实现关键字过虑二(附源码)
- python爬虫实例-Python爬虫案例集合
- C语言 · 未名湖边的烦恼
- springboot 2.4.4java.sql.SQLException Access denied for user ‘root‘@‘localhost‘ (using password YES)
- Word2Vec算法详解(CBOW和skip-gram算法详解)
- Hadoop1.2.0开发笔记(九)
- 1进程 ppid_Python每日3题什么是僵尸进程和孤儿进程?
- 20190930每日一句
- RC振荡电路——文氏桥振荡电路(OP07仿真)
- 一个画布有多个子图_如何把多张图拼成一张长图
- ThinkpadX230解决叹号_Win7系统设备管理器下的“未知设备”
- 数据源EPMSSqlDataSource的使用
- 男人说这几句话代表他不想娶你
- KindEditor 360浏览器系列无法显示
- Redis(十六),mysql索引面试题索引失效
- Random Forests C++实现:细节,使用与实验
- 【计算方法】插值法多项式的求法--利用Lagrange插值和Newton插值
- 心机 诚信 君子 小人 好人 坏人
- matlab plot作图线型及颜色及图标大全
热门文章
- cydia红字解决方法(cydia安装软件时出现红字怎么解决)
- 《终身成长》卡罗尔 德韦克_epub+mobi+azw3
- ThinkPHP5零食商城系统(前后台)
- 【转】win7旗舰版英文版下载(64位|32位)|Windows7英文版ISO镜像
- 国产化Demo(dm7+Tongweb7+java)
- steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。
- 你需要启用steam社区界面功能以进行购买_steam官网手机版免费下载-steam官网手机客户端下载...
- SQL Server迁移数据库文件(ldfmdf文件)到其他盘
- freebsd协议栈学习
- 使用exceljs导出excel表格