FT8CN/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/maidenhead/MaidenheadGrid.java

406 wiersze
13 KiB
Java
Czysty Zwykły widok Historia

2023-08-15 04:49:10 +00:00
package com.bg7yoz.ft8cn.maidenhead;
/**
*
* @author BGY70Z
* @date 2023-03-20
*/
import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import com.bg7yoz.ft8cn.GeneralVariables;
import com.bg7yoz.ft8cn.R;
import com.google.android.gms.maps.model.LatLng;
import java.util.List;
public class MaidenheadGrid {
private static final String TAG = "MaidenheadGrid";
private static final double EARTH_RADIUS = 6371393; // 平均半径,单位m不是赤道半径。赤道为6378左右
/**
* 46nullll,
*
* @param grid
* @return LatLng null
*/
public static LatLng gridToLatLng(String grid) {
if (grid==null) return null;
if (grid.length()==0) return null;
//判断是不是符合梅登海德网格的规则
if (grid.length() != 2&&grid.length() != 4 && grid.length() != 6) {
return null;
}
if (grid.equalsIgnoreCase("RR73")) return null;
if (grid.equalsIgnoreCase("RR")) return null;
double x=0;
double y=0;
double z=0;
//纬度
double lat=0;
if (grid.length()==2){
x=grid.toUpperCase().getBytes()[1]-'A'+0.5f;
}else {
x=grid.toUpperCase().getBytes()[1]-'A';
}
x*=10;
if (grid.length()==4){
y=grid.getBytes()[3]-'0'+0.5f;
}else if (grid.length()==6){
y=grid.getBytes()[3]-'0';
}
if (grid.length()==6){
z=grid.toUpperCase().getBytes()[5]-'A'+0.5f;
z=z*(1/18f);
}
lat=x+y+z-90;
//经度
x=0;
y=0;
z=0;
double lng=0;
if (grid.length()==2){
x=grid.toUpperCase().getBytes()[0]-'A'+0.5;
}else {
x=grid.toUpperCase().getBytes()[0]-'A';
}
x*=20;
if (grid.length()==4){
y=grid.getBytes()[2]-'0'+0.5;
}else if (grid.length()==6){
y=grid.getBytes()[2]-'0';
}
y*=2;
if (grid.length()==6){
z=grid.toUpperCase().getBytes()[4]-'A'+0.5;
z=z*(2/18f);
}
lng=x+y+z-180;
if (lat>85) lat=85;//防止在地图上越界
if (lat<-85) lat=-85;//防止在地图上越界
return new LatLng(lat,lng);
}
public static LatLng[] gridToPolygon(String grid) {
if (grid.length() != 2 && grid.length() != 4 && grid.length() != 6) {
return null;
}
LatLng[] latLngs = new LatLng[4];
//纬度1
double x;
double y = 0;
double z = 0;
double lat1;
x = grid.toUpperCase().getBytes()[1] - 'A';
x *= 10;
if (grid.length() > 2) {
y = grid.getBytes()[3] - '0';
}
if (grid.length() > 4) {
z = grid.toUpperCase().getBytes()[5] - 'A';
z = z * (1f / 18f);
}
lat1 = x + y + z - 90;
if (lat1<-85.0){
lat1=-85.0;
}
if (lat1>85.0){
lat1=85.0;
}
//纬度2
x = 0;
y = 0;
z = 0;
double lat2;
if (grid.length() == 2) {
x = grid.toUpperCase().getBytes()[1] - 'A' + 1;
} else {
x = grid.toUpperCase().getBytes()[1] - 'A';
}
x *= 10;
if (grid.length() == 4) {
y = grid.getBytes()[3] - '0' + 1;
} else if (grid.length() == 6) {
y = grid.getBytes()[3] - '0';
}
if (grid.length() == 6) {
z = grid.toUpperCase().getBytes()[5] - 'A' + 1;
z = z * (1f / 18f);
}
lat2 = x + y + z - 90;
if (lat2<-85.0){
lat2=-85.0;
}
if (lat2>85.0){
lat2=85.0;
}
//经度1
x=0;y=0;z=0;
double lng1;
x=grid.toUpperCase().getBytes()[0]-'A';
x*=20;
if (grid.length()>2){
y=grid.getBytes()[2]-'0';
y*=2;
}
if (grid.length()>4){
z=grid.toUpperCase().getBytes()[4]-'A';
z=z*2/18f;
}
lng1=x+y+z-180;
//经度2
x=0;y=0;z=0;
double lng2;
if (grid.length()==2){
x=grid.toUpperCase().getBytes()[0]-'A'+1;
}else {
x=grid.toUpperCase().getBytes()[0]-'A';
}
x*=20;
if (grid.length()==4){
y=grid.getBytes()[2]-'0'+1;
}else if (grid.length()==6){
y=grid.getBytes()[2]-'0';
}
y*=2;
if (grid.length()==6){
z=grid.toUpperCase().getBytes()[4]-'A'+1;
z=z*2/18f;
}
lng2=x+y+z-180;
latLngs[0] = new LatLng(lat1,lng1);
latLngs[1] = new LatLng(lat1,lng2);
latLngs[2] = new LatLng(lat2,lng2);
latLngs[3] = new LatLng(lat2,lng1);
return latLngs;
}
/**
* 6 Maidenhead
* NMEA 西double
*
* @param location
* @return String
*/
public static String getGridSquare(LatLng location) {
double tempNumber;//用于中间计算
int index;//确定要显示的字符
double _long = location.longitude;
double _lat = location.latitude;
StringBuilder buff = new StringBuilder();
/*
*
*/
_long += 180; // 从太平洋中部开始
tempNumber = _long / 20; // 每个主要正方形都是 20 度宽
index = (int) tempNumber; // 大写字母的索引
buff.append(String.valueOf((char) (index + 'A'))); // 设置第一个字符
_long = _long - (index * 20); // 第 2 步的剩余部分
_lat += 90; //从南极开始 180 度
tempNumber = _lat / 10; // 每个大正方形高 10 度
index = (int) tempNumber; // 大写字母的索引
buff.append(String.valueOf((char) (index + 'A')));//设置第二个字符
_lat = _lat - (index * 10); // 第 2 步的剩余部分
/*
*
*/
tempNumber = _long / 2; // 步骤 1 的余数除以 2
index = (int) tempNumber; // 数字索引
buff.append(String.valueOf((char) (index + '0')));//设置第三个字符
_long = _long - (index * 2); //第 3 步的剩余部分
tempNumber = _lat; // 步骤 1 的余数除以 1
index = (int) tempNumber; // 数字索引
buff.append(String.valueOf((char) (index + '0')));//设置第四个字符
_lat = _lat - index; //第 3 步的剩余部分
/*
*
*/
tempNumber = _long / 0.083333; //步骤 2 的余数除以 0.083333
index = (int) tempNumber; // 小写字母的索引
buff.append(String.valueOf((char) (index + 'a')));//设置第五个字符
tempNumber = _lat / 0.0416665; // 步骤 2 的余数除以 0.0416665
index = (int) tempNumber; // 小写字母的索引
buff.append(String.valueOf((char) (index + 'a')));//设置第五个字符
return buff.toString().substring(0, 4);
}
/**
*
*
* @param latLng1
* @param latLng2
* @return
*/
public static double getDist(LatLng latLng1, LatLng latLng2) {
double radiansAX = Math.toRadians(latLng1.longitude); // A经弧度
double radiansAY = Math.toRadians(latLng1.latitude); // A纬弧度
double radiansBX = Math.toRadians(latLng2.longitude); // B经弧度
double radiansBY = Math.toRadians(latLng2.latitude); // B纬弧度
// 公式中“cosβ1cosβ2cosα1-α2+sinβ1sinβ2”的部分得到∠AOB的cos值
double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX)
+ Math.sin(radiansAY) * Math.sin(radiansBY);
double acos = Math.acos(cos); // 反余弦值
return EARTH_RADIUS * acos / 1000; // 最终结果km
}
/**
*
*
* @param mGrid1
* @param mGrid2 2
* @return double
*/
public static double getDist(String mGrid1, String mGrid2) {
LatLng latLng1 = gridToLatLng(mGrid1);
LatLng latLng2 = gridToLatLng(mGrid2);
if (latLng1 != null && latLng2 != null) {
return getDist(latLng1, latLng2);
} else {
return 0;
}
}
/**
*
*
* @param mGrid1
* @param mGrid2
* @return
*/
@SuppressLint("DefaultLocale")
public static String getDistStr(String mGrid1, String mGrid2) {
double dist = getDist(mGrid1, mGrid2);
if (dist == 0) {
return "";
} else {
return String.format(GeneralVariables.getStringFromResource(R.string.distance), dist);
}
}
public static String getDistLatLngStr(LatLng latLng1,LatLng latLng2){
return String.format(GeneralVariables.getStringFromResource(R.string.distance), getDist(latLng1,latLng2));
}
/**
*
*
* @param mGrid1
* @param mGrid2
* @return
*/
@SuppressLint("DefaultLocale")
public static String getDistStrEN(String mGrid1, String mGrid2) {
double dist = getDist(mGrid1, mGrid2);
if (dist == 0) {
return "";
} else {
return String.format("%.0f km", dist);
}
}
/**
*
*
* @param context context
* @return
*/
public static LatLng getLocalLocation(Context context) {
// 获取位置服务
String serviceName = Context.LOCATION_SERVICE;
// 调用getSystemService()方法来获取LocationManager对象
LocationManager locationManager = (LocationManager) context.getSystemService(serviceName);
// 指定LocationManager的定位方法
//String provider = LocationManager.GPS_PROVIDER;
// 调用getLastKnownLocation()方法获取当前的位置信息
List<String> providers = locationManager.getProviders(true);
Location location = null;
for (String s : providers) {
@SuppressLint("MissingPermission") Location l = locationManager.getLastKnownLocation(s);
if (l == null) {
continue;
}
if (location == null || l.getAccuracy() < location.getAccuracy()) {
// Found best last known location: %s", l);
location = l;
}
}
if (location != null) {
return new LatLng(location.getLatitude(), location.getLongitude());
} else {
return null;
}
}
/**
*
*
* @param context context
* @return String 6
*/
public static String getMyMaidenheadGrid(Context context) {
LatLng latLng = getLocalLocation(context);
if (latLng != null) {
return getGridSquare(latLng);
} else {
//ToastMessage.show("无法定位,请确认是否有定位的权限。");
return "";
}
}
/**
* false
*
* @param s
* @return boolean
*/
public static boolean checkMaidenhead(String s) {
if (s.length() != 4 && s.length() != 6) {
return false;
} else {
if (s.equals("RR73")) {
return false;
}
return Character.isAlphabetic(s.charAt(0))
&& Character.isAlphabetic(s.charAt(1))
&& Character.isDigit(s.charAt(2))
&& Character.isDigit(s.charAt(3));
}
}
}