package com.shkpr.service.alambizplugin.components.checker; import com.global.base.log.LogLevelFlag; import com.global.base.log.LogPrintMgr; import com.shkpr.service.alambizplugin.commtools.BeanUtil; import com.shkpr.service.alambizplugin.components.GisSurveySystemCheckResultManager; import com.shkpr.service.alambizplugin.constants.GisMetadataDefine; import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine; import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultPath; import com.shkpr.service.alambizplugin.constants.LogFlagBusiType; import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint; import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement; import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId; import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail; import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement; import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail; import com.shkpr.service.alambizplugin.dto.TypeDefine; import org.apache.commons.lang3.StringUtils; import org.locationtech.jts.geom.Coordinate; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component; import org.springframework.util.concurrent.ListenableFuture; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 重复点寻找器 * * @author 欧阳劲驰 * @since 1.0.0 */ @Component public class DuplicatePointsFinder { /** * 经纬度默认精度 */ private final static int DEFAULT_SCALE = 6; /** * 经度key */ private final static String LNG_KEY = "lng"; /** * 纬度key */ private final static String LAT_KEY = "lat"; /** * log */ private final String mStrClassName; private final String mBizType; private final GisSurveySystemCheckResultManager gisSurveySystemCheckResultManager; public DuplicatePointsFinder(GisSurveySystemCheckResultManager gisSurveySystemCheckResultManager) { mStrClassName = "DuplicatePointsFinder"; mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue(); this.gisSurveySystemCheckResultManager = gisSurveySystemCheckResultManager; } /** * 寻找重复点 *

根据 code 匹配

* * @param points 点集合 * @return 重复点 */ @Async public ListenableFuture>> findDuplicatePoints(List> points) throws InterruptedException { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重复点 ======>"); long begin = System.currentTimeMillis(); //根据code度分组 Map>> keyToPoints = points.parallelStream() //过滤类型为字符串 .filter(point -> point.get(GisSurveyImportDefine.POINT.NO) != null) .collect(Collectors.groupingBy(point -> point.get(GisSurveyImportDefine.POINT.NO), Collectors.toList()) ); //响应中断 if (Thread.interrupted()) throw new InterruptedException(); //并行流寻找重复点号 List groupElements = keyToPoints.entrySet().parallelStream() //过滤组内大于1 .filter(group -> group.getValue().size() > 1) .map(entry -> new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT, entry.getKey())) .collect(Collectors.toList()); long end = System.currentTimeMillis(); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName , String.format( "结束执行寻找重复点,用时(毫秒):%d" , (end - begin) ) ); return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, groupElements)); } /** * 寻找重复点 *

根据 精度 强匹配

* * @param points 点集合 * @param typeDefines 类型定义 * @return 重复点 */ @Async public ListenableFuture findDuplicatePoints(List points , List typeDefines, GisSurveySystemCheckId systemCheckId) throws InterruptedException { //经纬度精度 int lonScale = getScale(typeDefines, LNG_KEY); int latScale = getScale(typeDefines, LAT_KEY); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, String.format("开始执行寻找重复点 经度精度:%s 纬度精度:%s ======>", lonScale, latScale)); long begin = System.currentTimeMillis(); //根据经纬度分组 Map> keyToPoints = points.parallelStream() .collect(Collectors.groupingBy(point -> { //抹去经纬度精度,并设置为分组条件 Coordinate coordinate = point.getGis().getCoordinate(); BigDecimal bdLon = new BigDecimal(Double.toString(coordinate.getX())).setScale(lonScale, RoundingMode.DOWN); BigDecimal bdLat = new BigDecimal(Double.toString(coordinate.getY())).setScale(latScale, RoundingMode.DOWN); return String.format("%s%s%s", bdLon.toPlainString(), bdLat.toPlainString(), point.getElevation()); }, Collectors.toList())); //响应中断 if (Thread.interrupted()) throw new InterruptedException(); //并行流寻找重复点 List> groupElements = keyToPoints.values().parallelStream() //过滤组内大于1 .filter(group -> group.size() > 1) //转为返回元素 .map(group -> group.stream() .map(point -> BeanUtil.copy(point, GisSurveySystemCheckElement.class)) .collect(Collectors.toList()) ) .collect(Collectors.toList()); return new AsyncResult<>(createResult(groupElements, systemCheckId, begin)); } /** * 获取精度 * * @param typeDefines 类型定义 * @param key 类型定义key * @return 经度精度 */ private int getScale(List typeDefines, String key) { //空返回默认值 if (typeDefines == null || typeDefines.isEmpty()) return DEFAULT_SCALE; //过滤出纬度类型定义 TypeDefine typeDefine = typeDefines.stream() .filter(td -> key.equals(td.getKey())) .findFirst() .orElse(null); //解析参数而,转换成数字,大于等于0则使用字典 if (typeDefine != null && StringUtils.isNotBlank(typeDefine.getParam2())) { try { int lngScale = Integer.parseInt(typeDefine.getParam2()); return lngScale < 0 ? DEFAULT_SCALE : lngScale; } catch (NumberFormatException e) { return DEFAULT_SCALE; } } return DEFAULT_SCALE; } /** * 创建结果 * * @param data 数据 * @param systemCheckId 系统检查id * @param begin 开始时间 * @return 结果 */ private GisSurveySystemCheckResultDetail createResult(List> data , GisSurveySystemCheckId systemCheckId, long begin) { //数据大小 final int size = data.size(); //写入路径 String path = GisSurveySystemCheckResultPath.DUPLICATE_POINTS; //写入文件 gisSurveySystemCheckResultManager.writeResult(data, systemCheckId, path); long end = System.currentTimeMillis(); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName , String.format( "结束执行寻找重复点,用时(毫秒):%d" , (end - begin) ) ); //构建结果 return new GisSurveySystemCheckResultDetail(true, GisSurveySystemCheckResultPath.relativePath(systemCheckId, path), size); } }