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.AsyncResultManager; import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckKeys; import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultHead; import com.shkpr.service.alambizplugin.constants.LogFlagBusiType; import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine; import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement; import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId; import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.index.strtree.STRtree; 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.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * 交叉线差寻找器 * * @author 欧阳劲驰 * @since 1.0.0 */ @Component public class CrossLinesFinder { /** * log */ private final String mStrClassName; private final String mBizType; private final AsyncResultManager asyncResultManager; public CrossLinesFinder(AsyncResultManager asyncResultManager) { mStrClassName = "OverlapLinesFinder"; mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue(); this.asyncResultManager = asyncResultManager; } /** * 寻找交叉线 *

返回的为交叉线组,未交叉的线不会出现在返回结果

*

一组线,仅为两条交叉的线,长度固定为2

* * @param lines 线集合 * @return 交叉线分组 */ @Async public ListenableFuture findCrossLines(List lines , GisSurveySystemCheckId systemCheckId) throws InterruptedException { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重叠线========>"); long begin = System.currentTimeMillis(); //创建空间索引 STRtree tree = new STRtree(); //元素存入索引 for (GisSurveyLayerApplyLine layerApplyLine : lines) { if (layerApplyLine.getGis() == null) continue; LineString line = layerApplyLine.getGis(); tree.insert(line.getEnvelopeInternal(), layerApplyLine); } tree.build(); //结果 List> groupElements = new ArrayList<>(); //处理过的code Set processedCodes = new HashSet<>(); //遍历所有线 for (GisSurveyLayerApplyLine line1 : lines) { if (line1.getGis() == null) continue; //响应中断 if (Thread.interrupted()) throw new InterruptedException(); //查询索引内元素 List candidates = tree.query(line1.getGis().getEnvelopeInternal()); for (Object obj : candidates) { GisSurveyLayerApplyLine line2 = (GisSurveyLayerApplyLine) obj; //排除code相同或已经处理的元素, if (Objects.equals(line1.getCode(), line2.getCode()) || processedCodes.contains(line2.getCode()) || line2.getGis() == null ) continue; //响应中断 if (Thread.interrupted()) throw new InterruptedException(); // 判断是否交叉 if (line1.getGis().crosses(line2.getGis())) { //创建两两一组交叉线对 groupElements.add(Arrays.asList( BeanUtil.copy(line1, GisSurveySystemCheckElement.class), BeanUtil.copy(line2, GisSurveySystemCheckElement.class) )); } } //存入code,避免重复处理 processedCodes.add(line1.getCode()); } return new AsyncResult<>(createResult(groupElements, systemCheckId, begin)); } /** * 创建结果 * * @param data 数据 * @param systemCheckId 系统检查id * @param begin 开始时间 * @return 结果 */ private GisSurveySystemCheckResultDetail createResult(List> data , GisSurveySystemCheckId systemCheckId, long begin) { //数据大小 final int size = data.size(); //结果flag final String FLAG = systemCheckId.getFlag(); //写入json和excel结果 Path jsonPath = asyncResultManager.writeJson(data, FLAG, GisSurveySystemCheckKeys.CROSS_LINES + ".json"); Path excelPath = asyncResultManager.writeExcel(GisSurveySystemCheckResultHead.CROSS_LINES, buildExcel(data), FLAG, GisSurveySystemCheckKeys.CROSS_LINES + ".xlsx"); long end = System.currentTimeMillis(); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName , String.format( "结束执行寻找交叉线,用时(毫秒):%d" , (end - begin) ) ); //构建结果 return new GisSurveySystemCheckResultDetail(true , FLAG + "/" + jsonPath.getFileName() , FLAG + "/" + excelPath.getFileName() , size); } /** * 构建excel数据 * * @param data 数据 * @return excel数据 */ private List> buildExcel(List> data) { return IntStream.range(0, data.size()) .boxed() .flatMap(i -> data.get(i).stream().map(element -> { Map map = new HashMap<>(); map.put(GisSurveySystemCheckResultHead.KEYS.GROUP_NAME, i + 1); map.put(GisSurveySystemCheckResultHead.KEYS.UP_NO, element.getUpNo()); map.put(GisSurveySystemCheckResultHead.KEYS.DOWN_NO, element.getDownNo()); map.put(GisSurveySystemCheckResultHead.KEYS.CODE, element.getCode()); map.put(GisSurveySystemCheckResultHead.KEYS.UP_NODE, element.getUpNode()); map.put(GisSurveySystemCheckResultHead.KEYS.DOWN_NODE, element.getDownNode()); map.put(GisSurveySystemCheckResultHead.KEYS.NAME, element.getName()); return map; })).collect(Collectors.toList()); } }