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,用于在地图上添加Marker
        OverlayOptions 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() {
            @Override
            public 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,FILL
        p.setStrokeWidth(5);
        p.setColor(Color.LTGRAY);
        p.setTextAlign(Paint.Align.CENTER);
        p.setColor(Color.BLACK);
        p.setStyle(Paint.Style.FILL);//STROKE,FILL
        //判断是否为初始化,将位置置为0
        if(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=1
            xinterval=(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() {
            @Override
            public void run() {
                imageView.setImageBitmap(newb);
            }
        });

    }

4.行进模拟

开始(暂停):

此部分实现按钮的功能和信息展示的转换,在停止时按钮显示”开始“,点击按钮后,相应的计时模块开始进行计时,按钮信息显示为”暂停“,点击按钮,计时模块停止计时,按钮又显示为”开始“,再次点击,计时继续,按钮显示为”暂停“,如此循环。

public void startgo(View view) {
        if(!stop){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    startgo.setText("暂停");
                }
            });
            TIME2 = System.currentTimeMillis();
            if(Time3!=0) {
                Time4+=TIME2-Time3;
            }
            stop=!stop;


        }else{
            runOnUiThread(new Runnable() {
                @Override
                public 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() {
                    @Override
                    public 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() {
                            @Override
                            public 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() {
                        @Override
                        public void run() {
                            G.setText(str3);
                        }
                    });
                }
            }
        }
    }

 计时模块:

开始与暂停控制的就是此模块的计时功能。

private void TIME(){
        if(Timestart) {
            TIME1 = System.currentTimeMillis();
            new Thread(new Runnable() {
                SimpleDateFormat sd = new SimpleDateFormat("HH:mm:ss");
                @Override
                public 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() {
                                @Override
                                public 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() {
                        @Override
                        public void run() {
                            Time.setText("骑行时间");
                        }
                    });
                }
            }).start();
        }
    }

其他参数

最大速度,最小速度,大致卡路里计算 :

private void bikespeed(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                String  str1;
                String  str2;
                while(true) {
                    now = System.currentTimeMillis();   //1000=1s
                    if(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() {
                            @Override
                            public 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() {
                                    @Override
                                    public void run() {
                                        minV.setText(String.valueOf(MINV)+"m/s");
                                    }
                                });
                            }
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    maxV.setText(String.valueOf(MAXV)+"m/s");
                                }
                            });
                        }
                        //更新最小速度,当最小速度显示0的时候表示停止,再移动的时候最小速度不会显示0,为最小运动速度>0
                        if(two==0){
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    minV.setText(String.valueOf(two)+"m/s");
                                }
                            });
                        }else if(two<MINV&&two!=0){
                            MINV=two;
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    minV.setText(String.valueOf(MINV)+"m/s");
                                }
                            });
                        }else {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    minV.setText(String.valueOf(MINV)+"m/s");
                                }
                            });
                        }
                        last= System.currentTimeMillis();
                        Mile=Miles;
                    }
                }
            }
        }).start();
    }

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值