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;
}
}
}