using System.Collections.Generic; using System.Diagnostics; using Microsoft.Msagl.Core; using Microsoft.Msagl.Core.DataStructures; using Microsoft.Msagl.Core.Geometry; namespace Microsoft.Msagl.Routing.Visibility { [DebuggerDisplay("({Point.X} {Point.Y})")] internal class VisibilityVertex : IComparer { // This member is accessed a lot. Using a field instead of a property for performance. readonly internal Point Point; public bool isReal; bool _isTerminal; bool _isShortestPathTerminal; readonly List _inEdges = new List(); internal List InEdges { get { return _inEdges; } } readonly RbTree _outEdges; /* VisibilityEdge prev; */ /// /// this collection is sorted by the target point, in the lexicographical order /// internal RbTree OutEdges { get { return _outEdges; } } internal int Degree { get { return InEdges.Count + OutEdges.Count; } } /// /// needed for shortest path calculations /// internal double Distance { get; set; } internal bool IsTerminal { get { return _isTerminal; } set { _isTerminal = value; } } internal bool IsShortestPathTerminal { get { return _isShortestPathTerminal; } set { _isShortestPathTerminal = value; } } /* /// /// needed for shortest path calculations /// internal VisibilityVertex Prev { get { if (prev == null) return null; if(prev.Source==this) return prev.Target; return prev.Source; } } internal void SetPreviousEdge(VisibilityEdge e) { prev = e; } */ internal VisibilityVertex(Point point) { _outEdges = new RbTree(this); Point = point; } /// /// Rounded representation; DebuggerDisplay shows the unrounded form. /// /// public override string ToString() { return Point.ToString(); } /// /// These iterate from the end of the list because List.Remove is linear in /// the number of items, so callers have been optimized where possible to /// remove only the last or next-to-last edges (but in some cases such as /// rectilinear, this optimization isn't always possible). /// /// internal void RemoveOutEdge(VisibilityEdge edge) { OutEdges.Remove(edge); } internal void RemoveInEdge(VisibilityEdge edge) { for (int ii = InEdges.Count - 1; ii >= 0; --ii) { if (InEdges[ii] == edge) { InEdges.RemoveAt(ii); break; } } } /// /// avoiding using delegates in calling RBTree.FindFirst because of the memory allocations /// /// /// /// static RBNode FindFirst(RbTree tree, Point targetPoint) { return FindFirst(tree.Root, tree, targetPoint); } static RBNode FindFirst(RBNode n, RbTree tree, Point targetPoint) { if (n == tree.Nil) return null; RBNode good = null; while (n != tree.Nil) n = n.Item.TargetPoint >= targetPoint ? (good = n).left : n.right; return good; } internal bool TryGetEdge(VisibilityVertex target, out VisibilityEdge visEdge) { var node = FindFirst(OutEdges, target.Point);// OutEdges.FindFirst(e => e.TargetPoint >= target.Point); if (node != null) { if (node.Item.Target == target) { visEdge = node.Item; return true; } } node = FindFirst(target.OutEdges, Point);// target.OutEdges.FindFirst(e => e.TargetPoint >= Point); if (node != null) { if (node.Item.Target == this) { visEdge = node.Item; return true; } } visEdge = null; return false; } #region IComparer public int Compare(VisibilityEdge a, VisibilityEdge b) { return a.TargetPoint.CompareTo(b.TargetPoint); } #endregion // IComparer public void ClearEdges() { _outEdges.Clear(); _inEdges.Clear(); } } }