package com.ruoyi.common.utils.geo; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKTReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; public class GeoUtils { private static final Logger log = LoggerFactory.getLogger(GeoUtils.class); /** * geometryFactory */ private static final GeometryFactory geometryFactory = new GeometryFactory(); /** * Gets distance. * * @param lat1 the lat 1 * @param lon1 the lon 1 * @param lat2 the lat 2 * @param lon2 the lon 2 * @return the distance * @author chen.cheng */ public static double getDistance(double lat1, double lon1, double lat2, double lon2) { Point p1 = geometryFactory.createPoint(new Coordinate(lon1, lat1)); Point p2 = geometryFactory.createPoint(new Coordinate(lon2, lat2)); return p1.distance(p2); } /** * Gets poly center. * POLYGON((0 0, 0 5, 5 5, 5 0, 0 0)) * * @param wktPolygon the wkt polygon * @return the poly center * @author chen.cheng */ public static Point getPolyCenter(String wktPolygon) { // 创建WKTReader对象 WKTReader reader = new WKTReader(geometryFactory); // 从WKT字符串中读取几何对象 Geometry geometry = null; try { geometry = reader.read(wktPolygon); } catch (ParseException e) { log.info("Invalid WKT string: " + e.getMessage()); } // 获取中心点 return geometry.getCentroid(); } /** * getPolygon * POLYGON((0 0, 0 5, 5 5, 5 0, 0 0)) * * @param wktPolygon the wkt polygon * @return the poly center * @author chen.cheng */ public static Polygon getPolygon(String wktPolygon) { // 创建WKTReader对象 WKTReader reader = new WKTReader(geometryFactory); // 从WKT字符串中读取几何对象 Polygon geometry = null; try { geometry = (Polygon) reader.read(wktPolygon); } catch (ParseException e) { log.info("Invalid WKT string: " + e.getMessage()); } // 获取中心点 return geometry; } /** * 判断指定的GPS点是否在电子围栏内 * * @param fencePointsList 包含电子围栏的经纬度数据的列表,格式为 "经度,纬度" * @param pointStr 指定的GPS点,格式为 "经度,纬度" * @return 如果在电子围栏内则返回true,否则返回false */ public static boolean isPointInGeoFence(List fencePointsList, String pointStr) { // 将电子围栏的经纬度数据转换为坐标数组 Coordinate[] fencePoints = parseCoordinates(fencePointsList); // 将指定的GPS点转换为坐标 Coordinate targetPoint = parseCoordinate(pointStr); // 创建电子围栏多边形 Polygon geoFencePolygon = createPolygon(fencePoints); // 创建指定的GPS点 Point point = geometryFactory.createPoint(targetPoint); // 检查指定的GPS点是否在电子围栏内 return geoFencePolygon.contains(point); } /** * 判断指定的GPS点是否在电子围栏内 * * @param geoFencePolygon geo fence polygon * @param pointStr 指定的GPS点,格式为 "经度,纬度" * @return 如果在电子围栏内则返回true ,否则返回false * @since 2.0.0 */ public static boolean isPointInGeoFence(Polygon geoFencePolygon, String pointStr) { // 将指定的GPS点转换为坐标 Coordinate testPoint = parseCoordinate(pointStr); // 创建指定的GPS点 Point point = geometryFactory.createPoint(testPoint); // 检查指定的GPS点是否在电子围栏内 return geoFencePolygon.contains(point); } public static boolean isPointInGeoFence(Polygon geoFencePolygon, String lng, String lat) { // 将指定的GPS点转换为坐标 Coordinate testPoint = parseCoordinate(lng, lat); // 创建指定的GPS点 Point point = geometryFactory.createPoint(testPoint); // 检查指定的GPS点是否在电子围栏内 return geoFencePolygon.contains(point); } public static boolean isPointInGeoFence(Polygon geoFencePolygon, Double lng, Double lat) { // 将指定的GPS点转换为坐标 Coordinate testPoint = new Coordinate(lng, lat); // 创建指定的GPS点 Point point = geometryFactory.createPoint(testPoint); // 检查指定的GPS点是否在电子围栏内 return geoFencePolygon.contains(point); } /** * 判断指定的GPS点是否在电子围栏内 * * @param fencePointsList 包含电子围栏的经纬度数据的列表,格式为 "经度,纬度" * @return 如果在电子围栏内则返回true,否则返回false */ public static Polygon getPointInGeoFence(List fencePointsList) { // 将电子围栏的经纬度数据转换为坐标数组 Coordinate[] fencePoints = parseCoordinates(fencePointsList); // 创建电子围栏 return createPolygon(fencePoints); } /** * 根据GPS点集合创建多边形 * * @param coordinates GPS点集合 * @return 多边形对象 */ private static Polygon createPolygon(Coordinate[] coordinates) { // Ensure the polygon is closed by adding the first coordinate at the end if necessary if (!coordinates[0].equals(coordinates[coordinates.length - 1])) { Coordinate[] closedCoordinates = new Coordinate[coordinates.length + 1]; System.arraycopy(coordinates, 0, closedCoordinates, 0, coordinates.length); closedCoordinates[closedCoordinates.length - 1] = coordinates[0]; coordinates = closedCoordinates; } return geometryFactory.createPolygon(coordinates); } /** * 将包含经纬度数据的列表转换为坐标数组 * * @param pointsList 包含经纬度数据的列表 * @return 坐标数组 */ private static Coordinate[] parseCoordinates(List pointsList) { Coordinate[] coordinates = new Coordinate[pointsList.size()]; for (int i = 0; i < pointsList.size(); i++) { coordinates[i] = parseCoordinate(pointsList.get(i)); } return coordinates; } /** * 将经纬度数据字符串转换为坐标 * * @param pointStr 经纬度数据字符串,格式为 "经度,纬度" * @return 坐标 */ private static Coordinate parseCoordinate(String pointStr) { String[] parts = pointStr.split(","); double lon = Double.parseDouble(parts[0]); double lat = Double.parseDouble(parts[1]); return new Coordinate(lon, lat); } private static Coordinate parseCoordinate(String lng, String lat) { return new Coordinate(Double.parseDouble(lng), Double.parseDouble(lat)); } }