From a333551effb328efdb127913b1e390039541e131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Thu, 21 Sep 2023 15:03:41 +0900 Subject: [PATCH] =?UTF-8?q?LAANC=20=EA=B8=B0=EC=A4=80=20=EB=B0=94=EB=80=9C?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flight/model/BasFlightPlanLaancRs.java | 6 +- .../bas/flight/service/BasFlightService.java | 16 +- .../com/palnet/comn/utils/AirspaceUtils.java | 139 ++++++++++++------ 3 files changed, 111 insertions(+), 50 deletions(-) diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java index 747205ea..85307d60 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java @@ -25,13 +25,15 @@ public class BasFlightPlanLaancRs { private String acrftInsuranceYn; // 항공기보험여부 private String acrftDuplicatedYn; // 기체 중복여부 private String planAreaDuplicatdYn; // 비행계획서비행구역 중복여부 - private String airspaceDuplicatedYn; // 공역 중복여부 + private String evaluatedTargetAreaYn; // 평가대상지역여부 - 공역과 겹칠때만 + private String flightAreaYn; // LAANC 기준 비행가능여부 public boolean isValid() { return "Y".equals(pilotQlfcYn) && "Y".equals(acrftInsuranceYn) && "N".equals(acrftDuplicatedYn) && "N".equals(planAreaDuplicatdYn) - && "N".equals(airspaceDuplicatedYn); + && "Y".equals(evaluatedTargetAreaYn) + && "Y".equals(flightAreaYn); } } diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java index 208d471b..c661eb7c 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java @@ -151,9 +151,10 @@ public class BasFlightService { BasFlightPlanLaancRs rs = BasFlightPlanLaancRs.builder() .pilotQlfcYn("N") .acrftInsuranceYn("N") - .airspaceDuplicatedYn("N") .acrftDuplicatedYn("N") .planAreaDuplicatdYn("N") + .evaluatedTargetAreaYn("N") + .flightAreaYn("N") .build(); boolean isEqualsFltElev = false; @@ -295,8 +296,19 @@ public class BasFlightService { Integer fltElev = Integer.valueOf(rqArea.getFltElev()); if(fltElev == null) fltElev = 0; AirspaceUtils.FeatureInfo featureInfo = new AirspaceUtils.FeatureInfo(null, null, 0, fltElev, rqGeometry); + + // 평가 가능 지역 판단 boolean duplicatedAirspace = airspaceUtils.isDuplicatedAirspace(featureInfo); - rs.setAirspaceDuplicatedYn(duplicatedAirspace ? "Y" : "N"); + rs.setEvaluatedTargetAreaYn(duplicatedAirspace ? "Y" : "N"); + + // 비행 가능 지역 판단 + if(duplicatedAirspace){ + boolean validLaancAirspace = airspaceUtils.isValidLaancAirspace(featureInfo); + rs.setFlightAreaYn(validLaancAirspace ? "Y" : "N"); + } else { + rs.setFlightAreaYn("N"); + } + } return rs; } diff --git a/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java index 80bfb004..6a37fb9e 100644 --- a/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java +++ b/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.util.modeler.FeatureInfo; import org.geotools.geojson.feature.FeatureJSON; import org.geotools.geojson.geom.GeometryJSON; import org.json.simple.JSONArray; @@ -56,8 +57,17 @@ public class AirspaceUtils { 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; @@ -68,16 +78,47 @@ public class AirspaceUtils { Geometry airspaceGeometry = airspace.getGeometry(); // 임시로 0~최대고도 기준으로 검증 - if(airspaceHighElev <= targetHighElev) { + 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; + } + + public Geometry createGeometryByCoordinate(List target) { return this.createGeometryByCoordinate(target, "Polygon"); } @@ -102,11 +143,9 @@ public class AirspaceUtils { // 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화. private void getResourceAirspace() { ClassPathResource resource = new ClassPathResource(CLASS_PATH); - log.debug(">>> {}", resource); List geoJsonFiles = new ArrayList<>(); try { File folder = resource.getFile(); - log.debug(">>> {}", folder); File[] files = folder.listFiles(); for (File file : files) { if (file.isFile() && file.getName().endsWith("elev.json")) { @@ -120,7 +159,6 @@ public class AirspaceUtils { List featureInfos = new ArrayList<>(); for (File file : geoJsonFiles) { - log.debug("============ {} ===================", file.getName()); try (InputStreamReader isr = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { JSONParser jsonParser = new JSONParser(); JSONObject jsonObject = (JSONObject) jsonParser.parse(isr); @@ -253,12 +291,13 @@ public class AirspaceUtils { */ + log.info("=== 김포 정상 ==="); Coordinate[] polygonCoordinates6 = new Coordinate[]{ - new Coordinate(126.6186219,37.4260888), - new Coordinate(126.7662507,37.4473521), - new Coordinate(126.7223054,37.3578964), - new Coordinate(126.6186219,37.4260888) + new Coordinate(126.6186219, 37.4260888), + new Coordinate(126.7662507, 37.4473521), + new Coordinate(126.7223054, 37.3578964), + new Coordinate(126.6186219, 37.4260888) }; LinearRing linearRing6 = geometryFactory.createLinearRing(polygonCoordinates6); Polygon polygon6 = geometryFactory.createPolygon(linearRing6); @@ -266,15 +305,16 @@ public class AirspaceUtils { target6.setHighElev(0); target6.setLowElev(0); target6.setGeometry(polygon6); - boolean duplicatedAirspace6 = airspaceUtils.isDuplicatedAirspace(target6); +// boolean duplicatedAirspace6 = airspaceUtils.isDuplicatedAirspace(target6); + boolean duplicatedAirspace6 = airspaceUtils.isValidLaancAirspace(target6); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace6); log.info("=== 김포 120m 걸침 - 100 ==="); Coordinate[] polygonCoordinates7 = new Coordinate[]{ - new Coordinate(126.6828233,37.4553499), - new Coordinate(126.7456514,37.5082038), - new Coordinate(126.7796403,37.4414491), - new Coordinate(126.6828233,37.4553499) + new Coordinate(126.6828233, 37.4553499), + new Coordinate(126.7456514, 37.5082038), + new Coordinate(126.7796403, 37.4414491), + new Coordinate(126.6828233, 37.4553499) }; LinearRing linearRing7 = geometryFactory.createLinearRing(polygonCoordinates7); Polygon polygon7 = geometryFactory.createPolygon(linearRing7); @@ -282,15 +322,16 @@ public class AirspaceUtils { target7.setHighElev(100); target7.setLowElev(0); target7.setGeometry(polygon7); - boolean duplicatedAirspace7 = airspaceUtils.isDuplicatedAirspace(target7); +// boolean duplicatedAirspace7 = airspaceUtils.isDuplicatedAirspace(target7); + boolean duplicatedAirspace7 = airspaceUtils.isValidLaancAirspace(target7); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace7); log.info("=== 김포 120m 걸침 - 150 ==="); Coordinate[] polygonCoordinates8 = new Coordinate[]{ - new Coordinate(126.6828233,37.4553499), - new Coordinate(126.7456514,37.5082038), - new Coordinate(126.7796403,37.4414491), - new Coordinate(126.6828233,37.4553499) + new Coordinate(126.6828233, 37.4553499), + new Coordinate(126.7456514, 37.5082038), + new Coordinate(126.7796403, 37.4414491), + new Coordinate(126.6828233, 37.4553499) }; LinearRing linearRing8 = geometryFactory.createLinearRing(polygonCoordinates8); Polygon polygon8 = geometryFactory.createPolygon(linearRing8); @@ -298,15 +339,16 @@ public class AirspaceUtils { target8.setHighElev(150); target8.setLowElev(0); target8.setGeometry(polygon8); - boolean duplicatedAirspace8 = airspaceUtils.isDuplicatedAirspace(target8); +// boolean duplicatedAirspace8 = airspaceUtils.isDuplicatedAirspace(target8); + boolean duplicatedAirspace8 = airspaceUtils.isValidLaancAirspace(target8); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace8); log.info("=== 김포 120m 걸침 - 120 ==="); Coordinate[] polygonCoordinates9 = new Coordinate[]{ - new Coordinate(126.6828233,37.4553499), - new Coordinate(126.7456514,37.5082038), - new Coordinate(126.7796403,37.4414491), - new Coordinate(126.6828233,37.4553499) + new Coordinate(126.6828233, 37.4553499), + new Coordinate(126.7456514, 37.5082038), + new Coordinate(126.7796403, 37.4414491), + new Coordinate(126.6828233, 37.4553499) }; LinearRing linearRing9 = geometryFactory.createLinearRing(polygonCoordinates9); Polygon polygon9 = geometryFactory.createPolygon(linearRing9); @@ -314,15 +356,16 @@ public class AirspaceUtils { target9.setHighElev(120); target9.setLowElev(0); target9.setGeometry(polygon9); - boolean duplicatedAirspace9 = airspaceUtils.isDuplicatedAirspace(target9); +// boolean duplicatedAirspace9 = airspaceUtils.isDuplicatedAirspace(target9); + boolean duplicatedAirspace9 = airspaceUtils.isValidLaancAirspace(target9); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace9); log.info("=== 김포 40m 걸침 - 20 ==="); Coordinate[] polygonCoordinates10 = new Coordinate[]{ - new Coordinate(126.6750825,37.5134229), - new Coordinate(126.7804826,37.5168269), - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.6750825,37.5134229) + new Coordinate(126.6750825, 37.5134229), + new Coordinate(126.7804826, 37.5168269), + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.6750825, 37.5134229) }; LinearRing linearRing10 = geometryFactory.createLinearRing(polygonCoordinates10); Polygon polygon10 = geometryFactory.createPolygon(linearRing10); @@ -330,15 +373,16 @@ public class AirspaceUtils { target10.setHighElev(20); target10.setLowElev(0); target10.setGeometry(polygon10); - boolean duplicatedAirspace10 = airspaceUtils.isDuplicatedAirspace(target10); +// boolean duplicatedAirspace10 = airspaceUtils.isDuplicatedAirspace(target10); + boolean duplicatedAirspace10 = airspaceUtils.isValidLaancAirspace(target10); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace10); log.info("=== 김포 40m 걸침 - 100 ==="); Coordinate[] polygonCoordinates11 = new Coordinate[]{ - new Coordinate(126.6750825,37.5134229), - new Coordinate(126.7804826,37.5168269), - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.6750825,37.5134229) + new Coordinate(126.6750825, 37.5134229), + new Coordinate(126.7804826, 37.5168269), + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.6750825, 37.5134229) }; LinearRing linearRing11 = geometryFactory.createLinearRing(polygonCoordinates11); Polygon polygon11 = geometryFactory.createPolygon(linearRing11); @@ -346,15 +390,16 @@ public class AirspaceUtils { target11.setHighElev(100); target11.setLowElev(0); target11.setGeometry(polygon11); - boolean duplicatedAirspace11 = airspaceUtils.isDuplicatedAirspace(target11); +// boolean duplicatedAirspace11 = airspaceUtils.isDuplicatedAirspace(target11); + boolean duplicatedAirspace11 = airspaceUtils.isValidLaancAirspace(target11); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace11); log.info("=== 김포 40m 걸침 - 40 ==="); Coordinate[] polygonCoordinates12 = new Coordinate[]{ - new Coordinate(126.6750825,37.5134229), - new Coordinate(126.7804826,37.5168269), - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.6750825,37.5134229) + new Coordinate(126.6750825, 37.5134229), + new Coordinate(126.7804826, 37.5168269), + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.6750825, 37.5134229) }; LinearRing linearRing12 = geometryFactory.createLinearRing(polygonCoordinates12); Polygon polygon12 = geometryFactory.createPolygon(linearRing12); @@ -362,15 +407,16 @@ public class AirspaceUtils { target12.setHighElev(40); target12.setLowElev(0); target12.setGeometry(polygon12); - boolean duplicatedAirspace12 = airspaceUtils.isDuplicatedAirspace(target12); +// boolean duplicatedAirspace12 = airspaceUtils.isDuplicatedAirspace(target12); + boolean duplicatedAirspace12 = airspaceUtils.isValidLaancAirspace(target12); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace12); log.info("=== 김포 0 ==="); Coordinate[] polygonCoordinates13 = new Coordinate[]{ - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.8074335,37.5572547), - new Coordinate(126.9097436,37.4477632), - new Coordinate(126.7679513,37.4853679) + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.8074335, 37.5572547), + new Coordinate(126.9097436, 37.4477632), + new Coordinate(126.7679513, 37.4853679) }; LinearRing linearRing13 = geometryFactory.createLinearRing(polygonCoordinates13); Polygon polygon13 = geometryFactory.createPolygon(linearRing13); @@ -378,7 +424,8 @@ public class AirspaceUtils { target13.setHighElev(0); target13.setLowElev(0); target13.setGeometry(polygon13); - boolean duplicatedAirspace13 = airspaceUtils.isDuplicatedAirspace(target13); +// boolean duplicatedAirspace13 = airspaceUtils.isDuplicatedAirspace(target13); + boolean duplicatedAirspace13 = airspaceUtils.isValidLaancAirspace(target13); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace13); // 김포