坐标转换
parent
66d846c80d
commit
c5134d4c6b
|
|
@ -0,0 +1,106 @@
|
|||
package com.njzscloud.common.core.utils;
|
||||
|
||||
import com.njzscloud.common.core.tuple.Tuple2;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 坐标转换工具类:WGS-84转GCJ-02(火星坐标系)
|
||||
* WGS-84:GPS设备获取的原始坐标
|
||||
* 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-84坐标转换为GCJ-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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue