DuplicatePointsFinder.java 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package com.shkpr.service.alambizplugin.components.checker;
  2. import com.global.base.log.LogLevelFlag;
  3. import com.global.base.log.LogPrintMgr;
  4. import com.shkpr.service.alambizplugin.commtools.BeanUtil;
  5. import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
  6. import com.shkpr.service.alambizplugin.dto.GisSurveyCheckElement;
  7. import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
  8. import com.shkpr.service.alambizplugin.dto.TypeDefine;
  9. import org.apache.commons.lang3.StringUtils;
  10. import org.locationtech.jts.geom.Coordinate;
  11. import org.springframework.scheduling.annotation.Async;
  12. import org.springframework.scheduling.annotation.AsyncResult;
  13. import org.springframework.stereotype.Component;
  14. import org.springframework.util.concurrent.ListenableFuture;
  15. import java.math.BigDecimal;
  16. import java.math.RoundingMode;
  17. import java.util.List;
  18. import java.util.Map;
  19. import java.util.stream.Collectors;
  20. /**
  21. * 重复点寻找器
  22. */
  23. @Component
  24. public class DuplicatePointsFinder {
  25. /**
  26. * 经纬度默认精度
  27. */
  28. private final static int DEFAULT_SCALE = 6;
  29. /**
  30. * 经度key
  31. */
  32. private final static String LNG_KEY = "lng";
  33. /**
  34. * 纬度key
  35. */
  36. private final static String LAT_KEY = "lat";
  37. /**
  38. * log
  39. */
  40. private final String mStrClassName;
  41. private final String mBizType;
  42. public DuplicatePointsFinder() {
  43. mStrClassName = "DuplicatePointsFinder";
  44. mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
  45. }
  46. /**
  47. * 寻找重复点
  48. * <p>根据 <strong>精度</strong> 强匹配</p>
  49. *
  50. * @param points 点集合
  51. * @param typeDefines 类型定义
  52. * @return 重复点
  53. */
  54. @Async
  55. public ListenableFuture<List<List<GisSurveyCheckElement>>> findDuplicatePoints(List<GisSurveyLayerApplyPoint> points, List<TypeDefine> typeDefines) throws InterruptedException {
  56. //经纬度精度
  57. int lonScale = getScale(typeDefines, LNG_KEY);
  58. int latScale = getScale(typeDefines, LAT_KEY);
  59. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName,
  60. String.format("开始执行寻找重复点 经度精度:%s 纬度精度:%s ======>", lonScale, latScale));
  61. long begin = System.currentTimeMillis();
  62. //根据经纬度分组
  63. Map<String, List<GisSurveyLayerApplyPoint>> keyToPoints = points.parallelStream()
  64. .collect(Collectors.groupingBy(point -> {
  65. //抹去经纬度精度,并设置为分组条件
  66. Coordinate coordinate = point.getGis().getCoordinate();
  67. BigDecimal bdLon = new BigDecimal(Double.toString(coordinate.getX())).setScale(lonScale, RoundingMode.DOWN);
  68. BigDecimal bdLat = new BigDecimal(Double.toString(coordinate.getY())).setScale(latScale, RoundingMode.DOWN);
  69. return String.format("%s%s%s", bdLon.toPlainString(), bdLat.toPlainString(), point.getElevation());
  70. }, Collectors.toList()));
  71. //响应中断
  72. if (Thread.interrupted()) throw new InterruptedException();
  73. //并行流处理
  74. List<List<GisSurveyCheckElement>> collect = keyToPoints.values().parallelStream()
  75. //过滤组内大于1
  76. .filter(group -> group.size() > 1)
  77. //转为返回元素
  78. .map(group -> group.stream()
  79. .map(point-> BeanUtil.copy(point, GisSurveyCheckElement.class))
  80. .collect(Collectors.toList())
  81. )
  82. .collect(Collectors.toList());
  83. long end = System.currentTimeMillis();
  84. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  85. , String.format(
  86. "结束执行寻找重复点,用时(毫秒):%d"
  87. , (end - begin)
  88. )
  89. );
  90. return new AsyncResult<>(collect);
  91. }
  92. /**
  93. * 获取精度
  94. *
  95. * @param typeDefines 类型定义
  96. * @param key 类型定义key
  97. * @return 经度精度
  98. */
  99. private int getScale(List<TypeDefine> typeDefines, String key) {
  100. //空返回默认值
  101. if (typeDefines == null || typeDefines.isEmpty()) return DEFAULT_SCALE;
  102. //过滤出纬度类型定义
  103. TypeDefine typeDefine = typeDefines.stream()
  104. .filter(td -> key.equals(td.getKey()))
  105. .findFirst()
  106. .orElse(null);
  107. //解析参数而,转换成数字,大于等于0则使用字典
  108. if (typeDefine != null && StringUtils.isNotBlank(typeDefine.getParam2())) {
  109. try {
  110. int lngScale = Integer.parseInt(typeDefine.getParam2());
  111. return lngScale < 0 ? DEFAULT_SCALE : lngScale;
  112. } catch (NumberFormatException e) {
  113. return DEFAULT_SCALE;
  114. }
  115. }
  116. return DEFAULT_SCALE;
  117. }
  118. }