Exemplo n.º 1
0
        private static IEnumerable <uint> Add(this TiledBarrierGraph graph, IEnumerable <OsmGeo> osmGeos,
                                              Func <TagsCollectionBase, bool> isBarrier)
        {
            var uncoveredTiles = new HashSet <uint>();

            // collect all nodes with more than one barrier way.
            var nodes       = new Dictionary <long, (double longitude, double latitude)?>();
            var vertexNodes = new Dictionary <long, int>();

            foreach (var osmGeo in osmGeos)
            {
                if (!(osmGeo is Way way))
                {
                    continue;
                }
                if (way.Nodes == null)
                {
                    continue;
                }
                if (!isBarrier(way.Tags))
                {
                    continue;
                }

                for (var n = 0; n < way.Nodes.Length; n++)
                {
                    var nodeId = way.Nodes[n];

                    if (graph.TryGetVertex(nodeId, out var vertex))
                    {
                        // node already there as a vertex.
                        vertexNodes[nodeId] = vertex;
                    }
                    else
                    {
                        // not yet a vertex.
                        // keep first, last and reused nodes are intersections.
                        if (n == 0 || n == way.Nodes.Length - 1 ||
                            nodes.ContainsKey(nodeId))
                        {
                            vertexNodes[nodeId] = int.MaxValue;
                        }
                    }

                    nodes[nodeId] = null;
                }
            }

            // add all vertices new vertices and store node locations.
            using var enumerator = osmGeos.GetEnumerator();
            var hasNext = true;

            while (hasNext)
            {
                hasNext = enumerator.MoveNext();
                if (!hasNext)
                {
                    break;
                }

                if (!(enumerator.Current is Node node))
                {
                    break;
                }
                if (node.Id == null || node.Latitude == null || node.Longitude == null)
                {
                    continue;
                }
                if (graph.TryGetVertex(node.Id.Value, out _))
                {
                    continue;
                }
                if (!nodes.ContainsKey(node.Id.Value))
                {
                    continue;                                    // not part of a barrier way.
                }
                nodes[node.Id.Value] = (node.Longitude.Value, node.Latitude.Value);

                var tile = TileStatic.WorldTileLocalId(node.Longitude.Value, node.Latitude.Value, graph.Zoom);
                if (!vertexNodes.ContainsKey(node.Id.Value) &&
                    graph.HasTile(tile))
                {
                    continue; // node is not a vertex and inside a loaded tile.
                }
                var vertex = graph.AddVertex(node.Longitude.Value, node.Latitude.Value, node.Id.Value);
                vertexNodes[node.Id.Value] = vertex;

                if (!graph.HasTile(tile))
                {
                    uncoveredTiles.Add(tile);
                }
            }

            // add all edges.
            var shape = new List <(double longitude, double latitude)>();

            while (hasNext)
            {
                if (!hasNext)
                {
                    break;
                }

                if (!(enumerator.Current is Way way))
                {
                    break;
                }
                if (way.Nodes == null || way.Tags == null || way.Id == null)
                {
                    hasNext = enumerator.MoveNext();
                    continue;
                }
                if (!isBarrier(way.Tags))
                {
                    hasNext = enumerator.MoveNext();
                    continue;
                }
                if (graph.HasWay(way.Id.Value))
                {
                    hasNext = enumerator.MoveNext();
                    continue;
                }

                // way is a barrier, add it as one or more edges.
                shape.Clear();
                var vertex1 = int.MaxValue;
                foreach (var node in way.Nodes)
                {
                    if (!vertexNodes.TryGetValue(node, out var vertex))
                    {
                        if (!nodes.TryGetValue(node, out var nodeLocation))
                        {
                            throw new InvalidDataException(
                                      $"Node {node} in way {way.Id} not found!");
                        }
                        if (nodeLocation == null)
                        {
                            OsmSharp.Logging.Logger.Log(nameof(TiledBarrierGraphBuilder), TraceEventType.Warning,
                                                        $"Node location for node {node} in way {way.Id} not found!");
                        }
                        else
                        {
                            shape.Add(nodeLocation.Value);
                        }
                        continue;
                    }
                    else if (vertex == int.MaxValue)
                    {
                        OsmSharp.Logging.Logger.Log(nameof(TiledBarrierGraphBuilder), TraceEventType.Warning,
                                                    $"Node {node} in way {way.Id} not found in tile!");
                        continue;
                    }

                    if (vertex1 == int.MaxValue)
                    {
                        vertex1 = vertex;
                        continue;
                    }

                    graph.AddEdgeFlattened(vertex1, vertex, shape, way.Tags, way.Id.Value);
                    vertex1 = vertex;
                    shape.Clear();
                }

                hasNext = enumerator.MoveNext();
            }

            return(uncoveredTiles);
        }
Exemplo n.º 2
0
        public static (bool success, IEnumerable <uint> missingTiles) AssignFaces(this TiledBarrierGraph graph,
                                                                                  uint tile)
        {
            if (!graph.HasTile(tile))
            {
                return(false, new[] { tile });
            }
            var tileBox = TileStatic.Box(graph.Zoom, tile);

            var tilesMissing = new HashSet <uint>();

            graph.ResetFaces();

            // the default face for the case where a loop cannot be found.
            var unAssignableFace = graph.AddFace();

            // check each edges for faces and if missing assign them.
            var enumerator = graph.GetEnumerator();

            for (var v = 0; v < graph.VertexCount; v++)
            {
                if (!enumerator.MoveTo(v))
                {
                    continue;
                }
                if (!enumerator.MoveNext())
                {
                    continue;
                }

                var vBox = graph.GetVertexBox(v);
                if (vBox == null || !vBox.Value.Overlaps(tileBox))
                {
                    continue;
                }
                // var vTile = TileStatic.WorldTileLocalId(vLocation.longitude, vLocation.latitude, graph.Zoom);
                // if (vTile != tile) continue;

                enumerator.MoveTo(v);
                while (enumerator.MoveNext())
                {
                    if (enumerator.Forward && enumerator.FaceRight != int.MaxValue)
                    {
                        continue;
                    }
                    if (!enumerator.Forward && enumerator.FaceLeft != int.MaxValue)
                    {
                        continue;
                    }

                    // check if the edge bbox overlaps the tiles.
                    var eBox = enumerator.Box;
                    if (!eBox.Overlaps(tileBox))
                    {
                        continue;
                    }

                    // ok this edge has an undetermined face.
                    var result = enumerator.AssignFace(unAssignableFace);
                    if (!result.success)
                    {
                        tilesMissing.UnionWith(result.missingTiles);
                    }
                }
            }

            if (tilesMissing.Count > 0)
            {
                return(false, tilesMissing);
            }

            return(true, Enumerable.Empty <uint>());
        }