Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用GPS数据确定用户是否在特定区域 我想了解用户在特定区域使用GPS数据,并考虑精度信息来减少错误,因为程序会提示用户如果用户绝对离开了区域。_Java_Android_Gps_Geolocation_Collision Detection - Fatal编程技术网

Java 使用GPS数据确定用户是否在特定区域 我想了解用户在特定区域使用GPS数据,并考虑精度信息来减少错误,因为程序会提示用户如果用户绝对离开了区域。

Java 使用GPS数据确定用户是否在特定区域 我想了解用户在特定区域使用GPS数据,并考虑精度信息来减少错误,因为程序会提示用户如果用户绝对离开了区域。,java,android,gps,geolocation,collision-detection,Java,Android,Gps,Geolocation,Collision Detection,GPS传感器返回纬度、经度和精度(以米为单位),我可以使用这些数据画一个圆: 135.500908,34.661964,30.0 有一组坐标按顺序表示特定区域: 135.500350,34.667011 135.506101,34.666853 135.505972,34.663076 135.505135,34.663111 135.504942,34.662387 135.504084,34.662440 135.504062,34.663146 135.502968,34.663217

GPS传感器返回纬度、经度和精度(以米为单位),我可以使用这些数据画一个圆:

135.500908,34.661964,30.0
有一组坐标按顺序表示特定区域:

135.500350,34.667011
135.506101,34.666853
135.505972,34.663076
135.505135,34.663111
135.504942,34.662387
135.504084,34.662440
135.504062,34.663146
135.502968,34.663217
135.502689,34.663764
135.502431,34.664205
135.502110,34.664646
135.501680,34.665105
135.501509,34.665246
135.500844,34.665229
135.500371,34.665511
我的想法是通过使用线-圆碰撞检测算法来确定多边形是否与圆发生碰撞,但我的代码中似乎有错误,而且由于半径/度的原因,我似乎无法直接使用该信息,有人能帮我吗?或者让我知道是否有更简单的解决方案

    public static boolean possiblyInside(List<Double> arrayX, List<Double> arrayY, double locationX, double locationY, double locationAccuracy) {
    if (arrayX.size() != arrayY.size()) {
        throw new IllegalArgumentException("Array length not equal");
    }

    boolean anyCircleLineIntersection = false;
    if (arrayX.size() > 1) {
        for (int i = 0; i < arrayX.size(); i++) {
            double p1x = i == 0 ? arrayX.get(arrayX.size() - 1) : arrayX.get(i - 1);
            double p1y = i == 0 ? arrayY.get(arrayY.size() - 1) : arrayY.get(i - 1);
            double p2x = arrayX.get(i);
            double p2y = arrayY.get(i);

            if (circleLineIntersection(p1x, p1y, p2x, p2y, locationX, locationY, locationAccuracy)) {
                anyCircleLineIntersection = true;
                break;
            }
        }
    }

    return anyCircleLineIntersection;
}

private static boolean circleLineIntersection(double p1X, double p1Y, double p2X, double p2Y, double centerX, double centerY, double locationAccuracy) {
    double rad = (180 / Math.PI);
    double r = (locationAccuracy / 1000);

    p1X = p1X * rad;
    p1Y = p1Y * rad;
    p2X = p2X * rad;
    p2Y = p2Y * rad;
    centerX = centerX * rad;
    centerY = centerY * rad;

    // Transform to local coordinates
    double localP1X = p1X - centerX;
    double localP1Y = p1Y - centerY;
    double localP2X = p2X - centerX;
    double localP2Y = p2Y - centerY;

    // Pre-calculate this value. We use it often
    double pDiffX = localP2X - localP1X;
    double pDiffY = localP2Y - localP1Y;

    double a = (pDiffX) * (pDiffX) + (pDiffY) * (pDiffY);
    double b = 2 * ((pDiffX * localP1X) + (pDiffY * localP1Y));
    double c = (localP1X * localP1X) + (localP1Y * localP1Y) - (r * r);

    double delta = b * b - (4 * a * c);
    return delta >= 0.0;
}
public static boolean possiblyInside(列表arrayX、列表arrayY、双位置x、双位置y、双位置精度){
如果(arrayX.size()!=arrayY.size()){
抛出新的IllegalArgumentException(“数组长度不相等”);
}
布尔anyCircleLineIntersection=false;
如果(arrayX.size()>1){
对于(int i=0;i=0.0;
}
有一个方法称为。谷歌已经为你提供了这样的功能。你不必处理所有这些复杂的计算

您可以在用户进入特定区域/退出特定区域/在特定区域停留一段时间后触发事件。或者你可以做不同的组合


这是一篇关于如何使用地理围栏的文章。它由4篇独立的文章组成。

感谢托多·科斯托夫的回答

我知道Android已经提供了GeoFenging API,但由于其实现和局限性,它并不完全适合我的情况,我也想将该算法与iOS版本的应用程序同步。(就连我都知道算法不如iOS或Android提供的好,而且看起来也有点傻)

最后,我用这种方式解决了这个问题:

  • 确保当前位置不在多边形内(使用多边形中的点算法)

  • 循环遍历区域多边形的所有线段,找出 距离当前位置(点B)最近的坐标(点A)

  • 计算点A和点B之间的距离,将其转换为米(X)

  • 如果X>定位精度(也以米为单位),则用户肯定不在特定区域内

  • p、 我不擅长数学和地理定位,如果有错误,请指出

    public static boolean possiblyInside(列表arrayX、列表arrayY、双位置x、双位置y、双位置精度){
    如果(arrayX.size()!=arrayY.size()){
    抛出新的IllegalArgumentException(“数组长度不相等”);
    }
    if(arrayX.size()<3){
    返回false;
    }
    双最小距离=双最大值;
    对于(int i=0;i只是为了弄清楚——你想确定用户是否在一个特定区域,如果用户不在该区域,提示警报,对吗?是的,但是如果用户“可能在里面”,则不提示,所以我不想使用点在多边形中,因为很难考虑GPS的准确性。
    
    public static boolean possiblyInside(List<Double> arrayX, List<Double> arrayY, double locationX, double locationY, double locationAccuracy) {
        if (arrayX.size() != arrayY.size()) {
            throw new IllegalArgumentException("Array length not equal");
        }
    
        if (arrayX.size() < 3) {
            return false;
        }
    
        double minimumDistance = Double.MAX_VALUE;
        for (int i = 0; i < arrayX.size(); i++) {
            double p1x = i == 0 ? arrayX.get(arrayX.size() - 1) : arrayX.get(i - 1);
            double p1y = i == 0 ? arrayY.get(arrayY.size() - 1) : arrayY.get(i - 1);
            double p2x = arrayX.get(i);
            double p2y = arrayY.get(i);
    
            Coordinate closest = getClosestPointOnLine(p1x, p1y, p2x, p2y, locationX, locationY);
            double currentDistance = distanceMeterBetweenPoints(closest.latitude, closest.longitude, locationX, locationY);
            if (currentDistance < minimumDistance) {
                minimumDistance = currentDistance;
            }
        }
    
        return (minimumDistance <= locationAccuracy);
    }
    
    private static Coordinate getClosestPointOnLine(double sx1, double sy1, double sx2, double sy2, double px, double py) {
        double xDelta = sx2 - sx1;
        double yDelta = sy2 - sy1;
    
        if ((xDelta == 0) && (yDelta == 0)) {
            throw new IllegalArgumentException("Line start equals line end");
        }
    
        double u = ((px - sx1) * xDelta + (py - sy1) * yDelta) / (xDelta * xDelta + yDelta * yDelta);
    
        final Coordinate closestPoint;
        if (u < 0.0) {
            closestPoint = new Coordinate(sx1, sy1);
        } else if (u > 1.0) {
            closestPoint = new Coordinate(sx2, sy2);
        } else  {
            closestPoint = new Coordinate((int) Math.round(sx1 + u * xDelta), (int) Math.round(sy1 + u * yDelta));
        }
    
        return closestPoint;
    }
    
    public static double distanceMeterBetweenPoints(double aX, double aY, double bX, double bY) {
        double rad = Math.PI / 180;
        int r = 6371;
    
        double dLat = (aX - bX) * rad;
        double dLng = (aY - bY) * rad;
    
        double x = Math.pow(Math.sin(dLat / 2), 2) + Math.cos(aX * rad) * Math.cos(bX * rad) * Math.pow(Math.sin(dLng / 2), 2);
        double y = 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x));
    
        return r * y * 1000;
    }