给定一组经纬度如何判断某点是否在这组经纬度的范围之内(电子围栏实现代码)
方法一:
使用JTS Topology Suite 是 Java 的空间数据模型和空间分析操作的库,用于处理地理空间数据和进行空间分析。
1.1引入maven
<dependency> <groupId>org.locationtech.jts</groupId> <artifactId>jts-core</artifactId> <version>1.18.0</version> </dependency>
1.2:代码实现
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "坐标对象", description = "")
@Data
public class CoordinateGeog implements Comparator<CoordinateGeog> {
@ApiModelProperty("经度")
private BigDecimal lng;
@ApiModelProperty("纬度")
private BigDecimal lat;
@Override
public int compare(CoordinateGeog point1, CoordinateGeog point2) {
double angle1 = Math.atan2(point1.getLat().subtract(lat).doubleValue(),
point1.getLng().subtract(lng).doubleValue());
double angle2 = Math.atan2(point2.getLat().subtract(lat).doubleValue(),
point2.getLng().subtract(lng).doubleValue());
return Double.compare(angle1, angle2);
}
}
public class SpatialGeographyUtil {
/**
* 给定一组经纬度坐标集合,判断某点坐标是否在这组坐标所围的范围之内
*/
public static Polygon constructionScope( List<CoordinateGeog> innerCoordinateGeogs,GeometryFactory geometryFactory){
List<Coordinate> coordinates = new ArrayList<>();
innerCoordinateGeogs.forEach(i -> {
Coordinate coordinate = new Coordinate(i.getLng().doubleValue(), i.getLat().doubleValue());
coordinates.add(coordinate);
});
// 对坐标点进行极角排序
sortCoordinatesByPolarAngle(coordinates);
// 确保首尾坐标点相同,以确保闭合
List<Coordinate> newCoordinates = endToEnd(coordinates);
Coordinate[] coordinatesArray = newCoordinates.toArray(new Coordinate[newCoordinates.size()]);
LinearRing linearRing = geometryFactory.createLinearRing(coordinatesArray);
return geometryFactory.createPolygon(linearRing, null);
}
//按照参考点计算每个点相对于参考点的极角,然后进行排序
public static void sortCoordinatesByPolarAngle(List<Coordinate> coordinates) {
Coordinate reference = findReferencePointCoordinate(coordinates);
coordinates.sort(Comparator.comparingDouble(point ->
Math.atan2(point.y - reference.y, point.x - reference.x)
));
}
//找到具有最小纬度的点
public static Coordinate findReferencePointCoordinate(List<Coordinate> coordinates) {
Coordinate reference = coordinates.get(0);
for (Coordinate point : coordinates) {
if (point.y < reference.y || (point.y == reference.y && point.x < reference.x)) {
reference = point;
}
}
return reference;
}
private static List<Coordinate> endToEnd(List<Coordinate> coordinates) {
if (!coordinates.isEmpty()) {
Coordinate first = coordinates.get(0);
Coordinate last = coordinates.get(coordinates.size() - 1);
if (!first.equals2D(last)) {
coordinates.add(new Coordinate(first));
}
}
return coordinates;
}
}
方法二:.Path2D
是 Java 中用于创建和操作基本几何形状(如线条和曲线)的类。它是 Java 2D API 中的一部分,提供了一种可用于绘制 2D 图形的机制。
public class SpatialGeographyUtil {
public static Path2D.Double createClosedPathForPolygon(List<CoordinateGeog> innerCoordinateGeogs) {
// 确保首尾坐标点相同,以确保闭合
List<CoordinateGeog> coordinateGeogs = ensurePolygonClosure(innerCoordinateGeogs);
// 对坐标点进行极角排序
List<CoordinateGeog> newCoordinateGeogs = sortPointsByPolarAngle(coordinateGeogs);
Path2D.Double path = new Path2D.Double();
for (int i = 0; i < newCoordinateGeogs.size() - 1; i++) {
CoordinateGeog coords = newCoordinateGeogs.get(i);
if (i == 0) {
path.moveTo(coords.getLng().doubleValue(), coords.getLat().doubleValue());
} else {
path.lineTo(coords.getLng().doubleValue(), coords.getLat().doubleValue());
}
}
path.closePath();
return path;
}
public static Boolean checkPointInPathContainment(Path2D path, double lng, double lat) {
Point2D point2Dr= new Point2D.Double(lng,lat);
return path.contains(point2Dr);
}
public static List<CoordinateGeog> sortPointsByPolarAngle(List<CoordinateGeog> points) {
// 找到最左下角的点作为参考点
CoordinateGeog reference = findReferencePoint(points);
// 使用极角比较器进行排序
Collections.sort(points, new CoordinateGeog(reference.getLng(), reference.getLat()));
return points;
}
//确保多边形闭合
public static List<CoordinateGeog> ensurePolygonClosure(List<CoordinateGeog> polygon) {
CoordinateGeog firstCoords = polygon.get(0);
CoordinateGeog lastCoords = polygon.get(polygon.size() - 1);
if (!firstCoords.getLng().equals(lastCoords.getLng()) || !firstCoords.getLat().equals(lastCoords.getLat())) {
polygon.add(firstCoords); // 如果首尾不相连,将第一个点添加到最后
}
return polygon;
}
//集合中找到一个作为参考点的特定点
public static CoordinateGeog findReferencePoint(List<CoordinateGeog> points) {
CoordinateGeog reference = points.get(0);
for (CoordinateGeog point : points) {
if (point.getLat().compareTo(reference.getLat()) < 0 ||
(point.getLat().compareTo(reference.getLat()) == 0 && point.getLng().compareTo(reference.getLng()) < 0)) {
reference = point;
}
}
return reference;
}
}
总结:
两个方法都是用来处理多边形和点的关系,但是它们的功能和逻辑略有不同。
constructionScope
主要负责创建多边形,而isPointInPolygon
主要用于判断点是否在多边形内部。两者都使用了极角排序的方法来确保多边形的正确性,并在需要时确保多边形的闭合。