public class JWD {
static double Rc = 6378137; // 赤道半径
double Rj = 6356725; // 极半径
double m_LoDeg, m_LoMin, m_LoSec; // longtitude 经度
double m_LaDeg, m_LaMin, m_LaSec;
double m_Longitude, m_Latitude;
double m_RadLo, m_RadLa;
double Ec;
double Ed;
public static void main(String[] args) {
List
for (JWD jwd : jwds) {
System.out.println(jwd.m_Longitude+","+jwd.m_Latitude);
}
//System.out.println(isPtInPoly(106.486653,29.490295,jwds));
}
public static List
List
for (JWD jwd : jwds) {
gps.add(jwd.m_Longitude+","+jwd.m_Latitude);
}
return gps;
}
/**
* 查询4个距离AB两点为distance并且垂直AB连线的4个点
* @param lng1
* @param lat1
* @param lng2
* @param lat2
* @param distance
* @return
*/
public static List
JWD A = new JWD(lng1,lat1);
JWD B = new JWD(lng2,lat2);
List
//查询AB连线相当于正北方向的角度
double angle = getAngle(A, B);
//查询4个距离AB垂直距离为distance的点
jwds.add(GetJWDB(A,distance,angle+90));
jwds.add(GetJWDB(A,distance,angle-90));
jwds.add(GetJWDB(B,distance,angle+90));
jwds.add(GetJWDB(B,distance,angle-90));
return jwds;
}
public static String findJWD(JWD jwd) {
return jwd.m_Longitude+","+jwd.m_Latitude;
}
/**
* 查询4个距离AB两点为distance并且垂直AB连线的4个点
* @param lng1
* @param lat1
* @param lng2
* @param lat2
* @param distance
* @return
*/
public static Map
JWD A = new JWD(lng1,lat1);
JWD B = new JWD(lng2,lat2);
Map
//查询AB连线相当于正北方向的角度
double angle = getAngle(A, B);
//查询4个距离AB垂直距离为distance的点
map.put(1,findJWD(GetJWDB(A,distance,angle+90)));
map.put(2,findJWD(GetJWDB(A,distance,angle-90)));
map.put(3,findJWD(GetJWDB(B,distance,angle-90)));
map.put(4,findJWD(GetJWDB(B,distance,angle+90)));
return map;
}
public JWD(double longitude, double latitude)
{
m_LoDeg = (int)longitude;
m_LoMin = (int)((longitude - m_LoDeg)*60);
m_LoSec = (longitude - m_LoDeg - m_LoMin/60.)*3600;
m_LaDeg = (int)latitude;
m_LaMin = (int)((latitude - m_LaDeg)*60);
m_LaSec = (latitude - m_LaDeg - m_LaMin/60.)*3600;
m_Longitude = longitude;
m_Latitude = latitude;
m_RadLo = longitude * Math.PI/180.;
m_RadLa = latitude * Math.PI/180.;
Ec = Rj + (Rc - Rj) * (90.-m_Latitude) / 90.;
Ed = Ec * Math.cos(m_RadLa);
}
/**通过一个点和与其对应的方向角和与该点相距的距离确定ling
**/
public static JWD GetJWDB(JWD A, double distance, double angle)
{
double dx = distance * Math.sin(angle * Math.PI /180.);
double dy = distance * Math.cos(angle * Math.PI /180.);
double BJD = (dx/A.Ed + A.m_RadLo) * 180./Math.PI;
double BWD = (dy/A.Ec + A.m_RadLa) * 180./Math.PI;
JWD B = new JWD(BJD, BWD);
return B;
}
//! 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度
/*!
* /param longitude 已知点A经度
* /param latitude 已知点A纬度
* /param distance B点到A点的距离
* /param angle B点相对于A点的方位
* /return B点的经纬度坐标
*/
public static JWD GetJWDB(double longitude, double latitude, double distance, double angle)
{
JWD A = new JWD(longitude,latitude);
return GetJWDB(A, distance, angle);
}
/**
* 计算AB连线与正北方向的夹角
* @param A
* @param B
* @return
*/
public static double getAngle(JWD A,JWD B)
{
double dx=(B.m_RadLo-A.m_RadLo)*A.Ed;
double dy=(B.m_RadLa-A.m_RadLa)*A.Ec;
double angle=0.0;
angle=Math.atan(Math.abs(dx/dy))*180/Math.PI;
double dLo=B.m_Longitude-A.m_Longitude;
double dLa=B.m_Latitude-A.m_Latitude;
if(dLo>0&&dLa<=0)
{
angle=(90-angle)+90;
}
else if(dLo<=0&&dLa<0)
{
angle=angle+180;
}else if(dLo<0&&dLa>=0)
{
angle= (90-angle)+270;
}
return angle;
}
/**
* 判断前面的点是否在后面的点和距离确定的圆上
* @param lng1
* @param lat1
* @param lng2
* @param lat2
* @param distatnce 距离
* @return
*/
public static boolean isPtInCircle(double lng1, double lat1, double lng2, double lat2,double distatnce){
double distance_ab = distance(lng1, lat1,lng2, lat2);
if(distance_ab>distatnce){
return false;
}
return true;
}
/**
* 计算地球上任意两点(经纬度)距离
*
* @param lng1 第一点经度
* @param lat1 第一点纬度
* @param lng2 第二点经度
* @param lat2 第二点纬度
* @return 返回距离 单位:米
*/
public static double distance(double lng1, double lat1, double lng2, double lat2) {
double a, b;
lat1 = lat1 * Math.PI / 180.0;
lat2 = lat2 * Math.PI / 180.0;
a = lat1 - lat2;
b = (lng1 - lng2) * Math.PI / 180.0;
double d;
double sa2, sb2;
sa2 = Math.sin(a / 2.0);
sb2 = Math.sin(b / 2.0);
d = 2 * Rc * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
return d;
}
/**
* 判断经纬度是否在矩形(四边形范围内),以及缺点电子围栏的AB两点与距离为半径确定的圆内
* @param lng 需要判断点的经度
* @param lat 需要判断点的纬度
* @param lng1 电子围栏的路径点A的经度
* @param lat1 电子围栏的路径点A的纬度
* @param lng2 电子围栏的路径点B的经度
* @param lat2 电子围栏的路径点B的纬度
* @param distance 电子围栏路径的一半宽度
* @return
*/
public static boolean isPtInPoly(double lng , double lat , double lng1,double lat1,double lng2,double lat2,double distance){
JWD a = new JWD(lng,lat);
//获取电子围栏四个角的经纬度
List
boolean flag1 = isPtInPoly(a,jwds);
boolean flag2 = isPtInCircle(lng,lat,lng1,lat1,distance);
boolean flag3 = isPtInCircle(lng,lat,lng2,lat2,distance);
//如果不在矩形内,不在两个点和距离确定的圆内,则该点不在电子围栏范围内
if(!flag1 && !flag2 && !flag3){
return false;
}
return true;
}
/**
* 判断点是否在多边形内,如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
* 参考 https://blog.csdn.net/zhaoliangbao2778/article/details/78084733
* @param point 检测点
* @param pts 多边形的顶点
* @return 点在多边形内返回true,否则返回false
*/
public static boolean isPtInPoly(JWD point, List
int N = pts.size();
boolean boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
int intersectCount = 0;//cross points count of x
double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
JWD p1, p2;//neighbour bound vertices
JWD p = point; //当前点
p1 = pts.get(0);//left vertex
for(int i = 1; i <= N; ++i){//check all rays
if(p.equals(p1)){
return boundOrVertex;//p is an vertex
}
p2 = pts.get(i % N);//right vertex
if(p.m_Longitude < Math.min(p1.m_Longitude, p2.m_Longitude) || p.m_Longitude > Math.max(p1.m_Longitude, p2.m_Longitude)){//ray is outside of our interests
p1 = p2;
continue;//next ray left point
}
if(p.m_Longitude > Math.min(p1.m_Longitude, p2.m_Longitude) && p.m_Longitude < Math.max(p1.m_Longitude, p2.m_Longitude)){//ray is crossing over by the algorithm (common part of)
if(p.m_Latitude <= Math.max(p1.m_Latitude, p2.m_Latitude)){//x is before of ray
if(p1.m_Longitude == p2.m_Longitude && p.m_Latitude >= Math.min(p1.m_Latitude, p2.m_Latitude)){//overlies on a horizontal ray
return boundOrVertex;
}
if(p1.m_Latitude == p2.m_Latitude){//ray is vertical
if(p1.m_Latitude == p.m_Latitude){//overlies on a vertical ray
return boundOrVertex;
}else{//before ray
++intersectCount;
}
}else{//cross point on the left side
double xinters = (p.m_Longitude - p1.m_Longitude) * (p2.m_Latitude - p1.m_Latitude) / (p2.m_Longitude - p1.m_Longitude) + p1.m_Latitude;//cross point of y
if(Math.abs(p.m_Latitude - xinters) < precision){//overlies on a ray
return boundOrVertex;
}
if(p.m_Latitude < xinters){//before ray
++intersectCount;
}
}
}
}else{//special case when ray is crossing through the vertex
if(p.m_Longitude== p2.m_Longitude&& p.m_Latitude <= p2.m_Latitude){//p crossing over p2
JWD p3 = pts.get((i+1) % N); //next vertex
if(p.m_Longitude>= Math.min(p1.m_Longitude, p3.m_Longitude) && p.m_Longitude<= Math.max(p1.m_Longitude, p3.m_Longitude)){//p.m_Longitudelies between p1.m_Longitude& p3.m_Longitude
++intersectCount;
}else{
intersectCount += 2;
}
}
}
p1 = p2;//next ray left point
}
if(intersectCount % 2 == 0){//偶数在多边形外
return false;
} else { //奇数在多边形内
return true;
}
}
}