コード例 #1
0
        public void TiledBarrierGraph_RemoveEdge_2Edges_RemoveFirst_ShouldLeave1()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2     = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var v3     = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341432);
            var e1     = graphs.AddEdge(v1, v2, Enumerable.Empty <(double longitude, double latitude)>(),
                                        new TagsCollection());;
            var e2 = graphs.AddEdge(v1, v3, Enumerable.Empty <(double longitude, double latitude)>(),
                                    new TagsCollection());

            graphs.DeleteEdge(e1);

            var enumerator = graphs.GetEnumerator();

            Assert.True(enumerator.MoveTo(v1));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(v1, enumerator.Vertex1);
            Assert.Equal(v3, enumerator.Vertex2);
            Assert.Equal(e2, enumerator.Edge);
            Assert.False(enumerator.MoveNext());

            Assert.True(enumerator.MoveTo(v2));
            Assert.False(enumerator.MoveNext());

            Assert.True(enumerator.MoveTo(v3));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(v1, enumerator.Vertex2);
            Assert.Equal(v3, enumerator.Vertex1);
            Assert.Equal(e2, enumerator.Edge);
            Assert.False(enumerator.MoveNext());
        }
コード例 #2
0
        /// <summary>
        /// Builds a guid for the given face.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="face">The face.</param>
        public static Guid?GetFaceGuid(this TiledBarrierGraph graph, int face)
        {
            var locations = graph.FaceToClockwiseCoordinates(face).Select(x =>
                                                                          TileStatic.ToLocalTileCoordinates(14, x, 16384)).ToArray();

            return(GetFaceGuidFor(locations));
        }
コード例 #3
0
        public void TiledBarrierGraphExtensions_NextClockwise_TwoOtherEdges_ShouldBeClockWise()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(
                4.801325798034667,
                51.268153126307524);
            var v2 = graphs.AddVertex(
                4.801331162452698,
                51.267829233580834);
            var v3 = graphs.AddVertex(
                4.801816642284393,
                51.26783426820025);
            var v4 = graphs.AddVertex(
                4.801317751407623,
                51.26754225936128);
            var e1 = graphs.AddEdge(v1, v2);
            var e2 = graphs.AddEdge(v2, v3);
            var e3 = graphs.AddEdge(v2, v4);

            var enumerator = graphs.GetEnumerator();

            enumerator.MoveTo(v1);
            enumerator.MoveNext();

            using var clockwise = enumerator.NextClockwise().GetEnumerator();
            Assert.True(clockwise.MoveNext());
            Assert.Equal(v4, clockwise.Current.Vertex2);
            Assert.True(clockwise.MoveNext());
            Assert.Equal(v3, clockwise.Current.Vertex2);
            Assert.False(clockwise.MoveNext());
        }
コード例 #4
0
        internal static void AddTileFor(this TiledBarrierGraph graph, int vertex, Func <uint, IEnumerable <OsmGeo> > getTile,
                                        Func <TagsCollectionBase, bool> isBarrier)
        {
            var vLocation = graph.GetVertex(vertex);
            var t         = TileStatic.WorldTileLocalId(vLocation.longitude, vLocation.latitude, graph.Zoom);

            graph.AddTiles(new[] { t }, getTile, isBarrier);
        }
コード例 #5
0
        public void TiledBarrierGraph_RemoveEdge_2Edges_Add4_Remove2_ShouldLeave2()
        {
            var graphs = new TiledBarrierGraph();

            var v1 = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2 = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var v3 = graphs.AddVertex(4.752981662750244, 50.978996666362015, 564341432);
            var v4 = graphs.AddVertex(4.7518390417099, 50.97881090537897, 564341433);
            var e1 = graphs.AddEdge(v1, v2);
            var e2 = graphs.AddEdge(v3, v4);

            var v5 = graphs.AddVertex(4.752375483512878, 50.97889534228157);
            var e3 = graphs.AddEdge(v1, v5);
            var e4 = graphs.AddEdge(v5, v2);
            var e5 = graphs.AddEdge(v3, v5);
            var e6 = graphs.AddEdge(v5, v4);

            graphs.DeleteEdge(e1);
            graphs.DeleteEdge(e2);

            var enumerator = graphs.GetEnumerator();

            Assert.True(enumerator.MoveTo(v1));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(e3, enumerator.Edge);
            Assert.False(enumerator.MoveNext());

            Assert.True(enumerator.MoveTo(v2));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(e4, enumerator.Edge);
            Assert.False(enumerator.MoveNext());

            Assert.True(enumerator.MoveTo(v3));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(e5, enumerator.Edge);
            Assert.False(enumerator.MoveNext());

            Assert.True(enumerator.MoveTo(v4));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(e6, enumerator.Edge);
            Assert.False(enumerator.MoveNext());

            var expected = new HashSet <int>(new [] { e3, e4, e5, e6 });

            Assert.True(enumerator.MoveTo(v5));
            Assert.True(enumerator.MoveNext());
            Assert.True(expected.Remove(enumerator.Edge));
            Assert.True(enumerator.MoveNext());
            Assert.True(expected.Remove(enumerator.Edge));
            Assert.True(enumerator.MoveNext());
            Assert.True(expected.Remove(enumerator.Edge));
            Assert.True(enumerator.MoveNext());
            Assert.True(expected.Remove(enumerator.Edge));
            Assert.False(enumerator.MoveNext());
            Assert.Empty(expected);
        }
コード例 #6
0
        /// <summary>
        /// Builds a guid for the given vertex.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="vertex">The vertex.</param>
        public static Guid GetVertexGuid(this TiledBarrierGraph graph, int vertex)
        {
            // we have a planar graph so location <-> guid.
            // we generate an id based on the vertex location relative in a tile.

            var location     = graph.GetVertex(vertex);
            var tileLocation = TileStatic.ToLocalTileCoordinates(graph.Zoom, location, 16384);

            return(GuidUtility.Create(Namespace, tileLocation.GetBytes()));
        }
コード例 #7
0
        public void TiledBarrierGraph_Enumerator_1Vertex_ShouldEnumerate1Vertex()
        {
            var graphs = new TiledBarrierGraph();
            var v      = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);

            var enumerator = graphs.GetEnumerator();

            Assert.True(enumerator.MoveTo(v));
            Assert.False(enumerator.MoveNext());
        }
コード例 #8
0
        public void TiledBarrierGraph_AddVertex_1Vertex_ShouldAddVertex0()
        {
            var graphs = new TiledBarrierGraph();
            var v      = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);

            Assert.Equal(1, graphs.VertexCount);
            Assert.Equal(0, v);

            var vLocation = graphs.GetVertex(v);

            Assert.Equal((4.7522735595703125, 50.97918242660188), vLocation);
        }
コード例 #9
0
        internal static void LoadForTile(this TiledBarrierGraph graph, uint tile,
                                         Func <uint, IEnumerable <OsmGeo> > getTile,
                                         Func <TagsCollectionBase, bool> isBarrier)
        {
            // mark tile as loaded.
            graph.SetTileLoaded(tile);

            // first load the tile in question.
            var tileData   = getTile(tile);
            var extraTiles = graph.Add(tileData, isBarrier);

            // add all the tiles.
            graph.AddTiles(extraTiles, getTile, isBarrier);
        }
コード例 #10
0
        public void Faces_AssignFaces_OneLoop2_ShouldAssign2()
        {
            var graphs = new TiledBarrierGraph();

            //    0
            //   / \
            //  1---2

            var v1 = graphs.AddVertex(
                4.788075685501099,
                51.26676188180721, 564341430);
            var v2 = graphs.AddVertex(
                4.786123037338257,
                51.26496276736555, 564341431);
            var v3 = graphs.AddVertex(
                4.790832996368408,
                51.265137311403734, 564341432);

            var e1 = graphs.AddEdge(v1, v2);
            var e2 = graphs.AddEdge(v3, v2);
            var e3 = graphs.AddEdge(v3, v1);

            graphs.SetTileLoaded(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v1), 14));
            graphs.SetTileLoaded(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v2), 14));
            graphs.SetTileLoaded(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v3), 14));

            graphs.AssignFaces(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v1), 14));

            Assert.Equal(3, graphs.FaceCount);
            var enumerator = graphs.GetEnumerator();

            enumerator.MoveTo(v1);
            enumerator.MoveNextUntil(e1);

            Assert.NotEqual(int.MaxValue, enumerator.FaceLeft);
            var left = enumerator.FaceLeft;

            Assert.NotEqual(int.MaxValue, enumerator.FaceRight);
            var right = enumerator.FaceRight;

            enumerator.MoveTo(v2);
            enumerator.MoveNextUntil(e2);
            Assert.False(enumerator.Forward);
            Assert.Equal(left, enumerator.FaceRight);
            Assert.Equal(right, enumerator.FaceLeft);
            enumerator.MoveTo(v3);
            enumerator.MoveNextUntil(e3);
            Assert.Equal(left, enumerator.FaceLeft);
            Assert.Equal(right, enumerator.FaceRight);
        }
コード例 #11
0
        public void Faces_AssignFaces_OneEdge_ShouldAssign1()
        {
            var graphs = new TiledBarrierGraph();

            var v1   = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2   = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var e    = graphs.AddEdge(v1, v2);
            var tile = Tiles.TileStatic.WorldTileLocalId(4.7522735595703125, 50.97918242660188, 14);

            graphs.SetTileLoaded(tile);

            graphs.AssignFaces(tile);

            Assert.Equal(1, graphs.FaceCount);
        }
コード例 #12
0
        EnumerateFaceClockwise(
            this TiledBarrierGraph graph, int face, int maxFaceCount = ushort.MaxValue)
        {
            var enumerator = graph.GetFaceEnumerator();

            if (!enumerator.MoveTo(face))
            {
                yield break;
            }
            if (face == 0)
            {
                yield break;
            }

            var edges = new List <(int vertex1, int edge, bool forward, int vertex2, (double longitude, double latitude)[] shape)>();
コード例 #13
0
        public void TiledBarrierGraphExtensions_NextClockwise_NoOtherEdge_ShouldBeEmpty()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2     = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var e      = graphs.AddEdge(v1, v2);

            var enumerator = graphs.GetEnumerator();

            enumerator.MoveTo(v1);
            enumerator.MoveNext();

            var clockwise = enumerator.NextClockwise();

            Assert.Empty(clockwise);
        }
コード例 #14
0
        public void TiledBarrierGraph_SetFace_Right_1Edge_ShouldSetFaceRight()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2     = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var e      = graphs.AddEdge(v1, v2);

            var f = graphs.AddFace();

            graphs.SetFace(e, false, f);

            var enumerator = graphs.GetEnumerator();

            enumerator.MoveTo(v1);
            enumerator.MoveNext();
            Assert.Equal(int.MaxValue, enumerator.FaceLeft);
            Assert.Equal(f, enumerator.FaceRight);
        }
コード例 #15
0
        public void TiledBarrierGraph_FaceEnumerator_1Edge_Left_ShouldEnumerateEdge()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2     = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var e      = graphs.AddEdge(v1, v2);

            var f = graphs.AddFace();

            graphs.SetFace(e, true, f);

            var enumerator = graphs.GetFaceEnumerator();

            Assert.True(enumerator.MoveTo(f));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(e, enumerator.Edge);
            Assert.True(enumerator.IsLeft);
            Assert.False(enumerator.MoveNext());
        }
コード例 #16
0
        internal static void AddTiles(this TiledBarrierGraph graph, IEnumerable <uint> tiles,
                                      Func <uint, IEnumerable <OsmGeo> > getTile,
                                      Func <TagsCollectionBase, bool> isBarrier)
        {
            foreach (var tile in tiles)
            {
                // mark tile as loaded.
                graph.SetTileLoaded(tile);

                // get the data and load it.
                var tileData = getTile(tile);
                graph.Add(tileData, isBarrier);
            }

            // prune graph.
            graph.PruneDeadEnds();
            graph.PruneShapePoints();

            // standardize edges
            // loading them in a different order could lead to different start and end points
            graph.StandardizeEdges();
        }
コード例 #17
0
        public void TiledBarrierGraph_AddEdge_1Edge_ShouldAddEdge0()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(4.7522735595703125, 50.97918242660188, 564341430);
            var v2     = graphs.AddVertex(4.7525310516357420, 50.97851368626033, 564341431);
            var e      = graphs.AddEdge(v1, v2);

            Assert.Equal(2, graphs.VertexCount);
            Assert.Equal(0, e);

            var enumerator = graphs.GetEnumerator();

            Assert.True(enumerator.MoveTo(v1));
            Assert.True(enumerator.MoveNext());
            Assert.Equal(v1, enumerator.Vertex1);
            Assert.Equal(v2, enumerator.Vertex2);
            Assert.Equal(0, enumerator.Edge);
            Assert.NotNull(enumerator.Shape);
            Assert.Empty(enumerator.Shape);
            Assert.Equal(0, enumerator.Tags.Count);
            Assert.False(enumerator.MoveNext());
        }
コード例 #18
0
        public void Faces_RightTurnLoop_3EdgeLoop_Backward_ShouldReturnCounterClockwiseLoop()
        {
            var graphs = new TiledBarrierGraph();

            //    0
            //   / \
            //  1---2

            var v1 = graphs.AddVertex(
                4.788075685501099,
                51.26676188180721, 564341430);
            var v2 = graphs.AddVertex(
                4.786123037338257,
                51.26496276736555, 564341431);
            var v3 = graphs.AddVertex(
                4.790832996368408,
                51.265137311403734, 564341432);

            var e1 = graphs.AddEdge(v1, v2);
            var e2 = graphs.AddEdge(v2, v3);
            var e3 = graphs.AddEdge(v3, v1);

            graphs.SetTileLoaded(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v1), 14));
            graphs.SetTileLoaded(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v2), 14));
            graphs.SetTileLoaded(Tiles.TileStatic.WorldTileLocalId(graphs.GetVertex(v3), 14));

            // calculate right turn loop starting at e1.
            var enumerator = graphs.GetEnumerator();

            enumerator.MoveTo(v2);
            enumerator.MoveNextUntil(e1);
            var(loop, _) = enumerator.RightTurnLoop();

            Assert.NotNull(loop);
            Assert.Equal(3, loop.Count);
            Assert.Equal((v2, e1, false, v1), loop[0]);
            Assert.Equal((v1, e3, false, v3), loop[1]);
            Assert.Equal((v3, e2, false, v2), loop[2]);
        }
コード例 #19
0
        public void TiledBarrierGraphExtensions_NextClockwise_OneOtherEdge_ShouldBeSingle()
        {
            var graphs = new TiledBarrierGraph();
            var v1     = graphs.AddVertex(
                4.801331162452698,
                51.267829233580834);
            var v2 = graphs.AddVertex(
                4.801325798034667,
                51.268153126307524);
            var v3 = graphs.AddVertex(
                4.801816642284393,
                51.26783426820025);
            var e1 = graphs.AddEdge(v2, v1);
            var e2 = graphs.AddEdge(v1, v3);

            var enumerator = graphs.GetEnumerator();

            enumerator.MoveTo(v2);
            enumerator.MoveNext();

            var clockwise = enumerator.NextClockwise();

            Assert.Single(clockwise);
        }
コード例 #20
0
 public static void AssignLanduse(
     this TiledBarrierGraph tiledBarrierGraph, uint tile,
     Func <((double longitude, double latitude) topLeft, (double longitude, double latitude) bottomRight), IEnumerable <(Polygon polygon, string type)> > getLanduse)
コード例 #21
0
        public static void WriteTileTo(this TiledBarrierGraph graph, Stream stream, uint tile)
        {
            var enumerator = graph.GetEnumerator();

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

                // write vertex details.
                var vertexGuid = graph.GetVertexGuid(v);
                stream.Write(vertexGuid.ToByteArray());
                stream.Write(graph.GetVertexLocationBytes(v));
            }
            stream.Write(EmptyGuid);

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

                // check (and count) edges.
                var edges = 0;
                while (enumerator.MoveNext())
                {
                    if (enumerator.Forward)
                    {
                        edges++;
                    }
                }
                if (edges == 0)
                {
                    continue;
                }

                // write vertex1 details.
                var vertex1Guid = graph.GetVertexGuid(v);
                stream.Write(vertex1Guid.ToByteArray());

                // write edges details.
                stream.Write(BitConverter.GetBytes(edges)); // the number of edges.
                enumerator.MoveTo(v);
                while (enumerator.MoveNext())
                {
                    if (!enumerator.Forward)
                    {
                        continue;
                    }

                    enumerator.WriteToStream(stream);
                }
            }
            stream.Write(EmptyGuid);

            // write faces.
            for (var f = 1; f < graph.FaceCount; f++)
            {
                var faceGuid = graph.GetFaceGuid(f);
                if (faceGuid == null)
                {
                    continue;
                }
                stream.Write(faceGuid.Value.ToByteArray());

                // write edges.
                var edges = graph.EnumerateFaceClockwise(f).ToList();
                stream.Write(BitConverter.GetBytes(edges.Count));
                foreach (var edge in edges)
                {
                    enumerator.MoveTo(edge.vertex1);
                    enumerator.MoveNextUntil(edge.edge);

                    stream.Write(enumerator.GetEdgeGuid().ToByteArray());
                    stream.WriteByte(edge.forward ? (byte)1 :  (byte)0);
                }

                // write attributes.
                stream.WriteAttributes(graph.GetFaceData(f));
            }
            stream.Write(EmptyGuid);
        }
コード例 #22
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>());
        }
コード例 #23
0
        public void Faces_AssignFaces_NoEdges_ShouldDoNothing()
        {
            var graphs = new TiledBarrierGraph();

            graphs.AssignFaces(41525);
        }
コード例 #24
0
 private static byte[] GetVertexLocationBytes(this TiledBarrierGraph graph, int v)
 {
     return(TileStatic.ToLocalTileCoordinates(graph.Zoom, graph.GetVertex(v), 16384).GetBytes());
 }
コード例 #25
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);
        }
コード例 #26
0
        public static async Task BuildForTile(uint tile, string folder, Func <uint, IEnumerable <OsmGeo> > getTile,
                                              Func <TagsCollectionBase, bool> isBarrier)
        {
            // wait until tile is removed from queue.
            while (true)
            {
                if (_tiles.ContainsKey(tile))
                {
                    await Task.Delay(200);
                }
                else
                {
                    _tiles[tile] = tile;
                    break;
                }
            }

            try
            {
                var file = Path.Combine(folder, $"{tile}.tile.graph.zip");
                if (File.Exists(file))
                {
                    return;
                }

                // load data for tile.
                var graph = new TiledBarrierGraph();
                graph.LoadForTile(tile, getTile, isBarrier);

                // run face assignment for the tile.
                var result = graph.AssignFaces(tile);
                while (!result.success)
                {
                    // extra tiles need loading.-
                    graph.AddTiles(result.missingTiles, getTile, isBarrier);

                    // try again.
                    result = graph.AssignFaces(tile);
                }

                // assign landuse.
                IEnumerable <(Polygon polygon, string type)> GetLanduse(
                    ((double longitude, double latitude)topLeft, (double longitude, double latitude)bottomRight) box)
                {
                    return(LandusePolygons.GetLandusePolygons(box, graph.Zoom, getTile, t =>
                    {
                        if (DefaultMergeFactorCalculator.Landuses.TryCalculateValue(t, out var type))
                        {
                            return type;
                        }

                        return null;
                    }));
                }

                graph.AssignLanduse(tile, GetLanduse);

                await using var stream           = File.Open(file, FileMode.Create);
                await using var compressedStream = new GZipStream(stream, CompressionLevel.Fastest);
                graph.WriteTileTo(compressedStream, tile);
            }
            finally
            {
                _tiles.Remove(tile, out _);
            }
        }