|
|
|
@ -2,16 +2,29 @@ package com.palnet.comn.utils;
|
|
|
|
|
|
|
|
|
|
import com.fasterxml.jackson.annotation.JsonCreator; |
|
|
|
|
import com.fasterxml.jackson.annotation.JsonValue; |
|
|
|
|
import lombok.AllArgsConstructor; |
|
|
|
|
import lombok.Builder; |
|
|
|
|
import lombok.Data; |
|
|
|
|
import lombok.NoArgsConstructor; |
|
|
|
|
import lombok.*; |
|
|
|
|
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.HashMap; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
@ -25,8 +38,8 @@ public class AirAreaUtils {
|
|
|
|
|
private final String COMMON_PATH = "common/"; |
|
|
|
|
private final String CUSTOM_PATH = "custom/"; |
|
|
|
|
private final String SUFFIX_FILE_NAME = "Area.json"; |
|
|
|
|
|
|
|
|
|
private Map<String, List<FeatureInfo>> airAreaMap; |
|
|
|
|
@Getter |
|
|
|
|
private Map<AirAreaType, List<FeatureInfo>> airAreaMap = null; |
|
|
|
|
private GeometryFactory geometryFactory; |
|
|
|
|
|
|
|
|
|
private AirAreaUtils() { |
|
|
|
@ -42,10 +55,81 @@ public class AirAreaUtils {
|
|
|
|
|
private static final AirAreaUtils INSTANCE = new AirAreaUtils(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int getSize() { |
|
|
|
|
return airAreaMap.size(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public List<FeatureInfo> getAirAreaList() { |
|
|
|
|
return getAirAreaList(AirAreaType.ALL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public List<FeatureInfo> getAirAreaList(AirAreaType airAreaType) { |
|
|
|
|
if (airAreaType == null) airAreaType = AirAreaType.ALL; |
|
|
|
|
|
|
|
|
|
List<FeatureInfo> featureInfos = null; |
|
|
|
|
if (AirAreaType.ALL == airAreaType) { |
|
|
|
|
featureInfos = airAreaMap.values().stream() |
|
|
|
|
.flatMap(List::stream) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
} else { |
|
|
|
|
featureInfos = airAreaMap.get(airAreaType); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (featureInfos == null) { |
|
|
|
|
log.warn("featureInfos is null"); |
|
|
|
|
featureInfos = new ArrayList<>(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return featureInfos; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO 초기화
|
|
|
|
|
private void init() { |
|
|
|
|
airAreaMap = new HashMap<>(); |
|
|
|
|
geometryFactory = new GeometryFactory(); |
|
|
|
|
// TODO 데이터 로드
|
|
|
|
|
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); |
|
|
|
|
List<Resource> resources = new ArrayList<>(); |
|
|
|
|
try { |
|
|
|
|
resources.addAll(List.of(resolver.getResources("classpath*:" + RESOURCE_BASE_PATH + COMMON_PATH + "*" + SUFFIX_FILE_NAME))); |
|
|
|
|
resources.addAll(List.of(resolver.getResources("classpath*:" + RESOURCE_BASE_PATH + CUSTOM_PATH + "*" + SUFFIX_FILE_NAME))); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
log.error("Failed to load air area resources", e); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (resources.isEmpty()) { |
|
|
|
|
log.warn("air area resources is empty"); |
|
|
|
|
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.convertGeoJsonToFeatureInfo(jsonObject); |
|
|
|
|
|
|
|
|
|
if (fis.isEmpty()) { |
|
|
|
|
log.warn("FeatureInfo is empty"); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AirAreaType group = fis.get(0).getGroup(); |
|
|
|
|
List<FeatureInfo> featureInfos = airAreaMap.get(group); |
|
|
|
|
if (featureInfos == null) { |
|
|
|
|
featureInfos = new ArrayList<>(); |
|
|
|
|
} |
|
|
|
|
featureInfos.addAll(fis); |
|
|
|
|
|
|
|
|
|
airAreaMap.put(group, featureInfos); |
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
log.error("airspace resource read error : {} - {}", resource.getFilename(), e.getStackTrace()[0]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -273,6 +357,109 @@ public class AirAreaUtils {
|
|
|
|
|
return geometry; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* json to FeatureInfo |
|
|
|
|
* |
|
|
|
|
* @param jsonObject |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private List<FeatureInfo> convertGeoJsonToFeatureInfo(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)) { |
|
|
|
|
innerObject.add(firstCoords); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
FeatureJSON featureJSON = new FeatureJSON(); |
|
|
|
|
SimpleFeature simpleFeature = null; |
|
|
|
|
simpleFeature = featureJSON.readFeature(feature.toJSONString()); |
|
|
|
|
boolean isUse = Boolean.parseBoolean(String.valueOf(simpleFeature.getAttribute("isUse"))); |
|
|
|
|
if (isUse) { |
|
|
|
|
String name = String.valueOf(simpleFeature.getAttribute("name")); |
|
|
|
|
String description = String.valueOf(simpleFeature.getAttribute("description")); |
|
|
|
|
String propType = String.valueOf(simpleFeature.getAttribute("type")); |
|
|
|
|
Double lowElev = Double.parseDouble(String.valueOf(simpleFeature.getAttribute("lowElev"))); |
|
|
|
|
Double highElev = Double.parseDouble(String.valueOf(simpleFeature.getAttribute("highElev"))); |
|
|
|
|
Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry(); |
|
|
|
|
AirAreaType group = AirAreaType.fromCode(String.valueOf(simpleFeature.getAttribute("group"))); |
|
|
|
|
if (group == null) group = AirAreaType.COMMON; |
|
|
|
|
FeatureInfo info = FeatureInfo.builder() |
|
|
|
|
.name(name) |
|
|
|
|
.description(description) |
|
|
|
|
.type(propType) |
|
|
|
|
.lowElev(lowElev) |
|
|
|
|
.highElev(highElev) |
|
|
|
|
.geometry(geometry) |
|
|
|
|
.isUse(isUse) |
|
|
|
|
.group(group) |
|
|
|
|
.build(); |
|
|
|
|
featureInfos.add(info); |
|
|
|
|
} |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
log.error("geometry json read error : {}", e.getStackTrace()[0]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if ("Feature".equals(type)) { |
|
|
|
|
FeatureJSON featureJSON = new FeatureJSON(); |
|
|
|
|
try { |
|
|
|
|
SimpleFeature simpleFeature = featureJSON.readFeature(jsonObject.toJSONString()); |
|
|
|
|
boolean isUse = Boolean.parseBoolean(String.valueOf(simpleFeature.getAttribute("use"))); |
|
|
|
|
if (isUse) { |
|
|
|
|
String name = String.valueOf(simpleFeature.getAttribute("name")); |
|
|
|
|
String description = String.valueOf(simpleFeature.getAttribute("description")); |
|
|
|
|
String propType = String.valueOf(simpleFeature.getAttribute("type")); |
|
|
|
|
Double lowElev = Double.parseDouble(String.valueOf(simpleFeature.getAttribute("lowElev"))); |
|
|
|
|
Double highElev = Double.parseDouble(String.valueOf(simpleFeature.getAttribute("highElev"))); |
|
|
|
|
Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry(); |
|
|
|
|
AirAreaType group = AirAreaType.fromCode(String.valueOf(simpleFeature.getAttribute("group"))); |
|
|
|
|
if (group == null) group = AirAreaType.COMMON; |
|
|
|
|
FeatureInfo info = FeatureInfo.builder() |
|
|
|
|
.name(name) |
|
|
|
|
.description(description) |
|
|
|
|
.type(propType) |
|
|
|
|
.lowElev(lowElev) |
|
|
|
|
.highElev(highElev) |
|
|
|
|
.geometry(geometry) |
|
|
|
|
.isUse(isUse) |
|
|
|
|
.group(group) |
|
|
|
|
.build(); |
|
|
|
|
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 = FeatureInfo.builder() |
|
|
|
|
.geometry(geometry) |
|
|
|
|
.build(); |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
log.error("geometry json read error : {}", e.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return featureInfos; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Data |
|
|
|
|
@NoArgsConstructor |
|
|
|
@ -286,14 +473,16 @@ public class AirAreaUtils {
|
|
|
|
|
private Double highElev; |
|
|
|
|
private boolean isUse; |
|
|
|
|
private Geometry geometry; |
|
|
|
|
private AirAreaType group; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* AirAreaType - 모두, 김포 |
|
|
|
|
*/ |
|
|
|
|
public enum AirAreaType { |
|
|
|
|
ALL("all"), |
|
|
|
|
GIMPO("gimpo"); |
|
|
|
|
ALL("ALL"), |
|
|
|
|
COMMON("COMMON"), |
|
|
|
|
GIMPO("GMP"); |
|
|
|
|
|
|
|
|
|
private final String code; |
|
|
|
|
|
|
|
|
@ -353,8 +542,8 @@ public class AirAreaUtils {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO 가장 가까운 거리 반환
|
|
|
|
|
|
|
|
|
|
// TODO 가장 가까운 거리 반환
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) { |
|
|
|
@ -370,5 +559,11 @@ public class AirAreaUtils {
|
|
|
|
|
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()); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|