|
|
@ -6,13 +6,16 @@ import lombok.*; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
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.referencing.CRS; |
|
|
|
|
|
|
|
import org.geotools.referencing.GeodeticCalculator; |
|
|
|
import org.json.simple.JSONArray; |
|
|
|
import org.json.simple.JSONArray; |
|
|
|
import org.json.simple.JSONObject; |
|
|
|
import org.json.simple.JSONObject; |
|
|
|
import org.json.simple.parser.JSONParser; |
|
|
|
import org.json.simple.parser.JSONParser; |
|
|
|
import org.locationtech.jts.geom.Coordinate; |
|
|
|
import org.locationtech.jts.geom.*; |
|
|
|
import org.locationtech.jts.geom.Geometry; |
|
|
|
|
|
|
|
import org.locationtech.jts.geom.GeometryFactory; |
|
|
|
|
|
|
|
import org.opengis.feature.simple.SimpleFeature; |
|
|
|
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.Resource; |
|
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
|
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
|
|
|
import org.springframework.core.io.support.ResourcePatternResolver; |
|
|
|
import org.springframework.core.io.support.ResourcePatternResolver; |
|
|
@ -85,7 +88,9 @@ public class AirAreaUtils { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO 초기화
|
|
|
|
/** |
|
|
|
|
|
|
|
* 초기화 |
|
|
|
|
|
|
|
*/ |
|
|
|
private void init() { |
|
|
|
private void init() { |
|
|
|
airAreaMap = new HashMap<>(); |
|
|
|
airAreaMap = new HashMap<>(); |
|
|
|
geometryFactory = new GeometryFactory(); |
|
|
|
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) { |
|
|
|
public static void main(String[] args) { |
|
|
|