123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- 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.constants.LogFlagBusiType;
- import com.shkpr.service.alambizplugin.dto.GisSurveyCheckElement;
- import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
- import org.locationtech.jts.algorithm.Orientation;
- import org.locationtech.jts.geom.Coordinate;
- import org.locationtech.jts.geom.LineSegment;
- 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.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- /**
- * 寻找重复线
- *
- * @author 欧阳劲驰
- * @since 0.0.1
- */
- @Component
- public class OverlapLinesFinder {
- //双精度误差
- private static final double EPSILON = Double.longBitsToDouble(0x3ca0000000000000L);
- /**
- * log
- */
- private final String mStrClassName;
- private final String mBizType;
- public OverlapLinesFinder() {
- mStrClassName = "OverlapLinesFinder";
- mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
- }
- /**
- * 寻找重复线
- * <p>返回的为重复线组,未重复的线不会出现在返回结果</p>
- * <p>一组线,仅为两条重叠的线,长度固定为2</p>
- *
- * @param lines 线集合
- * @return 重复线分组
- */
- @Async
- public ListenableFuture<List<List<GisSurveyCheckElement>>> findDuplicateLines(List<GisSurveyLayerApplyLine> lines) throws InterruptedException {
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重复线========>");
- long begin = System.currentTimeMillis();
- //结果
- List<List<GisSurveyCheckElement>> result = new ArrayList<>();
- //双层循环遍历所有线
- for (int i = 0; i < lines.size(); i++) {
- GisSurveyLayerApplyLine line1 = lines.get(i);
- //响应中断
- if (Thread.interrupted()) throw new InterruptedException();
- for (int j = i + 1; j < lines.size(); j++) {
- GisSurveyLayerApplyLine line2 = lines.get(j);
- //响应中断
- if (Thread.interrupted()) throw new InterruptedException();
- // 判断是否重复
- if (calcDuplicateLines(line1, line2)) {
- // 创建两两一组的重复线对
- result.add(Arrays.asList(BeanUtil.copy(line1, GisSurveyCheckElement.class),
- BeanUtil.copy(line2, GisSurveyCheckElement.class)));
- }
- }
- }
- long end = System.currentTimeMillis();
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
- , String.format(
- "结束执行寻找重复线,用时(毫秒):%d"
- , (end - begin)
- )
- );
- return new AsyncResult<>(result);
- }
- /**
- * 计算重叠线
- *
- * @param line1 线段1
- * @param line2 线段2
- * @return 重叠状态
- */
- public boolean calcDuplicateLines(GisSurveyLayerApplyLine line1, GisSurveyLayerApplyLine line2) {
- //取出四个点
- Coordinate a = line2.getGis().getCoordinateN(0);
- Coordinate b = line1.getGis().getCoordinateN(1);
- Coordinate c = line2.getGis().getCoordinateN(0);
- Coordinate d = line2.getGis().getCoordinateN(1);
- //点数量判断
- if (a == null || b == null || c == null || d == null) return false;
- //检查C和D是否在AB的直线上(叉积为0,则方向一致)
- if (Orientation.index(a, b, c) != 0 || Orientation.index(a, b, d) != 0) return false;
- LineSegment seg1 = new LineSegment(a, b);
- LineSegment seg2 = new LineSegment(a, b);
- //四点共点判断
- if (seg1.equals(seg2)) return true;
- //获取C和D对于线段1的投影因子
- double tC = seg1.projectionFactor(c);
- double tD = seg1.projectionFactor(d);
- //获取最小和最大投影因子
- double cdMin = Math.min(tC, tD);
- double cdMax = Math.max(tC, tD);
- //排除前后延伸联通线
- if (cdMin == 1 && cdMax >= 1) return false;
- if (cdMax == 0 && cdMin <= 0) return false;
- //判断最大因子是否向前延伸或处于线段内,并且最小因子是否向后延伸或处于线段内
- return (cdMax + EPSILON >= 0) && (cdMin - EPSILON <= 1);
- }
- }
|