diff --git a/pav-server/src/main/java/com/palnet/comn/utils/AirAreaUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/AirAreaUtils.java index e7cf6339..4d401595 100644 --- a/pav-server/src/main/java/com/palnet/comn/utils/AirAreaUtils.java +++ b/pav-server/src/main/java/com/palnet/comn/utils/AirAreaUtils.java @@ -6,13 +6,16 @@ import lombok.*; import lombok.extern.slf4j.Slf4j; import org.geotools.geojson.feature.FeatureJSON; import org.geotools.geojson.geom.GeometryJSON; +import org.geotools.geometry.jts.JTS; +import org.geotools.referencing.CRS; +import org.geotools.referencing.GeodeticCalculator; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.*; import org.opengis.feature.simple.SimpleFeature; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.TransformException; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -85,7 +88,9 @@ public class AirAreaUtils { } - // TODO 초기화 + /** + * 초기화 + */ private void init() { airAreaMap = new HashMap<>(); geometryFactory = new GeometryFactory(); @@ -543,7 +548,116 @@ public class AirAreaUtils { } - // TODO 가장 가까운 거리 반환 + /** + * Cartesian 식으로 변환 + * + * @param lon + * @param lat + * @return + */ + public static Coordinate toCartesian(double lon, double lat) { + double radLon = Math.toRadians(lon); + double radLat = Math.toRadians(lat); + double x = Math.cos(radLat) * Math.cos(radLon); + double y = Math.cos(radLat) * Math.sin(radLon); + double z = Math.sin(radLat); + return new Coordinate(x, y, z); + } + + /** + * 구형으로 변환 + * + * @param cartesian + * @return + */ + public static Coordinate toSpherical(Coordinate cartesian) { + double x = cartesian.x; + double y = cartesian.y; + double z = cartesian.z; + double lon = Math.toDegrees(Math.atan2(y, x)); + double hyp = Math.sqrt(x * x + y * y); + double lat = Math.toDegrees(Math.atan2(z, hyp)); + return new Coordinate(lon, lat); + } + + /** + * 선분과 점 사이의 가장 가까운 점을 구한다.(곡률 적용) + * + * @param linePointA + * @param linePointB + * @param pointP + * @return + */ + public static Coordinate getClosestPoint(Coordinate linePointA, Coordinate linePointB, Coordinate pointP) { + Coordinate A3D = toCartesian(linePointA.x, linePointA.y); + Coordinate B3D = toCartesian(linePointB.x, linePointB.y); + Coordinate P3D = toCartesian(pointP.x, pointP.y); + + Coordinate AB = new Coordinate(B3D.x - A3D.x, B3D.y - A3D.y, B3D.z - A3D.z); + Coordinate AP = new Coordinate(P3D.x - A3D.x, P3D.y - A3D.y, P3D.z - A3D.z); + double t = (AP.x * AB.x + AP.y * AB.y + AP.z * AB.z) / (AB.x * AB.x + AB.y * AB.y + AB.z * AB.z); + t = Math.max(0, Math.min(1, t)); // t가 [0, 1] 범위 내에 있도록 제한 + + Coordinate closestPoint3D = new Coordinate( + A3D.x + t * AB.x, + A3D.y + t * AB.y, + A3D.z + t * AB.z + ); + + return toSpherical(closestPoint3D); + } + + /** + * 점과 점 사이의 거리를 구한다. + * + * @param point1 + * @param point2 + * @return + */ + public static Double calculatePointAndPointDistance(Coordinate point1, Coordinate point2) { + CoordinateReferenceSystem crs; + try { + crs = CRS.decode("EPSG:4326"); + } catch (Exception e) { + throw new RuntimeException("Error decoding CRS", e); + } + + GeodeticCalculator gc = new GeodeticCalculator(crs); + try { + gc.setStartingPosition(JTS.toDirectPosition(new Coordinate(point1.getY(), point1.getX()), crs)); + gc.setDestinationPosition(JTS.toDirectPosition(new Coordinate(point2.getY(), point2.getX()), crs)); + } catch (TransformException e) { + throw new RuntimeException("Error setting positions for distance calculation", e); + } + + return gc.getOrthodromicDistance(); + } + + /** + * x, y 좌표를 교환 + * + * @param originalGeometry + * @return + */ + public static Geometry swapCoordinates(Geometry originalGeometry) { + GeometryFactory geometryFactory = new GeometryFactory(); + Coordinate[] originalCoordinates = originalGeometry.getCoordinates(); + Coordinate[] swappedCoordinates = new Coordinate[originalCoordinates.length]; + + for (int i = 0; i < originalCoordinates.length; i++) { + swappedCoordinates[i] = new Coordinate(originalCoordinates[i].y, originalCoordinates[i].x); + } + + if (originalGeometry instanceof Point) { + return geometryFactory.createPoint(swappedCoordinates[0]); + } else if (originalGeometry instanceof LineString) { + return geometryFactory.createLineString(swappedCoordinates); + } else if (originalGeometry instanceof Polygon) { + return geometryFactory.createPolygon(swappedCoordinates); + } + // Add more geometry types as needed + return originalGeometry; // Return the original geometry if type is not handled + } public static void main(String[] args) {