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

本文详细介绍了如何在Android中自定义视图GnssSkyView,利用卫星的方位角和高度角信息绘制卫星天顶图。首先获取卫星信息,通过LocationManager的GnssStatus监听器;接着自定义视图,绘制底图,包括3个圆代表高度角和4条直线指示方位;然后绘制刻度和卫星,动态更新卫星位置;最后控制视图大小。整个过程涉及数学计算、自定义绘图和Android视图系统操作。

效果图:
在这里插入图片描述

首先介绍一下相关的概念:


方位角:是从某点的指北(地理北极)方向线起,依顺时针方向到目标方向线之间的水平夹角。
在这里插入图片描述
高度角:从一点至观测目标的方向线与水平面间的夹角。
在这里插入图片描述
卫星天顶图:即是根据每一颗卫星的方位角和高度角将其画在以观测位置为中心的天顶图上。

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

下面逐一介绍绘制的步骤

1 获取卫星信息


要想画出卫星图,必须先有卫星的方位角和高度角等基本信息。在Android中,可以通过向LocationManager类注册GnssStatus监听器获取卫星PRN、方位角、高度角、星座类型、卫星载噪比等与卫星本身有关的信息。


关于如何注册GNSS监听器,Android GNSS伪距计算 中有注册测量监听器的详细步骤,卫星状态监听器的注册方式完全类似。


不同的是在回调方法中的行为,在这里,我们需要使用数组将卫星信息保存起来,如下:

private float[] mElevations, mAzimuths, mSnrs;

private int[] mPrns, mConstellationTypes;

public void setGnssStatus(GnssStatus status) {
   
   
    if (mPrns == null) {
   
   
        final int MAX_LENGTH = 255;
        mPrns = new int[MAX_LENGTH];
        mElevations = new float[MAX_LENGTH];
        mAzimuths = new float[MAX_LENGTH];
        mConstellationTypes = new int[MAX_LENGTH];
        mSnrs = new float[MAX_LENGTH];
    }
    int length = status.getSatelliteCount();
    mSvCount = 0;
    while (mSvCount < length) {
   
   
        mPrns[mSvCount] = status.getSvid(mSvCount);
        mElevations[mSvCount] = status.getElevationDegrees(mSvCount);
        mAzimuths[mSvCount] = status.getAzimuthDegrees(mSvCount);
        mConstellationTypes[mSvCount] = status.getConstellationType(mSvCount);
        mSnrs[mSvCount] = status.getCn0DbHz(mSvCount);

        mSvCount++;
    }

    invalidate();
}

通过GnssStatus的参数对象status的 getSatelliteCount() 方法获取卫星数量,然后使用 getSvid()、getElevationDegrees()、getAzimuthDegrees()、getConstellationType()、getCn0DbHz() 方法分别获取卫星的 PRN、高度角、方位角、星座、载噪比


然后调用View对象的invalidate()方法重绘星空图,即更新。


2 自定义视图


由于Android中并没有一种系统控件可以让我们方便的展示卫星图,因此我们需要自定义一个天空图视图

public class GnssSkyView extends View { }


我们在碎片Fragment中加载这个视图,通过在碎片上注册监听器获得不断更新的信息,并在碎片的回调方法中调用 GnssSkyView 对象的 setGnssStatus 方法将信息传给它,从而使其获得数据来源,进而进行多样化地展示

3 绘制底图


底图包括三个圆、四条直线和外圈圆上的方位角刻度。

onDraw() 方法会在视图绘制的过程中系统自动调用,我们需要在这个方法中自定义绘制内容。

protected void onDraw(Canvas canvas) {
   
   
    super.onDraw(canvas);

    int minScreenDimen = Math.min(mWidth, mHeight);
    float radius = minScreenDimen / 2.0f;

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


因为我们要画的是一个圆,所以一定有一个外切正方形,上面的代码中,minScreenDimen 为视图长和宽的最小值,这个值就作为正方形的边长,也是外圈圆的直径


然后我们分别调用三个函数drawCircle()、drawLine()、drawDegree(),这三个函数是我们自己定义的,分别画圆、直线、刻度。


3.1 圆的画法


onDraw() 方法会给我们一个参数canvas,这个参数是视图画布Canvas的对象,通过调用canvas的 drawCircle() 方法,就能实现圆的绘制。


该方法的函数原型如下:

public void drawCircle(float cx, float cy, float radius, Paint paint) {
   
   
    super.drawCircle(cx, cy, radius, paint)
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值