Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in Router.TryCalculate #312

Open
luisarvayo opened this issue May 5, 2020 · 2 comments
Open

Bug in Router.TryCalculate #312

luisarvayo opened this issue May 5, 2020 · 2 comments

Comments

@luisarvayo
Copy link

luisarvayo commented May 5, 2020

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

@juliusfriedman
Copy link

See also #302

@juliusfriedman
Copy link

juliusfriedman commented May 16, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants