高德地图线路纠偏

本文描述了一个物流项目中如何在网页端实时显示司机运输轨迹,包括每秒发送定位、纠偏处理(删除重复点和使用高德地图纠偏接口)、批量操作以适应访问限制,并将纠偏后的轨迹保存到数据库,以便下次页面加载时显示已纠偏的轨迹。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

公司有个物流项目,要求在网页端显示司机的运输轨迹,大概思路如下,每三秒钟发送一个定位,最后把位置信息以json格式保存到数据库,在网页中显示,现在需求如下,需要把保存的点位进行纠偏,轨迹集合删除相邻的相同定位的点,并进行纠偏,由于高德地图的纠偏接口一次只支持500个点位,并且有访问次数限制,于是进行批量纠偏操作,并把纠偏的结果保存到数据库,下次再打开网页时显示已经纠偏过的轨迹

整体前台代码

$(function () {
            var orderLoadList = [[${model.orderLoad}]];
            //初始化地图对象,加载地图
            //         var position = [orderLoadList[i].varMapX, orderLoadList[i].varMapY];

            var map = new AMap.Map("container", {
                resizeEnable: true,
                center: [orderLoadList[0].varMapX, orderLoadList[0].varMapY],
                zoom: 13,

            });
            for (var i = 0; i < orderLoadList.length; i++) {
                var icon = "";
                if (i == 0) {
                    icon = "/content/images/load.png"
                } else {
                    icon = "/content/images/unLoad.png"
                }
                var marker = new AMap.Marker({
                    position: [orderLoadList[i].varMapX, orderLoadList[i].varMapY], // 基点位置
                    title: orderLoadList[i].varName,
                    icon: icon,
                    offset: new AMap.Pixel(0, 0), // 设置点标记偏移量
                    anchor: 'bottom-left', // 设置锚点方位,
                });
                map.add(marker);
            }
            var isGps=[[${model.order.isGps}]];
            var path=[(${model.order.varWheelPath==null?'[]':model.order.varWheelPath})];
            console.log('原始path长度=='+path.length+',内容==='+JSON.stringify(path));
            var isHaveCorrection=$("#isHaveCorrection").val();
            var pathAfterCorrection = [(${model.order.varWheelPathAfterCorrection==null?'[]':model.order.varWheelPathAfterCorrection})];
            //如果该线路已经纠偏,直接调用数据库里的纠偏后的数组进行画图
            if(isHaveCorrection=='true'){
                if(Array.isArray(pathAfterCorrection)){
                    if(pathAfterCorrection[0] && pathAfterCorrection[0] instanceof Object){
                        console.log('该路线已经纠偏完成,显示数据库中已经纠偏好的路线,数据库中已经纠偏的线路长度=='+pathAfterCorrection.length+',内容==='+JSON.stringify(pathAfterCorrection));
                        var path2=[];
                        for(var i =0;i<pathAfterCorrection.length;i+=1){
                            path2.push([pathAfterCorrection[i].x,pathAfterCorrection[i].y])
                        }
                        console.log('纠偏后保存到数据库中的路线画图:');
                        console.log(path2);
                        var polyline = new AMap.Polyline({
                            path: path2,
                            strokeWeight: 4, // 线条宽度,默认为 1
                            strokeOpacity: 1,
                            strokeColor: '#3780e0', // 线条颜色
                            lineJoin: 'round', // 折线拐点连接处样式
                            strokeStyle: 'dashed'
                        });
                        map.add(polyline);
                        map.setFitView();
                    }
                }
            }else{
                if (Array.isArray(path)) {
                    if (path[0]?.constructor === Object) {
                        var pathGPS=[];
                        var path
                        for(var j=0,lengt=path.length;j<lengt;j++){
                            pathGPS.push([path[j].x,path[j].y])
                        }
                        var pathGD=[];
                        function batchCorrect(path, callback) {
                            /*
                            var batchSize = 400; // 批量大小,可以根据实际情况调整
                            var batches = [];
                            for (var i = 0; i < path.length; i += batchSize) {
                                batches.push(path.slice(i, i + batchSize));
                            }*/
                            var zhengNum = Math.floor(path.length / 250);
                            var batches = splitArray(path, zhengNum);
                            function splitArray(array, n) {
                                var result = [];
                                if(n==0) {n=1;}
                                var step = Math.ceil(array.length / n);
                                for (var i = 0; i < n; i++) {
                                    result.push(array.slice(i * step, (i + 1) * step));
                                }
                                return result;
                            }
                            var correctedPoints = [];
                            var batchIndex = 0;
                            function processBatch() {
                                if (batchIndex >= batches.length) {
                                    console.log('批量纠偏完成');
                                    callback(null, correctedPoints);
                                    return;
                                }
                                var currentBatch = batches[batchIndex];
                                var path2 = [];
                                AMap.plugin('AMap.GraspRoad', function() {
                                    var grasp = new AMap.GraspRoad();
                                    grasp.driving(currentBatch, function(error, result) {
                                        if (!error) {
                                            console.log("正确入参长度=="+currentBatch.length);
                                            correctedPoints = correctedPoints.concat(result.data.points);
                                            console.log("纠偏后正确出参长度=="+correctedPoints.length+",内容==="+JSON.stringify(correctedPoints));
                                        }
                                        if(error){
                                            console.log("错误入参长度=="+currentBatch.length+",内容==="+JSON.stringify(currentBatch));
                                            console.log('错误编码=='+error.errcode);
                                            console.log('错误原因=='+error.errdetail);
                                            console.log('错误日志=='+error.errmsg);
                                            var newPath = currentBatch;
                                            for(var i =0;i<newPath.length;i+=1){
                                                path2.push([newPath[i].x,newPath[i].y])
                                            }
                                            console.log('将无法纠偏的线路直接用黑色线条画图');
                                            console.log(path2)
                                            var oldLine = new AMap.Polyline({
                                                path:path2,
                                                strokeWeight: 4, // 线条宽度,默认为 1
                                                strokeOpacity: 1,
                                                strokeColor: '#3780e0' // 线条颜色
                                            })
                                            map.add(oldLine);
                                            map.setFitView();
                                        }
                                        batchIndex++;
                                        processBatch();
                                    });
                                });
                            }
                            processBatch();
                        }
                        if(isGps==true){
                            console.log('该线路的值是gps格式');
                            AMap.convertFrom(pathGPS, 'gps', function (status, result) {
                                if (result.info === 'ok') {
                                    pathGD = result.locations; // Array.<LngLat>
                                    for(var t=0,leng=path.length;t<leng;t++){
                                        path[t].x=pathGD[t].lng;
                                        path[t].y=pathGD[t].lat;
                                    }
                                    var path2 = [];
                                    batchCorrect(path, function(error, correctedPath) {
                                        if (!error) {
                                            console.log("gps格式纠偏成功,纠偏后的路线长度=="+correctedPath.length+",内容==="+JSON.stringify(correctedPath));
                                            // 在这里使用纠偏后的轨迹
                                            for(var i =0;i<correctedPath.length;i+=1){
                                                path2.push([correctedPath[i].x,correctedPath[i].y]);
                                            }
                                            console.log('gps格式纠偏成功,即将画图');
                                            console.log(path2);
                                            var polyline = new AMap.Polyline({
                                                path: path2,
                                                strokeWeight: 4, // 线条宽度,默认为 1
                                                strokeOpacity: 1,
                                                strokeColor: '#3780e0', // 线条颜色
                                                lineJoin: 'round', // 折线拐点连接处样式
                                                strokeStyle: 'dashed'
                                            });
                                            map.add(polyline);
                                            map.setFitView();
                                            savaLineAfterCorrection(correctedPath);
                                        }
                                    });
                                }
                            });
                        }else{
                            console.log('该线路的值不是gps格式');
                            var path2 = [];
                            batchCorrect(path, function(error, correctedPath) {
                                if (!error) {
                                    console.log("非gps格式纠偏成功,纠偏后的路线长度=="+correctedPath.length+",内容==="+JSON.stringify(correctedPath));
                                    // 在这里使用纠偏后的轨迹
                                    for(var i =0;i<correctedPath.length;i+=1){
                                        path2.push([correctedPath[i].x,correctedPath[i].y]);
                                    }
                                    console.log('非gps格式纠偏成功,即将画图');
                                    console.log(path2);
                                    var polyline = new AMap.Polyline({
                                        path: path2,
                                        strokeWeight: 4, // 线条宽度,默认为 1
                                        strokeOpacity: 1,
                                        strokeColor: '#3780e0', // 线条颜色
                                        lineJoin: 'round', // 折线拐点连接处样式
                                        strokeStyle: 'dashed'
                                    });
                                    map.add(polyline);
                                    map.setFitView();
                                    savaLineAfterCorrection(correctedPath);
                                }
                            });
                        }
                    }else{
                        console.log('该线路数组中的内容不是对象,原始path长度=='+path.length+',内容==='+JSON.stringify(path));
                        AMap.convertFrom(path, 'gps', function (status, result) {
                            if (result.info === 'ok') {
                                var lnglats = result.locations; // Array.<LngLat>
                                console.log('该线路数组中的内容不是对象,直接画图');
                                console.log(lnglats);
                                var polyline = new AMap.Polyline({
                                    path: lnglats,
                                    strokeWeight: 4, // 线条宽度,默认为 1
                                    strokeOpacity: 1,
                                    strokeColor: '#3780e0', // 线条颜色
                                    lineJoin: 'round', // 折线拐点连接处样式
                                    strokeStyle: 'dashed'
                                });
                                map.add(polyline);
                            }
                        });
                    }
                }
            }
        })
function savaLineAfterCorrection(pathAfterCorrection) {
            var pathAfterCorrectionStr = JSON.stringify(pathAfterCorrection);
            if(null!=pathAfterCorrectionStr && pathAfterCorrectionStr!=''){
                $.ajax({
                    type: 'post',
                    url: '/transaction/updateOrderAfterCorrection',
                    dataType: 'Json',
                    data: {"id":$("#orderId").val(),
                        "isHaveCorrect":1,
                        "pathAfterCorrectionStr":pathAfterCorrectionStr},
                    async: false,
                    success: function (data) {
                    }
                });
            }
        }

代码拆分

这段代码是将所有的轨迹进行拆分纠偏,代码如下,grasp.driving是纠偏方法

var originPath = [  
    {"x":116.478928,"y":39.997761,"sp":19,"ag":0, "tm":1478031031},  
    // ... 其他点  
];  
  
function batchCorrect(path, callback) {  
    var batchSize = 100; // 批量大小,可以根据实际情况调整  
    var batches = [];  
    for (var i = 0; i < path.length; i += batchSize) {  
        batches.push(path.slice(i, i + batchSize));  
    }  
      
    var correctedPoints = [];  
    var batchIndex = 0;  
    function processBatch() {  
        if (batchIndex >= batches.length) {  
            callback(null, correctedPoints);  
            return;  
        }  
          
        var currentBatch = batches[batchIndex];  
        AMap.plugin('AMap.GraspRoad', function() {  
            var grasp = new AMap.GraspRoad();  
            grasp.driving(currentBatch, function(error, result) {  
                if (!error) {  
                    correctedPoints = correctedPoints.concat(result.data.points);  
                }  
                batchIndex++;  
                processBatch();  
            });  
        });  
    }  
      
    processBatch();  
}  
  
batchCorrect(originPath, function(error, correctedPath) {  
    if (!error) {  
        // 在这里使用纠偏后的轨迹  
        var newPath = correctedPath;  
        var distance = result.data.distance; // 里程  
    }  
});

 这段代码是将所有的点位进行平均分段。代码如下

var zhengNum = Math.floor(path.length / 250);
var batches = splitArray(path, zhengNum);
function splitArray(array, n) {
     var result = [];
     if(n==0) {n=1;}
     var step = Math.ceil(array.length / n);
     for (var i = 0; i < n; i++) {
         result.push(array.slice(i * step, (i + 1) * step));
     }
    return result;
}

这段代码是将纠偏后的结果在页面进行画图

var polyline = new AMap.Polyline({
     path: path2,
     strokeWeight: 4, // 线条宽度,默认为 1
     strokeOpacity: 1,
     strokeColor: '#3780e0', // 线条颜色
     lineJoin: 'round', // 折线拐点连接处样式
     strokeStyle: 'dashed'
 });
 map.add(polyline);
 map.setFitView();

 

这段代码是将纠偏后的结果通过ajax保存到后台数据库,代码如下

function savaLineAfterCorrection(pathAfterCorrection) {
            var pathAfterCorrectionStr = JSON.stringify(pathAfterCorrection);
            if(null!=pathAfterCorrectionStr && pathAfterCorrectionStr!=''){
                $.ajax({
                    type: 'post',
                    url: '/transaction/updateOrderAfterCorrection',
                    dataType: 'Json',
                    data: {"id":$("#orderId").val(),
                        "isHaveCorrect":1,
                        "pathAfterCorrectionStr":pathAfterCorrectionStr},
                    async: false,
                    success: function (data) {
                    }
                });
            }
        }

后台代码

轨迹集合删除相邻的相同定位的点,后台处理的逻辑如下,varWheelPath  是后台返回给前台的处理过的轨迹集合,代码如下

        TOrder order = tOrderMapper.selectById(id);

        Boolean isHaveCorrection = order.getIsHaveCorrection();
        String varWheelPath = order.getVarWheelPath();

        if(null!=varWheelPath && (isHaveCorrection==null||!isHaveCorrection)){
            Gson gson = new Gson();
            Type type = new TypeToken<List<Map<String, Object>>>() {}.getType();
            List<Map<String, Object>> oldData = gson.fromJson(varWheelPath, type);
            List<Map<String, Object>> newData = new ArrayList<Map<String, Object>>();
            Stack<Map<String, Object>> stack = new Stack<Map<String, Object>>();
            for (Map<String, Object> item : oldData) {
                if (!stack.isEmpty() && stack.peek().get("x").toString().equals(item.get("x").toString()) && stack.peek().get("y").toString().equals(item.get("y").toString())) {
                    continue; // 如果栈不为空并且栈顶元素与当前元素x、y值相同,则跳过当前元素
                }
                stack.push(item); // 将元素压入栈中
            }
            for (Map<String, Object> item : stack) {
                newData.add(item);
            }
            String varWheelPathNew =new GsonBuilder().create().toJson(newData);
            order.setVarWheelPath(varWheelPathNew);
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值