/// <summary> /// Initialize OsmSnapper, which allows you to snap GPS tracks to on-road geometries /// </summary> /// <param name="overpassApi"></param> /// <param name="boundingBox"></param> /// <param name="parameters"></param> /// <param name="printConsoleUpdates"></param> public OsmSnapper(OverpassApi overpassApi, BoundingBox boundingBox = null, MapMatcherParameters parameters = null, bool printConsoleUpdates = false, bool useSearchGrid = true) { _printConsoleUpdates = printConsoleUpdates; _useSearchGrid = useSearchGrid; if (parameters == null) { parameters = MapMatcherParameters.Default; } Parameters = parameters; if (overpassApi == OverpassApi.DeloreanGray) { _overpassApi = Config.Urls.DeloreanGray; } else if (overpassApi == OverpassApi.MainOverpass) { _overpassApi = Config.Urls.MainOverpassApi; } else { throw new ArgumentException("Invalid overpass enum"); } if (boundingBox != null) { SnappingArea = boundingBox; // Build graph in bounding box and initialize map matcher (involves computing search grid data structure) var graph = OsmGraphBuilder.BuildInRegion(_overpassApi, boundingBox); MapMatcher = new OsmMapMatcher(graph, parameters, _useSearchGrid); } }
/// <summary> /// Snaps track to OSM roads. Returns a list of snapped geometries - if it fails to find one continuous OSM geometry corresponding to the track, the list contain more than one geometry. /// </summary> /// <param name="track"></param> /// <param name="timeStamps"></param> /// <param name="highwayTags"></param> /// <param name="railTags"></param> /// <returns> List of snapped geometries. If it fails to find one continuous OSM geometry corresponding to the track, the list contains more than one geometry. Otherwise count = 1</returns> public List <List <Coord> > SnapDat(IEnumerable <Coord> track, IEnumerable <DateTime> timeStamps = null, bool highwayTags = true, bool railTags = true, bool ignoreOneWays = false) { if (track.Count() < 2) { return(new List <List <Coord> >() { track.ToList() }); } var result = new List <List <Coord> >(); // Initialize total snap time stopwatch var totalTimeStopwatch = new System.Diagnostics.Stopwatch(); totalTimeStopwatch.Start(); OsmMapMatcher mapMatcher;//= new MapMatcher(osmGraph); if (MapMatcher == null) { // Build graph in region and initialize map matcher var boundingBoxes = track.GetSmartBoundingBoxes(); var osmGraph = OsmGraphBuilder.BuildInRegion(_overpassApi, boundingBoxes, highwayTags, railTags, ignoreOneWays); mapMatcher = new OsmMapMatcher(osmGraph, Parameters, _useSearchGrid); } else { mapMatcher = MapMatcher.Clone(); } // Initialize snap time stopwatch var performSnapStopwatch = new System.Diagnostics.Stopwatch(); performSnapStopwatch.Start(); // Clean input co-ordinates var cleanedCoords = track.GetCleanedCoordinates(timeStamps); // Initialize snap summary & list for update times SnapSummary = new SnapSummary(); SnapSummary.UpdateCount = cleanedCoords.Count; var updateTimesInMilliseconds = new List <double>(); int startIndex = 0; int breakIndex = 0; for (int i = 0; i < cleanedCoords.Count; i++) { Coord coord = cleanedCoords[i]; if (mapMatcher.TryUpdateState(coord, printUpdateAnalyticsToConsole: _printConsoleUpdates)) { updateTimesInMilliseconds.Add(mapMatcher.UpdateInfo.UpdateTimeInMilliseconds); } else { SnapSummary.BreakCount += 1; breakIndex = i; if (startIndex < breakIndex) { var shape = GetSnappedSection(mapMatcher, cleanedCoords, startIndex, breakIndex); result.Add(shape); } startIndex = i + 1; mapMatcher.Reset(); } } if (startIndex < cleanedCoords.Count - 1) { var lastShape = GetSnappedSection(mapMatcher, cleanedCoords, startIndex, cleanedCoords.Count - 1); result.Add(lastShape); } // Snap summary values performSnapStopwatch.Stop(); SnapSummary.PerformSnapTimeInSeconds = performSnapStopwatch.Elapsed.TotalSeconds; totalTimeStopwatch.Stop(); SnapSummary.TotalSnapTimeInSeconds = totalTimeStopwatch.Elapsed.TotalSeconds; SnapSummary.MeanUpdateTimeInMilliseconds = updateTimesInMilliseconds.Average(); // Print summary info to the console SnapSummary.PrintSummaryToConsole(); return(result); }