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 8ba0d6b0..4974280e 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 @@ -7,6 +7,7 @@ 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.geometry.jts.JTSFactoryFinder; import org.geotools.referencing.CRS; import org.geotools.referencing.GeodeticCalculator; import org.json.simple.JSONArray; @@ -20,7 +21,9 @@ import org.locationtech.proj4j.BasicCoordinateTransform; import org.locationtech.proj4j.CRSFactory; import org.locationtech.proj4j.ProjCoordinate; import org.opengis.feature.simple.SimpleFeature; +import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.springframework.cache.annotation.Cacheable; import org.springframework.core.io.Resource; @@ -41,6 +44,7 @@ import java.util.stream.Collectors; @Slf4j public class AirAreaUtils { + private final int PERIMETER_OF_EARTH = 40075 * 1000; // 지구 둘레(m) private final String RESOURCE_BASE_PATH = "air/airspace/"; private final String COMMON_PATH = "common/"; private final String CUSTOM_PATH = "custom/"; @@ -93,7 +97,7 @@ public class AirAreaUtils { /** - * 초기화 + * 초기화 */ private void init() { airAreaMap = new HashMap<>(); @@ -663,9 +667,15 @@ public class AirAreaUtils { return originalGeometry; // Return the original geometry if type is not handled } + public static List swapCoordinates(List originalCoordinates) { + return originalCoordinates.stream().map(coordinate -> new Coordinate(coordinate.y, coordinate.x)).collect(Collectors.toList()); + + } + // ---------------------- AreaUtils ---------------------- // TODO 버퍼 생성시 임의로 좌표변환을 해야만 하는지 확인 ex) espg:4326 -> espg:5181 -> espg:4326 + /** * 좌표계 변환 * @@ -685,7 +695,7 @@ public class AirAreaUtils { List result = new ArrayList<>(); - for(Coordinate coord : coordList) { + for (Coordinate coord : coordList) { ProjCoordinate projCoordinate = new ProjCoordinate(coord.getX(), coord.getY()); ProjCoordinate projTrasform = transform.transform(projCoordinate, new ProjCoordinate()); @@ -706,7 +716,7 @@ public class AirAreaUtils { */ public List buffer(List coordList, double bufferZone) { - LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[] {})); + LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[]{})); Geometry geometry = geometryFactory.createGeometry(line); // buffer @@ -726,6 +736,7 @@ public class AirAreaUtils { } // TODO 곡률로 구성된 원 생성방법 확인(타원이 아닌) + /** * 타원 생성 * @@ -740,9 +751,9 @@ public class AirAreaUtils { double lat = CircleCoord.y; double diameterInMeters = BufferZone; - shapeFactory.setCentre(new Coordinate(lng , lat)); + shapeFactory.setCentre(new Coordinate(lng, lat)); shapeFactory.setHeight((diameterInMeters * 2) / 111320d); - shapeFactory.setWidth((diameterInMeters * 2) / (40075000 * Math.cos(Math.toRadians(lat)) / 360)); + shapeFactory.setWidth((diameterInMeters * 2) / (PERIMETER_OF_EARTH * Math.cos(Math.toRadians(lat)) / 360)); shapeFactory.setNumPoints(64); final Polygon circle = shapeFactory.createCircle(); @@ -756,43 +767,86 @@ public class AirAreaUtils { return coordList; } + /* + // 라인 버퍼 생성 샘플 + public static void main(String[] args) throws FactoryException, TransformException { + // EPSG:4326 좌표계 정의 + CoordinateReferenceSystem crs4326 = CRS.decode("EPSG:4326"); + // EPSG:3857 좌표계 정의 (투영 좌표계) +// CoordinateReferenceSystem crs3857 = CRS.decode("EPSG:3857"); + CoordinateReferenceSystem crs3857 = CRS.decode("EPSG:5181"); - public static void main(String[] args) { - AirAreaUtils utils = AirAreaUtils.getInstance(); - log.info("utils: {}", utils); - -// AirAreaUtils utils2 = AirAreaUtils.getInstance(); -// log.info("utils2: {}", utils2); -// log.info("utils == utils2: {}", utils == utils2); -// -// List list = List.of(1, 2, 3, 4, 5); -// boolean b = list.stream().anyMatch(i -> i == 3); -// log.info("b:: {}", b); -// List list2 = new ArrayList<>(); -// boolean b2 = list2.stream().anyMatch(i -> i == 3); -// log.info("b2:: {}", b2); - - Map> airMap = utils.getAirAreaMap(); - airMap.forEach((k, v) -> { - log.info("{} - {}", k, v.size()); - }); - - List beforeCoordinates = List.of( - new Coordinate(126.0, 37.0), - new Coordinate(126.0, 38.0), - new Coordinate(127.0, 38.0), + // 좌표 변환기 설정 + MathTransform transformTo3857 = CRS.findMathTransform(crs4326, crs3857); + MathTransform transformTo4326 = CRS.findMathTransform(crs3857, crs4326); + + // GeometryFactory 생성 + GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(); + + // LineString 좌표 정의 (EPSG:4326) + Coordinate[] coordinates = new Coordinate[]{ new Coordinate(127.0, 37.0), - new Coordinate(126.0, 37.0) - ); + new Coordinate(127.1, 37.1), + new Coordinate(127.2, 37.2) + }; + List coordinates1 = AirAreaUtils.swapCoordinates(Arrays.asList(coordinates)); + LineString lineString = geometryFactory.createLineString(coordinates1.toArray(new Coordinate[0])); + + // LineString을 EPSG:3857로 변환 + LineString transformedLineString = (LineString) JTS.transform(lineString, transformTo3857); + + // 거리 (단위: 미터) + double distance = 1000; // 1km + + // Buffer를 사용하여 LineString을 둘러싼 Polygon 생성 (EPSG:3857) + Polygon bufferedPolygon = (Polygon) transformedLineString.buffer(distance); + + // Buffered Polygon을 EPSG:4326로 변환 + Polygon finalPolygon = (Polygon) JTS.transform(bufferedPolygon, transformTo4326); + List finalCoordinates = Arrays.stream(finalPolygon.getCoordinates()).map(coordinate -> new de.micromata.opengis.kml.v_2_2_0.Coordinate(coordinate.y, coordinate.x)).collect(Collectors.toList()); + + // 결과 출력 + KmlUtils.KmlRq bufferRq = KmlUtils.KmlRq.builder() + .name("test") + .type(KmlUtils.TYPE.POLYGON) + .coordinates(finalCoordinates) + .build(); + KmlUtils.KmlRq lineRq = KmlUtils.KmlRq.builder() + .name("test") + .type(KmlUtils.TYPE.LINESTRING) + .coordinates(Arrays.stream(coordinates).map(coordinate -> new de.micromata.opengis.kml.v_2_2_0.Coordinate(coordinate.x, coordinate.y)).collect(Collectors.toList())) + .build(); + String str = KmlUtils.createKmlPolygons(List.of(bufferRq, lineRq)); + System.out.println(str); + + } + */ - List transCoordList = utils.transform(beforeCoordinates, "EPSG:4326", "EPSG:5181"); - List bufferList = utils.buffer(transCoordList, 50); // buffer 영역 생성 + public static Coordinate transformCoordinate(Coordinate sourceCoord, String sourceCRSCode, String targetCRSCode) throws Exception { + // 소스와 타겟 CRS 정의 + CoordinateReferenceSystem sourceCRS = CRS.decode(sourceCRSCode); + CoordinateReferenceSystem targetCRS = CRS.decode(targetCRSCode); - List transBufferList = utils.transform(bufferList, "EPSG:5181", "EPSG:4326"); // buffer 영역 좌표계 변환 - log.info("transBufferList: {}", transBufferList); + // MathTransform 객체 생성 + MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS); + + // 좌표 변환 + return JTS.transform(sourceCoord, null, transform); + } + public static void main(String[] args) { + try { + Coordinate sourceCoord = new Coordinate(37.111, 127.1133); + Coordinate transformedCoord = transformCoordinate(sourceCoord, "EPSG:4326", "EPSG:5181"); + System.out.println("Transformed Coordinate1: " + transformedCoord); + Coordinate transformedCoord2 = transformCoordinate(transformedCoord, "EPSG:5181", "EPSG:4326"); + System.out.println("Transformed Coordinate2: " + transformedCoord2); + } catch (Exception e) { + e.printStackTrace(); + } } + }