/// <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()); }