lkd9125(이경도)
7 months ago
13 changed files with 869 additions and 10 deletions
@ -0,0 +1,284 @@
|
||||
package kr.co.palnet.kac.api.util; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.geotools.geojson.feature.FeatureJSON; |
||||
import org.geotools.geojson.geom.GeometryJSON; |
||||
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.opengis.feature.simple.SimpleFeature; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
||||
import org.springframework.core.io.support.ResourcePatternResolver; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.math.BigDecimal; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
@Slf4j |
||||
public class AirspaceUtils { |
||||
|
||||
private final String CLASS_PATH = "air/elev2d"; |
||||
private final GeometryFactory geometryFactory = new GeometryFactory(); |
||||
private List<FeatureInfo> airspaces; |
||||
|
||||
|
||||
private AirspaceUtils() { |
||||
// 초기화
|
||||
log.info("===== AirspaceUtils init ====="); |
||||
this.loadResourceAirspace(); |
||||
} |
||||
|
||||
public static AirspaceUtils getInstance() { |
||||
return LazyHolder.INSTANCE; |
||||
} |
||||
|
||||
private static class LazyHolder { |
||||
private static final AirspaceUtils INSTANCE = new AirspaceUtils(); |
||||
} |
||||
|
||||
// 공영 중복 검사 - 고도x
|
||||
public boolean isDuplicatedAirspace(FeatureInfo target) { |
||||
Geometry targetGeometry = target.getGeometry(); |
||||
return this.airspaces.stream().anyMatch(featureInfo -> { |
||||
Geometry featureGeometry = featureInfo.getGeometry(); |
||||
return featureGeometry.intersects(targetGeometry); |
||||
}); |
||||
} |
||||
|
||||
// 공역 중복 검사
|
||||
public boolean isDuplicatedAirspaceElev(FeatureInfo target) { |
||||
if (this.airspaces == null || this.airspaces.isEmpty()) return true; |
||||
Integer targetHighElev = target.getHighElev(); |
||||
if (targetHighElev == null) targetHighElev = 0; |
||||
Geometry targetGeometry = target.getGeometry(); |
||||
|
||||
for (FeatureInfo airspace : this.airspaces) { |
||||
Integer airspaceHighElev = airspace.getHighElev(); |
||||
Geometry airspaceGeometry = airspace.getGeometry(); |
||||
|
||||
// 임시로 0~최대고도 기준으로 검증
|
||||
if (airspaceHighElev <= targetHighElev) { |
||||
if (airspaceGeometry.intersects(targetGeometry)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/* |
||||
LAANC 공역 검사 |
||||
- 비행구역이 공역(금지구역)에 접근할 경우만 검사 - 통과 true, 실패 false |
||||
- 겹치지 않을 경우는 실패로 처리 - false |
||||
*/ |
||||
public boolean isValidLaancAirspace(FeatureInfo target) { |
||||
if (this.airspaces == null || this.airspaces.isEmpty()) return true; |
||||
final int targetHighElev = target.getHighElev() != null ? target.getHighElev() : 0; |
||||
Geometry targetGeometry = target.getGeometry(); |
||||
|
||||
boolean isDuplicated = this.airspaces.stream().anyMatch(featureInfo -> { |
||||
Geometry featureGeometry = featureInfo.getGeometry(); |
||||
return featureGeometry.intersects(targetGeometry); |
||||
}); |
||||
// 공역(금지구역)과 겹치지 않을 경우는 실패로 처리
|
||||
if (!isDuplicated) return false; |
||||
|
||||
// 겹칠 경우 공역과 비교
|
||||
for (FeatureInfo featureInfo : this.airspaces) { |
||||
Geometry airspaceGeometry = featureInfo.getGeometry(); |
||||
int airspaceHighElev = featureInfo.getHighElev() != null ? featureInfo.getHighElev() : 0; |
||||
// 0~최대고도 기준으로 검증
|
||||
if (airspaceHighElev == 0 || airspaceHighElev < targetHighElev) { |
||||
if (airspaceGeometry.intersects(targetGeometry)) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
// get allowable elevation
|
||||
public Integer getAllowElevation(Geometry target) { |
||||
Integer allowElevation = null; |
||||
if (this.airspaces == null || this.airspaces.isEmpty()) return null; |
||||
// target과 겹치는 airspace 조회
|
||||
List<FeatureInfo> duplicationAirspace = this.airspaces.stream().filter(featureInfo -> { |
||||
Geometry featureGeometry = featureInfo.getGeometry(); |
||||
return featureGeometry.intersects(target); |
||||
}).collect(Collectors.toList()); |
||||
// 중복된 airspace가 없을 경우 기본 허용고도 반환 150m(관제권x)
|
||||
if (duplicationAirspace.isEmpty()) return 150; |
||||
allowElevation = duplicationAirspace.stream().map(FeatureInfo::getHighElev).min(Integer::compareTo).orElse(150); |
||||
return allowElevation; |
||||
} |
||||
|
||||
// convert coordiate to geometry
|
||||
public Geometry createGeometryByCoordinate(List<Coordinate> target) { |
||||
return this.createGeometryByCoordinate(target, "Polygon"); |
||||
} |
||||
|
||||
// convert coordiate to geometry
|
||||
public Geometry createGeometryByCoordinate(List<Coordinate> target, String type) { |
||||
Geometry geometry = null; |
||||
if ("Polygon".equals(type)) { |
||||
if (target == null || target.isEmpty()) return null; |
||||
log.info(">>> {}", target.get(0) != target.get(target.size() - 1)); |
||||
if (target.get(0) != target.get(target.size() - 1)) { |
||||
target.add(target.get(0)); |
||||
} |
||||
geometry = this.geometryFactory.createPolygon(target.toArray(new Coordinate[0])); |
||||
} else if ("LineString".equals(type)) { |
||||
geometry = this.geometryFactory.createLineString(target.toArray(new Coordinate[0])); |
||||
} else if ("Point".equals(type)) { |
||||
geometry = this.geometryFactory.createPoint(target.get(0)); |
||||
} |
||||
return geometry; |
||||
} |
||||
|
||||
// get geometry
|
||||
private List<Geometry> getAirspaceGeometry() { |
||||
return this.airspaces.stream().map(FeatureInfo::getGeometry).collect(Collectors.toList()); |
||||
} |
||||
|
||||
// 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화.
|
||||
private void loadResourceAirspace() { |
||||
|
||||
List<FeatureInfo> featureInfos = new ArrayList<>(); |
||||
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); |
||||
Resource[] resources = null; |
||||
try { |
||||
resources = resolver.getResources("classpath:" + CLASS_PATH + "/*-elev.json"); |
||||
} catch (IOException e) { |
||||
log.warn("airspaces load error : {}", e.getMessage()); |
||||
} |
||||
|
||||
if (resources == null) { |
||||
log.info("airspace resources is null"); |
||||
return; |
||||
} |
||||
|
||||
for (Resource resource : resources) { |
||||
try (InputStream is = resource.getInputStream()) { |
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); |
||||
JSONParser jsonParser = new JSONParser(); |
||||
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader); |
||||
List<FeatureInfo> fis = this.convertGeoJsonToGeometry(jsonObject); |
||||
featureInfos.addAll(fis); |
||||
} catch (Exception e) { |
||||
log.warn("airspace resource read error : {}", e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
log.info(">>> featureInfos size : {}", featureInfos.size()); |
||||
|
||||
this.airspaces = featureInfos; |
||||
} |
||||
|
||||
private List<FeatureInfo> convertGeoJsonToGeometry(JSONObject jsonObject) { |
||||
List<FeatureInfo> featureInfos = new ArrayList<>(); |
||||
String type = (String) jsonObject.get("type"); |
||||
if ("FeatureCollection".equals(type)) { |
||||
List<JSONObject> features = (List<JSONObject>) jsonObject.get("features"); |
||||
// log.debug(">>> features size : {}", features.size());
|
||||
for (JSONObject feature : features) { |
||||
JSONObject geometryObject = (JSONObject) feature.get("geometry"); |
||||
String geometryType = String.valueOf(geometryObject.get("type")); |
||||
|
||||
List<JSONObject> coordinatesObject = (List<JSONObject>) geometryObject.get("coordinates"); |
||||
if ("Polygon".equals(geometryType)) { |
||||
List<JSONArray> innerObject = (List<JSONArray>) coordinatesObject.get(0); |
||||
JSONArray firstCoords = innerObject.get(0); |
||||
JSONArray lastCoords = innerObject.get(innerObject.size() - 1); |
||||
BigDecimal ff = new BigDecimal(String.valueOf(firstCoords.get(0))); |
||||
BigDecimal fl = new BigDecimal(String.valueOf(firstCoords.get(1))); |
||||
BigDecimal lf = new BigDecimal(String.valueOf(lastCoords.get(0))); |
||||
BigDecimal ll = new BigDecimal(String.valueOf(lastCoords.get(1))); |
||||
if (!ff.equals(lf) || !fl.equals(ll)) { |
||||
JSONObject propertiesObject = (JSONObject) feature.get("properties"); |
||||
// String nameObject = String.valueOf(propertiesObject.get("name"));
|
||||
// String descriptionObject = String.valueOf(propertiesObject.get("description"));
|
||||
// log.info("coords first and last coords not eqauls : name/descriion = {}/{}", nameObject, descriptionObject);
|
||||
innerObject.add(firstCoords); |
||||
} |
||||
} |
||||
|
||||
try { |
||||
FeatureJSON featureJSON = new FeatureJSON(); |
||||
SimpleFeature simpleFeature = null; |
||||
simpleFeature = featureJSON.readFeature(feature.toJSONString()); |
||||
Boolean use = Boolean.valueOf(String.valueOf(simpleFeature.getAttribute("use"))); |
||||
if (use) { |
||||
String name = String.valueOf(simpleFeature.getAttribute("name")); |
||||
String description = String.valueOf(simpleFeature.getAttribute("description")); |
||||
Integer lowElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("lowElev"))); |
||||
Integer highElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("highElev"))); |
||||
Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry(); |
||||
// log.debug(">>> name, description, use, lowElev, highElev : {}, {}, {}, {}, {}", name, description, use, lowElev, highElev);
|
||||
FeatureInfo info = new FeatureInfo(name, description, lowElev, highElev, geometry); |
||||
featureInfos.add(info); |
||||
} |
||||
} catch (IOException e) { |
||||
log.error("geometry json read error : {}", e.getMessage()); |
||||
} |
||||
} |
||||
} else if ("Feature".equals(type)) { |
||||
FeatureJSON featureJSON = new FeatureJSON(); |
||||
try { |
||||
SimpleFeature simpleFeature = featureJSON.readFeature(jsonObject.toJSONString()); |
||||
Boolean use = Boolean.valueOf(String.valueOf(simpleFeature.getAttribute("use"))); |
||||
if (use) { |
||||
String name = String.valueOf(simpleFeature.getAttribute("name")); |
||||
String description = String.valueOf(simpleFeature.getAttribute("description")); |
||||
Integer lowElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("lowElev"))); |
||||
Integer highElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("highElev"))); |
||||
Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry(); |
||||
FeatureInfo info = new FeatureInfo(name, description, lowElev, highElev, geometry); |
||||
featureInfos.add(info); |
||||
} |
||||
} catch (IOException e) { |
||||
log.error("geometry json read error : {}", e.getMessage()); |
||||
} |
||||
|
||||
} else { |
||||
GeometryJSON geoJson = new GeometryJSON(); |
||||
try { |
||||
Geometry geometry = geoJson.read(jsonObject.toJSONString()); |
||||
FeatureInfo info = new FeatureInfo(null, null, null, null, geometry); |
||||
} catch (IOException e) { |
||||
log.error("geometry json read error : {}", e.getMessage()); |
||||
} |
||||
} |
||||
return featureInfos; |
||||
} |
||||
|
||||
public int getSize() { |
||||
if(this.airspaces == null) return 0; |
||||
return this.airspaces.size(); |
||||
} |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
public static class FeatureInfo { |
||||
private String name; |
||||
private String description; |
||||
private Integer lowElev; |
||||
private Integer highElev; |
||||
private Geometry geometry; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,344 @@
|
||||
package kr.co.palnet.kac.api.util; |
||||
|
||||
import kr.co.palnet.kac.api.util.model.FlightPlanAreaCoordModel; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.json.simple.JSONArray; |
||||
import org.json.simple.JSONObject; |
||||
import org.json.simple.parser.JSONParser; |
||||
import org.locationtech.jts.geom.*; |
||||
import org.locationtech.jts.operation.buffer.BufferOp; |
||||
import org.locationtech.jts.operation.buffer.BufferParameters; |
||||
import org.locationtech.jts.util.GeometricShapeFactory; |
||||
import org.locationtech.proj4j.BasicCoordinateTransform; |
||||
import org.locationtech.proj4j.CRSFactory; |
||||
import org.locationtech.proj4j.CoordinateReferenceSystem; |
||||
import org.locationtech.proj4j.ProjCoordinate; |
||||
import org.springframework.cache.annotation.Cacheable; |
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
@Component |
||||
@Slf4j |
||||
public class AreaUtils { |
||||
|
||||
private List<Polygon> polygons = new ArrayList<>(); |
||||
private List<Point> points = new ArrayList<>(); |
||||
|
||||
private GeometryFactory geometryFactory = new GeometryFactory(); |
||||
|
||||
public AreaUtils() throws Exception { |
||||
this.init(); |
||||
} |
||||
|
||||
/** |
||||
* TODO 좌표계 변환 |
||||
* |
||||
* @param coordList |
||||
* @return |
||||
*/ |
||||
@Cacheable(value = "coordTransform") |
||||
public List<Coordinate> transform(List<Coordinate> coordList, String from, String to) { |
||||
CRSFactory factory = new CRSFactory(); |
||||
|
||||
CoordinateReferenceSystem srcCRS = factory.createFromName(from); |
||||
CoordinateReferenceSystem tgtCRS = factory.createFromName(to); |
||||
|
||||
BasicCoordinateTransform transform = new BasicCoordinateTransform(srcCRS, tgtCRS); |
||||
|
||||
List<Coordinate> result = new ArrayList<>(); |
||||
|
||||
for(Coordinate coord : coordList) { |
||||
ProjCoordinate projCoordinate = new ProjCoordinate(coord.getX(), coord.getY()); |
||||
ProjCoordinate projTrasform = transform.transform(projCoordinate, new ProjCoordinate()); |
||||
|
||||
Coordinate target = new Coordinate(projTrasform.x, projTrasform.y); |
||||
|
||||
result.add(target); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* TODO 비행 구역 생성시 장애물 영역 포함 체크 |
||||
* |
||||
* @param targetCoordList - 비행구역 좌표 리스트 |
||||
* @return boolean - true(비정상), false(정상) |
||||
*/ |
||||
public boolean overlaps(List<Coordinate> targetCoordList) { |
||||
boolean result = false; |
||||
targetCoordList.add(targetCoordList.get(0)); |
||||
Polygon targetPolygon = geometryFactory.createPolygon(targetCoordList.toArray(new Coordinate[] {})); |
||||
|
||||
/* 공역 데이터 */ |
||||
if(polygons.size() > 0) { |
||||
for(Polygon polygon : polygons) { |
||||
Geometry overlabsGeometry = geometryFactory.createGeometry(polygon); |
||||
Geometry targetGeometry = geometryFactory.createGeometry(targetPolygon); |
||||
|
||||
boolean over = targetPolygon.overlaps(polygon); |
||||
|
||||
if(over) { |
||||
result = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* TODO 구역 포함 여부 |
||||
* |
||||
* @param targetCoordList - 생성 구역 |
||||
* @param effectiveCoordList - 유효한 비행 구역 |
||||
* @return boolean - true(비정상), false(정상) |
||||
*/ |
||||
public boolean overlaps(List<Coordinate> targetCoordList, List<Coordinate> effectiveCoordList) { |
||||
targetCoordList.add(targetCoordList.get(0)); |
||||
Polygon targetPolygon = geometryFactory.createPolygon(targetCoordList.toArray(new Coordinate[] {})); |
||||
|
||||
effectiveCoordList.add(effectiveCoordList.get(0)); |
||||
Polygon effectivePolygon = geometryFactory.createPolygon(effectiveCoordList.toArray(new Coordinate[] {})); |
||||
|
||||
return targetPolygon.overlaps(effectivePolygon); |
||||
} |
||||
|
||||
/** |
||||
* TODO 드론 관제시 정상 비행 체크 (공역) |
||||
* |
||||
* @param targetCoordinate - 드론 좌표 정보 |
||||
* @return boolean - true(비정상), false(정상) |
||||
*/ |
||||
public boolean contains(Coordinate targetCoordinate) { |
||||
boolean result = true; |
||||
|
||||
Point target = geometryFactory.createPoint(targetCoordinate); |
||||
|
||||
for(Polygon polygon : polygons) { |
||||
boolean contains = polygon.contains(target); |
||||
|
||||
if(contains) { |
||||
result = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* TODO 드론 관제시 정상 비행 체크 (비행 구역) |
||||
* |
||||
* @param areaCoordList - 비행 구역 좌표 리스트 |
||||
* @param targetCoordinate - 드론 좌표 정보 |
||||
* @return boolean - true(비정상), false(정상) |
||||
*/ |
||||
public boolean contains(List<Coordinate> areaCoordList, Coordinate targetCoordinate) { |
||||
boolean result = true; |
||||
areaCoordList.add(areaCoordList.get(0)); |
||||
if(targetCoordinate != null) { |
||||
Polygon plan = geometryFactory.createPolygon(areaCoordList.toArray(new Coordinate[]{})); // 비행 구역
|
||||
Point target = geometryFactory.createPoint(targetCoordinate); |
||||
|
||||
result = plan.contains(target); |
||||
// target.contains(plan);
|
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* TODO 비행 구역 - Buffer 영역 생성 |
||||
* |
||||
* @param coordList - 비행 구역 기초 좌표 리스트 |
||||
* @param bufferZone - 반경 |
||||
* |
||||
*/ |
||||
public List<Coordinate> buffer(List<Coordinate> coordList, double bufferZone) { |
||||
List<Coordinate> bufferList = new ArrayList<>(); |
||||
|
||||
LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[] {})); |
||||
Geometry geometry = geometryFactory.createGeometry(line); |
||||
|
||||
// buffer
|
||||
int nSegments = 10; |
||||
int cap = BufferParameters.CAP_SQUARE; |
||||
int join = BufferParameters.JOIN_ROUND; |
||||
|
||||
BufferParameters bufferParam = new BufferParameters(nSegments, cap, join, join); |
||||
BufferOp ops = new BufferOp(geometry, bufferParam); |
||||
|
||||
// Geometry bufTrans = ops.getResultGeometry((bufferZone/177763.63662580872)*2);
|
||||
Geometry bufTrans = ops.getResultGeometry(bufferZone); |
||||
|
||||
Coordinate[] coords = bufTrans.getCoordinates(); |
||||
|
||||
bufferList.addAll(Arrays.asList(coords)); |
||||
|
||||
return bufferList; |
||||
} |
||||
|
||||
/** |
||||
* TODO 타원 생성 |
||||
* |
||||
* @param CircleCoord |
||||
* @param BufferZone |
||||
* @return |
||||
*/ |
||||
public List<Coordinate> createCircle(Coordinate CircleCoord, double BufferZone) { |
||||
GeometricShapeFactory shapeFactory = new GeometricShapeFactory(); |
||||
|
||||
double lng = CircleCoord.x; |
||||
double lat = CircleCoord.y; |
||||
double diameterInMeters = BufferZone; |
||||
|
||||
shapeFactory.setCentre(new Coordinate(lng , lat)); |
||||
shapeFactory.setHeight((diameterInMeters * 2) / 111320d); |
||||
shapeFactory.setWidth((diameterInMeters * 2) / (40075000 * Math.cos(Math.toRadians(lat)) / 360)); |
||||
shapeFactory.setNumPoints(64); |
||||
|
||||
final Polygon circle = shapeFactory.createCircle(); |
||||
circle.setSRID(4326); |
||||
|
||||
Geometry geometry = geometryFactory.createGeometry(circle); |
||||
Coordinate[] coords = geometry.getCoordinates(); |
||||
List<Coordinate> coordList = new ArrayList<>(); |
||||
coordList.addAll(Arrays.asList(coords)); |
||||
|
||||
return coordList; |
||||
} |
||||
|
||||
/** |
||||
* TODO service model -> jts model mapping |
||||
* |
||||
* @param coordList |
||||
* @return |
||||
*/ |
||||
public List<Coordinate> convertCoordinates(List<FlightPlanAreaCoordModel> coordList) { |
||||
List<Coordinate> coordinates = new ArrayList<>(); |
||||
|
||||
for(FlightPlanAreaCoordModel coord : coordList) { |
||||
Coordinate coordinate = new Coordinate(coord.getLon(), coord.getLat()); |
||||
|
||||
coordinates.add(coordinate); |
||||
} |
||||
|
||||
return coordinates; |
||||
} |
||||
|
||||
/** |
||||
* TODO jts model -> service model mapiing |
||||
* |
||||
* @param bufferList |
||||
* @return |
||||
*/ |
||||
public List<FlightPlanAreaCoordModel> convertModel(List<Coordinate> bufferList) { |
||||
List<FlightPlanAreaCoordModel> bufferCoordList = new ArrayList<>(); |
||||
|
||||
for(Coordinate buffer : bufferList) { |
||||
FlightPlanAreaCoordModel bufferCoord = new FlightPlanAreaCoordModel(); |
||||
|
||||
bufferCoord.setLat(buffer.getY()); |
||||
bufferCoord.setLon(buffer.getX()); |
||||
|
||||
bufferCoordList.add(bufferCoord); |
||||
} |
||||
|
||||
return bufferCoordList; |
||||
} |
||||
|
||||
// TODO 공역 데이터 생성
|
||||
public void init() throws Exception { |
||||
// 1. file read
|
||||
ClassPathResource resource = new ClassPathResource("air/airgeo.json"); |
||||
InputStream jsonInputStream = resource.getInputStream(); |
||||
InputStreamReader inputStreamReader = new InputStreamReader(jsonInputStream, "UTF-8"); |
||||
BufferedReader reader = new BufferedReader(inputStreamReader); |
||||
|
||||
// 2. json parsing
|
||||
JSONParser jsonParser = new JSONParser(); |
||||
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader); |
||||
|
||||
List<JSONObject> features = (List<JSONObject>) jsonObject.get("features"); |
||||
|
||||
for(int i=0; i<features.size(); i++) { |
||||
JSONObject geometry = (JSONObject) features.get(i).get("geometry"); |
||||
|
||||
List<JSONArray> coordinates = (List<JSONArray>) geometry.get("coordinates"); |
||||
String type = (String) geometry.get("type"); |
||||
|
||||
if("Polygon".equals(type)) { |
||||
for(JSONArray coordList : coordinates) { |
||||
List<Coordinate> polygonPaths = new ArrayList<>(); |
||||
|
||||
for(Object coord : coordList) { |
||||
Object y = ((JSONArray) coord).get(0); |
||||
Object x = ((JSONArray) coord).get(1); |
||||
|
||||
Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y); |
||||
Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x); |
||||
|
||||
Coordinate areaCoord = new Coordinate(lon, lat); |
||||
|
||||
polygonPaths.add(areaCoord); |
||||
} |
||||
|
||||
Polygon polygon = geometryFactory.createPolygon(polygonPaths.toArray(new Coordinate[] {})); |
||||
|
||||
polygons.add(polygon); |
||||
} |
||||
} |
||||
|
||||
if("LineString".equals(type)) { |
||||
List<Coordinate> lineStringPaths = new ArrayList<>(); |
||||
for(JSONArray coordList : coordinates) { |
||||
|
||||
Object y = coordList.get(0); |
||||
Object x = coordList.get(1); |
||||
|
||||
Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y); |
||||
Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x); |
||||
|
||||
Coordinate areaCoord = new Coordinate(lon, lat); |
||||
|
||||
lineStringPaths.add(areaCoord); |
||||
} |
||||
|
||||
Polygon polygon = geometryFactory.createPolygon(lineStringPaths.toArray(new Coordinate[] {})); |
||||
|
||||
polygons.add(polygon); |
||||
} |
||||
|
||||
if("Point".equals(type)) { |
||||
Object y = coordinates.get(0); |
||||
Object x = coordinates.get(1); |
||||
|
||||
Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y); |
||||
Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x); |
||||
|
||||
Coordinate areaCoord = new Coordinate(lon, lat); |
||||
|
||||
Point point = geometryFactory.createPoint(areaCoord); |
||||
points.add(point); |
||||
} |
||||
} |
||||
} |
||||
public Geometry coordinateToGeometry(List<Coordinate> target) { |
||||
if (target == null || target.isEmpty()) return null; |
||||
log.info(">>> {}", target.get(0) != target.get(target.size() - 1)); |
||||
if (target.get(0) != target.get(target.size() - 1)) { |
||||
target.add(target.get(0)); |
||||
} |
||||
return geometryFactory.createPolygon(target.toArray(new Coordinate[]{})); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,22 @@
|
||||
package kr.co.palnet.kac.api.util.model; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
@Data |
||||
public class FlightPlanAreaCoordModel { |
||||
private Integer planAreaCoordSno; |
||||
private Integer planAreaSno; |
||||
@Schema(description = "x 좌표", example = "37.5208864") |
||||
private double lat; |
||||
@Schema(description = "y 좌표", example = "126.6071164") |
||||
private double lon; |
||||
@Schema(hidden = true) |
||||
private String createUserId; |
||||
@Schema(hidden = true) |
||||
private LocalDateTime createDt; |
||||
@Schema(hidden = true) |
||||
private String docState = "R"; |
||||
} |
@ -0,0 +1,11 @@
|
||||
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class LaancAllowableElevationRS { |
||||
|
||||
private List<Integer> allowableElevation; |
||||
} |
@ -0,0 +1,21 @@
|
||||
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class LaancAreaByAirspaceModel { |
||||
|
||||
@Schema(description = "구역종류", example = "CIRCLE") |
||||
private String areaType; |
||||
|
||||
@Schema(description = "버퍼존", example = "100") |
||||
private Integer bufferZone; |
||||
|
||||
@Schema(description = "고도", example = "110") |
||||
private String fltElev; |
||||
|
||||
private List<LaancAreaCoordModel> coordList; |
||||
} |
@ -0,0 +1,19 @@
|
||||
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class LaancAreaByElevModel { |
||||
|
||||
@Schema(description = "구역종류", example = "CIRCLE") |
||||
private String areaType; |
||||
|
||||
@Schema(description = "버퍼존", example = "100") |
||||
private Integer bufferZone; |
||||
|
||||
private List<LaancAreaCoordModel> coordList; |
||||
|
||||
} |
@ -0,0 +1,14 @@
|
||||
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class LaancAreaCoordModel { |
||||
|
||||
@Schema(description = "위도", example = "127.33") |
||||
private double lat; |
||||
|
||||
@Schema(description = "경도", example = "37.99") |
||||
private double lon; |
||||
} |
@ -0,0 +1,15 @@
|
||||
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
@Builder |
||||
public class LaancDuplicatedAirspaceRs { |
||||
private boolean isDuplicated; |
||||
private LaancAreaByAirspaceModel rq; |
||||
} |
Loading…
Reference in new issue