空间计算误差减小、边界点包含

This commit is contained in:
attiya 2025-04-24 09:15:33 +08:00
parent 46c1445737
commit f7a9c475ff
2 changed files with 21 additions and 17 deletions

View File

@ -99,7 +99,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, UserOrd
ResGPSDto resGpsDto = JSONObject.parseObject(jsonString, ResGPSDto.class); ResGPSDto resGpsDto = JSONObject.parseObject(jsonString, ResGPSDto.class);
boolean pointInOperation = bikeInOperation(resGpsDto.getLongitude(), resGpsDto.getLatitude(), regionDto.getOrgId(), regionDto.getRegionId()); boolean pointInOperation = bikeInOperation(resGpsDto.getLongitude(), resGpsDto.getLatitude(), regionDto.getOrgId(), regionDto.getRegionId());
if (!pointInOperation){ if (!pointInOperation){
throw new RuntimeException("当前车辆运营区外"); throw new RuntimeException("当前车辆运营区外");
} }
//开锁,并且等待结果 //开锁,并且等待结果
CompletableFuture<String> stringCompletableFuture = ebikeCoreHandler.executeCommand(ecuInfo, CmdCode.UNLOCK, Long.valueOf(bikeInfoDto.getBikeId()), userId); CompletableFuture<String> stringCompletableFuture = ebikeCoreHandler.executeCommand(ecuInfo, CmdCode.UNLOCK, Long.valueOf(bikeInfoDto.getBikeId()), userId);

View File

@ -1,17 +1,20 @@
package com.cdzy.orders.uitls; package com.cdzy.orders.uitls;
import com.cdzy.common.utils.CoordinateUtil;
import com.cdzy.orders.model.dto.res.RedisPoint; import com.cdzy.orders.model.dto.res.RedisPoint;
import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.io.WKTReader;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*; import org.springframework.data.geo.*;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands; import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -33,8 +36,7 @@ public class RedisUtil {
private final String parkingKey = "parking_geo"; private final String parkingKey = "parking_geo";
private final String operationKey = "operation_geo"; private final String operationKey = "operation_geo";
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(new PrecisionModel(1000));
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
private static final WKTReader WKT_READER = new WKTReader(GEOMETRY_FACTORY); private static final WKTReader WKT_READER = new WKTReader(GEOMETRY_FACTORY);
@ -235,16 +237,6 @@ public class RedisUtil {
* @return true-在内部false-在外部或边界上根据业务需求调整 * @return true-在内部false-在外部或边界上根据业务需求调整
*/ */
public boolean isPointInOperation(double lng, double lat,Long orgId,Long areaId) { public boolean isPointInOperation(double lng, double lat,Long orgId,Long areaId) {
//查询附近停车区
// List<String> nearbyParking = findNearbyAreaByOperation(lng, lat,orgId);
// if (nearbyParking.isEmpty()) {
// return false;
// }
//获取第一个包含该点位的停车区
// String areaId = checkPointInArea(lng, lat, nearbyParking,orgId);
// if (areaId == null) {
// return false;
// }
String polygonFromWKT = getPolygonFromWKT(orgId,String.valueOf(areaId),"operation_area:meta:"); String polygonFromWKT = getPolygonFromWKT(orgId,String.valueOf(areaId),"operation_area:meta:");
Polygon polygon = parsePolygonFromWKT(polygonFromWKT); Polygon polygon = parsePolygonFromWKT(polygonFromWKT);
return isPointInPolygon(lng, lat, polygon); return isPointInPolygon(lng, lat, polygon);
@ -268,9 +260,21 @@ public class RedisUtil {
* @return true-在内部false-在外部或边界上根据业务需求调整 * @return true-在内部false-在外部或边界上根据业务需求调整
*/ */
public static boolean isPointInPolygon(double lng, double lat, Polygon polygon) { public static boolean isPointInPolygon(double lng, double lat, Polygon polygon) {
Coordinate coord = new Coordinate(lng, lat); // 1. 高精度坐标转换
double[] doubles = CoordinateUtil.WGS84ToGCJ02(lng, lat);
Coordinate coord = new Coordinate(
BigDecimal.valueOf(doubles[0]).setScale(9, RoundingMode.HALF_UP).doubleValue(),
BigDecimal.valueOf(doubles[1]).setScale(9, RoundingMode.HALF_UP).doubleValue()
);
// 2. 创建几何对象确认使用双精度
org.locationtech.jts.geom.Point point = GEOMETRY_FACTORY.createPoint(coord); org.locationtech.jts.geom.Point point = GEOMETRY_FACTORY.createPoint(coord);
return polygon.contains(point); // 使用 contains 方法精确判断
// 3. 对多边形做0.5米缓冲假设平面坐标系需调整缓冲量
Geometry bufferedPolygon = polygon.buffer(0.00000899);
// 4. 结合距离判断
return bufferedPolygon.covers(point) || polygon.distance(point) < 1.0;
} }
/** /**