Browse Source

feat: 신규 금지공역 관리 유틸 생성

feature/change-airspace
지대한 2 months ago
parent
commit
bdb54b105f
  1. 374
      pav-server/src/main/java/com/palnet/comn/utils/AirAreaUtils.java
  2. 4
      pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java

374
pav-server/src/main/java/com/palnet/comn/utils/AirAreaUtils.java

@ -0,0 +1,374 @@
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.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
// TODO areaUtils, airspaceUtils merge
// TODO airspaceUtils의 검증 관련 로직은 해당 표시에서 적용.
@Slf4j
public class AirAreaUtils {
private final String RESOURCE_BASE_PATH = "air/airspace/";
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;
private GeometryFactory geometryFactory;
private AirAreaUtils() {
log.info("===== AirAreaUtils init =====");
this.init();
}
public static AirAreaUtils getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final AirAreaUtils INSTANCE = new AirAreaUtils();
}
// TODO 초기화
private void init() {
geometryFactory = new GeometryFactory();
// TODO 데이터 로드
}
/**
* air area와 중복 여부(고도 무시)
*
* @param targetfeatureInfo
* @return
*/
public boolean isDuplicatedAirAreaIgnoreElev(FeatureInfo targetfeatureInfo) {
return isDuplicatedAirAreaIgnoreElev(targetfeatureInfo, AirAreaType.ALL);
}
/**
* air area와 중복 여부(고도 무시)
*
* @param targetFeatureInfo
* @param airAreaType
* @return
*/
public boolean isDuplicatedAirAreaIgnoreElev(FeatureInfo targetFeatureInfo, AirAreaType airAreaType) {
if (targetFeatureInfo == null) return false;
if (airAreaMap == null || airAreaMap.isEmpty()) {
log.warn("airAreaMap is empty");
return false;
}
if (airAreaType == null) airAreaType = AirAreaType.ALL;
Geometry targetGeometry = targetFeatureInfo.getGeometry();
if (targetGeometry == null) return false;
List<FeatureInfo> duplicatedAirAreaFeatureInfos = getDuplicatedAirAreaIgnoreElev(targetFeatureInfo, airAreaType);
return !duplicatedAirAreaFeatureInfos.isEmpty();
}
/**
* air area와 중복 여부(고도 포함)
*
* @param featureInfo
* @return
*/
public boolean isDuplicatedAirArea(FeatureInfo featureInfo) {
return isDuplicatedAirArea(featureInfo, AirAreaType.ALL);
}
/**
* air area와 중복 여부(고도 포함)
*
* @param targetFeatureInfo
* @param airAreaType
* @return
*/
public boolean isDuplicatedAirArea(FeatureInfo targetFeatureInfo, AirAreaType airAreaType) {
if (targetFeatureInfo == null) return false;
if (airAreaMap == null || airAreaMap.isEmpty()) {
log.warn("airAreaMap is empty");
return false;
}
if (airAreaType == null) airAreaType = AirAreaType.ALL;
List<FeatureInfo> duplicatedAirAreaFeatureInfos = getDuplicatedAirArea(targetFeatureInfo, airAreaType);
return !duplicatedAirAreaFeatureInfos.isEmpty();
}
/**
* 중복되는 air area FeatureInfo 반환(고도 무시)
*
* @param targetFeatureInfo
* @return
*/
public List<FeatureInfo> getDuplicatedAirAreaIgnoreElev(FeatureInfo targetFeatureInfo) {
return getDuplicatedAirAreaIgnoreElev(targetFeatureInfo, AirAreaType.ALL);
}
/**
* 중복되는 air area FeatureInfo 반환(고도 무시)
*
* @param targetFeatureInfo
* @param airAreaType
* @return
*/
public List<FeatureInfo> getDuplicatedAirAreaIgnoreElev(FeatureInfo targetFeatureInfo, AirAreaType airAreaType) {
Geometry targetGeometry = targetFeatureInfo.getGeometry();
if (targetGeometry == null) return new ArrayList<>();
List<FeatureInfo> airAreaFeatureInfos = null;
if (AirAreaType.ALL == airAreaType) {
airAreaFeatureInfos = airAreaMap.values().stream()
.flatMap(List::stream)
.collect(Collectors.toList());
} else {
airAreaFeatureInfos = airAreaMap.get(airAreaType.getCode());
}
return airAreaFeatureInfos.stream()
.filter(airAreaFeatureInfo -> {
Geometry airAreaGeometry = airAreaFeatureInfo.getGeometry();
if (airAreaGeometry == null) return false;
return airAreaGeometry.intersects(targetGeometry);
})
.collect(Collectors.toList());
}
/**
* 중복되는 air area FeatureInfo 반환(고도 포함)
*
* @param targetFeatureInfo
* @return
*/
public List<FeatureInfo> getDuplicatedAirArea(FeatureInfo targetFeatureInfo) {
return getDuplicatedAirArea(targetFeatureInfo, AirAreaType.ALL);
}
/**
* 중복되는 air area FeatureInfo 반환(고도 포함)
*
* @param targetFeatureInfo
* @param airAreaType
* @return
*/
public List<FeatureInfo> getDuplicatedAirArea(FeatureInfo targetFeatureInfo, AirAreaType airAreaType) {
List<FeatureInfo> duplicatedAirAreaFeatureInfosIgnoreElev = getDuplicatedAirAreaIgnoreElev(targetFeatureInfo, airAreaType);
final double targetHighElev = targetFeatureInfo.getHighElev() != null ? targetFeatureInfo.getHighElev() : 0D;
return duplicatedAirAreaFeatureInfosIgnoreElev.stream().filter(airAreaFeatureInfo -> {
final double airAreaHighElev = airAreaFeatureInfo.getHighElev() != null ? airAreaFeatureInfo.getHighElev() : 0D;
return targetHighElev <= airAreaHighElev;
}).collect(Collectors.toList());
}
/**
* FeatureInfo 생성
*
* @param coordinates
* @return
*/
public FeatureInfo craeteFeatureInfo(List<Coordinate> coordinates) {
return craeteFeatureInfo(coordinates, GeometryType.POLYGON, null);
}
/**
* FeatureInfo 생성
*
* @param coordinates
* @param geometryType
* @param highElev
* @return
*/
public FeatureInfo craeteFeatureInfo(List<Coordinate> coordinates, GeometryType geometryType, Double highElev) {
return craeteFeatureInfo(coordinates, geometryType, null, null, null, highElev);
}
/**
* FeatureInfo 생성
*
* @param coordinates
* @param geometryType
* @param name
* @param description
* @param type
* @param highElev
* @return
*/
public FeatureInfo craeteFeatureInfo(List<Coordinate> coordinates, GeometryType geometryType, String name, String description, String type, Double highElev) {
return craeteFeatureInfo(coordinates, geometryType, name, description, type, null, highElev, true);
}
/**
* FeatureInfo 생성
*
* @param coordinates
* @param geometryType
* @param name
* @param description
* @param type
* @param lowElev
* @param highElev
* @param isUse
* @return
*/
public FeatureInfo craeteFeatureInfo(List<Coordinate> coordinates, GeometryType geometryType, String name, String description, String type, Double lowElev, Double highElev, boolean isUse) {
Geometry geometry = createGeometryByCoordinate(coordinates, geometryType);
return FeatureInfo.builder()
.name(name)
.description(description)
.type(type)
.lowElev(lowElev)
.highElev(highElev)
.isUse(isUse)
.geometry(geometry)
.build();
}
/**
* Geometry 생성
* 좌표 목록과 GeometryType을 이용하여 Geometry 생성
*
* @param target
* @param type
* @return
*/
public Geometry createGeometryByCoordinate(List<Coordinate> target, GeometryType type) {
if (target == null || target.isEmpty()) return null;
if (type == null) {
if (target.size() == 1) {
type = GeometryType.POINT;
} else if (target.size() == 2) {
type = GeometryType.LINESTRING;
} else {
type = GeometryType.POLYGON;
}
}
Geometry geometry = null;
if (GeometryType.POLYGON == type) {
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 (GeometryType.LINESTRING == type) {
geometry = this.geometryFactory.createLineString(target.toArray(new Coordinate[0]));
} else if (GeometryType.POINT == type) {
geometry = this.geometryFactory.createPoint(target.get(0));
}
return geometry;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class FeatureInfo {
private String name;
private String description;
private String type;
private Double lowElev;
private Double highElev;
private boolean isUse;
private Geometry geometry;
}
/**
* AirAreaType - 모두, 김포
*/
public enum AirAreaType {
ALL("all"),
GIMPO("gimpo");
private final String code;
@JsonValue
public String getCode() {
return code;
}
AirAreaType(String code) {
this.code = code;
}
@JsonCreator
public static AirAreaType fromCode(String code) {
for (AirAreaType type : AirAreaType.values()) {
if (type.code.equals(code)) {
return type;
}
}
log.warn("Unknown AirAreaType code: {}", code);
return null;
}
}
/**
* GeometryType - Point, LineString, Polygon
*/
public enum GeometryType {
POINT("Point"),
LINESTRING("LineString"),
POLYGON("Polygon");
// MULTIPOINT("MultiPoint"),
// MULTILINESTRING("MultiLineString"),
// MULTIPOLYGON("MultiPolygon"),
// GEOMETRYCOLLECTION("GeometryCollection");
private final String code;
@JsonValue
public String getCode() {
return code;
}
GeometryType(String code) {
this.code = code;
}
@JsonCreator
public static GeometryType fromCode(String code) {
for (GeometryType type : GeometryType.values()) {
if (type.code.equals(code)) {
return type;
}
}
log.warn("Unknown GeometryType code: {}", code);
return null;
}
}
// TODO 가장 가까운 거리 반환
public static void main(String[] args) {
AirAreaUtils utils = AirAreaUtils.getInstance();
log.info("utils: {}", utils);
AirAreaUtils utils2 = AirAreaUtils.getInstance();
log.info("utils2: {}", utils2);
log.info("utils == utils2: {}", utils == utils2);
List<Integer> list = List.of(1, 2, 3, 4, 5);
boolean b = list.stream().anyMatch(i -> i == 3);
log.info("b:: {}", b);
List<Integer> list2 = new ArrayList<>();
boolean b2 = list2.stream().anyMatch(i -> i == 3);
log.info("b2:: {}", b2);
}
}

4
pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java

@ -56,7 +56,7 @@ public class AirspaceUtils {
private static final AirspaceUtils INSTANCE = new AirspaceUtils();
}
// 공 중복 검사 - 고도x
// 공 중복 검사 - 고도x
public boolean isDuplicatedAirspace(FeatureInfo target) {
Geometry targetGeometry = target.getGeometry();
@ -70,7 +70,7 @@ public class AirspaceUtils {
});
}
// 공 중복 검사 - 고도x
// 공 중복 검사 - 고도x
public boolean isDuplicatedAirspace(FeatureInfo target, AirspaceType airspaceType) {
Geometry targetGeometry = target.getGeometry();

Loading…
Cancel
Save