Geojson Polygon DATA Operating System Build Complete - Daniel C No.5

This commit is contained in:
sanghyeonhd
2025-11-27 17:50:17 +09:00
parent 9d32c85fd0
commit bacd321666
47 changed files with 37945 additions and 39180 deletions

View File

@@ -3,11 +3,15 @@ package com.kamco.cd.kamcoback.geojson.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataEntity;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataGeomEntity;
import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataGeomRepository;
import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataRepository;
import java.time.ZonedDateTime;
import java.util.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.geojson.GeoJsonReader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -18,7 +22,9 @@ import org.springframework.transaction.annotation.Transactional;
public class GeoJsonDataService {
private final MapSheetLearnDataRepository mapSheetLearnDataRepository;
private final MapSheetLearnDataGeomRepository mapSheetLearnDataGeomRepository;
private final ObjectMapper objectMapper;
private final GeoJsonReader geoJsonReader = new GeoJsonReader();
/** GeoJSON 파일들을 데이터베이스에 저장 */
@Transactional
@@ -37,6 +43,11 @@ public class GeoJsonDataService {
if (savedId != null) {
savedIds.add(savedId);
log.debug("GeoJSON 파일 저장 성공: {} (ID: {})", fileName, savedId);
// 학습 모델 결과 파일인지 확인하여 geometry 데이터 처리
if (isLearningModelResult(fileName, geoJsonContent)) {
processLearningModelGeometry(savedId, geoJsonContent, fileName);
}
}
} catch (Exception e) {
log.error("GeoJSON 파일 처리 실패: {}", fileName, e);
@@ -163,7 +174,24 @@ public class GeoJsonDataService {
/** 연도 정보 추출 */
private void setYearInformation(MapSheetLearnDataEntity entity, String fileName) {
// 파일명에서 연도 추출 시도 (예: kamco_2021_2022_35813023.geojson)
// 학습 모델 결과 파일인지 확인하고 특별 처리
if (fileName.matches(".*캠코_\\d{4}_\\d{4}_\\d+.*")) {
String[] parts = fileName.split("_");
if (parts.length >= 4) {
String beforeYear = parts[1];
String afterYear = parts[2];
// 비교년도 정보를 첫 번째 연도의 정수로 저장
try {
entity.setCompareYyyy(Integer.parseInt(beforeYear));
log.debug("학습 모델 연도 정보 설정: {}", beforeYear);
} catch (NumberFormatException e) {
log.warn("연도 파싱 실패: {}", beforeYear, e);
}
return;
}
}
// 기존 로직: 파일명에서 연도 추출 시도
String[] parts = fileName.split("_");
for (String part : parts) {
if (part.matches("\\d{4}")) { // 4자리 숫자 (연도)
@@ -226,4 +254,177 @@ public class GeoJsonDataService {
return true;
}
/** 학습 모델 결과 파일인지 확인 */
private boolean isLearningModelResult(String fileName, String geoJsonContent) {
try {
// 파일명으로 확인 (캠코_YYYY_YYYY_번호 패턴)
if (fileName.matches(".*캠코_\\d{4}_\\d{4}_\\d+.*\\.geojson")) {
return true;
}
// GeoJSON 내용으로 확인 (학습 모델 특화 필드 존재 여부)
JsonNode rootNode = objectMapper.readTree(geoJsonContent);
if (rootNode.has("features")) {
JsonNode features = rootNode.get("features");
if (features.isArray() && features.size() > 0) {
JsonNode firstFeature = features.get(0);
if (firstFeature.has("properties")) {
JsonNode properties = firstFeature.get("properties");
// 학습 모델 특화 필드 확인
return properties.has("cd_prob")
|| properties.has("class")
|| (properties.has("before") && properties.has("after"));
}
}
}
} catch (Exception e) {
log.debug("학습 모델 결과 파일 확인 중 오류: {}", fileName, e);
}
return false;
}
/** 학습 모델 결과의 geometry 데이터 처리 */
@Transactional
public void processLearningModelGeometry(Long dataUid, String geoJsonContent, String fileName) {
try {
log.info("학습 모델 geometry 데이터 처리 시작: {} (dataUid: {})", fileName, dataUid);
JsonNode rootNode = objectMapper.readTree(geoJsonContent);
// 메타데이터 추출
String mapSheetName =
rootNode.has("name") ? rootNode.get("name").asText() : fileName.replace(".geojson", "");
// 파일명에서 연도 및 지도번호 추출 (캠코_2021_2022_35813023)
String[] parts = mapSheetName.split("_");
String beforeYear = null, afterYear = null, mapSheetNum = null;
if (parts.length >= 4) {
beforeYear = parts[1];
afterYear = parts[2];
mapSheetNum = parts[3];
}
if (beforeYear == null || afterYear == null) {
log.warn("연도 정보를 추출할 수 없습니다: {}", fileName);
return;
}
JsonNode features = rootNode.get("features");
if (features == null || !features.isArray()) {
log.warn("features 배열이 없습니다: {}", fileName);
return;
}
List<MapSheetLearnDataGeomEntity> geomEntities = new ArrayList<>();
int processedCount = 0;
for (JsonNode feature : features) {
try {
MapSheetLearnDataGeomEntity geomEntity =
createGeometryEntity(feature, dataUid, beforeYear, afterYear, mapSheetNum);
if (geomEntity != null) {
geomEntities.add(geomEntity);
processedCount++;
}
} catch (Exception e) {
log.warn("Feature geometry 처리 실패 (feature {}): {}", processedCount, e.getMessage());
}
}
// 배치 저장
if (!geomEntities.isEmpty()) {
mapSheetLearnDataGeomRepository.saveAll(geomEntities);
log.info("학습 모델 geometry 데이터 저장 완료: {} ({}개 feature)", fileName, geomEntities.size());
}
} catch (Exception e) {
log.error("학습 모델 geometry 데이터 처리 실패: {}", fileName, e);
}
}
/** 개별 feature에서 geometry entity 생성 */
private MapSheetLearnDataGeomEntity createGeometryEntity(
JsonNode feature, Long dataUid, String beforeYear, String afterYear, String mapSheetNum) {
JsonNode properties = feature.get("properties");
JsonNode geometry = feature.get("geometry");
if (properties == null || geometry == null) {
return null;
}
MapSheetLearnDataGeomEntity entity = new MapSheetLearnDataGeomEntity();
// 기본 정보
entity.setDataUid(dataUid);
entity.setBeforeYyyy(Integer.parseInt(beforeYear));
entity.setAfterYyyy(Integer.parseInt(afterYear));
if (mapSheetNum != null) {
try {
entity.setMapSheetNum(Long.parseLong(mapSheetNum));
} catch (NumberFormatException e) {
log.warn("지도번호 파싱 실패: {}", mapSheetNum, e);
}
}
// 변화 탐지 확률
if (properties.has("cd_prob")) {
entity.setCdProb(properties.get("cd_prob").asDouble());
}
// 면적 정보
if (properties.has("area")) {
entity.setArea(properties.get("area").asDouble());
}
// 분류 정보 처리
if (properties.has("class")) {
JsonNode classNode = properties.get("class");
// before 분류
if (classNode.has("before") && classNode.get("before").isArray()) {
JsonNode beforeArray = classNode.get("before");
if (beforeArray.size() > 0) {
JsonNode firstBefore = beforeArray.get(0);
if (firstBefore.has("class_name")) {
entity.setClassBeforeName(firstBefore.get("class_name").asText());
}
if (firstBefore.has("probability")) {
entity.setClassBeforeProb(firstBefore.get("probability").asDouble());
}
}
}
// after 분류
if (classNode.has("after") && classNode.get("after").isArray()) {
JsonNode afterArray = classNode.get("after");
if (afterArray.size() > 0) {
JsonNode firstAfter = afterArray.get(0);
if (firstAfter.has("class_name")) {
entity.setClassAfterName(firstAfter.get("class_name").asText());
}
if (firstAfter.has("probability")) {
entity.setClassAfterProb(firstAfter.get("probability").asDouble());
}
}
}
}
// geometry 변환
try {
Geometry geom = geoJsonReader.read(geometry.toString());
if (geom != null) {
geom.setSRID(5186); // EPSG:5186
entity.setGeom(geom);
}
} catch (Exception e) {
log.warn("Geometry 파싱 실패: {}", e.getMessage());
return null;
}
return entity;
}
}