|
|
|
@ -17,14 +17,9 @@ import org.locationtech.jts.geom.*;
|
|
|
|
|
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.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 org.springframework.core.io.ClassPathResource; |
|
|
|
|
|
|
|
|
|
import java.io.*; |
|
|
|
|
import java.math.BigDecimal; |
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
@ -36,10 +31,10 @@ import java.util.stream.Collectors;
|
|
|
|
|
@Slf4j |
|
|
|
|
public class AirspaceUtils { |
|
|
|
|
|
|
|
|
|
private final String CLASS_PATH = "air/elev2d"; |
|
|
|
|
private final String CLASS_PATH = "air" + File.separator + "airspace"; |
|
|
|
|
private final GeometryFactory geometryFactory = new GeometryFactory(); |
|
|
|
|
// private List<FeatureInfo> airspaces;
|
|
|
|
|
private Map<String, List<FeatureInfo>> airspaceMap; |
|
|
|
|
private Map<AirspaceType, List<FeatureInfo>> airspaceMap; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private AirspaceUtils() { |
|
|
|
@ -74,7 +69,7 @@ public class AirspaceUtils {
|
|
|
|
|
public boolean isDuplicatedAirspace(FeatureInfo target, AirspaceType airspaceType) { |
|
|
|
|
Geometry targetGeometry = target.getGeometry(); |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.get(airspaceType.name()); |
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.get(airspaceType); |
|
|
|
|
|
|
|
|
|
return airspaces.stream().anyMatch(featureInfo -> { |
|
|
|
|
Geometry featureGeometry = featureInfo.getGeometry(); |
|
|
|
@ -83,11 +78,10 @@ public class AirspaceUtils {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 공역 중복 검사
|
|
|
|
|
public boolean isDuplicatedAirspaceElev(FeatureInfo target) { |
|
|
|
|
|
|
|
|
|
if(this.airspaceMap == null || this.airspaceMap.isEmpty()) return true; |
|
|
|
|
if (this.airspaceMap == null || this.airspaceMap.isEmpty()) return true; |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.values().stream() |
|
|
|
|
.flatMap(List::stream) |
|
|
|
@ -120,7 +114,7 @@ public class AirspaceUtils {
|
|
|
|
|
*/ |
|
|
|
|
public boolean isValidLaancAirspace(FeatureInfo target) { |
|
|
|
|
|
|
|
|
|
if(this.airspaceMap == null || this.airspaceMap.isEmpty()) return true; |
|
|
|
|
if (this.airspaceMap == null || this.airspaceMap.isEmpty()) return true; |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.values().stream() |
|
|
|
|
.flatMap(List::stream) |
|
|
|
@ -156,7 +150,7 @@ public class AirspaceUtils {
|
|
|
|
|
|
|
|
|
|
public boolean isValidLaancAirspace(FeatureInfo target, AirspaceType airspaceType) { |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.get(airspaceType.name()); |
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.get(airspaceType); |
|
|
|
|
|
|
|
|
|
if (airspaces.isEmpty()) return true; |
|
|
|
|
|
|
|
|
@ -190,7 +184,7 @@ public class AirspaceUtils {
|
|
|
|
|
public Double getAllowElevation(Geometry target) { |
|
|
|
|
Double allowElevation = null; |
|
|
|
|
|
|
|
|
|
if(this.airspaceMap == null || this.airspaceMap.isEmpty()) return null; |
|
|
|
|
if (this.airspaceMap == null || this.airspaceMap.isEmpty()) return null; |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.values().stream() |
|
|
|
|
.flatMap(List::stream) |
|
|
|
@ -247,6 +241,7 @@ public class AirspaceUtils {
|
|
|
|
|
return this.airspaceMap.get(airspaceType.name()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
// 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화.
|
|
|
|
|
private void loadResourceAirspace() { |
|
|
|
|
|
|
|
|
@ -295,6 +290,59 @@ public class AirspaceUtils {
|
|
|
|
|
|
|
|
|
|
this.airspaceMap = featureInfoMap; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화.
|
|
|
|
|
private void loadResourceAirspace() { |
|
|
|
|
// D_NO_FLY_ZONE, // 비행금지구역
|
|
|
|
|
// D_RESTRICTED_FLIGHT_AREA, // 비행제한구역
|
|
|
|
|
// D_CONTROL_AIRPORT, // 관제권(공항)
|
|
|
|
|
// D_CONTROL_MILITARY_CIVILIAN, // 관제권(군사/민간)
|
|
|
|
|
// D_LIGHT_AIRCRAFT, // 경량항공기이착륙장
|
|
|
|
|
// D_ULTRA_LIGHT_AIRCRAFT, // 초경량비행장치공역
|
|
|
|
|
Map<AirspaceType, String> resourceInfo = Map.of( |
|
|
|
|
AirspaceType.D_NO_FLY_ZONE, "default_airspace/_prohibitedArea.json", |
|
|
|
|
AirspaceType.D_RESTRICTED_FLIGHT_AREA, "default_airspace/_restrictedArea.json", |
|
|
|
|
AirspaceType.D_CONTROL_AIRPORT, "default_airspace/_airFieldArea.json", |
|
|
|
|
AirspaceType.D_CONTROL_MILITARY_CIVILIAN, "default_airspace/_aerodromeArea.json", |
|
|
|
|
AirspaceType.D_LIGHT_AIRCRAFT, "default_airspace/_airFieldArea.json", |
|
|
|
|
AirspaceType.D_ULTRA_LIGHT_AIRCRAFT, "default_airspace/_ultraLightVehicleArea.json", |
|
|
|
|
AirspaceType.C_CONTROL_GIMPO, "custom_airspace/flatGimpoAirportAirArea.json", |
|
|
|
|
AirspaceType.C_CONTROL_ULSAN, "custom_airspace/flatUlsanAirArea.json" |
|
|
|
|
); |
|
|
|
|
Map<AirspaceType, List<FeatureInfo>> featureInfoMap = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
resourceInfo.keySet().forEach(airspaceType -> { |
|
|
|
|
|
|
|
|
|
ClassPathResource resource = new ClassPathResource(CLASS_PATH + File.separator + resourceInfo.get(airspaceType)); |
|
|
|
|
if (!resource.exists()) { |
|
|
|
|
log.warn("airspace resource not found : {} - {}", airspaceType, CLASS_PATH + File.separator + resourceInfo.get(airspaceType)); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> featureInfos = featureInfoMap.get(airspaceType); |
|
|
|
|
if (featureInfos == null) { |
|
|
|
|
featureInfos = new ArrayList<>(); |
|
|
|
|
} |
|
|
|
|
featureInfos.addAll(fis); |
|
|
|
|
featureInfoMap.put(airspaceType, featureInfos); |
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
log.warn("airspace resource read error : {}", e.getMessage()); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
for (Map.Entry<AirspaceType, List<FeatureInfo>> entry : featureInfoMap.entrySet()) { |
|
|
|
|
log.info(">>> key : {}, size : {}", entry.getKey(), entry.getValue().size()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.airspaceMap = featureInfoMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private List<FeatureInfo> convertGeoJsonToGeometry(JSONObject jsonObject) { |
|
|
|
|
List<FeatureInfo> featureInfos = new ArrayList<>(); |
|
|
|
@ -391,7 +439,7 @@ public class AirspaceUtils {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public int getSize() { |
|
|
|
|
if(this.airspaceMap == null || this.airspaceMap.isEmpty()) return 0; |
|
|
|
|
if (this.airspaceMap == null || this.airspaceMap.isEmpty()) return 0; |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> airspaces = this.airspaceMap.values().stream() |
|
|
|
|
.flatMap(List::stream) |
|
|
|
@ -413,8 +461,19 @@ public class AirspaceUtils {
|
|
|
|
|
private Geometry geometry; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static enum AirspaceType { |
|
|
|
|
GIMPO, ETC |
|
|
|
|
// 기본
|
|
|
|
|
D_NO_FLY_ZONE, // 비행금지구역
|
|
|
|
|
D_RESTRICTED_FLIGHT_AREA, // 비행제한구역
|
|
|
|
|
D_CONTROL_AIRPORT, // 관제권(공항)
|
|
|
|
|
D_CONTROL_MILITARY_CIVILIAN, // 관제권(군사/민간)
|
|
|
|
|
D_LIGHT_AIRCRAFT, // 경량항공기이착륙장
|
|
|
|
|
D_ULTRA_LIGHT_AIRCRAFT, // 초경량비행장치공역
|
|
|
|
|
// 커스텀
|
|
|
|
|
C_CONTROL_GIMPO, // 김포공항관제권
|
|
|
|
|
C_CONTROL_ULSAN, // 울산공항관제권
|
|
|
|
|
C_CONTROL_JEJU // 제주공항관제권
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Coordinate toCartesian(double lon, double lat) { |
|
|
|
|