You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Google OR-Tools VRP解决方案中获取实际位置索引与经纬度

解决方案实现步骤

1. 传递位置列表到打印方法

当前PrintSolution方法无法访问VRP方法中创建的locations列表,需将其作为参数传入。修改VRP方法内的调用代码:

if (solution is not null)
{
    PrintSolution(routing, manager, solution, vehicles.Count, locations);
}

同时更新PrintSolution的方法签名:

static void PrintSolution(in RoutingModel routing, in RoutingIndexManager manager, in Assignment solution, in int count, List<Location> locations)

2. 修改PrintSolution方法,打印完整位置详情与经纬度

在遍历车辆路线时,通过节点索引匹配对应的Location对象,输出地址、经纬度,同时补充时间、容量等关键信息:

static void PrintSolution(in RoutingModel routing, in RoutingIndexManager manager, in Assignment solution, in int count, List<Location> locations)
{
    Console.WriteLine($"目标值 {solution.ObjectiveValue()}:");

    // 打印被跳过的节点
    string droppedNodes = "被跳过的节点:";
    for (int index = 0; index < routing.Size(); ++index)
    {
        if (routing.IsStart(index) || routing.IsEnd(index))
        {
            continue;
        }
        if (solution.Value(routing.NextVar(index)) == index)
        {
            int nodeId = manager.IndexToNode(index);
            var loc = locations[nodeId];
            droppedNodes += $" [{nodeId}] {loc.Address} (Lng:{loc.Lng}, Lat:{loc.Lat})";
        }
    }
    Console.WriteLine(droppedNodes);

    // 获取维度对象,用于打印额外信息
    RoutingDimension distanceDim = routing.GetMutableDimension("Distance");
    RoutingDimension timeDim = routing.GetMutableDimension("Time");
    RoutingDimension capacityDim = routing.GetMutableDimension("Capacity");

    long totalDistance = 0;
    long totalTime = 0;

    for (int i = 0; i < count; ++i)
    {
        Console.WriteLine($"\n车辆 {i} 的路线:");
        long routeDistance = 0;

        var index = routing.Start(i);
        // 打印起点信息
        int startNode = manager.IndexToNode((int)index);
        var startLoc = locations[startNode];
        long startTime = solution.Value(timeDim.CumulVar(index));
        long startCapacity = solution.Value(capacityDim.CumulVar(index));
        Console.WriteLine($"起点: [{startNode}] {startLoc.Address} (Lng:{startLoc.Lng}, Lat:{startLoc.Lat})");
        Console.WriteLine($"  出发时间: {DateTimeOffset.FromUnixTimeSeconds(startTime).LocalDateTime}");
        Console.WriteLine($"  当前容量: {startCapacity}");

        while (routing.IsEnd(index) == false)
        {
            var previousIndex = index;
            index = solution.Value(routing.NextVar(index));
            int prevNode = manager.IndexToNode((int)previousIndex);
            int currNode = manager.IndexToNode((int)index);

            var prevLoc = locations[prevNode];
            var currLoc = locations[currNode];

            // 计算路段距离
            long arcDistance = routing.GetArcCostForVehicle(previousIndex, index, i);
            routeDistance += arcDistance;

            // 获取当前节点的时间与容量数据
            long arrivalTime = solution.Value(timeDim.CumulVar(index));
            long currentCapacity = solution.Value(capacityDim.CumulVar(index));

            Console.WriteLine($"\n[{prevNode}] {prevLoc.Address} -> [{currNode}] {currLoc.Address}");
            Console.WriteLine($"  路段距离: {arcDistance}m");
            Console.WriteLine($"  到达时间: {DateTimeOffset.FromUnixTimeSeconds(arrivalTime).LocalDateTime}");
            Console.WriteLine($"  当前容量: {currentCapacity}");
            Console.WriteLine($"  坐标: Lng={currLoc.Lng}, Lat={currLoc.Lat}");
        }

        // 打印终点信息
        int endNode = manager.IndexToNode((int)index);
        var endLoc = locations[endNode];
        long endTime = solution.Value(timeDim.CumulVar(index));
        long endCapacity = solution.Value(capacityDim.CumulVar(index));
        Console.WriteLine($"\n终点: [{endNode}] {endLoc.Address} (Lng:{endLoc.Lng}, Lat:{endLoc.Lat})");
        Console.WriteLine($"  到达时间: {DateTimeOffset.FromUnixTimeSeconds(endTime).LocalDateTime}");
        Console.WriteLine($"  当前容量: {endCapacity}");

        long routeTime = endTime - startTime;
        totalDistance += routeDistance;
        totalTime += routeTime;

        Console.WriteLine($"\n车辆 {i} 路线总距离: {routeDistance}m");
        Console.WriteLine($"车辆 {i} 路线总耗时: {TimeSpan.FromSeconds(routeTime)}");
    }

    Console.WriteLine($"\n所有路线总距离: {totalDistance}m");
    Console.WriteLine($"所有路线总耗时: {TimeSpan.FromSeconds(totalTime)}");
}

3. 确认Location类包含经纬度属性

确保你的Location类已定义经度和纬度字段:

public class Location
{
    public string Address { get; set; }
    public double Lng { get; set; } // 经度
    public double Lat { get; set; } // 纬度
    // 其他业务属性...
}

核心逻辑说明

  • 通过manager.IndexToNode(index)将路由索引转换为节点ID,再从locations列表中匹配对应位置对象,直接获取经纬度信息。
  • 新增了时间窗实际到达时间、容量变化、路段距离等维度数据,让解决方案详情更全面。
  • 被跳过的节点也会打印位置信息,便于后续问题排查。

内容的提问来源于stack exchange,提问作者DPTP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:55:16