review-to-geojson 로직 수정

This commit is contained in:
2026-03-06 10:52:03 +09:00
parent e833173756
commit 55010f0618
171 changed files with 861 additions and 1608 deletions

View File

@@ -0,0 +1,41 @@
package com.kamcoback.cd.review.common.utils.geometry;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.geojson.GeoJsonReader;
import org.springframework.util.StringUtils;
public class GeometryDeserializer<T extends Geometry> extends StdDeserializer<T> {
public GeometryDeserializer() {
super(Geometry.class);
}
public GeometryDeserializer(Class<T> targetType) {
super(targetType);
}
@SuppressWarnings("unchecked")
@Override
public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JacksonException {
String json = jsonParser.readValueAsTree().toString();
if (!StringUtils.hasText(json)) {
return null;
}
try {
GeoJsonReader reader = new GeoJsonReader();
Geometry geometry = reader.read(json);
geometry.setSRID(5186);
return (T) geometry;
} catch (Exception e) {
throw new IllegalArgumentException("Failed to deserialize GeoJSON into Geometry", e);
}
}
}

View File

@@ -0,0 +1,30 @@
package com.kamcoback.cd.review.common.utils.geometry;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Objects;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.geojson.GeoJsonWriter;
public class GeometrySerializer<T extends Geometry> extends StdSerializer<T> {
public GeometrySerializer(Class<T> targetType) {
super(targetType);
}
@Override
public void serialize(
T geometry, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (Objects.nonNull(geometry)) {
// default: 8자리 강제로 반올림시킴. 16자리로 늘려줌
GeoJsonWriter writer = new GeoJsonWriter(16);
String json = writer.write(geometry);
jsonGenerator.writeRawValue(json);
} else {
jsonGenerator.writeNull();
}
}
}

View File

@@ -0,0 +1,32 @@
package com.kamcoback.cd.review.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.kamcoback.cd.review.common.utils.geometry.GeometryDeserializer;
import com.kamcoback.cd.review.common.utils.geometry.GeometrySerializer;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public ObjectMapper objectMapper() {
SimpleModule module = new SimpleModule();
module.addSerializer(Geometry.class, new GeometrySerializer<>(Geometry.class));
module.addDeserializer(Geometry.class, new GeometryDeserializer<>(Geometry.class));
module.addSerializer(Polygon.class, new GeometrySerializer<>(Polygon.class));
module.addDeserializer(Polygon.class, new GeometryDeserializer<>(Polygon.class));
module.addSerializer(Point.class, new GeometrySerializer<>(Point.class));
module.addDeserializer(Point.class, new GeometryDeserializer<>(Point.class));
return Jackson2ObjectMapperBuilder.json().modulesToInstall(module).build();
}
}

View File

@@ -2,15 +2,16 @@ package com.kamcoback.cd.review.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.List;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.node.ObjectNode;
public class TrainingDataReviewJobDto {
@@ -83,7 +84,8 @@ public class TrainingDataReviewJobDto {
private JsonNode geometry;
private Properties properties;
public CompleteLabelData(Long geoUid, String type, String geomStr, Properties properties) {
public CompleteLabelData(Long geoUid, String type, String geomStr, Properties properties)
throws JsonProcessingException {
this.geoUid = geoUid;
this.type = type;
this.geomStr = geomStr;

View File

@@ -14,7 +14,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
@@ -35,14 +34,6 @@ public class TrainingDataReviewJobService {
@Value("${training-data.geojson-dir}")
private String trainingDataDir;
private boolean isLocalProfile() {
return "local".equalsIgnoreCase(profile);
}
public void runTask() {
exportGeojsonLabelingGeom(null);
}
@Transactional
public void exportGeojsonLabelingGeom(LocalDate baseDate) {
@@ -52,7 +43,7 @@ public class TrainingDataReviewJobService {
log.info("[Step 1-1] geojson 파일 생성할 경로: {}", targetDir);
// 2) 진행중인 회차 중, complete_cnt 가 존재하는 회차 목록 가져오기
log.info("[Step 1-2] 진행중인 회차 중, complete_cnt 가 존재하는 회차 목록 가져오기");
log.info("[Step 1-2] 진행중(ING)인 회차 중, 검수완료한(complete_cnt) 갯수가 존재하는 회차 목록 가져오기");
List<AnalCntInfo> analList = trainingDataReviewJobCoreService.findAnalCntInfoList();
log.info("[Step 1-3] 회차 리스트 건수: {}", analList == null ? 0 : analList.size());
@@ -62,19 +53,15 @@ public class TrainingDataReviewJobService {
}
for (AnalCntInfo info : analList) {
log.info("[Step 2-1] 회차 폴리곤 전체 건수 == 파일 생성 건수 같은지 확인");
log.info("=== info.getAllCnt(): {}", info.getAllCnt());
log.info("=== info.getFileCnt(): {}", info.getFileCnt());
if (Objects.equals(info.getAllCnt(), info.getFileCnt())) {
log.info("[Step 2-2] 회차 폴리곤 전체 건수 == 파일 생성 건수 같아서 파일 생성 진행하지 않음 continue");
continue;
}
log.info("[Step 2-1] 회차별 조회하여 작업 시작");
String resultUid = info.getResultUid(); // 회차의 대문자 uid (폴더명으로 사용)
// 3) 회차 + 어제까지 검수 완료된 총 데이터의 도엽별 목록 가져오기
log.info("[Step 3-1] 회차 + 어제까지 검수 완료된 총 데이터의 도엽별 목록 가져오기");
log.info(" === 기준일자 baseDate : " + baseDate);
log.info(" === 검수완료일자 < 기준일자인 폴리곤의 도엽 목록을 조회");
List<AnalMapSheetList> analMapList =
trainingDataReviewJobCoreService.findCompletedAnalMapSheetList(
info.getAnalUid(), baseDate);
@@ -85,7 +72,7 @@ public class TrainingDataReviewJobService {
continue;
}
log.info("[Step 4-1] 도엽별 geom 데이터 가지고 와서 geojson 만들기 시작");
log.info("[Step 4-1] 도엽별 geom 데이터 가지고 와서 geojson 만들기 시작");
for (AnalMapSheetList mapSheet : analMapList) {
// 4) 도엽별 geom 데이터 가지고 와서 geojson 만들기
log.info("[Step 4-2] 도엽별 검수완료된 폴리곤 데이터 목록 조회");
@@ -124,9 +111,7 @@ public class TrainingDataReviewJobService {
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
objectMapper.writeValue(outputPath.toFile(), collection);
// geoUids : file_create_yn = true 로 업데이트
log.info("[Step 6-3] learn_data_geom 에 file_create_yn = true 로 업데이트");
trainingDataReviewJobCoreService.updateLearnDataGeomFileCreateYn(geoUids);
log.info("[Step 6-3] geoJson 파일 생성 완료");
} catch (IOException e) {
log.error(e.getMessage());