百度地图电子围栏,根据两点确定距离两点相应距离的电子围栏区域,并判断相应点是否在电子围栏区域内

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 jwds=findJWD(106.486654,29.490295,106.581515,29.615467,10000);
            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 findJWD(List jwds){
           List gps = new ArrayList();
           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 findJWD(double lng1,double lat1,double lng2,double lat2,double distance){
           JWD A = new JWD(lng1,lat1);
           JWD B = new JWD(lng2,lat2);
           List jwds = new ArrayList();
           
           //查询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 findJWDMap(double lng1,double lat1,double lng2,double lat2,double distance){
           JWD A = new JWD(lng1,lat1);
           JWD B = new JWD(lng2,lat2);
           Map map = new HashMap();
           
           
           //查询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 jwds = findJWD(lng1,lat1,lng2,lat2,distance);
            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 pts){    
               
           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;    
           }    
       }    

}

你可能感兴趣的:(百度地图电子围栏,根据两点确定距离两点相应距离的电子围栏区域,并判断相应点是否在电子围栏区域内)