坐标转换

localizer
lzq 2025-10-16 13:17:40 +08:00
parent 66d846c80d
commit c5134d4c6b
3 changed files with 157 additions and 2 deletions

View File

@ -0,0 +1,106 @@
package com.njzscloud.common.core.utils;
import com.njzscloud.common.core.tuple.Tuple2;
import java.math.BigDecimal;
/**
* WGS-84GCJ-02()
* WGS-84GPS
* GCJ-02使
*/
public class CoordinateConverter {
// 长半径
private static final double PI = 3.1415926535897932384626;
private static final double A = 6378245.0;
// 扁率
private static final double EE = 0.00669342162296594323;
/**
*
*
* @param lat
* @param lon
* @return
*/
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347) {
return true;
}
if (lat < 0.8293 || lat > 55.8271) {
return true;
}
return false;
}
/**
*
*
* @param x
* @param y
* @return
*/
private static double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
*
*
* @param x
* @param y
* @return
*/
private static double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
/**
* WGS-84GCJ-02
*
* @param wgsLat WGS-84
* @param wgsLon WGS-84
* @return [, ]
*/
public static Tuple2<Double, Double> wgs84ToGcj02(double wgsLat, double wgsLon) {
// 如果不在中国境内,直接返回原坐标
if (outOfChina(wgsLat, wgsLon)) {
return Tuple2.create(wgsLat, wgsLon);
}
double dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0);
double dLon = transformLon(wgsLon - 105.0, wgsLat - 35.0);
double radLat = wgsLat / 180.0 * PI;
double magic = Math.sin(radLat);
magic = 1 - EE * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
dLon = (dLon * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
// 保留6位小数约10厘米精度
double gcjLat = round(wgsLat + dLat, 6);
double gcjLon = round(wgsLon + dLon, 6);
return Tuple2.create(gcjLat, gcjLon);
}
/**
*
*
* @param value
* @param scale
* @return
*/
private static double round(double value, int scale) {
return new BigDecimal(value).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}

View File

@ -11,7 +11,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.thread.ThreadPool;
import com.njzscloud.common.core.tuple.Tuple2;
import com.njzscloud.common.core.tuple.Tuple3;
import com.njzscloud.common.core.utils.CoordinateConverter;
import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
@ -512,6 +514,9 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
return;
}
}
Tuple2<Double, Double> doubles = CoordinateConverter.wgs84ToGcj02(record.getLatitude(), record.getLongitude());
record.setLatitude(doubles.get_0())
.setLongitude(doubles.get_1());
boolean publish = Websocket.publish(new WsMsg()
.setEvent("down/truck_location_track/history")
.setData(R.success(record))
@ -608,6 +613,9 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
}
}
startTime = record.getLocationTime();
Tuple2<Double, Double> doubles = CoordinateConverter.wgs84ToGcj02(record.getLatitude(), record.getLongitude());
record.setLatitude(doubles.get_0())
.setLongitude(doubles.get_1());
boolean publish = Websocket.publish(new WsMsg()
.setEvent("down/truck_location_track/realtime")
.setData(R.success(record))

View File

@ -21,6 +21,8 @@ import com.njzscloud.common.mqtt.util.Mqtt;
import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.common.security.util.SecurityUtil;
import com.njzscloud.common.sn.support.SnUtil;
import com.njzscloud.common.ws.support.Websocket;
import com.njzscloud.common.ws.support.WsMsg;
import com.njzscloud.supervisory.biz.constant.AuditStatus;
import com.njzscloud.supervisory.biz.constant.BizObj;
import com.njzscloud.supervisory.biz.pojo.entity.*;
@ -718,6 +720,16 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
String licensePlate = truckInfo.getLicensePlate();
startTuqiangTrack(gpsId, licensePlate, orderInfoId, truckId);
CompletableFuture.runAsync(() -> Websocket.publish(new WsMsg().setEvent("down/order/status_change")
.setData(MapUtil.builder()
.put("sn", orderInfo.getSn())
.put("licensePlate", licensePlate)
.put("orderStatus", OrderStatus.QingYunZhong)
.build()))).exceptionally(e -> {
log.error("订单状态改变事件发布失败,订单{},状态{}", orderInfo.getSn(), OrderStatus.QingYunZhong, e);
return null;
});
}
private void startTuqiangTrack(String gpsId, String licensePlate, Long orderInfoId, Long truckId) {
@ -800,7 +812,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
Assert.notNull(orderInfo, () -> Exceptions.clierr("订单不存在"));
OrderStatus orderStatus = orderInfo.getOrderStatus();
Assert.isTrue(orderStatus == OrderStatus.YiYuYue
|| orderStatus == OrderStatus.DaiPaiDan
|| orderStatus == OrderStatus.DaiPaiDan
|| orderStatus == OrderStatus.DaiJieDan
|| orderStatus == OrderStatus.YiJieDan,
() -> Exceptions.clierr("当前订单状态,无法取消"));
@ -913,6 +925,21 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
.setCarInOutId(carInOutId)
.setOrderStatus(OrderStatus.YiJinChang)
);
CompletableFuture.runAsync(() -> {
Long truckId = orderInfoEntity.getTruckId();
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String licensePlate = truckInfo.getLicensePlate();
Websocket.publish(new WsMsg().setEvent("down/order/status_change")
.setData(MapUtil.builder()
.put("sn", orderInfoEntity.getSn())
.put("licensePlate", licensePlate)
.put("orderStatus", OrderStatus.YiJinChang)
.build()));
}).exceptionally(e -> {
log.error("订单状态改变事件发布失败,订单{},状态{}", orderInfoEntity.getSn(), OrderStatus.YiJinChang, e);
return null;
});
}
/**
@ -932,15 +959,29 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
baseMapper.busyTruck(orderInfoEntity.getTruckId(), Boolean.FALSE);
PaymentStatus paymentStatus = orderInfoEntity.getPaymentStatus();
OrderStatus newOrderStatus = paymentStatus == PaymentStatus.WeiZhiFu ? OrderStatus.YiChuChang : OrderStatus.YiWanCheng;
this.updateById(new OrderInfoEntity()
.setAutoOrder(3 ^ (i << 1))
.setId(orderInfoEntity.getId())
.setOrderStatus(paymentStatus == PaymentStatus.WeiZhiFu ? OrderStatus.YiChuChang : OrderStatus.YiWanCheng)
.setOrderStatus(newOrderStatus)
);
OrderCategory orderCategory = orderInfoEntity.getOrderCategory();
// 计算本单净重(或结算重量),作为结算时的数量依据
Integer settleWeight = orderCarInOutService.truckOut(orderInfoEntity.getCarInOutId(), truckLeavingOrderParam, orderCategory, truckId);
CompletableFuture.runAsync(() -> {
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String licensePlate = truckInfo.getLicensePlate();
Websocket.publish(new WsMsg().setEvent("down/order/status_change")
.setData(MapUtil.builder()
.put("sn", orderInfoEntity.getSn())
.put("licensePlate", licensePlate)
.put("orderStatus", newOrderStatus)
.build()));
}).exceptionally(e -> {
log.error("订单状态改变事件发布失败,订单{},状态{}", orderInfoEntity.getSn(), newOrderStatus, e);
return null;
});
// 结算(目前仅针对清运公司):
// 1) 复制“产品”到 order_expense_items
// 2) 从 expense_items_config 读取可用付费项并按 scope 过滤all / customer_type=QiYe|GeTi / customer 包含 trans_company_id