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); } }
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]);
internal static void MoveNextUntil(this TiledBarrierGraph.BarrierGraphEnumerator enumerator, int edge) { while (enumerator.MoveNext()) { if (enumerator.Edge == edge) { break; } } }
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>()); }
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>()); }
/// <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)); }
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); } }