namespace MIConvexHull { using System; using System.Collections.Generic; /// /// Used to effectively store vertices beyond. /// /// sealed class VertexBuffer { VertexWrap[] items; int count; int capacity; /// /// Number of elements present in the buffer. /// public int Count { get { return count; } } /// /// Get the i-th element. /// /// /// public VertexWrap this[int i] { get { return items[i]; } } /// /// Size matters. /// void EnsureCapacity() { if (count + 1 > capacity) { if (capacity == 0) capacity = 4; else capacity = 2 * capacity; Array.Resize(ref items, capacity); } } /// /// Adds a vertex to the buffer. /// /// public void Add(VertexWrap item) { EnsureCapacity(); items[count++] = item; } /// /// Sets the Count to 0, otherwise does nothing. /// public void Clear() { count = 0; } } /// /// A priority based linked list. /// sealed class FaceList { ConvexFaceInternal first, last; /// /// Get the first element. /// public ConvexFaceInternal First { get { return first; } } /// /// Adds the element to the beginning. /// /// void AddFirst(ConvexFaceInternal face) { face.InList = true; this.first.Previous = face; face.Next = this.first; this.first = face; } /// /// Adds a face to the list. /// /// public void Add(ConvexFaceInternal face) { if (face.InList) { //if (this.first.FurthestDistance < face.FurthestDistance) if (this.first.VerticesBeyond.Count < face.VerticesBeyond.Count) { Remove(face); AddFirst(face); } return; } face.InList = true; //if (first != null && first.FurthestDistance < face.FurthestDistance) if (first != null && first.VerticesBeyond.Count < face.VerticesBeyond.Count) { this.first.Previous = face; face.Next = this.first; this.first = face; } else { if (this.last != null) { this.last.Next = face; } face.Previous = this.last; this.last = face; if (this.first == null) { this.first = face; } } } /// /// Removes the element from the list. /// /// public void Remove(ConvexFaceInternal face) { if (!face.InList) return; face.InList = false; if (face.Previous != null) { face.Previous.Next = face.Next; } else if (/*first == face*/ face.Previous == null) { this.first = face.Next; } if (face.Next != null) { face.Next.Previous = face.Previous; } else if (/*last == face*/ face.Next == null) { this.last = face.Previous; } face.Next = null; face.Previous = null; } } /// /// Connector list. /// sealed class ConnectorList { FaceConnector first, last; /// /// Get the first element. /// public FaceConnector First { get { return first; } } /// /// Adds the element to the beginning. /// /// void AddFirst(FaceConnector connector) { this.first.Previous = connector; connector.Next = this.first; this.first = connector; } /// /// Adds a face to the list. /// /// public void Add(FaceConnector element) { if (this.last != null) { this.last.Next = element; } element.Previous = this.last; this.last = element; if (this.first == null) { this.first = element; } } /// /// Removes the element from the list. /// /// public void Remove(FaceConnector connector) { if (connector.Previous != null) { connector.Previous.Next = connector.Next; } else if (/*first == face*/ connector.Previous == null) { this.first = connector.Next; } if (connector.Next != null) { connector.Next.Previous = connector.Previous; } else if (/*last == face*/ connector.Next == null) { this.last = connector.Previous; } connector.Next = null; connector.Previous = null; } } }