Exemplo n.º 1
0
        /// <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;
        }
Exemplo n.º 2
0
        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
            });
        }
Exemplo n.º 3
0
        private static void UpdateForWalking(Dictionary <TileIndex, RoutingTile> result, RoutingTile sourceTile,
                                             int level, float speedInMetersPerSecond, float isochroneLimit, Size size)
        {
            var tileRange = TileHelper.CalculateTileRange(sourceTile, isochroneLimit, speedInMetersPerSecond, level);

            // The code below could be optimized if we start at the center and stop as soon
            // as an update does not improve a weight.

            for (var x = tileRange.Left; x <= tileRange.Right; x++)
            {
                for (var y = tileRange.Top; y <= tileRange.Bottom; y++)
                {
                    // note: The value of the node itself is included by adding zero in case distance is zero.

                    // todo: Ignore tiles outside tile schema.

                    var distance = Math.Sqrt(
                        Math.Pow((sourceTile.Index.X - x) * size.Width, 2) +
                        Math.Pow((sourceTile.Index.Y - y) * size.Height, 2));

                    var walkingWeight = sourceTile.Weight + distance * speedInMetersPerSecond;

                    var tileIndex = new TileIndex(x, y);

                    if (result.ContainsKey(tileIndex))
                    {
                        var routingTile = result[tileIndex];
                        routingTile.Weight = (float)Math.Min(walkingWeight, routingTile.Weight);
                        result[tileIndex]  = routingTile;
                    }
                    else
                    {
                        result[tileIndex] = new RoutingTile
                        {
                            Weight = (float)walkingWeight,
                            Index  = tileIndex,
                        };
                    }
                }
            }
        }
Exemplo n.º 4
0
        /// <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;
        }
Exemplo n.º 5
0
        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;
                        }
                    }
                }
            }
        }