Java 使用GPS数据确定用户是否在特定区域 我想了解用户在特定区域使用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
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提供的好,而且看起来也有点傻) 最后,我用这种方式解决了这个问题:
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;
}