| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- package com.ruoyi.app.flashdelivery.route;
- import com.ruoyi.system.domain.flash.FlashDeliveryVehicleType;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
- /** 路线距离服务:优先请求地图路线,异常时使用球面直线距离保证报价仍然可用。 */
- @Service
- public class FlashDeliveryRouteService {
- private static final double EARTH_RADIUS_METERS = 6_371_000D;
- private static final Logger log = LoggerFactory.getLogger(FlashDeliveryRouteService.class);
- private final RouteDistanceProvider provider;
- public FlashDeliveryRouteService(RouteDistanceProvider provider) {
- this.provider = provider;
- }
- /** 按用户选择车型计算取送路线:优先地图路线,异常或无结果时降级球面直线距离。 */
- public RouteDistance calculate(GeoPoint origin, GeoPoint destination, Integer vehicleType) {
- validate(origin);
- validate(destination);
- int selectedVehicle = FlashDeliveryVehicleType.isSupported(vehicleType)
- ? vehicleType : FlashDeliveryVehicleType.MOTORCYCLE;
- try {
- RouteDistance route = provider.route(origin.latitude(), origin.longitude(),
- destination.latitude(), destination.longitude(), selectedVehicle);
- if (route != null && route.distanceMeters() > 0) {
- return route;
- }
- } catch (RuntimeException exception) {
- // 不记录地址、坐标或 Key;保留车型和失败原因以定位 Google Routes 降级。
- log.warn("Google Routes unavailable; use straight-line fallback. vehicleType={}, reason={}",
- selectedVehicle, exception.getMessage());
- }
- // Haversine 只作为降级结果,并通过 source=STRAIGHT_LINE 明确告知调用方。
- double lat1 = Math.toRadians(origin.latitude().doubleValue());
- double lat2 = Math.toRadians(destination.latitude().doubleValue());
- double deltaLat = lat2 - lat1;
- double deltaLon = Math.toRadians(destination.longitude().doubleValue()
- - origin.longitude().doubleValue());
- double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
- + Math.cos(lat1) * Math.cos(lat2)
- * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
- int meters = (int) Math.round(EARTH_RADIUS_METERS * 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a)));
- return new RouteDistance(Math.max(1, meters), null, "STRAIGHT_LINE");
- }
- private void validate(GeoPoint point) {
- if (point == null || point.latitude() == null || point.longitude() == null
- || point.latitude().doubleValue() < -90D || point.latitude().doubleValue() > 90D
- || point.longitude().doubleValue() < -180D || point.longitude().doubleValue() > 180D) {
- throw new IllegalArgumentException("invalid coordinates");
- }
- }
- }
|