コード例 #1
0
        public static void WriteToStream(this TiledBarrierGraph.BarrierGraphEnumerator enumerator, Stream stream)
        {
            var graph = enumerator.Graph;

            stream.Write(enumerator.GetEdgeGuid().ToByteArray());

            var vertex2Guid = graph.GetVertexGuid(enumerator.Vertex2);

            stream.Write(vertex2Guid.ToByteArray());

            var shape = enumerator.Shape;

            stream.Write(BitConverter.GetBytes(shape.Length));
            for (var s = 0; s < shape.Length; s++)
            {
                stream.Write(TileStatic.ToLocalTileCoordinates(graph.Zoom, shape[s], 16384).GetBytes());
            }

            var tags = enumerator.Tags;

            stream.Write(BitConverter.GetBytes(tags.Count));
            foreach (var tag in tags)
            {
                stream.WriteWithSize(tag.Key);
                stream.WriteWithSize(tag.Value);
            }
        }
コード例 #2
0
 internal static (double longitude, double latitude) FirstNonVertex2(
     this TiledBarrierGraph.BarrierGraphEnumerator enumerator)
 {
     if (enumerator.Shape.Length == 0)
     {
         return(enumerator.Graph.GetVertex(enumerator.Vertex1));
     }
     if (enumerator.Forward)
     {
         return(enumerator.Shape[^ 1]);
コード例 #3
0
 internal static void MoveNextUntil(this TiledBarrierGraph.BarrierGraphEnumerator enumerator, int edge)
 {
     while (enumerator.MoveNext())
     {
         if (enumerator.Edge == edge)
         {
             break;
         }
     }
 }
コード例 #4
0
        private static (bool success, IEnumerable <uint> missingTiles) AssignFace(this TiledBarrierGraph.BarrierGraphEnumerator enumerator,
                                                                                  int unAssignableFace)
        {
            var(loop, missingTiles) = enumerator.RightTurnLoop();
            if (loop == null)
            {
                return(false, missingTiles);
            }

            var face = unAssignableFace;

            if (loop[0].vertex1 == loop[^ 1].vertex2)
            {
                // remove parts that go over the same edge twice.
                var removed = true;
                while (removed)
                {
                    removed = false;
                    var edges = new Dictionary <int, int>();
                    for (var i = 0; i < loop.Count; i++)
                    {
                        var e = loop[i].edge;
                        if (edges.TryGetValue(e, out var fi))
                        {
                            var copy = new List <(int vertex1, int edge, bool forward, int vertex2)>(loop);

                            // a duplicate was detected.
                            copy.RemoveRange(fi, i - fi + 1);
                            loop = copy;

                            removed = true;
                            break;
                        }

                        edges.Add(e, i);
                    }
                }

                // if loop is closed then we have a new face.
                face = enumerator.Graph.AddFace();
            }

            // set face.
            foreach (var(_, e, f, _) in loop)
            {
                var left = !f;
                enumerator.Graph.SetFace(e, left, face);
            }

            return(true, Enumerable.Empty <uint>());
        }
コード例 #5
0
        internal static (IReadOnlyList <(int vertex1, int edge, bool forward, int vertex2)>?loop, IEnumerable <uint> missingTiles) RightTurnLoop(
            this TiledBarrierGraph.BarrierGraphEnumerator enumerator)
        {
            var edges = new HashSet <(int e, bool dir)>();

            edges.Add((enumerator.Edge, enumerator.Forward));
            var path = new List <(int v1, int e, bool f, int v2)>
            {
                (enumerator.Vertex1, enumerator.Edge, enumerator.Forward, enumerator.Vertex2)
            };

            // find a closed loop by always going right.
            var first = enumerator.NextRight();

            while (first != null)
            {
                // check for a u-turn.
                if (first.Edge == path[^ 1].e)
                {
                    break;
                }

                if (!enumerator.Graph.HasTileFor(first.Vertex2))
                {
                    return(null, new [] { enumerator.Graph.TileFor(first.Vertex2) });
                }

                path.Add((first.Vertex1, first.Edge, first.Forward, first.Vertex2));
                if (edges.Contains((first.Edge, first.Forward)))
                {
                    OsmSharp.Logging.Logger.Log(nameof(TiledBarrierGraphBuilder), TraceEventType.Warning,
                                                $"Edge visited twice in same direction!");
                    return(null, Enumerable.Empty <uint>());
                }
                edges.Add((first.Edge, first.Forward));

                if (first.Vertex2 == path[0].v1)
                {
                    break;
                }

                first = first.NextRight();
            }

            return(path, Enumerable.Empty <uint>());
        }
コード例 #6
0
        /// <summary>
        /// Builds a guid for the given edge.
        /// </summary>
        /// <param name="enumerator">The enumerator moved to the edge.</param>
        public static Guid GetEdgeGuid(this TiledBarrierGraph.BarrierGraphEnumerator enumerator)
        {
            var bytes = new List <byte>();

            if (!enumerator.Forward)
            {
                var otherEnumerator = enumerator.Graph.GetEnumerator();
                otherEnumerator.MoveTo(enumerator.Vertex2);
                otherEnumerator.MoveNextUntil(enumerator.Edge);
                enumerator = otherEnumerator;
            }

            foreach (var c in enumerator.CompleteShape())
            {
                var tiledLocation = TileStatic.ToLocalTileCoordinates(enumerator.Graph.Zoom, c, 16384);
                bytes.AddRange(tiledLocation.GetBytes());
            }

            return(GuidUtility.Create(Namespace, bytes));
        }
コード例 #7
0
        internal static IEnumerable <TiledBarrierGraph.BarrierGraphEnumerator> NextClockwise(this TiledBarrierGraph.BarrierGraphEnumerator enumerator)
        {
            var nextEnumerator = enumerator.Graph.GetEnumerator();

            nextEnumerator.MoveTo(enumerator.Vertex2);
            var graph = enumerator.Graph;

            // get a sorted list by angle clockwise relative to the selected edge.
            var v2NonLocation = enumerator.FirstNonVertex2();
            var v2Location    = graph.GetVertex(enumerator.Vertex2);
            var sortedByAngle = new SortedDictionary <double, int>();

            while (nextEnumerator.MoveNext())
            {
                if (nextEnumerator.Edge == enumerator.Edge)
                {
                    continue;
                }

                var nextNonLocation = nextEnumerator.FirstNonVertex1();
                var angle           = GeoExtensions.Angle(v2NonLocation, v2Location, nextNonLocation);
                if (angle == double.NaN)
                {
                    Debug.Assert(false);
                }
                sortedByAngle[angle] = nextEnumerator.Edge;
            }

            // enumerate edges by the order determined above.
            foreach (var p in sortedByAngle)
            {
                nextEnumerator.MoveTo(enumerator.Vertex2);
                nextEnumerator.MoveNextUntil(p.Value);
                yield return(nextEnumerator);
            }
        }