DuplicatePointsFinder.java 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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.components.GisSurveySystemCheckResultManager;
  6. import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
  7. import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine;
  8. import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultPath;
  9. import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
  10. import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyPoint;
  11. import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement;
  12. import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId;
  13. import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
  14. import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement;
  15. import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail;
  16. import com.shkpr.service.alambizplugin.dto.TypeDefine;
  17. import org.apache.commons.lang3.StringUtils;
  18. import org.locationtech.jts.geom.Coordinate;
  19. import org.springframework.scheduling.annotation.Async;
  20. import org.springframework.scheduling.annotation.AsyncResult;
  21. import org.springframework.stereotype.Component;
  22. import org.springframework.util.concurrent.ListenableFuture;
  23. import java.math.BigDecimal;
  24. import java.math.RoundingMode;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.stream.Collectors;
  28. /**
  29. * 重复点寻找器
  30. *
  31. * @author 欧阳劲驰
  32. * @since 1.0.0
  33. */
  34. @Component
  35. public class DuplicatePointsFinder {
  36. /**
  37. * 经纬度默认精度
  38. */
  39. private final static int DEFAULT_SCALE = 6;
  40. /**
  41. * 经度key
  42. */
  43. private final static String LNG_KEY = "lng";
  44. /**
  45. * 纬度key
  46. */
  47. private final static String LAT_KEY = "lat";
  48. /**
  49. * log
  50. */
  51. private final String mStrClassName;
  52. private final String mBizType;
  53. private final GisSurveySystemCheckResultManager gisSurveySystemCheckResultManager;
  54. public DuplicatePointsFinder(GisSurveySystemCheckResultManager gisSurveySystemCheckResultManager) {
  55. mStrClassName = "DuplicatePointsFinder";
  56. mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
  57. this.gisSurveySystemCheckResultManager = gisSurveySystemCheckResultManager;
  58. }
  59. /**
  60. * 寻找重复点
  61. * <p>根据 <strong>code</strong> 匹配</p>
  62. *
  63. * @param points 点集合
  64. * @return 重复点
  65. */
  66. @Async
  67. public ListenableFuture<GisSurveyThirdImportResultDetail<List<GisSurveyThirdImportElement>>> findDuplicatePoints(List<Map<String, String>> points) throws InterruptedException {
  68. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重复点 ======>");
  69. long begin = System.currentTimeMillis();
  70. //根据code度分组
  71. Map<String, List<Map<String, String>>> keyToPoints = points.parallelStream()
  72. //过滤类型为字符串
  73. .filter(point ->
  74. point.get(GisSurveyImportDefine.POINT.NO) != null)
  75. .collect(Collectors.groupingBy(point ->
  76. point.get(GisSurveyImportDefine.POINT.NO),
  77. Collectors.toList())
  78. );
  79. //响应中断
  80. if (Thread.interrupted()) throw new InterruptedException();
  81. //并行流寻找重复点号
  82. List<GisSurveyThirdImportElement> groupElements = keyToPoints.entrySet().parallelStream()
  83. //过滤组内大于1
  84. .filter(group -> group.getValue().size() > 1)
  85. .map(entry -> new GisSurveyThirdImportElement(GisMetadataDefine.TYPE_KINE.POINT, entry.getKey()))
  86. .collect(Collectors.toList());
  87. long end = System.currentTimeMillis();
  88. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  89. , String.format(
  90. "结束执行寻找重复点,用时(毫秒):%d"
  91. , (end - begin)
  92. )
  93. );
  94. return new AsyncResult<>(new GisSurveyThirdImportResultDetail<>(true, groupElements));
  95. }
  96. /**
  97. * 寻找重复点
  98. * <p>根据 <strong>精度</strong> 强匹配</p>
  99. *
  100. * @param points 点集合
  101. * @param typeDefines 类型定义
  102. * @return 重复点
  103. */
  104. @Async
  105. public ListenableFuture<GisSurveySystemCheckResultDetail> findDuplicatePoints(List<GisSurveyLayerApplyPoint> points
  106. , List<TypeDefine> typeDefines, GisSurveySystemCheckId systemCheckId) throws InterruptedException {
  107. //经纬度精度
  108. int lonScale = getScale(typeDefines, LNG_KEY);
  109. int latScale = getScale(typeDefines, LAT_KEY);
  110. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName,
  111. String.format("开始执行寻找重复点 经度精度:%s 纬度精度:%s ======>", lonScale, latScale));
  112. long begin = System.currentTimeMillis();
  113. //根据经纬度分组
  114. Map<String, List<GisSurveyLayerApplyPoint>> keyToPoints = points.parallelStream()
  115. .collect(Collectors.groupingBy(point -> {
  116. //抹去经纬度精度,并设置为分组条件
  117. Coordinate coordinate = point.getGis().getCoordinate();
  118. BigDecimal bdLon = new BigDecimal(Double.toString(coordinate.getX())).setScale(lonScale, RoundingMode.DOWN);
  119. BigDecimal bdLat = new BigDecimal(Double.toString(coordinate.getY())).setScale(latScale, RoundingMode.DOWN);
  120. return String.format("%s%s%s", bdLon.toPlainString(), bdLat.toPlainString(), point.getElevation());
  121. }, Collectors.toList()));
  122. //响应中断
  123. if (Thread.interrupted()) throw new InterruptedException();
  124. //并行流寻找重复点
  125. List<List<GisSurveySystemCheckElement>> groupElements = keyToPoints.values().parallelStream()
  126. //过滤组内大于1
  127. .filter(group -> group.size() > 1)
  128. //转为返回元素
  129. .map(group -> group.stream()
  130. .map(point -> BeanUtil.copy(point, GisSurveySystemCheckElement.class))
  131. .collect(Collectors.toList())
  132. )
  133. .collect(Collectors.toList());
  134. return new AsyncResult<>(createResult(groupElements, systemCheckId, begin));
  135. }
  136. /**
  137. * 获取精度
  138. *
  139. * @param typeDefines 类型定义
  140. * @param key 类型定义key
  141. * @return 经度精度
  142. */
  143. private int getScale(List<TypeDefine> typeDefines, String key) {
  144. //空返回默认值
  145. if (typeDefines == null || typeDefines.isEmpty()) return DEFAULT_SCALE;
  146. //过滤出纬度类型定义
  147. TypeDefine typeDefine = typeDefines.stream()
  148. .filter(td -> key.equals(td.getKey()))
  149. .findFirst()
  150. .orElse(null);
  151. //解析参数而,转换成数字,大于等于0则使用字典
  152. if (typeDefine != null && StringUtils.isNotBlank(typeDefine.getParam2())) {
  153. try {
  154. int lngScale = Integer.parseInt(typeDefine.getParam2());
  155. return lngScale < 0 ? DEFAULT_SCALE : lngScale;
  156. } catch (NumberFormatException e) {
  157. return DEFAULT_SCALE;
  158. }
  159. }
  160. return DEFAULT_SCALE;
  161. }
  162. /**
  163. * 创建结果
  164. *
  165. * @param data 数据
  166. * @param systemCheckId 系统检查id
  167. * @param begin 开始时间
  168. * @return 结果
  169. */
  170. private GisSurveySystemCheckResultDetail createResult(List<List<GisSurveySystemCheckElement>> data
  171. , GisSurveySystemCheckId systemCheckId, long begin) {
  172. //数据大小
  173. final int size = data.size();
  174. //写入路径
  175. String path = GisSurveySystemCheckResultPath.DUPLICATE_POINTS;
  176. //写入文件
  177. gisSurveySystemCheckResultManager.writeResult(data, systemCheckId, path);
  178. long end = System.currentTimeMillis();
  179. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  180. , String.format(
  181. "结束执行寻找重复点,用时(毫秒):%d"
  182. , (end - begin)
  183. )
  184. );
  185. //构建结果
  186. return new GisSurveySystemCheckResultDetail(true, GisSurveySystemCheckResultPath.relativePath(systemCheckId, path), size);
  187. }
  188. }