forked from dyf/fys-Multi-tenant
电子围栏
This commit is contained in:
@ -0,0 +1,24 @@
|
||||
package com.fuyuanshen.equipment.utils.map;
|
||||
|
||||
/**
|
||||
* @author: 默苍璃
|
||||
* @date: 2025-09-1110:27
|
||||
*/
|
||||
public class Coordinate {
|
||||
private double lat;
|
||||
private double lng;
|
||||
|
||||
// 构造函数
|
||||
public Coordinate() {}
|
||||
|
||||
public Coordinate(double lat, double lng) {
|
||||
this.lat = lat;
|
||||
this.lng = lng;
|
||||
}
|
||||
|
||||
// getter和setter方法
|
||||
public double getLat() { return lat; }
|
||||
public void setLat(double lat) { this.lat = lat; }
|
||||
public double getLng() { return lng; }
|
||||
public void setLng(double lng) { this.lng = lng; }
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
package com.fuyuanshen.equipment.utils.map;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: 默苍璃
|
||||
* @date: 2025-09-1110:13
|
||||
*/
|
||||
public class GeoFenceChecker {
|
||||
|
||||
/**
|
||||
* 点是否在围栏内
|
||||
*
|
||||
* @param pointLat 点的纬度
|
||||
* @param pointLng 点的经度
|
||||
* @param fenceType 围栏类型:0 POLYGON 或 1 CIRCLE
|
||||
* @param coordinates 围栏坐标点列表
|
||||
* @param radius 圆形围栏半径(米),仅对CIRCLE类型有效
|
||||
* @return true表示在围栏内,false表示在围栏外
|
||||
*/
|
||||
public static boolean isPointInFence(double pointLat, double pointLng,
|
||||
Integer fenceType,
|
||||
List<Coordinate> coordinates,
|
||||
Long radius) {
|
||||
if (fenceType == 0) {
|
||||
return isPointInPolygon(pointLat, pointLng, coordinates);
|
||||
} else if (fenceType == 1) {
|
||||
if (coordinates == null || coordinates.isEmpty() || radius == null) {
|
||||
return false;
|
||||
}
|
||||
// 圆形围栏只有一个坐标点(圆心)
|
||||
Coordinate center = coordinates.get(0);
|
||||
return isPointInCircle(pointLat, pointLng, center.lat, center.lng, radius);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用射线投射算法判断点是否在多边形内
|
||||
*
|
||||
* @param pointLat 点的纬度
|
||||
* @param pointLng 点的经度
|
||||
* @param polygon 多边形顶点坐标列表
|
||||
* @return true表示在多边形内,false表示在多边形外
|
||||
*/
|
||||
public static boolean isPointInPolygon(double pointLat, double pointLng,
|
||||
List<Coordinate> polygon) {
|
||||
if (polygon == null || polygon.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int intersectCount = 0;
|
||||
int vertexCount = polygon.size();
|
||||
|
||||
// 遍历多边形的每条边
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
Coordinate p1 = polygon.get(i);
|
||||
Coordinate p2 = polygon.get((i + 1) % vertexCount);
|
||||
|
||||
// 检查点是否在边的y范围内
|
||||
if (p1.lat != p2.lat &&
|
||||
(pointLat >= Math.min(p1.lat, p2.lat)) &&
|
||||
(pointLat < Math.max(p1.lat, p2.lat))) {
|
||||
|
||||
// 计算边与从点发出的水平射线的交点经度
|
||||
double intersectLng = (pointLat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng;
|
||||
|
||||
// 如果交点在点的右侧,则计数加1
|
||||
if (pointLng < intersectLng) {
|
||||
intersectCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 奇数个交点表示点在多边形内
|
||||
return intersectCount % 2 == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断点是否在圆形内
|
||||
*
|
||||
* @param pointLat 点的纬度
|
||||
* @param pointLng 点的经度
|
||||
* @param centerLat 圆心纬度
|
||||
* @param centerLng 圆心经度
|
||||
* @param radius 半径(米)
|
||||
* @return true表示在圆内,false表示在圆外
|
||||
*/
|
||||
public static boolean isPointInCircle(double pointLat, double pointLng,
|
||||
double centerLat, double centerLng,
|
||||
Long radius) {
|
||||
double distance = calculateDistance(pointLat, pointLng, centerLat, centerLng);
|
||||
return distance <= radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两点间距离(使用Haversine公式)
|
||||
*
|
||||
* @param lat1 点1纬度
|
||||
* @param lng1 点1经度
|
||||
* @param lat2 点2纬度
|
||||
* @param lng2 点2经度
|
||||
* @return 距离(米)
|
||||
*/
|
||||
public static double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
|
||||
final double EARTH_RADIUS = 6371000; // 地球半径(米)
|
||||
|
||||
double dLat = Math.toRadians(lat2 - lat1);
|
||||
double dLng = Math.toRadians(lng2 - lng1);
|
||||
|
||||
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
|
||||
Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
||||
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
|
||||
return EARTH_RADIUS * c;
|
||||
}
|
||||
|
||||
/**
|
||||
* 坐标点类
|
||||
*/
|
||||
public static class Coordinate {
|
||||
public double lat;
|
||||
public double lng;
|
||||
|
||||
public Coordinate() {
|
||||
}
|
||||
|
||||
public Coordinate(double lat, double lng) {
|
||||
this.lat = lat;
|
||||
this.lng = lng;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user