|
|
@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.geotools.geojson.feature.FeatureJSON; |
|
|
|
import org.geotools.geojson.feature.FeatureJSON; |
|
|
|
import org.geotools.geojson.geom.GeometryJSON; |
|
|
|
import org.geotools.geojson.geom.GeometryJSON; |
|
|
|
import org.geotools.geometry.jts.JTS; |
|
|
|
import org.geotools.geometry.jts.JTS; |
|
|
|
|
|
|
|
import org.geotools.geometry.jts.JTSFactoryFinder; |
|
|
|
import org.geotools.referencing.CRS; |
|
|
|
import org.geotools.referencing.CRS; |
|
|
|
import org.geotools.referencing.GeodeticCalculator; |
|
|
|
import org.geotools.referencing.GeodeticCalculator; |
|
|
|
import org.json.simple.JSONArray; |
|
|
|
import org.json.simple.JSONArray; |
|
|
@ -20,7 +21,9 @@ import org.locationtech.proj4j.BasicCoordinateTransform; |
|
|
|
import org.locationtech.proj4j.CRSFactory; |
|
|
|
import org.locationtech.proj4j.CRSFactory; |
|
|
|
import org.locationtech.proj4j.ProjCoordinate; |
|
|
|
import org.locationtech.proj4j.ProjCoordinate; |
|
|
|
import org.opengis.feature.simple.SimpleFeature; |
|
|
|
import org.opengis.feature.simple.SimpleFeature; |
|
|
|
|
|
|
|
import org.opengis.referencing.FactoryException; |
|
|
|
import org.opengis.referencing.crs.CoordinateReferenceSystem; |
|
|
|
import org.opengis.referencing.crs.CoordinateReferenceSystem; |
|
|
|
|
|
|
|
import org.opengis.referencing.operation.MathTransform; |
|
|
|
import org.opengis.referencing.operation.TransformException; |
|
|
|
import org.opengis.referencing.operation.TransformException; |
|
|
|
import org.springframework.cache.annotation.Cacheable; |
|
|
|
import org.springframework.cache.annotation.Cacheable; |
|
|
|
import org.springframework.core.io.Resource; |
|
|
|
import org.springframework.core.io.Resource; |
|
|
@ -41,6 +44,7 @@ import java.util.stream.Collectors; |
|
|
|
@Slf4j |
|
|
|
@Slf4j |
|
|
|
public class AirAreaUtils { |
|
|
|
public class AirAreaUtils { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final int PERIMETER_OF_EARTH = 40075 * 1000; // 지구 둘레(m)
|
|
|
|
private final String RESOURCE_BASE_PATH = "air/airspace/"; |
|
|
|
private final String RESOURCE_BASE_PATH = "air/airspace/"; |
|
|
|
private final String COMMON_PATH = "common/"; |
|
|
|
private final String COMMON_PATH = "common/"; |
|
|
|
private final String CUSTOM_PATH = "custom/"; |
|
|
|
private final String CUSTOM_PATH = "custom/"; |
|
|
@ -663,9 +667,15 @@ public class AirAreaUtils { |
|
|
|
return originalGeometry; // Return the original geometry if type is not handled
|
|
|
|
return originalGeometry; // Return the original geometry if type is not handled
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static List<Coordinate> swapCoordinates(List<Coordinate> originalCoordinates) { |
|
|
|
|
|
|
|
return originalCoordinates.stream().map(coordinate -> new Coordinate(coordinate.y, coordinate.x)).collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ---------------------- AreaUtils ----------------------
|
|
|
|
// ---------------------- AreaUtils ----------------------
|
|
|
|
|
|
|
|
|
|
|
|
// TODO 버퍼 생성시 임의로 좌표변환을 해야만 하는지 확인 ex) espg:4326 -> espg:5181 -> espg:4326
|
|
|
|
// TODO 버퍼 생성시 임의로 좌표변환을 해야만 하는지 확인 ex) espg:4326 -> espg:5181 -> espg:4326
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 좌표계 변환 |
|
|
|
* 좌표계 변환 |
|
|
|
* |
|
|
|
* |
|
|
@ -685,7 +695,7 @@ public class AirAreaUtils { |
|
|
|
|
|
|
|
|
|
|
|
List<Coordinate> result = new ArrayList<>(); |
|
|
|
List<Coordinate> result = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
for(Coordinate coord : coordList) { |
|
|
|
for (Coordinate coord : coordList) { |
|
|
|
ProjCoordinate projCoordinate = new ProjCoordinate(coord.getX(), coord.getY()); |
|
|
|
ProjCoordinate projCoordinate = new ProjCoordinate(coord.getX(), coord.getY()); |
|
|
|
ProjCoordinate projTrasform = transform.transform(projCoordinate, new ProjCoordinate()); |
|
|
|
ProjCoordinate projTrasform = transform.transform(projCoordinate, new ProjCoordinate()); |
|
|
|
|
|
|
|
|
|
|
@ -706,7 +716,7 @@ public class AirAreaUtils { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public List<Coordinate> buffer(List<Coordinate> coordList, double bufferZone) { |
|
|
|
public List<Coordinate> buffer(List<Coordinate> coordList, double bufferZone) { |
|
|
|
|
|
|
|
|
|
|
|
LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[] {})); |
|
|
|
LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[]{})); |
|
|
|
Geometry geometry = geometryFactory.createGeometry(line); |
|
|
|
Geometry geometry = geometryFactory.createGeometry(line); |
|
|
|
|
|
|
|
|
|
|
|
// buffer
|
|
|
|
// buffer
|
|
|
@ -726,6 +736,7 @@ public class AirAreaUtils { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO 곡률로 구성된 원 생성방법 확인(타원이 아닌)
|
|
|
|
// TODO 곡률로 구성된 원 생성방법 확인(타원이 아닌)
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 타원 생성 |
|
|
|
* 타원 생성 |
|
|
|
* |
|
|
|
* |
|
|
@ -740,9 +751,9 @@ public class AirAreaUtils { |
|
|
|
double lat = CircleCoord.y; |
|
|
|
double lat = CircleCoord.y; |
|
|
|
double diameterInMeters = BufferZone; |
|
|
|
double diameterInMeters = BufferZone; |
|
|
|
|
|
|
|
|
|
|
|
shapeFactory.setCentre(new Coordinate(lng , lat)); |
|
|
|
shapeFactory.setCentre(new Coordinate(lng, lat)); |
|
|
|
shapeFactory.setHeight((diameterInMeters * 2) / 111320d); |
|
|
|
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); |
|
|
|
shapeFactory.setNumPoints(64); |
|
|
|
|
|
|
|
|
|
|
|
final Polygon circle = shapeFactory.createCircle(); |
|
|
|
final Polygon circle = shapeFactory.createCircle(); |
|
|
@ -756,43 +767,86 @@ public class AirAreaUtils { |
|
|
|
return coordList; |
|
|
|
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(); |
|
|
|
MathTransform transformTo3857 = CRS.findMathTransform(crs4326, crs3857); |
|
|
|
log.info("utils: {}", utils); |
|
|
|
MathTransform transformTo4326 = CRS.findMathTransform(crs3857, crs4326); |
|
|
|
|
|
|
|
|
|
|
|
// AirAreaUtils utils2 = AirAreaUtils.getInstance();
|
|
|
|
// GeometryFactory 생성
|
|
|
|
// log.info("utils2: {}", utils2);
|
|
|
|
GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(); |
|
|
|
// log.info("utils == utils2: {}", utils == utils2);
|
|
|
|
|
|
|
|
//
|
|
|
|
// LineString 좌표 정의 (EPSG:4326)
|
|
|
|
// List<Integer> list = List.of(1, 2, 3, 4, 5);
|
|
|
|
Coordinate[] coordinates = new Coordinate[]{ |
|
|
|
// boolean b = list.stream().anyMatch(i -> i == 3);
|
|
|
|
|
|
|
|
// log.info("b:: {}", b);
|
|
|
|
|
|
|
|
// List<Integer> list2 = new ArrayList<>();
|
|
|
|
|
|
|
|
// boolean b2 = list2.stream().anyMatch(i -> i == 3);
|
|
|
|
|
|
|
|
// log.info("b2:: {}", b2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map<AirAreaType, List<FeatureInfo>> airMap = utils.getAirAreaMap(); |
|
|
|
|
|
|
|
airMap.forEach((k, v) -> { |
|
|
|
|
|
|
|
log.info("{} - {}", k, v.size()); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Coordinate> beforeCoordinates = List.of( |
|
|
|
|
|
|
|
new Coordinate(126.0, 37.0), |
|
|
|
|
|
|
|
new Coordinate(126.0, 38.0), |
|
|
|
|
|
|
|
new Coordinate(127.0, 38.0), |
|
|
|
|
|
|
|
new Coordinate(127.0, 37.0), |
|
|
|
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<Coordinate> 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<de.micromata.opengis.kml.v_2_2_0.Coordinate> 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<Coordinate> transCoordList = utils.transform(beforeCoordinates, "EPSG:4326", "EPSG:5181"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Coordinate> 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<Coordinate> transBufferList = utils.transform(bufferList, "EPSG:5181", "EPSG:4326"); // buffer 영역 좌표계 변환
|
|
|
|
// MathTransform 객체 생성
|
|
|
|
log.info("transBufferList: {}", transBufferList); |
|
|
|
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(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|