Browse Source

좌표에 따른 지표면 고도 조회 기능

AGL 기준의 고도 변환(MSL > AGL)
MSL 기준의 고도 변환(AGL > MSL)
pull/11/head
지대한 10 months ago
parent
commit
f6f1a23536
  1. 33
      pav-server/src/main/java/com/palnet/biz/api/bas/dron/controller/BasDronController.java
  2. 113
      pav-server/src/main/java/com/palnet/biz/api/comn/elev/controller/ComnElevController.java
  3. 16
      pav-server/src/main/java/com/palnet/biz/api/comn/elev/model/ComnElevRq.java
  4. 17
      pav-server/src/main/java/com/palnet/biz/api/comn/elev/model/ComnElevRs.java
  5. 15
      pav-server/src/main/java/com/palnet/biz/api/comn/elev/model/ComnGroundElevRq.java
  6. 72
      pav-server/src/main/java/com/palnet/biz/api/comn/elev/service/ComnElevService.java
  7. 2
      pav-server/src/main/java/com/palnet/biz/api/external/service/SunRiseSetService.java
  8. 4
      pav-server/src/main/java/com/palnet/biz/config/InitRunner.java
  9. 5
      pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java
  10. 20
      pav-server/src/main/java/com/palnet/comn/utils/DigitalElevationModelUtils.java
  11. BIN
      pav-server/src/main/resources/map/dem/dem_korea_010.tif
  12. BIN
      pav-server/src/main/resources/map/dem/dem_korea_011.tif

33
pav-server/src/main/java/com/palnet/biz/api/bas/dron/controller/BasDronController.java

@ -1,23 +1,5 @@
package com.palnet.biz.api.bas.dron.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.palnet.biz.api.bas.dron.model.BasDronModel;
import com.palnet.biz.api.bas.dron.model.BasDronRqModel;
import com.palnet.biz.api.bas.dron.model.BasIdntfModel;
@ -29,14 +11,23 @@ import com.palnet.biz.api.comn.response.ErrorResponse;
import com.palnet.biz.api.comn.response.SuccessResponse;
import com.palnet.comn.code.RSErrorCode;
import com.palnet.comn.exception.CustomException;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Log4j2
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/bas/dron", produces = {MediaType.APPLICATION_JSON_VALUE})

113
pav-server/src/main/java/com/palnet/biz/api/comn/elev/controller/ComnElevController.java

@ -0,0 +1,113 @@
package com.palnet.biz.api.comn.elev.controller;
import com.palnet.biz.api.comn.elev.model.ComnElevRq;
import com.palnet.biz.api.comn.elev.model.ComnElevRs;
import com.palnet.biz.api.comn.elev.model.ComnGroundElevRq;
import com.palnet.biz.api.comn.elev.service.ComnElevService;
import com.palnet.biz.api.comn.response.BasicResponse;
import com.palnet.biz.api.comn.response.ErrorResponse;
import com.palnet.biz.api.comn.response.SuccessResponse;
import com.palnet.comn.exception.CustomException;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Tag(name = "공통 API", description = "공통 API")
@RequiredArgsConstructor
@RequestMapping("/api/comn/elev")
@RestController
public class ComnElevController {
private final ComnElevService comnElevService;
@PostMapping(value = "/ground")
@ApiOperation(value = "지표면 고도 가져오기")
@Tag(name = "공통 API", description = "공통 API")
public ResponseEntity<? extends BasicResponse> getGroundElev(@RequestBody List<ComnGroundElevRq> rq) {
List<ComnElevRs> rs = null;
try {
log.debug(">>> rq : {}", rq);
rs = comnElevService.getGroundElev(rq);
} catch (CustomException e) {
Map<String, Object> resultMap = new HashMap<>();
log.error("IGNORE : ", e);
resultMap.put("result", false);
resultMap.put("errorCode", e.getErrorCode());
resultMap.put("errorMessage", e.getMessage());
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap));
} catch (Exception e) {
log.error("IGNORE : ", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse("Server Error", "-1"));
}
return ResponseEntity.ok().body(new SuccessResponse<>(rs));
}
@PostMapping(value = "/to/agl")
@ApiOperation(value = "msl을 agl로 변환")
@Tag(name = "공통 API", description = "공통 API")
public ResponseEntity<? extends BasicResponse> convertMslToAgl(@RequestBody List<ComnElevRq> rq) {
List<ComnElevRs> rs = null;
try {
log.debug(">>> rq : {}", rq);
rs = comnElevService.convertMslToAgl(rq);
} catch (CustomException e) {
Map<String, Object> resultMap = new HashMap<>();
log.error("IGNORE : ", e);
resultMap.put("result", false);
resultMap.put("errorCode", e.getErrorCode());
resultMap.put("errorMessage", e.getMessage());
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap));
} catch (Exception e) {
log.error("IGNORE : ", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse("Server Error", "-1"));
}
return ResponseEntity.ok().body(new SuccessResponse<>(rs));
}
@PostMapping(value = "/to/msl")
@ApiOperation(value = "agl을 msl로 변환")
@Tag(name = "공통 API", description = "공통 API")
public ResponseEntity<? extends BasicResponse> convertAglToMsl(@RequestBody List<ComnElevRq> rq) {
List<ComnElevRs> rs = null;
try {
log.debug(">>> rq : {}", rq);
rs = comnElevService.convertAglToMsl(rq);
} catch (CustomException e) {
Map<String, Object> resultMap = new HashMap<>();
log.error("IGNORE : ", e);
resultMap.put("result", false);
resultMap.put("errorCode", e.getErrorCode());
resultMap.put("errorMessage", e.getMessage());
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap));
} catch (Exception e) {
log.error("IGNORE : ", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse("Server Error", "-1"));
}
return ResponseEntity.ok().body(new SuccessResponse<>(rs));
}
}

16
pav-server/src/main/java/com/palnet/biz/api/comn/elev/model/ComnElevRq.java

@ -0,0 +1,16 @@
package com.palnet.biz.api.comn.elev.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ComnElevRq {
private Double lat;
private Double lon;
private Double elev;
}

17
pav-server/src/main/java/com/palnet/biz/api/comn/elev/model/ComnElevRs.java

@ -0,0 +1,17 @@
package com.palnet.biz.api.comn.elev.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ComnElevRs {
private String elevType;
private Double lat;
private Double lon;
private Double elev;
}

15
pav-server/src/main/java/com/palnet/biz/api/comn/elev/model/ComnGroundElevRq.java

@ -0,0 +1,15 @@
package com.palnet.biz.api.comn.elev.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ComnGroundElevRq {
private Double lat;
private Double lon;
}

72
pav-server/src/main/java/com/palnet/biz/api/comn/elev/service/ComnElevService.java

@ -0,0 +1,72 @@
package com.palnet.biz.api.comn.elev.service;
import com.palnet.biz.api.comn.elev.model.ComnElevRq;
import com.palnet.biz.api.comn.elev.model.ComnElevRs;
import com.palnet.biz.api.comn.elev.model.ComnGroundElevRq;
import com.palnet.comn.utils.DigitalElevationModelUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RequiredArgsConstructor
@Service
public class ComnElevService {
// 지표면 고도 가져오기
public List<ComnElevRs> getGroundElev(List<ComnGroundElevRq> rq) {
DigitalElevationModelUtils demUtils = DigitalElevationModelUtils.getInstance();
List<ComnElevRs> rs = rq.stream().map(elev -> {
Coordinate coord = new Coordinate(elev.getLon(), elev.getLat());
Double groundElevation = demUtils.getGroundElevation(coord);
return ComnElevRs.builder()
.elevType("ground")
.lat(elev.getLat())
.lon(elev.getLon())
.elev(groundElevation)
.build();
}).collect(Collectors.toList());
return rs;
}
// msl 기준 고도 > agl 기준 고도 변환
public List<ComnElevRs> convertMslToAgl(List<ComnElevRq> rq) {
DigitalElevationModelUtils demUtils = DigitalElevationModelUtils.getInstance();
List<ComnElevRs> rs = rq.stream().map(elev -> {
Coordinate coord = new Coordinate(elev.getLon(), elev.getLat());
// 해수면기준 고도 - 지표면 고도 = AGL기준 고도(지표면에서 떨어진 높이)
Double groundElevation = demUtils.getGroundElevation(coord);
Double aglElevation = (Math.round((elev.getElev() - groundElevation) * 100.0) / 100.0);
return ComnElevRs.builder()
.elevType("agl")
.lat(elev.getLat())
.lon(elev.getLon())
.elev(aglElevation)
.build();
}).collect(Collectors.toList());
return rs;
}
// agl 기준 고도 > msl 기준 고도 변환
public List<ComnElevRs> convertAglToMsl(List<ComnElevRq> rq) {
DigitalElevationModelUtils demUtils = DigitalElevationModelUtils.getInstance();
List<ComnElevRs> rs = rq.stream().map(elev -> {
Coordinate coord = new Coordinate(elev.getLon(), elev.getLat());
// AGL기준 고도 + 지표면 고도 = 해수면기준 고도(해수면에서 떨어진 높이)
Double groundElevation = demUtils.getGroundElevation(coord);
Double aglElevation = (Math.round((elev.getElev() + groundElevation) * 100.0) / 100.0);
return ComnElevRs.builder()
.elevType("msl")
.lat(elev.getLat())
.lon(elev.getLon())
.elev(aglElevation)
.build();
}).collect(Collectors.toList());
return rs;
}
}

2
pav-server/src/main/java/com/palnet/biz/api/external/service/SunRiseSetService.java vendored

@ -59,7 +59,7 @@ public class SunRiseSetService {
// continue 20240201
List<String> locations = getLocation();
// LocalDate targetDate = LocalDate.now();
LocalDate targetDate = LocalDate.of(2024, 5, 1);
LocalDate targetDate = LocalDate.of(2024, 6, 1);
LocalDate end = targetDate.plusMonths(6);
List<SunRiseSetRs> sunRiseSet = new ArrayList<>();

4
pav-server/src/main/java/com/palnet/biz/config/InitRunner.java

@ -16,12 +16,14 @@ public class InitRunner implements ApplicationRunner {
// DEM(Digital Elevation Model load
try {
DigitalElevationModelUtils demUtils = DigitalElevationModelUtils.getInstance();
log.info("DSM size : {}", demUtils.getSize());
} catch (Exception e) {
log.warn("===== InitRunner run error[DigitalElevationModelUtils] : {}", e.getMessage());
}
// airspace load
try {
AirspaceUtils.getInstance();
AirspaceUtils apUtils = AirspaceUtils.getInstance();
log.info("Air Space Count : {}", apUtils.getSize());
} catch (Exception e) {
log.warn("===== InitRunner run error[AirspaceUtils] : {}", e.getMessage());
}

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

@ -264,6 +264,11 @@ public class AirspaceUtils {
return featureInfos;
}
public int getSize() {
if(this.airspaces == null) return 0;
return this.airspaces.size();
}
@Data
@NoArgsConstructor
@AllArgsConstructor

20
pav-server/src/main/java/com/palnet/comn/utils/DigitalElevationModelUtils.java

@ -13,6 +13,7 @@ import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.opengis.geometry.DirectPosition;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@ -85,13 +86,14 @@ public class DigitalElevationModelUtils {
this.dems = demList;
}
public Double getGroundElevation(double lon, double lat) {
public Double getGroundElevation(Coordinate coord) {
if (this.dems == null || dems.isEmpty()) return null;
DirectPosition posWorld = null;
try {
CoordinateReferenceSystem wgs84CRS = CRS.decode("EPSG:4326");
posWorld = new DirectPosition2D(wgs84CRS, lon, lat);
// posWorld = new DirectPosition2D(wgs84CRS, lon, lat);
posWorld = new DirectPosition2D(wgs84CRS, coord.x, coord.y);
} catch (FactoryException e) {
throw new RuntimeException(e);
}
@ -123,6 +125,11 @@ public class DigitalElevationModelUtils {
return null;
}
public int getSize() {
if (this.dems == null) return 0;
return this.dems.size();
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ -131,4 +138,13 @@ public class DigitalElevationModelUtils {
private Raster raster;
private GridCoverage2D coverage;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class DigitalElevationCoordinate {
private Raster raster;
private GridCoverage2D coverage;
}
}

BIN
pav-server/src/main/resources/map/dem/dem_korea_010.tif

Binary file not shown.

BIN
pav-server/src/main/resources/map/dem/dem_korea_011.tif

Binary file not shown.
Loading…
Cancel
Save