예제 #1
0
        /// <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);
        }
        /// <summary>
        /// Extracts segments for the given tile.
        /// </summary>
        public static Segment[] ExtractSegments(this RouterDb routerDb, ulong tileId,
                                                SegmentLayerConfig config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }
            if (config.Name == null)
            {
                throw new ArgumentException("Layer configuration has no name set.");
            }

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

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

            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);

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

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

                    // check if this edge needs to be included or not.
                    if (config != null && config.IncludeProfileFunc != null &&
                        !config.IncludeProfileFunc(edgeData.Profile, edgeData.MetaId))
                    { // include profile returns false
                        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);
                            }

                            segments.Add(new Segment()
                            {
                                Meta    = edgeData.MetaId,
                                Profile = edgeData.Profile,
                                Shape   = shape.ToArray()
                            });
                            shape.Clear();
                            previous = false;
                        }
                    }

                    if (shape.Count >= 2)
                    {
                        segments.Add(new Segment()
                        {
                            Meta    = edgeData.MetaId,
                            Profile = edgeData.Profile,
                            Shape   = shape.ToArray()
                        });
                        shape.Clear();
                    }
                }
            }

            return(segments.ToArray());
        }