LocationUtil.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package com.ylx.massage.utils;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import com.ylx.common.constant.MassageConstants;
  4. import com.ylx.massage.domain.Location;
  5. import com.ylx.massage.domain.TJs;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.apache.commons.compress.utils.Lists;
  8. import org.redisson.api.RGeoAsync;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.data.geo.*;
  11. import org.springframework.data.redis.connection.RedisGeoCommands;
  12. import org.springframework.data.redis.core.BoundGeoOperations;
  13. import org.springframework.data.redis.core.GeoOperations;
  14. import org.springframework.data.redis.core.RedisTemplate;
  15. import org.springframework.stereotype.Component;
  16. import java.math.BigDecimal;
  17. import java.util.*;
  18. /**
  19. * @author jianlong
  20. * @date 2024-04-07 15:49
  21. */
  22. @Component
  23. @Slf4j
  24. public class LocationUtil {
  25. @Autowired
  26. private RedisTemplate<String, String> redisTemplate;
  27. /**
  28. * 作为存储经纬度列表的key值
  29. */
  30. public static final String GEO_KEY = MassageConstants.ATLAS + "JS_POSITION";
  31. public static final String GEO_KEY_USER = MassageConstants.ATLAS + "USER_POSITION";
  32. /**
  33. * 将经纬度信息添加到redis中
  34. *
  35. * @param geoKey 存储经纬度列表的key值
  36. * @param certId 标识
  37. * @param longitude 经度
  38. * @param latitude 纬度
  39. */
  40. public void geoAdd(String geoKey,String certId, double longitude, double latitude) {
  41. log.info("LocationUtil.geoAdd:" + geoKey + ":" + certId + ":" + longitude + ":" + latitude);
  42. GeoOperations geoOperations = redisTemplate.opsForGeo();
  43. Point point = new Point(longitude, latitude);
  44. RedisGeoCommands.GeoLocation geoLocation = new RedisGeoCommands.GeoLocation(certId, point);
  45. Long add = geoOperations.add(geoKey, geoLocation);
  46. log.info("LocationUtil.geoAdd:" + add);
  47. }
  48. public void remove(String geoKey,String certId1,String certId2) {
  49. GeoOperations geoOperations = redisTemplate.opsForGeo();
  50. Long remove = geoOperations.remove(geoKey, certId1, certId2);
  51. log.info("LocationUtil.remove:" + remove);
  52. }
  53. /**
  54. * 两个人之间的距离
  55. *
  56. * @param certId1
  57. * @param certId2
  58. * @return
  59. */
  60. public double distanceBetween(String certId1, String certId2) {
  61. GeoOperations geoOperations = redisTemplate.opsForGeo();
  62. Distance distance = geoOperations.distance(GEO_KEY, certId1, certId2);
  63. return distance.getValue();
  64. }
  65. /**
  66. * 查询距离某个人指定范围内的人,包括距离多少米
  67. *
  68. * @param certId
  69. * @param distance
  70. * @return
  71. */
  72. public Map<String, Double> distanceInclude(String certId, double distance) {
  73. Map<String, Double> map = new LinkedHashMap<>();
  74. GeoOperations geoOperations = redisTemplate.opsForGeo();
  75. RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
  76. GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = geoOperations.radius(GEO_KEY, certId, new Distance(distance), geoRadiusCommandArgs.includeDistance());
  77. if (geoResults != null) {
  78. Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = geoResults.iterator();
  79. while (iterator.hasNext()) {
  80. GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = iterator.next();
  81. // 与目标点相距的距离信息
  82. Distance geoResultDistance = geoResult.getDistance();
  83. // 该点的信息
  84. RedisGeoCommands.GeoLocation<String> geoResultContent = geoResult.getContent();
  85. map.put(geoResultContent.getName(), geoResultDistance.getValue());
  86. }
  87. }
  88. return map;
  89. }
  90. /**
  91. * 获取附近的技师以及距离
  92. *
  93. * @param locationBo 位置信息
  94. * @return List<TJs> 附近的技师以及距离
  95. */
  96. public List<TJs> dis(Location locationBo) {
  97. ArrayList<TJs> js = Lists.newArrayList();
  98. //设置当前位置
  99. Point point = new Point(locationBo.getLongitude(), locationBo.getLatitude());
  100. //设置半径范围
  101. Metric metric = RedisGeoCommands.DistanceUnit.KILOMETERS;
  102. Distance distance = new Distance(locationBo.getRadius(), metric);
  103. Circle circle = new Circle(point, distance);
  104. //设置参数 包括距离、坐标、条数
  105. RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands
  106. .GeoRadiusCommandArgs
  107. .newGeoRadiusArgs()
  108. .includeDistance()
  109. .includeCoordinates()
  110. .sortAscending()
  111. .limit(locationBo.getLimit());
  112. BoundGeoOperations<String, String> stringStringBoundGeoOperations = redisTemplate.boundGeoOps(GEO_KEY);
  113. GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringStringBoundGeoOperations.radius(circle, args);
  114. if (radius == null || CollectionUtil.isEmpty(radius.getContent())) {
  115. return null;
  116. }
  117. radius.forEach(content -> {
  118. TJs tJs = new TJs();
  119. tJs.setcPhone(content.getContent().getName());
  120. tJs.setDistance(BigDecimal.valueOf(content.getDistance().getValue()));
  121. js.add(tJs);
  122. });
  123. return js;
  124. }
  125. /**
  126. * 获得两点之间的距离
  127. *
  128. * @param jsKey 技师key
  129. * @param userKey 用户key
  130. * @return double 距离
  131. * */
  132. public double getDistance(String jsKey,String userKey) {
  133. // 获取两个城市之间的距离
  134. Distance distance = redisTemplate.opsForGeo().distance(GEO_KEY_USER, jsKey, userKey, RedisGeoCommands.DistanceUnit.KILOMETERS);
  135. log.info("distance:"+distance.toString());
  136. log.info("获取"+jsKey + "--"+userKey +"两之间的距离:"+distance.getValue()+"千米");
  137. return distance.getValue();
  138. }
  139. }