예제 #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;
        }
예제 #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
            });
        }
예제 #3
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;
        }
예제 #4
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;
                        }
                    }
                }
            }
        }