2024-08-15升级记录:Android开发-实现绘制卫星天顶图/卫星星空图/方位图/卫星星座

一、效果

Android中实现卫星天顶图/卫星星空图/方位图/卫星星座,

最后效果:

卫星天顶图:即是根据每一颗卫星的方位角和高度角将其画在以观测位置为中心的天顶图上。

天顶图其底图为由外向内的三个圆和四条直线。三个圆由外向内依次代表高度角0°、30°、60°,中心点代表90°;四条直线分别表示正北-正南、东北-西南、正东-正西、东南-西北的方位角方向。

二、卫星信息获取

通过GnssStatus.Callback接口的,GnssStatus的参数对象来获取,具体参见我的另一篇:

2024-08-06升级记录:Android开发接口-获取定位卫星相关信息-CSDN博客

三、自定义显示控件

1、绘制底图:

        圆、线、刻度、文字:

    //高度角三圆
    private void drawCircle(Canvas c, float radius) {
        c.drawCircle(radius, radius + Y_TRANSLATION, elevationToRadius(radius, 60.0f), mPaintGnss);
        c.drawCircle(radius, radius + Y_TRANSLATION, elevationToRadius(radius, 30.0f), mPaintGnss);
        c.drawCircle(radius, radius + Y_TRANSLATION, elevationToRadius(radius, 0.0f), mPaintGnss);
    }

    /***
     * 计算不同高度角的半径
     * @param s 最外圆的半径
     * @param elev 点的高度角
     * @return
     */
    private float elevationToRadius(float s, float elev) {
        return s * (1.0f - (elev / 90.0f));
    }

    //米叉线
    private void drawLine(Canvas c, int s, float radius) {
        c.drawLine(radius, Y_TRANSLATION, radius, s + Y_TRANSLATION, mPaintGnss);
        c.drawLine(0, radius + Y_TRANSLATION, s, radius + Y_TRANSLATION, mPaintGnss);

        final float cos45 = (float) Math.cos(Math.PI / 4);
        float d1 = radius * (1 - cos45);
        float d2 = radius * (1 + cos45);
        c.drawLine(d1, d1 + Y_TRANSLATION, d2, d2 + Y_TRANSLATION, mPaintGnss);
        c.drawLine(d2, d1 + Y_TRANSLATION, d1, d2 + Y_TRANSLATION, mPaintGnss);
    }

    //刻度和文字
    private void drawDegree(Canvas c, float radius) {
        int iText_Offset = -10;
        int iText_Offset_X = -15;
        for (int i = 0; i < 360; i += 15) {
            if (i == 45 || i == 135 || i == 225 || i == 315) {
                c.drawText(String.valueOf(i), radius+iText_Offset_X, iText_Offset + Y_TRANSLATION, mPaintText);
            } else if (i == 0) {
                c.drawText("N", radius+iText_Offset_X, iText_Offset + Y_TRANSLATION, mPaintText);
            } else if (i == 90) {
//                c.drawText("E", radius+iText_Offset_X, iText_Offset + Y_TRANSLATION, mPaintText);
            } else if (i == 180) {
                c.drawText("S", radius+iText_Offset_X, iText_Offset + Y_TRANSLATION, mPaintText);
            } else if (i == 270) {
//                c.drawText("W", radius+iText_Offset_X, iText_Offset + Y_TRANSLATION, mPaintText);
            } else {
                c.drawLine(radius, Y_TRANSLATION, radius, 20 + Y_TRANSLATION, mPaintGnss);
            }

            c.rotate(15, radius, radius + Y_TRANSLATION);
        }
    }

2、根据高度角和方位角绘制卫星图标和标识号

//卫星图标
    private Bitmap getSatelliteBitmap(int constellationType) {
        Bitmap baseMap, newMap;
        int width, height;
        switch (constellationType) {
            case GnssStatus.CONSTELLATION_BEIDOU:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_beidou);
                break;
            case GnssStatus.CONSTELLATION_GPS:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_gps);
                break;
            case GnssStatus.CONSTELLATION_GALILEO:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_galileo);
                break;
            case GnssStatus.CONSTELLATION_GLONASS:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_glonass);
                break;
            case GnssStatus.CONSTELLATION_QZSS:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_qzss);
                break;
            case GnssStatus.CONSTELLATION_SBAS:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_sbas);
                break;
            case GnssStatus.CONSTELLATION_UNKNOWN:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_ufo);
                break;
            case 7:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_india);
                break;
            default:
                baseMap = BitmapFactory.decodeResource(getResources(), R.drawable.flag_other);
        }
        width = baseMap.getWidth();
        height = baseMap.getHeight();

        newMap = scaling(baseMap, (SAT_RADIUS * 2.0f) / width, (SAT_RADIUS * 2.0f) / height);
        return newMap;
    }

    //缩放卫星图标
    private static Bitmap scaling(Bitmap bitmap, float widthScale, float heightScale) {
        Matrix matrix = new Matrix();
        matrix.postScale(widthScale, heightScale); //长和宽放大缩小的比例
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }

    /***
     * 绘制卫星图标
     * @param c 画布
     * @param s 最外圆半径
     * @param elev 卫星高度角
     * @param azim 卫星方位角
     * @param snr
     * @param prn
     * @param constellationType 星座枚举类型
     */
    private void drawSatellite(Canvas c, float s, float elev, float azim, float snr, int prn, int constellationType) {
        double radius, angle;
        float x, y;

        Bitmap satMap;
        satMap = getSatelliteBitmap(constellationType);

        String satText;
        satText = getSatelliteText(prn, constellationType);

        radius = elevationToRadius(s / 2.0f, elev);
        angle = (float) Math.toRadians(azim);

        x = (float) ((s / 2.0f) + (radius * Math.sin(angle)));
        y = (float) ((s / 2.0f) - (radius * Math.cos(angle)));

        c.drawBitmap(satMap, x - SAT_RADIUS, y - SAT_RADIUS + Y_TRANSLATION, null);
        c.drawText(satText, x - SAT_RADIUS, y + SAT_RADIUS * 1.5f + Y_TRANSLATION, mPaintText);
    }

    private String getSatelliteText(int prn, int constellationType) {
        StringBuilder builder = new StringBuilder();
        switch (constellationType) {
            case GnssStatus.CONSTELLATION_BEIDOU:
                builder.append("C");
                break;
            case GnssStatus.CONSTELLATION_GPS:
                builder.append("G");
                break;
            case GnssStatus.CONSTELLATION_GALILEO:
                builder.append("E");
                break;
            case GnssStatus.CONSTELLATION_GLONASS:
                builder.append("R");
                break;
            case GnssStatus.CONSTELLATION_QZSS:
                builder.append("Q");
                break;
            case GnssStatus.CONSTELLATION_SBAS:
                builder.append("S");
                break;
            case 7:
                builder.append("I");
                break;
            case GnssStatus.CONSTELLATION_UNKNOWN:
                builder.append("u");
                break;
            default:
                builder.append("x");
        }
        builder.append(prn);
        return builder.toString();
    }

3、根据实时信号更新显示内容

 //实时更新卫星数据
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void updateGnssStatus(GnssStatus status) {

        int length = status.getSatelliteCount();
        arrPrns = new int[length];
        arrElevations = new float[length];
        arrAzimuths = new float[length];
        arrConstellationTypes = new int[length];
        arrSnrs = new float[length];
        int mSvCount = 0;
        while (mSvCount < length) {
            arrPrns[mSvCount] = status.getSvid(mSvCount);
            arrElevations[mSvCount] = status.getElevationDegrees(mSvCount);
            arrAzimuths[mSvCount] = status.getAzimuthDegrees(mSvCount);
            arrConstellationTypes[mSvCount] = status.getConstellationType(mSvCount);
            arrSnrs[mSvCount] = status.getCn0DbHz(mSvCount);

            mSvCount++;
        }

        invalidate();
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int minScreenDimen = Math.min(getWidth(), getHeight());
        float radius = minScreenDimen / 2.0f;

        drawCircle(canvas, radius);
        drawLine(canvas, minScreenDimen, radius);
        drawDegree(canvas, radius);


        if(arrPrns !=null){
            if(arrPrns.length>0){
                for(int i = 0; i< arrPrns.length; i++){
                    if(arrConstellationTypes[i]>0) {
                        drawSatellite(canvas, minScreenDimen, arrElevations[i], arrAzimuths[i], arrSnrs[i], arrPrns[i], arrConstellationTypes[i]);

                    }
                }
            }
        }

    }

四、获取卫星星座状态

参见:2024-08-09升级记录:各导航卫星系统星座状态和卫星发射记录-CSDN博客

参考链接:

Android GNSS 可视卫星星空图/卫星天顶图 原理及画法介绍-CSDN博客

安卓应用开发学习:获取导航卫星信息_android 获取卫星位置-CSDN博客

  • 17
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值