/// <summary>
        /// Extracts a vector tile of the given tile.
        /// </summary>
        public static VectorTile ExtractTile(this RouterDb routerDb, ulong tileId,
                                             VectorTileConfig config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var layers = routerDb.ExtractLayers(tileId, config);

            return(new VectorTile()
            {
                Layers = new List <Layer>(layers),
                TileId = tileId
            });
        }
Beispiel #2
0
        /// <summary>
        /// Extract data for the given tile.
        /// </summary>
        public static VectorTile ExtractTile(this MultimodalDb db, ulong tileId, VectorTileConfig config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var layers = new List <Layer>();

            if (config.SegmentLayerConfig != null)
            {
                layers.Add(db.RouterDb.ExtractSegmentLayer(tileId, config.SegmentLayerConfig));
            }
            if (config.StopLayerConfig != null)
            {
                layers.Add(db.TransitDb.ExtractPointLayerForStops(tileId, config.StopLayerConfig));
            }

            return(new VectorTile()
            {
                Layers = layers,
                TileId = tileId
            });
        }
        /// <summary>
        /// Extracts a segment layer for the given tile.
        /// </summary>
        public static IEnumerable <Layer> ExtractLayers(this RouterDb routerDb, ulong tileId,
                                                        VectorTileConfig config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var tile    = new Tile(tileId);
            var diffX   = (tile.Top - tile.Bottom);
            var diffY   = (tile.Right - tile.Left);
            var marginX = diffX / 512;
            var marginY = diffY / 512;

            var tileBox = new LocalGeo.Box(tile.Bottom - marginY, tile.Left - marginX,
                                           tile.Top + marginY, tile.Right + marginX);

            // initialize vertex layers.
            var vertexLayers = new List <VertexLayer>();

            if (config.VertexLayerConfigs != null)
            {
                foreach (var vertexLayerConfig in config.VertexLayerConfigs)
                {
                    vertexLayers.Add(vertexLayerConfig.NewLayer());
                }
            }

            // initialize edge layers.
            var edgeLayers = new List <EdgeLayer>();

            if (config.EdgeLayerConfigs != null)
            {
                foreach (var edgeLayerConfig in config.EdgeLayerConfigs)
                {
                    edgeLayers.Add(edgeLayerConfig.NewLayer());
                }
            }

            if (edgeLayers.Count == 0 && vertexLayers.Count == 0)
            {
                return(Enumerable.Empty <Layer>());
            }

            var vertices = HilbertExtensions.Search(routerDb.Network.GeometricGraph,
                                                    tileBox.MinLat - diffY, tileBox.MinLon - diffX,
                                                    tileBox.MaxLat + diffY, tileBox.MaxLon + diffX);
            var edges = new HashSet <long>();

            var edgeEnumerator = routerDb.Network.GetEdgeEnumerator();

            foreach (var vertex in vertices)
            {
                var coordinateFrom = routerDb.Network.GetVertex(vertex);

                if (!edgeEnumerator.MoveTo(vertex))
                {
                    continue;
                }

                // add vertex to each layer that wants it.
                foreach (var vertexLayer in vertexLayers)
                {
                    if (vertexLayer.Config.GetAttributesFunc(vertex, tile.Zoom) != null)
                    {
                        vertexLayer.Vertices.Add(new Vertex()
                        {
                            Latitude  = coordinateFrom.Latitude,
                            Longitude = coordinateFrom.Longitude,
                            Id        = vertex
                        });
                    }
                }

                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    if (edges.Contains(edgeEnumerator.Id))
                    {
                        continue;
                    }
                    edges.Add(edgeEnumerator.Id);

                    // loop over shape.
                    var edgeData = edgeEnumerator.Data;

                    // build a list of layers to included or not.
                    var include = edgeLayers.Where(l => l.Config.GetAttributesFunc(edgeEnumerator.Id, tile.Zoom) != null)
                                  .ToList();
                    if (include.Count == 0)
                    { // nothing to include.
                        continue;
                    }

                    // get shape.
                    var coordinateTo = routerDb.Network.GetVertex(edgeEnumerator.To);
                    var shape        = new List <Coordinate>();
                    var enumShape    = routerDb.Network.GetShape(edgeEnumerator.Current);

                    // reverse shape if edge is reversed.
                    if (edgeEnumerator.DataInverted)
                    {
                        enumShape.Reverse();
                    }

                    // split at tile edges.
                    var previous = false;
                    for (var i = 0; i < enumShape.Count; i++)
                    {
                        var location = enumShape[i];
                        if (tileBox.Overlaps(location.Latitude, location.Longitude))
                        {
                            if (previous == false && i > 0)
                            { // come up with intersection point and add that first.
                                var intersection = tileBox.Intersection(new Line(location, enumShape[i - 1]));
                                if (intersection != null)
                                {
                                    shape.Add(intersection.Value);
                                }
                            }

                            // add location.
                            shape.Add(location);
                            previous = true;
                        }
                        else if (previous)
                        { // come up with intersection point and add that as last point.
                            var intersection = tileBox.Intersection(new Line(location, enumShape[i - 1]));
                            if (intersection != null)
                            {
                                shape.Add(intersection.Value);
                            }

                            foreach (var layer in include)
                            {
                                layer.Edges.Add(new Edge()
                                {
                                    Shape  = shape.ToArray(),
                                    EdgeId = edgeEnumerator.Id,
                                });
                            }
                            shape.Clear();
                            previous = false;
                        }
                    }

                    if (shape.Count >= 2)
                    {
                        foreach (var layer in include)
                        {
                            layer.Edges.Add(new Edge()
                            {
                                Shape  = shape.ToArray(),
                                EdgeId = edgeEnumerator.Id,
                            });
                        }
                        shape.Clear();
                    }
                }
            }

            var layers = new List <Layer>(vertexLayers);

            layers.AddRange(edgeLayers);
            return(layers);
        }