routing icon indicating copy to clipboard operation
routing copied to clipboard

Bug in Router.TryCalculate

Open luisarvayo opened this issue 4 years ago • 2 comments

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

luisarvayo avatar May 05 '20 23:05 luisarvayo

See also https://github.com/itinero/routing/pull/302

juliusfriedman avatar May 15 '20 22:05 juliusfriedman

Also noticing that your calling AddContraction if the db was already contracted I do not believe this is necessary, simply Deserialize on a RouterDB which was previously contracted will just work.

juliusfriedman avatar May 16 '20 13:05 juliusfriedman