routing
routing copied to clipboard
Bug in Router.TryCalculate
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
See also https://github.com/itinero/routing/pull/302
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.