/// <summary> /// Executes the actual algorithm. /// </summary> protected override void DoRun() { var tiles = new Dictionary <TileIndex, RoutingTile>(); _edgeVisitor.Visit += (id, startVertex, startWeight, endVertex, endWeight, shape) => { var endCoordinate = shape[shape.Count - 1]; var index = TileIndex.WorldToTileIndex(endCoordinate.Latitude, endCoordinate.Longitude, _level); RoutingTile tile; if (!tiles.TryGetValue(index, out tile)) { tile = new RoutingTile { Weight = endWeight, Count = 1, Index = index }; } else { tile.Weight = (tile.Weight * tile.Count + endWeight) / tile.Count + 1; tile.Count++; } tiles[index] = tile; }; _edgeVisitor.Run(); _result = new HeatmapResult(); _result.Data = new HeatmapSample[tiles.Count]; var max = 0f; var i = 0; foreach (var pair in tiles) { var location = TileIndex.TileIndexToWorld(pair.Key.X, pair.Key.Y, _level); _result.Data[i] = new HeatmapSample() { Latitude = location.Latitude, Longitude = location.Longitude, Value = pair.Value.Weight }; if (max < pair.Value.Weight) { max = pair.Value.Weight; } i++; } _result.Max = max; this.HasSucceeded = true; }
private static Size GetTileSize(RoutingTile sourceTile, int level) { // There is probably a more direct way to calculate this. var sourceTopLeft = TileIndex.TileIndexToWorld(sourceTile.Index.X, sourceTile.Index.Y, level); var sourceBottomLeft = TileIndex.TileIndexToWorld(sourceTile.Index.X, sourceTile.Index.Y + 1, level); var sourceTopRight = TileIndex.TileIndexToWorld(sourceTile.Index.X + 1, sourceTile.Index.Y, level); var tileHeight = Coordinate.DistanceEstimateInMeter(sourceTopLeft, sourceBottomLeft); var tileWidth = Coordinate.DistanceEstimateInMeter(sourceTopLeft, sourceTopRight); return(new Size { Width = tileWidth, Height = tileHeight }); }
/// <summary> /// Executes the actual algorithm. /// </summary> protected override void DoRun(CancellationToken cancellationToken) { var tiles = new Dictionary <TileIndex, RoutingTile>(); _edgeVisitor.Visit += (path) => { var e = path.Edge; var endWeight = path.Weight; if (e == Constants.NO_EDGE) { return(false); } // Calculate weight at start vertex. uint edgeId; if (e > 0) { edgeId = (uint)e - 1; } else { edgeId = (uint)((-e) - 1); } var edge = _graph.GetEdge(edgeId); var shape = _graph.GetShape(edge); var endCoordinate = shape[shape.Count - 1]; var index = TileIndex.WorldToTileIndex(endCoordinate.Latitude, endCoordinate.Longitude, _level); RoutingTile tile; if (!tiles.TryGetValue(index, out tile)) { tile = new RoutingTile { Weight = endWeight, Count = 1, Index = index }; } else { tile.Weight = (tile.Weight * tile.Count + endWeight) / tile.Count + 1; tile.Count++; } tiles[index] = tile; return(false); }; _edgeVisitor.Run(cancellationToken); _result = new HeatmapResult(); _result.Data = new HeatmapSample[tiles.Count]; var max = 0f; var i = 0; foreach (var pair in tiles) { var location = TileIndex.TileIndexToWorld(pair.Key.X, pair.Key.Y, _level); _result.Data[i] = new HeatmapSample() { Latitude = location.Latitude, Longitude = location.Longitude, Value = pair.Value.Weight }; if (max < pair.Value.Weight) { max = pair.Value.Weight; } i++; } _result.Max = max; this.HasSucceeded = true; }
private void AddEdgeVisit(Dictionary <TileIndex, RoutingTile> tiles, float startWeight, float endWeight, List <Coordinate> shape) { var startCoordinate = shape[0]; var startTile = TileIndex.WorldToTileIndex(startCoordinate.Latitude, startCoordinate.Longitude, _level); var startTileTopLeft = TileIndex.TileIndexToWorld(startTile.X, startTile.Y, _level); var startTileBottomRight = TileIndex.TileIndexToWorld(startTile.X + 1, startTile.Y + 1, _level); var latitudeDiff = System.Math.Abs(startTileTopLeft.Latitude - startTileBottomRight.Latitude); var longitudeDiff = System.Math.Abs(startTileTopLeft.Longitude - startTileBottomRight.Longitude); var offsetLat = Coordinate.DistanceEstimateInMeter(startCoordinate.Latitude, startCoordinate.Longitude, startCoordinate.Latitude + latitudeDiff, startCoordinate.Longitude); var offsetLon = Coordinate.DistanceEstimateInMeter(startCoordinate.Latitude, startCoordinate.Longitude, startCoordinate.Latitude, startCoordinate.Longitude + longitudeDiff); var offsetMin = System.Math.Min(offsetLat, offsetLon); var length = Coordinate.DistanceEstimateInMeter(shape); var weight = endWeight - startWeight; var currentLength = 0f; for (var i = 0; i < shape.Count; i++) { var coordinate = shape[i]; var index = TileIndex.WorldToTileIndex(coordinate.Latitude, coordinate.Longitude, _level); if (i > 0) { currentLength += Coordinate.DistanceEstimateInMeter(shape[i - 1], shape[i]); } var tileWeight = startWeight + (currentLength / length) * weight; RoutingTile tile; if (!tiles.TryGetValue(index, out tile)) { tile = new RoutingTile { Weight = tileWeight, Count = 1, Index = index }; } else { tile.Weight = (tile.Weight * tile.Count + tileWeight) / tile.Count + 1; tile.Count++; } tiles[index] = tile; if (i < shape.Count - 1) { var distance = Coordinate.DistanceEstimateInMeter(shape[i], shape[i + 1]); if (distance > offsetMin) { // it's possible these two skipped over a tile. var count = (float)System.Math.Ceiling(distance / offsetMin); var latOffset = (shape[i + 1].Latitude - shape[i].Latitude) / count; var lonOffset = (shape[i + 1].Longitude - shape[i].Longitude) / count; for (var j = 0; j < count - 1; j++) { coordinate = new Coordinate(shape[i].Latitude + (latOffset * (j + 1)), shape[i].Longitude + (lonOffset * (j + 1))); index = TileIndex.WorldToTileIndex(coordinate.Latitude, coordinate.Longitude, _level); var offsetLength = Coordinate.DistanceEstimateInMeter(shape[i], coordinate); tileWeight = startWeight + ((currentLength + offsetLength) / length) * weight; if (!tiles.TryGetValue(index, out tile)) { tile = new RoutingTile { Weight = tileWeight, Count = 1, Index = index }; } else { tile.Weight = (tile.Weight * tile.Count + tileWeight) / tile.Count + 1; tile.Count++; } tiles[index] = tile; } } } } }