如何验证一个点是否位于由地理坐标构成的扇区内

时间:2016-01-24 17:58:18

标签: java google-maps geometry

我编写了一个Java代码,用于验证点是否位于圆定义半径的扇区内。点和圆心均以纬度和经度表示。

Java代码如下 -

public boolean isPointWithin(float centreLat,float centreLong,float pointLat,float pointLong,int maxDistance)
    {                               
        float adjFactor=0.0f;
        double angleRange,bisectorIVector,bisectorJVector,IVector,JVector,VectorLength,dotProduct,EnodeBAngle,
        latScale=0.0,longScale=0.0,distance,lower,upper,count,adjustmentFactor=0.0,jVector,dist1,dist2;
        dist1=Math.pow(centreLat-pointLat, 2)+Math.pow(centreLong-pointLong, 2);
        dist2=Math.pow(centreLat-pointLat, 2)+Math.pow(360-(Math.abs(centreLong)+Math.abs(pointLong)), 2);
        if(dist1>dist2)
        {
            adjFactor=360-(Math.abs(pointLong)+Math.abs(centreLong));
            if(centreLong>0)
                pointLong=(centreLong+adjFactor);
            else
                pointLong=(centreLong-adjFactor);
        }
        latScale=(111132.954-(559.822*Math.cos(2*Math.toRadians(pointLat)))+1.175*Math.cos(4*Math.toRadians(pointLat)))/1000;

        angleRange=Math.toRadians(sectorAngle);

        bisectorIVector=maxDistance*Precision.round(Math.sin(Math.toRadians(sectorDirection)),8);
        bisectorJVector=maxDistance*Precision.round(Math.cos(Math.toRadians(sectorDirection)),8);

        IVector=pointLong-centreLong; 
        JVector=pointLat-centreLat;

        if(pointLong<centreLong)
        {
            lower=pointLong;
            upper=centreLong;
        }
        else
        {
            upper=pointLong;
            lower=centreLong;
        }
        count=lower;
        while(Math.ceil(count)<Math.floor(upper))
        {
            jVector=((JVector/IVector)*(count-centreLong))+centreLat;
            longScale+=Math.cos(Math.toRadians(jVector)); 
            count++;
        }
        longScale*=latScale;
        if((upper-lower)>Math.floor((upper-lower)))
        {
            jVector=((JVector/IVector)*(upper-centreLong))+centreLat;
            adjustmentFactor=Math.cos(Math.toRadians(jVector))*latScale*((upper-lower)-Math.floor((upper-lower)));
        }
        longScale+=adjustmentFactor;


        distance=Math.sqrt(Math.pow(longScale,2) + Math.pow(JVector*latScale,2));
        VectorLength=Math.sqrt(Math.pow(IVector,2) + Math.pow(JVector,2));
        if(VectorLength==0.0)
            return true;

        dotProduct=bisectorIVector*IVector+bisectorJVector*JVector;
        EnodeBAngle=Precision.round(Math.acos(dotProduct/(maxDistance*VectorLength)),8);

        if(EnodeBAngle<=Precision.round(angleRange/2,8) && distance<=maxDistance)
            return true;
        else
            return false;
    }

现在如果该点位于该区域内,我正在尝试使用google api标记在地图上绘制的扇区上的点。

但问题是,即使我的java代码返回true,即点仍位于扇区内,谷歌地图上绘制的相应扇区显示该点位于扇区之外。

请帮我看看我是否出错?

1 个答案:

答案 0 :(得分:0)

地球表面的距离不是拉特的斜边。而且很长。距离。你必须找到大圆弧的长度。请查看第一部分here

JavaScript摘录:

var R = 6371000; // metres
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c;

你说过扇区 - 但扇区参数(起始角或中心角,扫掠角)在哪里? 您可能会计算方向角(轴承),如轴承部分中提到的链接所示。