Skip to content

Bug in Router.TryCalculate #312

@luisarvayo

Description

@luisarvayo

Hello,

The following code throw an exception when trying to calculate the route between two points inside a city. Map is from Mexico and I downloaded from fabrik.de, (mexico-latest.osm.pbf). Exception is:

'route.Value' threw an exception of type 'Itinero.Exceptions.RouteNotFoundException'

The two points are relatively close one to another.

The code is the following:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
internal static RouterDb RouterDb { get; set; }
internal static string OsmPbfFile { get; set; }
internal static bool RouterInMemory { get; set; } = true;
internal static bool HasContracted { get; set; } = false;
internal static Stream Stream { get; set; }
internal string GetBaseDir()
{
string userFilePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string companyPath = Path.Combine(userFilePath, "DemoCompany");
if (!Directory.Exists(companyPath))
{
Directory.CreateDirectory(companyPath);
}
string appPath = Path.Combine(companyPath, "ItineroBug");
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
return appPath;
}
internal void BuildRouterDb()
{
if (RouterDb != null) return;
string dataSubdir = Path.Combine(GetBaseDir(), "pbf");
if (!Directory.Exists(dataSubdir)) return;
string pbfFile = "mexico-latest.osm.pbf";

        var files = Directory.GetFiles(dataSubdir, "*.osm.pbf");
        var fileswe = files.Select(item => Path.GetFileName(item)).ToList();
        if (fileswe.FirstOrDefault(item => string.Compare(item, pbfFile, true, CultureInfo.InvariantCulture) == 0) == null)
        {
            pbfFile = fileswe.First();
        }
        if (pbfFile == null)
        {
            MessageBox.Show("Pbf file not found !");
            return;
        }
        OsmPbfFile = Path.Combine(dataSubdir, pbfFile);
        string temposmpbffile = Path.GetFileNameWithoutExtension(OsmPbfFile);
        while (!string.IsNullOrEmpty(Path.GetExtension(temposmpbffile))) temposmpbffile = Path.ChangeExtension(temposmpbffile, null);
        string filerouterdb = Path.ChangeExtension(Path.Combine(dataSubdir, temposmpbffile), ".routerdb");
        if (!File.Exists(filerouterdb))
        {
            RouterDb = new RouterDb();
            using (var stream = new FileInfo(Path.Combine(dataSubdir, pbfFile)).OpenRead())
            {
                RouterDb.LoadOsmData(stream, Itinero.Osm.Vehicles.Vehicle.Car);
            }
            using (var stream = new FileInfo(filerouterdb).Open(FileMode.Create))
            {
                RouterDb.Serialize(stream);
            }
            RouterDb = null;
        }
        if (RouterDb == null)
        {
            if (RouterInMemory)
            {
                using (var stream = new FileInfo(filerouterdb).OpenRead())
                {
                    // add a contracted version
                    RouterDb = RouterDb.Deserialize(stream);
                    if (HasContracted && !RouterDb.HasContractedFor(Itinero.Osm.Vehicles.Vehicle.Car.Fastest()))
                    {
                        RouterDb.AddContracted(Itinero.Osm.Vehicles.Vehicle.Car.Fastest());
                    }
                }
            }
            else
            {
                Stream = new FileInfo(filerouterdb).OpenRead();
                RouterDb = RouterDb.Deserialize(Stream, RouterDbProfile.NoCache);
                if (HasContracted && !RouterDb.HasContractedFor(Itinero.Osm.Vehicles.Vehicle.Car.Fastest()))
                {
                    RouterDb.AddContracted(Itinero.Osm.Vehicles.Vehicle.Car.Fastest());
                }
            }
        }
    }
    internal static RouterPoint[] ResolvePoints(Router router, Profile profile, List<Itinero.LocalGeo.Coordinate> locstops, out int numfails)
    {
        numfails = 0;
        List<RouterPoint> result = new List<RouterPoint>();
        try
        {
            var stops = locstops.ToArray();
            for (int i = 0; i < stops.Length; i++)
            {
                bool solved;
                float searchDistanceInMeter = Itinero.Constants.SearchDistanceInMeter;
                Itinero.LocalGeo.Coordinate test = stops[i];
                Result<RouterPoint> routePoint;
                
                solved = false;
                routePoint = router.TryResolve(profile, test, searchDistanceInMeter);

                if (!routePoint.IsError)
                {
                    result.Add(routePoint.Value);
                    solved = true;
                }
                else 
                {
                    RouterPoint routerPoint = new RouterPoint(test.Latitude, test.Longitude, 0, 0);
                    routePoint = new Result<RouterPoint>(routerPoint);
                    result.Add(routePoint.Value);
                    solved = true;
                }
                if (!solved)
                {
                    numfails++;
                }
            }
        }
        finally
        {
        }
        return result.ToArray();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        BuildRouterDb();
        Itinero.Profiles.Vehicle vehicle = RouterDb.GetSupportedVehicle("car");
        var router = new Router(RouterDb);
        var profile = vehicle.Fastest();
        int numfails;
        List<Itinero.LocalGeo.Coordinate> locations = new List<Itinero.LocalGeo.Coordinate>();
        //locations.Add(new Itinero.LocalGeo.Coordinate((float)29.10028, (float)-110.9889));
        //locations.Add(new Itinero.LocalGeo.Coordinate((float)29.09842, (float)-110.9922));
        locations.Add(new Itinero.LocalGeo.Coordinate((float)29.09842, (float)-110.9922));
        locations.Add(new Itinero.LocalGeo.Coordinate((float)29.09408, (float)-110.9982));
        RouterPoint[] solvedstops = ResolvePoints(router, profile, locations, out numfails);
 // exception is thrown here !!
        Result<Route> route = solvedstops.Length >= locations.Count ? router.TryCalculate(profile, solvedstops) : null;
        if(route == null || route.IsError)
        {
            MessageBox.Show(route.ErrorMessage);
            return;
        }
        if (route.Value.Attributes.TryGetValue("distance", out string diststr)) double.TryParse(diststr, out double distance);
        if (route.Value.Attributes.TryGetValue("time", out string timestr)) double.TryParse(timestr, out double time);
    }
}

In another project, instead of RouteNotFoundException, after a long time, the Dykstra class throws an out of memory exception at the following line in method public bool Step()

_visits[_current.Edge] = _current;

If you need it, I can send you the full project.
Regards

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions