一、效果
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博客
参考链接: