Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/ConvexHullView.Designer.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/ConvexHullView.Designer.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/ConvexHullView.Designer.cs	(revision 9730)
@@ -0,0 +1,55 @@
+﻿namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views {
+  partial class ConvexHullView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.testConvexHullButton = new System.Windows.Forms.Button();
+      this.SuspendLayout();
+      // 
+      // testConvexHullButton
+      // 
+      this.testConvexHullButton.Location = new System.Drawing.Point(3, 3);
+      this.testConvexHullButton.Name = "testConvexHullButton";
+      this.testConvexHullButton.Size = new System.Drawing.Size(97, 23);
+      this.testConvexHullButton.TabIndex = 0;
+      this.testConvexHullButton.Text = "Test Convex Hull";
+      this.testConvexHullButton.UseVisualStyleBackColor = true;
+      this.testConvexHullButton.Click += new System.EventHandler(this.testConvexHullButton_Click);
+      // 
+      // ConvexHullView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.testConvexHullButton);
+      this.Name = "ConvexHullView";
+      this.Size = new System.Drawing.Size(486, 175);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button testConvexHullButton;
+
+  }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/ConvexHullView.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/ConvexHullView.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/ConvexHullView.cs	(revision 9730)
@@ -0,0 +1,62 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+using MIConvexHull;
+
+namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views {
+  [View("ConvexHull View")]
+  [Content(typeof(PermutationSolutionDictionary<PermutationWrapper, PermutationInformation>), false)]
+  public partial class ConvexHullView : ItemView {
+    public ConvexHullView() {
+      InitializeComponent();
+    }
+
+    public new PermutationSolutionDictionary<PermutationWrapper, PermutationInformation> Content {
+      get { return (PermutationSolutionDictionary<PermutationWrapper, PermutationInformation>)base.Content; }
+      set { base.Content = value; }
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+
+      if (Content != null) { }
+    }
+
+    private void testConvexHullButton_Click(object sender, System.EventArgs e) {
+      var sols = Content.GetSolutionsFromGeneration(1);
+      var input = sols.Select(x => ConvertPermutationToVertex(x.GetPermutation()));
+      var result = ConvexHull.Create(input);
+      //TODO
+    }
+
+    private DefaultVertex ConvertPermutationToVertex(Permutation p) {
+      DefaultVertex vertex = new DefaultVertex();
+      vertex.Position = p.Select(x => (double)x).ToArray();
+      return vertex;
+    }
+  }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views-3.3.csproj
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views-3.3.csproj	(revision 9729)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views-3.3.csproj	(revision 9730)
@@ -83,4 +83,8 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Encodings.PermutationEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Encodings.PermutationEncoding-3.3.dll</HintPath>
+    </Reference>
     <Reference Include="HeuristicLab.MainForm-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
       <Private>False</Private>
@@ -129,4 +133,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ConvexHullView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ConvexHullView.Designer.cs">
+      <DependentUpon>ConvexHullView.cs</DependentUpon>
+    </Compile>
     <Compile Include="CreateExperimentDialog.cs">
       <SubType>Form</SubType>
@@ -151,4 +161,9 @@
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
     <Compile Include="SuccessorConfigurator.cs">
       <SubType>Form</SubType>
@@ -170,8 +185,16 @@
       <Private>False</Private>
     </ProjectReference>
+    <ProjectReference Include="..\..\MIConvexHull\MIConvexHull.csproj">
+      <Project>{2337776d-7d0c-40aa-a439-c26c3ce24fab}</Project>
+      <Name>MIConvexHull</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="CreateExperimentDialog.resx">
       <DependentUpon>CreateExperimentDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
     </EmbeddedResource>
   </ItemGroup>
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/PermutationSolutionDictionaryView.Designer.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/PermutationSolutionDictionaryView.Designer.cs	(revision 9729)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/PermutationSolutionDictionaryView.Designer.cs	(revision 9730)
@@ -30,4 +30,7 @@
       this.partialSizeTextBox = new System.Windows.Forms.TextBox();
       this.completeSizeTextBox = new System.Windows.Forms.TextBox();
+      this.toolStrip = new System.Windows.Forms.ToolStrip();
+      this.analyzeToolStripButton = new System.Windows.Forms.ToolStripDropDownButton();
+      this.toolStrip.SuspendLayout();
       this.SuspendLayout();
       // 
@@ -35,5 +38,5 @@
       // 
       this.label1.AutoSize = true;
-      this.label1.Location = new System.Drawing.Point(3, 10);
+      this.label1.Location = new System.Drawing.Point(3, 60);
       this.label1.Name = "label1";
       this.label1.Size = new System.Drawing.Size(64, 13);
@@ -44,5 +47,5 @@
       // 
       this.label2.AutoSize = true;
-      this.label2.Location = new System.Drawing.Point(3, 42);
+      this.label2.Location = new System.Drawing.Point(3, 92);
       this.label2.Name = "label2";
       this.label2.Size = new System.Drawing.Size(108, 13);
@@ -53,5 +56,5 @@
       // 
       this.label3.AutoSize = true;
-      this.label3.Location = new System.Drawing.Point(3, 74);
+      this.label3.Location = new System.Drawing.Point(3, 124);
       this.label3.Name = "label3";
       this.label3.Size = new System.Drawing.Size(123, 13);
@@ -63,5 +66,5 @@
       this.cacheSizeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-      this.cacheSizeTextBox.Location = new System.Drawing.Point(132, 7);
+      this.cacheSizeTextBox.Location = new System.Drawing.Point(132, 57);
       this.cacheSizeTextBox.Name = "cacheSizeTextBox";
       this.cacheSizeTextBox.ReadOnly = true;
@@ -73,5 +76,5 @@
       this.partialSizeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-      this.partialSizeTextBox.Location = new System.Drawing.Point(132, 39);
+      this.partialSizeTextBox.Location = new System.Drawing.Point(132, 89);
       this.partialSizeTextBox.Name = "partialSizeTextBox";
       this.partialSizeTextBox.ReadOnly = true;
@@ -83,5 +86,5 @@
       this.completeSizeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-      this.completeSizeTextBox.Location = new System.Drawing.Point(132, 71);
+      this.completeSizeTextBox.Location = new System.Drawing.Point(132, 121);
       this.completeSizeTextBox.Name = "completeSizeTextBox";
       this.completeSizeTextBox.ReadOnly = true;
@@ -89,8 +92,26 @@
       this.completeSizeTextBox.TabIndex = 5;
       // 
+      // toolStrip
+      // 
+      this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.analyzeToolStripButton});
+      this.toolStrip.Location = new System.Drawing.Point(0, 0);
+      this.toolStrip.Name = "toolStrip";
+      this.toolStrip.Size = new System.Drawing.Size(486, 25);
+      this.toolStrip.TabIndex = 6;
+      // 
+      // analyzeToolStripButton
+      // 
+      this.analyzeToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+      this.analyzeToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+      this.analyzeToolStripButton.Name = "analyzeToolStripButton";
+      this.analyzeToolStripButton.Size = new System.Drawing.Size(61, 22);
+      this.analyzeToolStripButton.Text = "Analyze";
+      // 
       // PermutationSolutionDictionaryView
       // 
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.toolStrip);
       this.Controls.Add(this.completeSizeTextBox);
       this.Controls.Add(this.partialSizeTextBox);
@@ -100,5 +121,7 @@
       this.Controls.Add(this.label1);
       this.Name = "PermutationSolutionDictionaryView";
-      this.Size = new System.Drawing.Size(486, 98);
+      this.Size = new System.Drawing.Size(486, 175);
+      this.toolStrip.ResumeLayout(false);
+      this.toolStrip.PerformLayout();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -114,4 +137,6 @@
     private System.Windows.Forms.TextBox partialSizeTextBox;
     private System.Windows.Forms.TextBox completeSizeTextBox;
+    private System.Windows.Forms.ToolStrip toolStrip;
+    private System.Windows.Forms.ToolStripDropDownButton analyzeToolStripButton;
   }
 }
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/PermutationSolutionDictionaryView.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/PermutationSolutionDictionaryView.cs	(revision 9729)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views/3.3/PermutationSolutionDictionaryView.cs	(revision 9730)
@@ -20,7 +20,10 @@
 #endregion
 
+using System;
+using System.Linq;
 using System.Windows.Forms;
 using HeuristicLab.Core.Views;
 using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
 
 namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers.Views {
@@ -48,5 +51,29 @@
         completeSizeTextBox.Text = Content.NumberOfCompleteSolutions().ToString();
       }
-    }                                                                             
+    }
+
+    protected override void OnInitialized(EventArgs e) {
+      base.OnInitialized(e);
+      var viewTypes = MainFormManager.GetViewTypes(typeof(PermutationSolutionDictionary<PermutationWrapper, PermutationInformation>), true);
+      foreach (Type viewType in viewTypes.OrderBy(x => ViewAttribute.GetViewName(x))) {
+        if ((viewType != typeof(PermutationSolutionDictionaryView)) && (viewType != typeof(ViewHost))) {
+          ToolStripMenuItem menuItem = new ToolStripMenuItem();
+          menuItem.Text = ViewAttribute.GetViewName(viewType);
+          menuItem.Tag = viewType;
+          menuItem.Click += new EventHandler(menuItem_Click);
+          analyzeToolStripButton.DropDownItems.Add(menuItem);
+        }
+      }
+    }
+
+    private void menuItem_Click(object sender, EventArgs e) {
+      ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;
+      Type viewType = (Type)menuItem.Tag;
+      IContentView view = MainFormManager.MainForm.ShowContent(Content, viewType);
+      if (view != null) {
+        view.Locked = Locked;
+        view.ReadOnly = ReadOnly;
+      }
+    }
   }
 }
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/SolutionsCaching/PermutationSolutionDictionary.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/SolutionsCaching/PermutationSolutionDictionary.cs	(revision 9729)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/SolutionsCaching/PermutationSolutionDictionary.cs	(revision 9730)
@@ -92,4 +92,8 @@
       return solutionDictionary.Where(x => x.Key.ElementType == ElementType.Complete).Count();
     }
+
+    public List<PermutationWrapper> GetSolutionsFromGeneration(int generation) {
+      return solutionDictionary.Where(x => x.Value.Where(y => y.Generation == generation).Count() != 0).Select(x => x.Key).ToList<PermutationWrapper>();
+    }
   }
 }
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.sln
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.sln	(revision 9729)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.sln	(revision 9730)
@@ -15,4 +15,6 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlgorithmBehaviorUnitTests", "AlgorithmBehaviorUnitTests\AlgorithmBehaviorUnitTests.csproj", "{8EFDEA16-A348-401F-82FC-C7E08FDA1C5A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MIConvexHull", "MIConvexHull\MIConvexHull.csproj", "{2337776D-7D0C-40AA-A439-C26C3CE24FAB}"
 EndProject
 Global
@@ -62,4 +64,12 @@
 		{8EFDEA16-A348-401F-82FC-C7E08FDA1C5A}.Release|x64.ActiveCfg = Release|Any CPU
 		{8EFDEA16-A348-401F-82FC-C7E08FDA1C5A}.Release|x86.ActiveCfg = Release|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Release|x64.ActiveCfg = Release|Any CPU
+		{2337776D-7D0C-40AA-A439-C26C3CE24FAB}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/Collections.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/Collections.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/Collections.cs	(revision 9730)
@@ -0,0 +1,230 @@
+﻿namespace MIConvexHull
+{
+    using System;
+    using System.Collections.Generic;
+
+    /// <summary>
+    /// Used to effectively store vertices beyond.
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    sealed class VertexBuffer
+    {
+        VertexWrap[] items;
+        int count;
+        int capacity;
+
+        /// <summary>
+        /// Number of elements present in the buffer.
+        /// </summary>
+        public int Count { get { return count; } }
+
+        /// <summary>
+        /// Get the i-th element.
+        /// </summary>
+        /// <param name="i"></param>
+        /// <returns></returns>
+        public VertexWrap this[int i]
+        {
+            get { return items[i]; }
+        }
+
+        /// <summary>
+        /// Size matters.
+        /// </summary>
+        void EnsureCapacity()
+        {
+            if (count + 1 > capacity)
+            {
+                if (capacity == 0) capacity = 4;
+                else capacity = 2 * capacity;
+                Array.Resize(ref items, capacity);
+            }
+        }
+
+        /// <summary>
+        /// Adds a vertex to the buffer.
+        /// </summary>
+        /// <param name="item"></param>
+        public void Add(VertexWrap item)
+        {
+            EnsureCapacity();
+            items[count++] = item;
+        }
+
+        /// <summary>
+        /// Sets the Count to 0, otherwise does nothing.
+        /// </summary>
+        public void Clear()
+        {
+            count = 0;
+        }
+    }
+        
+    /// <summary>
+    /// A priority based linked list.
+    /// </summary>
+    sealed class FaceList
+    {
+        ConvexFaceInternal first, last;
+
+        /// <summary>
+        /// Get the first element.
+        /// </summary>
+        public ConvexFaceInternal First { get { return first; } }
+
+        /// <summary>
+        /// Adds the element to the beginning.
+        /// </summary>
+        /// <param name="face"></param>
+        void AddFirst(ConvexFaceInternal face)
+        {
+            face.InList = true;
+            this.first.Previous = face;
+            face.Next = this.first;
+            this.first = face;
+        }
+
+        /// <summary>
+        /// Adds a face to the list.
+        /// </summary>
+        /// <param name="face"></param>
+        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;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Removes the element from the list.
+        /// </summary>
+        /// <param name="face"></param>
+        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;
+        }
+    }
+
+    /// <summary>
+    /// Connector list.
+    /// </summary>
+    sealed class ConnectorList
+    {
+        FaceConnector first, last;
+
+        /// <summary>
+        /// Get the first element.
+        /// </summary>
+        public FaceConnector First { get { return first; } }
+
+        /// <summary>
+        /// Adds the element to the beginning.
+        /// </summary>
+        /// <param name="connector"></param>
+        void AddFirst(FaceConnector connector)
+        {
+            this.first.Previous = connector;
+            connector.Next = this.first;
+            this.first = connector;
+        }
+
+        /// <summary>
+        /// Adds a face to the list.
+        /// </summary>
+        /// <param name="element"></param>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Removes the element from the list.
+        /// </summary>
+        /// <param name="connector"></param>
+        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;
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexFace.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexFace.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexFace.cs	(revision 9730)
@@ -0,0 +1,38 @@
+﻿namespace MIConvexHull
+{
+    /// <summary>
+    /// A convex face representation containing adjacency information.
+    /// </summary>
+    public abstract class ConvexFace<TVertex, TFace>
+        where TVertex : IVertex
+        where TFace : ConvexFace<TVertex, TFace>
+    {
+        /// <summary>
+        /// Adjacency. Array of length "dimension".
+        /// If F = Adjacency[i] then the vertices shared with F are Vertices[j] where j != i.
+        /// In the context of triangulation, can be null (indicates the cell is at boundary).
+        /// </summary>
+        public TFace[] Adjacency { get; set; }
+
+        /// <summary>
+        /// The vertices stored in clockwise order (for dimensions 2 - 4, higher dimensions the order is arbitrary).
+        /// Unless I accidentally switch some index somewhere in which case the order is CCW. Either way, it is consistent.
+        /// 3D Normal = (V[1] - V[0]) x (V[2] - V[1]).
+        /// </summary>
+        public TVertex[] Vertices { get; set; }
+
+        /// <summary>
+        /// The normal vector of the face. Null if used in triangulation.
+        /// </summary>
+        public double[] Normal { get; set; }
+    }
+
+    /// <summary>
+    /// A default convex face representation.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    public class DefaultConvexFace<TVertex> : ConvexFace<TVertex, DefaultConvexFace<TVertex>>
+        where TVertex : IVertex
+    {
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexFaceInternal.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexFaceInternal.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexFaceInternal.cs	(revision 9730)
@@ -0,0 +1,226 @@
+﻿namespace MIConvexHull
+{
+    using System.Collections.Generic;
+
+    /// <summary>
+    /// Wraps each IVertex to allow marking of nodes.
+    /// </summary>
+    sealed class VertexWrap
+    {
+        /// <summary>
+        /// Ref. to the original vertex.
+        /// </summary>
+        public IVertex Vertex;
+
+        /// <summary>
+        /// Direct reference to PositionData makes IsVertexOverFace faster.
+        /// </summary>
+        public double[] PositionData;
+
+        /// <summary>
+        /// Vertex index.
+        /// </summary>
+        public int Index;
+
+        /// <summary>
+        /// Used mostly to enumerate unique vertices.
+        /// </summary>
+        public bool Marked;
+    }
+
+    /// <summary>
+    /// Compare vertices based on their indices.
+    /// </summary>
+    class VertexWrapComparer : IComparer<VertexWrap>
+    {
+        public static readonly VertexWrapComparer Instance = new VertexWrapComparer();
+
+        public int Compare(VertexWrap x, VertexWrap y)
+        {
+            return x.Index.CompareTo(y.Index);
+        }
+    }
+
+    /// <summary>
+    /// A helper class used to connect faces.
+    /// </summary>
+    sealed class FaceConnector
+    {
+        /// <summary>
+        /// The face.
+        /// </summary>
+        public ConvexFaceInternal Face;
+
+        /// <summary>
+        /// The edge to be connected.
+        /// </summary>
+        public int EdgeIndex;
+
+        /// <summary>
+        /// The vertex indices.
+        /// </summary>
+        public int[] Vertices;
+
+        /// <summary>
+        /// The hash code computed from indices.
+        /// </summary>
+        public uint HashCode;
+
+        /// <summary>
+        /// Prev node in the list.
+        /// </summary>
+        public FaceConnector Previous;
+
+        /// <summary>
+        /// Next node in the list.
+        /// </summary>
+        public FaceConnector Next;
+
+        /// <summary>
+        /// Ctor.
+        /// </summary>
+        /// <param name="dimension"></param>
+        public FaceConnector(int dimension)
+        {
+            Vertices = new int[dimension - 1];
+        }
+
+        /// <summary>
+        /// Updates the connector.
+        /// </summary>
+        /// <param name="face"></param>
+        /// <param name="edgeIndex"></param>
+        /// <param name="dim"></param>
+        public void Update(ConvexFaceInternal face, int edgeIndex, int dim)
+        {
+            this.Face = face;
+            this.EdgeIndex = edgeIndex;
+
+            uint hashCode = 31;
+
+            var vs = face.Vertices;
+            for (int i = 0, c = 0; i < dim; i++)
+            {
+                if (i != edgeIndex)
+                {
+                    var v = vs[i].Index;
+                    this.Vertices[c++] = v;
+                    hashCode += unchecked(23 * hashCode + (uint)v);
+                }
+            }
+
+            this.HashCode = hashCode;
+        }
+
+        /// <summary>
+        /// Can two faces be connected.
+        /// </summary>
+        /// <param name="a"></param>
+        /// <param name="b"></param>
+        /// <param name="dim"></param>
+        /// <returns></returns>
+        public static bool AreConnectable(FaceConnector a, FaceConnector b, int dim)
+        {
+            if (a.HashCode != b.HashCode) return false;
+
+            var n = dim - 1;
+            var av = a.Vertices;
+            var bv = b.Vertices;
+            for (int i = 0; i < n; i++)
+            {
+                if (av[i] != bv[i]) return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Connect two faces.
+        /// </summary>
+        /// <param name="a"></param>
+        /// <param name="b"></param>
+        public static void Connect(FaceConnector a, FaceConnector b)
+        {
+            a.Face.AdjacentFaces[a.EdgeIndex] = b.Face;
+            b.Face.AdjacentFaces[b.EdgeIndex] = a.Face;
+        }
+    }
+
+    /// <summary>
+    /// This internal class manages the faces of the convex hull. It is a 
+    /// separate class from the desired user class.
+    /// </summary>
+    sealed class ConvexFaceInternal
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ConvexFaceInternal"/> class.
+        /// </summary>
+        public ConvexFaceInternal(int dimension, VertexBuffer beyondList)
+        {
+            AdjacentFaces = new ConvexFaceInternal[dimension];
+            VerticesBeyond = beyondList;
+            Normal = new double[dimension];
+            Vertices = new VertexWrap[dimension];
+        }
+
+        /// <summary>
+        /// Gets or sets the adjacent face data.
+        /// </summary>
+        public ConvexFaceInternal[] AdjacentFaces;
+
+        /// <summary>
+        /// Gets or sets the vertices beyond.
+        /// </summary>
+        public VertexBuffer VerticesBeyond;
+
+        /// <summary>
+        /// The furthest vertex.
+        /// </summary>
+        public VertexWrap FurthestVertex;
+
+        /////// <summary>
+        /////// Distance to the furthest vertex.
+        /////// </summary>
+        ////public double FurthestDistance;
+
+        /// <summary>
+        /// Gets or sets the vertices.
+        /// </summary>
+        public VertexWrap[] Vertices;
+        
+        /// <summary>
+        /// Gets or sets the normal vector.
+        /// </summary>
+        public double[] Normal;
+
+        /// <summary>
+        /// Is the normal flipped?
+        /// </summary>
+        public bool IsNormalFlipped;
+
+        /// <summary>
+        /// Face plane constant element.
+        /// </summary>
+        public double Offset;
+
+        /// <summary>
+        /// Used to traverse affected faces and create the Delaunay representation.
+        /// </summary>
+        public int Tag;
+
+        /// <summary>
+        /// Prev node in the list.
+        /// </summary>
+        public ConvexFaceInternal Previous;
+
+        /// <summary>
+        /// Next node in the list.
+        /// </summary>
+        public ConvexFaceInternal Next;
+
+        /// <summary>
+        /// Is it present in the list.
+        /// </summary>
+        public bool InList;
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexHull.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexHull.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexHull.cs	(revision 9730)
@@ -0,0 +1,88 @@
+﻿namespace MIConvexHull
+{
+    using System.Collections.Generic;
+    using System.Linq;
+
+    /// <summary>
+    /// Factory class for computing convex hulls.
+    /// </summary>
+    public static class ConvexHull
+    {
+        /// <summary>
+        /// Creates a convex hull of the input data.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TFace"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ConvexHull<TVertex, TFace> Create<TVertex, TFace>(IEnumerable<TVertex> data)
+            where TVertex : IVertex
+            where TFace : ConvexFace<TVertex, TFace>, new()
+        {
+            return ConvexHull<TVertex, TFace>.Create(data);
+        }
+
+        /// <summary>
+        /// Creates a convex hull of the input data.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ConvexHull<TVertex, DefaultConvexFace<TVertex>> Create<TVertex>(IEnumerable<TVertex> data)
+            where TVertex : IVertex
+        {
+            return ConvexHull<TVertex, DefaultConvexFace<TVertex>>.Create(data);
+        }
+
+        /// <summary>
+        /// Creates a convex hull of the input data.
+        /// </summary>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ConvexHull<DefaultVertex, DefaultConvexFace<DefaultVertex>> Create(IEnumerable<double[]> data)
+        {
+            var points = data.Select(p => new DefaultVertex { Position = p.ToArray() });
+            return ConvexHull<DefaultVertex, DefaultConvexFace<DefaultVertex>>.Create(points);
+        }
+    }
+
+    /// <summary>
+    /// Representation of a convex hull.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    /// <typeparam name="TFace"></typeparam>
+    public class ConvexHull<TVertex, TFace>
+        where TVertex : IVertex
+        where TFace : ConvexFace<TVertex, TFace>, new()
+    {
+        /// <summary>
+        /// Points of the convex hull.
+        /// </summary>
+        public IEnumerable<TVertex> Points { get; private set; }
+
+        /// <summary>
+        /// Faces of the convex hull.
+        /// </summary>
+        public IEnumerable<TFace> Faces { get; private set; }
+
+        /// <summary>
+        /// Creates the convex hull.
+        /// </summary>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ConvexHull<TVertex, TFace> Create(IEnumerable<TVertex> data)
+        {
+            if (!(data is IList<TVertex>)) data = data.ToArray();
+            var ch = ConvexHullInternal.GetConvexHullAndFaces<TVertex, TFace>(data.Cast<IVertex>());
+            return new ConvexHull<TVertex, TFace> { Points = ch.Item1, Faces = ch.Item2 };
+        }
+
+        /// <summary>
+        /// Can only be created using a factory method.
+        /// </summary>
+        private ConvexHull()
+        {
+
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexHullInternal.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexHullInternal.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/ConvexHullInternal.cs	(revision 9730)
@@ -0,0 +1,1025 @@
+﻿namespace MIConvexHull
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+
+    internal class ConvexHullInternal
+    {
+        bool Computed;
+        readonly int Dimension;
+
+        List<VertexWrap> InputVertices;
+        List<VertexWrap> ConvexHull;
+        FaceList UnprocessedFaces;
+        List<ConvexFaceInternal> ConvexFaces;
+
+        #region "Buffers"
+        VertexWrap CurrentVertex;
+        double MaxDistance;
+        VertexWrap FurthestVertex;
+
+        /// <summary>
+        /// The centroid of the currently computed hull.
+        /// </summary>
+        double[] Center;
+
+        // Buffers for normal computation.
+        double[] ntX, ntY, ntZ;
+        double[] nDNormalSolveVector;
+        double[,] nDMatrix;
+        double[][] jaggedNDMatrix;
+
+        ConvexFaceInternal[] UpdateBuffer;
+        int[] UpdateIndices;
+
+
+        Stack<ConvexFaceInternal> TraverseStack;
+        Stack<ConvexFaceInternal> RecycledFaceStack;
+        Stack<FaceConnector> ConnectorStack;
+        Stack<VertexBuffer> EmptyBufferStack;
+        VertexBuffer EmptyBuffer; // this is used for VerticesBeyond for faces that are on the convex hull
+        VertexBuffer BeyondBuffer;
+        List<ConvexFaceInternal> AffectedFaceBuffer;
+
+        const int ConnectorTableSize = 2017;
+        ConnectorList[] ConnectorTable;
+
+        #endregion
+
+        /// <summary>
+        /// Initialize buffers and lists.
+        /// </summary>
+        void Initialize()
+        {
+            ConvexHull = new List<VertexWrap>();
+            UnprocessedFaces = new FaceList(); // new LinkedList<ConvexFaceInternal>();
+            ConvexFaces = new List<ConvexFaceInternal>();
+
+            Center = new double[Dimension];
+            ntX = new double[Dimension];
+            ntY = new double[Dimension];
+            ntZ = new double[Dimension];
+            TraverseStack = new Stack<ConvexFaceInternal>();
+            UpdateBuffer = new ConvexFaceInternal[Dimension];
+            UpdateIndices = new int[Dimension];
+            RecycledFaceStack = new Stack<ConvexFaceInternal>();
+            ConnectorStack = new Stack<FaceConnector>();
+            EmptyBufferStack = new Stack<VertexBuffer>();
+            EmptyBuffer = new VertexBuffer();
+            AffectedFaceBuffer = new List<ConvexFaceInternal>();
+            BeyondBuffer = new VertexBuffer();
+
+            ConnectorTable = Enumerable.Range(0, ConnectorTableSize).Select(_ => new ConnectorList()).ToArray();
+
+            nDNormalSolveVector = new double[Dimension];
+            jaggedNDMatrix = new double[Dimension][];
+            for (var i = 0; i < Dimension; i++)
+            {
+                nDNormalSolveVector[i] = 1.0;
+                jaggedNDMatrix[i] = new double[Dimension];
+            }
+            nDMatrix = new double[Dimension, Dimension];
+        }
+
+        /// <summary>
+        /// Check the dimensionality of the input data.
+        /// </summary>
+        int DetermineDimension()
+        {
+            var r = new Random();
+            var VCount = InputVertices.Count;
+            var dimensions = new List<int>();
+            for (var i = 0; i < 10; i++)
+                dimensions.Add(InputVertices[r.Next(VCount)].Vertex.Position.Length);
+            var dimension = dimensions.Min();
+            if (dimension != dimensions.Max()) throw new ArgumentException("Invalid input data (non-uniform dimension).");
+            return dimension;
+        }
+
+        /// <summary>
+        /// Create the first faces from (dimension + 1) vertices.
+        /// </summary>
+        /// <returns></returns>
+        ConvexFaceInternal[] InitiateFaceDatabase()
+        {
+            var faces = new ConvexFaceInternal[Dimension + 1];
+
+            for (var i = 0; i < Dimension + 1; i++)
+            {
+                var vertices = ConvexHull.Where((_, j) => i != j).ToArray(); // Skips the i-th vertex
+                var newFace = new ConvexFaceInternal(Dimension, new VertexBuffer());
+                newFace.Vertices = vertices;
+                Array.Sort(vertices, VertexWrapComparer.Instance);
+                CalculateFacePlane(newFace);
+                faces[i] = newFace;
+            }
+
+            // update the adjacency (check all pairs of faces)
+            for (var i = 0; i < Dimension; i++)
+            {
+                for (var j = i + 1; j < Dimension + 1; j++) UpdateAdjacency(faces[i], faces[j]);
+            }
+
+            return faces;
+        }
+        
+        /// <summary>
+        /// Calculates the normal and offset of the hyper-plane given by the face's vertices.
+        /// </summary>
+        /// <param name="face"></param>
+        /// <returns></returns>
+        private void CalculateFacePlane(ConvexFaceInternal face)
+        {
+            var vertices = face.Vertices;
+            var normal = face.Normal;
+            FindNormalVector(vertices, normal);
+
+            if (double.IsNaN(normal[0])) ThrowSingular();
+
+            double offset = 0.0;
+            double centerDistance = 0.0;
+            var fi = vertices[0].PositionData;
+            for (int i = 0; i < Dimension; i++)
+            {
+                double n = normal[i];
+                offset += n * fi[i];
+                centerDistance += n * Center[i];
+            }
+            face.Offset = -offset;
+            centerDistance -= offset;
+
+            if (centerDistance > 0)
+            {
+                for (int i = 0; i < Dimension; i++) normal[i] = -normal[i];
+                face.Offset = offset;
+                face.IsNormalFlipped = true;
+            }
+            else face.IsNormalFlipped = false;
+        }
+        
+        /// <summary>
+        /// Check if the vertex is "visible" from the face.
+        /// The vertex is "over face" if the return value is >= 0.
+        /// </summary>
+        /// <param name="v"></param>
+        /// <param name="f"></param>
+        /// <returns>The vertex is "over face" if the result is positive.</returns>
+        double GetVertexDistance(VertexWrap v, ConvexFaceInternal f)
+        {
+            double[] normal = f.Normal;
+            double[] p = v.PositionData;
+            double distance = f.Offset;
+            for (int i = 0; i < Dimension; i++) distance += normal[i] * p[i];
+            return distance;
+        }
+        
+        //unsafe double GetVertexDistance(VertexWrap v, ConvexFaceInternal f)
+        //{
+        //    fixed (double* pNormal = f.Normal)
+        //    fixed (double* pP = v.PositionData)
+        //    {
+        //        double* normal = pNormal;
+        //        double* p = pP;
+
+        //        double distance = f.Offset;
+        //        for (int i = 0; i < Dimension; i++)
+        //        {
+        //            distance += (*normal) * (*p);
+        //            normal++;
+        //            p++;
+        //        }
+        //        return distance;
+        //    }
+        //}
+
+        /// <summary>
+        /// Tags all faces seen from the current vertex with 1.
+        /// </summary>
+        /// <param name="currentFace"></param>
+        void TagAffectedFaces(ConvexFaceInternal currentFace)
+        {
+            AffectedFaceBuffer.Clear();
+            AffectedFaceBuffer.Add(currentFace);
+            TraverseAffectedFaces(currentFace);
+        }
+        
+        /// <summary>
+        /// Recursively traverse all the relevant faces.
+        /// </summary>
+        void TraverseAffectedFaces(ConvexFaceInternal currentFace)
+        {
+            TraverseStack.Clear();
+            TraverseStack.Push(currentFace);
+            currentFace.Tag = 1;
+
+            while (TraverseStack.Count > 0)
+            {
+                var top = TraverseStack.Pop();
+                for (int i = 0; i < Dimension; i++)
+                {
+                    var adjFace = top.AdjacentFaces[i];
+
+                    if (adjFace.Tag == 0 && GetVertexDistance(CurrentVertex, adjFace) >= 0)
+                    {
+                        AffectedFaceBuffer.Add(adjFace);
+                        //TraverseAffectedFaces(adjFace);
+                        adjFace.Tag = 1;
+                        TraverseStack.Push(adjFace);
+                    }
+                }
+            }
+            
+            ////for (int i = 0; i < Dimension; i++)
+            ////{
+            ////    var adjFace = currentFace.AdjacentFaces[i];
+
+            ////    if (adjFace.Tag == 0 && GetVertexDistance(CurrentVertex, adjFace) >= 0)
+            ////    {
+            ////        AffectedFaceBuffer.Add(adjFace);
+            ////        TraverseAffectedFaces(adjFace);
+            ////    }
+            ////}
+        }
+
+        /// <summary>
+        /// Check if 2 faces are adjacent and if so, update their AdjacentFaces array.
+        /// </summary>
+        /// <param name="l"></param>
+        /// <param name="r"></param>
+        void UpdateAdjacency(ConvexFaceInternal l, ConvexFaceInternal r)
+        {
+            var lv = l.Vertices;
+            var rv = r.Vertices;
+            int i;
+
+            // reset marks on the 1st face
+            for (i = 0; i < Dimension; i++) lv[i].Marked = false;
+
+            // mark all vertices on the 2nd face
+            for (i = 0; i < Dimension; i++) rv[i].Marked = true;
+
+            // find the 1st false index
+            for (i = 0; i < Dimension; i++) if (!lv[i].Marked) break;
+
+            // no vertex was marked
+            if (i == Dimension) return;
+
+            // check if only 1 vertex wasn't marked
+            for (int j = i + 1; j < Dimension; j++) if (!lv[j].Marked) return;
+
+            // if we are here, the two faces share an edge
+            l.AdjacentFaces[i] = r;
+
+            // update the adj. face on the other face - find the vertex that remains marked
+            for (i = 0; i < Dimension; i++) lv[i].Marked = false;
+            for (i = 0; i < Dimension; i++)
+            {
+                if (rv[i].Marked) break;
+            }
+            r.AdjacentFaces[i] = l;
+        }
+
+        #region Memory stuff.
+        
+        /// <summary>
+        /// Recycle face for future use.
+        /// </summary>
+        void RecycleFace(ConvexFaceInternal face)
+        {
+            for (int i = 0; i < Dimension; i++)
+            {
+                face.AdjacentFaces[i] = null;
+            }
+        }
+        
+        /// <summary>
+        /// Get a fresh face.
+        /// </summary>
+        /// <returns></returns>
+        ConvexFaceInternal GetNewFace()
+        {
+            return RecycledFaceStack.Count != 0
+                    ? RecycledFaceStack.Pop()
+                    : new ConvexFaceInternal(Dimension, EmptyBufferStack.Count != 0 ? EmptyBufferStack.Pop() : new VertexBuffer());
+        }
+
+        /// <summary>
+        /// Get a new connector.
+        /// </summary>
+        /// <returns></returns>
+        FaceConnector GetNewConnector()
+        {
+            return ConnectorStack.Count != 0
+                    ? ConnectorStack.Pop()
+                    : new FaceConnector(Dimension);
+        }        
+        #endregion
+
+        /// <summary>
+        /// Connect faces using a connector.
+        /// </summary>
+        /// <param name="connector"></param>
+        void ConnectFace(FaceConnector connector)
+        {
+            var index = connector.HashCode % ConnectorTableSize;
+            var list = ConnectorTable[index];
+
+            int count = 0;
+            for (var current = list.First; current != null; current = current.Next)
+            {
+                if (FaceConnector.AreConnectable(connector, current, Dimension))
+                {
+                    list.Remove(current);
+                    FaceConnector.Connect(current, connector);
+                    current.Face = null;
+                    connector.Face = null;
+                    ConnectorStack.Push(current);
+                    ConnectorStack.Push(connector);
+                    return;
+                }
+            }
+
+            list.Add(connector);
+        }
+
+        /// <summary>
+        /// Removes the faces "covered" by the current vertex and adds the newly created ones.
+        /// </summary>
+        private void CreateCone()
+        {
+            var oldFaces = AffectedFaceBuffer;
+
+            var currentVertexIndex = CurrentVertex.Index;
+
+            for (int fIndex = 0; fIndex < oldFaces.Count; fIndex++)
+            {
+                var oldFace = oldFaces[fIndex];
+
+                // Find the faces that need to be updated
+                int updateCount = 0;
+                for (int i = 0; i < Dimension; i++)
+                {
+                    var af = oldFace.AdjacentFaces[i];
+                    if (af.Tag == 0) // Tag == 0 when oldFaces does not contain af
+                    {
+                        UpdateBuffer[updateCount] = af;
+                        UpdateIndices[updateCount] = i;
+                        ++updateCount;
+                    }
+                }
+
+                // Recycle the face for future use
+                if (updateCount == 0)
+                {
+                    // If the face is present in the unprocessed list, remove it 
+                    UnprocessedFaces.Remove(oldFace);
+
+                    RecycleFace(oldFace);
+                    RecycledFaceStack.Push(oldFace);
+                }
+
+                for (int i = 0; i < updateCount; i++)
+                {
+                    var adjacentFace = UpdateBuffer[i];
+
+                    int oldFaceAdjacentIndex = 0;
+                    var adjFaceAdjacency = adjacentFace.AdjacentFaces;
+                    for (int j = 0; j < Dimension; j++)
+                    {
+                        if (object.ReferenceEquals(oldFace, adjFaceAdjacency[j]))
+                        {
+                            oldFaceAdjacentIndex = j;
+                            break;
+                        }
+                    }
+
+                    var forbidden = UpdateIndices[i]; // Index of the face that corresponds to this adjacent face
+
+                    ConvexFaceInternal newFace;
+
+                    int oldVertexIndex;
+                    VertexWrap[] vertices;
+
+                    // Recycle the oldFace
+                    if (i == updateCount - 1)
+                    {
+                        RecycleFace(oldFace);
+                        newFace = oldFace;
+                        vertices = newFace.Vertices;
+                        oldVertexIndex = vertices[forbidden].Index;
+                    }
+                    else // Pop a face from the recycled stack or create a new one
+                    {
+                        newFace = GetNewFace();
+                        vertices = newFace.Vertices;                        
+                        for (int j = 0; j < Dimension; j++) vertices[j] = oldFace.Vertices[j];
+                        oldVertexIndex = vertices[forbidden].Index;
+                    }
+
+                    int orderedPivotIndex;
+
+                    // correct the ordering
+                    if (currentVertexIndex < oldVertexIndex)
+                    {
+                        orderedPivotIndex = 0;
+                        for (int j = forbidden - 1; j >= 0; j--)
+                        {
+                            if (vertices[j].Index > currentVertexIndex) vertices[j + 1] = vertices[j];
+                            else
+                            {
+                                orderedPivotIndex = j + 1;
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        orderedPivotIndex = Dimension - 1;
+                        for (int j = forbidden + 1; j < Dimension; j++)
+                        {
+                            if (vertices[j].Index < currentVertexIndex) vertices[j - 1] = vertices[j];
+                            else
+                            {
+                                orderedPivotIndex = j - 1;
+                                break;
+                            }
+                        }
+                    }
+                    
+                    vertices[orderedPivotIndex] = CurrentVertex;
+
+                    CalculateFacePlane(newFace);
+                    newFace.AdjacentFaces[orderedPivotIndex] = adjacentFace;
+                    adjacentFace.AdjacentFaces[oldFaceAdjacentIndex] = newFace;
+
+                    // let there be a connection.
+                    for (int j = 0; j < Dimension; j++)
+                    {
+                        if (j == orderedPivotIndex) continue;
+                        var connector = GetNewConnector();
+                        connector.Update(newFace, j, Dimension);
+                        ConnectFace(connector);
+                    }
+                    
+                    // This could slightly help...
+                    if (adjacentFace.VerticesBeyond.Count < oldFace.VerticesBeyond.Count)
+                    {
+                        FindBeyondVertices(newFace, adjacentFace.VerticesBeyond, oldFace.VerticesBeyond);
+                    }
+                    else
+                    {
+                        FindBeyondVertices(newFace, oldFace.VerticesBeyond, adjacentFace.VerticesBeyond);
+                    }
+
+                    // This face will definitely lie on the hull
+                    if (newFace.VerticesBeyond.Count == 0)
+                    {
+                        ConvexFaces.Add(newFace);
+                        UnprocessedFaces.Remove(newFace);
+                        EmptyBufferStack.Push(newFace.VerticesBeyond);
+                        newFace.VerticesBeyond = EmptyBuffer;
+                    }
+                    else // Add the face to the list
+                    {
+                        UnprocessedFaces.Add(newFace);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Subtracts vectors x and y and stores the result to target.
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="target"></param>
+        void SubtractFast(double[] x, double[] y, double[] target)
+        {
+            for (int i = 0; i < Dimension; i++)
+            {
+                target[i] = x[i] - y[i];
+            }
+        }
+
+        /// <summary>
+        /// Finds 4D normal vector.
+        /// </summary>
+        /// <param name="vertices"></param>
+        /// <param name="normal"></param>
+        void FindNormalVector4D(VertexWrap[] vertices, double[] normal)
+        {
+            SubtractFast(vertices[1].PositionData, vertices[0].PositionData, ntX);
+            SubtractFast(vertices[2].PositionData, vertices[1].PositionData, ntY);
+            SubtractFast(vertices[3].PositionData, vertices[2].PositionData, ntZ);
+
+            var x = ntX;
+            var y = ntY;
+            var z = ntZ;
+
+            // This was generated using Mathematica
+            var nx = x[3] * (y[2] * z[1] - y[1] * z[2])
+                   + x[2] * (y[1] * z[3] - y[3] * z[1])
+                   + x[1] * (y[3] * z[2] - y[2] * z[3]);
+            var ny = x[3] * (y[0] * z[2] - y[2] * z[0])
+                   + x[2] * (y[3] * z[0] - y[0] * z[3])
+                   + x[0] * (y[2] * z[3] - y[3] * z[2]);
+            var nz = x[3] * (y[1] * z[0] - y[0] * z[1])
+                   + x[1] * (y[0] * z[3] - y[3] * z[0])
+                   + x[0] * (y[3] * z[1] - y[1] * z[3]);
+            var nw = x[2] * (y[0] * z[1] - y[1] * z[0])
+                   + x[1] * (y[2] * z[0] - y[0] * z[2])
+                   + x[0] * (y[1] * z[2] - y[2] * z[1]);
+
+            double norm = System.Math.Sqrt(nx * nx + ny * ny + nz * nz + nw * nw);
+
+            double f = 1.0 / norm;
+            normal[0] = f * nx;
+            normal[1] = f * ny;
+            normal[2] = f * nz;
+            normal[3] = f * nw;
+        }
+
+        /// <summary>
+        /// Finds 3D normal vector.
+        /// </summary>
+        /// <param name="vertices"></param>
+        /// <param name="normal"></param>
+        void FindNormalVector3D(VertexWrap[] vertices, double[] normal)
+        {
+            SubtractFast(vertices[1].PositionData, vertices[0].PositionData, ntX);
+            SubtractFast(vertices[2].PositionData, vertices[1].PositionData, ntY);
+
+            var x = ntX;
+            var y = ntY;
+
+            var nx = x[1] * y[2] - x[2] * y[1];
+            var ny = x[2] * y[0] - x[0] * y[2];
+            var nz = x[0] * y[1] - x[1] * y[0];
+
+            double norm = System.Math.Sqrt(nx * nx + ny * ny + nz * nz);
+
+            double f = 1.0 / norm;
+            normal[0] = f * nx;
+            normal[1] = f * ny;
+            normal[2] = f * nz;
+        }
+
+        /// <summary>
+        /// Finds 2D normal vector.
+        /// </summary>
+        /// <param name="vertices"></param>
+        /// <param name="normal"></param>
+        void FindNormalVector2D(VertexWrap[] vertices, double[] normal)
+        {
+            SubtractFast(vertices[1].PositionData, vertices[0].PositionData, ntX);
+
+            var x = ntX;
+
+            var nx = -x[1];
+            var ny = x[0];
+
+            double norm = System.Math.Sqrt(nx * nx + ny * ny);
+
+            double f = 1.0 / norm;
+            normal[0] = f * nx;
+            normal[1] = f * ny;
+        }
+
+        /// <summary>
+        /// Finds normal vector of a hyper-plane given by vertices.
+        /// Stores the results to normalData.
+        /// </summary>
+        /// <param name="vertices"></param>
+        /// <param name="normalData"></param>
+        private void FindNormalVector(VertexWrap[] vertices, double[] normalData)
+        {
+            switch (Dimension)
+            {
+                case 2: FindNormalVector2D(vertices, normalData); break;
+                case 3: FindNormalVector3D(vertices, normalData); break;
+                case 4: FindNormalVector4D(vertices, normalData); break;
+                default:
+                    {
+                        for (var i = 0; i < Dimension; i++) nDNormalSolveVector[i] = 1.0;
+                        for (var i = 0; i < Dimension; i++)
+                        {
+                            var row = jaggedNDMatrix[i];
+                            var pos = vertices[i].Vertex.Position;
+                            for (int j = 0; j < Dimension; j++) row[j] = pos[j];
+                        }
+                        StarMath.gaussElimination(Dimension, jaggedNDMatrix, nDNormalSolveVector, normalData);
+                        StarMath.normalizeInPlace(normalData, Dimension);
+                        break;
+                    }
+            }
+        }
+
+        /// <summary>
+        /// Check whether the vertex v is beyond the given face. If so, add it to beyondVertices.
+        /// </summary>
+        /// <param name="face"></param>
+        /// <param name="beyondVertices"></param>
+        /// <param name="v"></param>
+        void IsBeyond(ConvexFaceInternal face, VertexBuffer beyondVertices, VertexWrap v)
+        {
+            double distance = GetVertexDistance(v, face);
+            if (distance >= 0)
+            {
+                if (distance > MaxDistance)
+                {
+                    MaxDistance = distance;
+                    FurthestVertex = v;
+                }
+                beyondVertices.Add(v);
+            }
+        }
+
+        /// <summary>
+        /// Used in the "initialization" code.
+        /// </summary>
+        void FindBeyondVertices(ConvexFaceInternal face)
+        {
+            var beyondVertices = face.VerticesBeyond;
+
+            MaxDistance = double.NegativeInfinity;
+            FurthestVertex = null;
+
+            int count = InputVertices.Count;
+            for (int i = 0; i < count; i++) IsBeyond(face, beyondVertices, InputVertices[i]);
+
+            face.FurthestVertex = FurthestVertex;
+            //face.FurthestDistance = MaxDistance;
+        }
+
+        /// <summary>
+        /// Used by update faces.
+        /// </summary>
+        void FindBeyondVertices(ConvexFaceInternal face, VertexBuffer beyond, VertexBuffer beyond1)
+        {
+            var beyondVertices = BeyondBuffer;
+
+            MaxDistance = double.NegativeInfinity;
+            FurthestVertex = null;
+            VertexWrap v;
+
+            int count = beyond1.Count;
+            for (int i = 0; i < count; i++) beyond1[i].Marked = true;
+            CurrentVertex.Marked = false;
+            count = beyond.Count;
+            for (int i = 0; i < count; i++)
+            {
+                v = beyond[i];
+                if (object.ReferenceEquals(v, CurrentVertex)) continue;
+                v.Marked = false;
+                IsBeyond(face, beyondVertices, v);
+            }
+
+            count = beyond1.Count;
+            for (int i = 0; i < count; i++)
+            {
+                v = beyond1[i];
+                if (v.Marked) IsBeyond(face, beyondVertices, v);
+            }
+
+            face.FurthestVertex = FurthestVertex;
+            //face.FurthestDistance = MaxDistance;
+
+            // Pull the old switch a roo
+            var temp = face.VerticesBeyond;
+            face.VerticesBeyond = beyondVertices;
+            if (temp.Count > 0) temp.Clear();
+            BeyondBuffer = temp;
+        }
+                
+        /// <summary>
+        /// Recalculates the centroid of the current hull.
+        /// </summary>
+        void UpdateCenter()
+        {
+            for (int i = 0; i < Dimension; i++) Center[i] *= (ConvexHull.Count - 1);
+            double f = 1.0 / ConvexHull.Count;
+            for (int i = 0; i < Dimension; i++) Center[i] = f * (Center[i] + CurrentVertex.PositionData[i]);
+        }
+
+        /// <summary>
+        /// Find the (dimension+1) initial points and create the simplexes.
+        /// </summary>
+        void InitConvexHull()
+        {
+            var extremes = FindExtremes();
+            var initialPoints = FindInitialPoints(extremes);
+
+            // Add the initial points to the convex hull.
+            foreach (var vertex in initialPoints)
+            {
+                CurrentVertex = vertex;
+                ConvexHull.Add(CurrentVertex);
+                UpdateCenter();
+                InputVertices.Remove(vertex);
+
+                // Because of the AklTou heuristic.
+                extremes.Remove(vertex);
+            }
+
+            // Create the initial simplexes.
+            var faces = InitiateFaceDatabase();
+
+            // Init the vertex beyond buffers.
+            foreach (var face in faces)
+            {
+                FindBeyondVertices(face);
+                if (face.VerticesBeyond.Count == 0) ConvexFaces.Add(face); // The face is on the hull
+                else UnprocessedFaces.Add(face);
+            }
+        }
+
+        /// <summary>
+        /// Finds (dimension + 1) initial points.
+        /// </summary>
+        /// <param name="extremes"></param>
+        /// <returns></returns>
+        private List<VertexWrap> FindInitialPoints(List<VertexWrap> extremes)
+        {
+            List<VertexWrap> initialPoints = new List<VertexWrap>();// { extremes[0], extremes[1] };
+
+            VertexWrap first = null, second = null;
+            double maxDist = 0;
+            for (int i = 0; i < extremes.Count - 1; i++)
+            {
+                var a = extremes[i];
+                for (int j = i + 1; j < extremes.Count; j++)
+                {
+                    var b = extremes[j];
+                    var dist = StarMath.norm2(StarMath.subtract(a.PositionData, b.PositionData, Dimension), Dimension, true);
+                    if (dist > maxDist)
+                    {
+                        first = a;
+                        second = b;
+                        maxDist = dist;
+                    }
+                }
+            }
+
+            initialPoints.Add(first);
+            initialPoints.Add(second);
+
+            for (int i = 2; i <= Dimension; i++)
+            {
+                double maximum = 0.0001;
+                VertexWrap maxPoint = null;
+                for (int j = 0; j < extremes.Count; j++)
+                {
+                    var extreme = extremes[j];
+                    if (initialPoints.Contains(extreme)) continue;
+
+                    var val = GetSimplexVolume(extreme, initialPoints);
+
+                    if (val > maximum)
+                    {
+                        maximum = val;
+                        maxPoint = extreme;
+                    }
+                }
+                if (maxPoint != null) initialPoints.Add(maxPoint);
+                else
+                {
+                    int vCount = InputVertices.Count;
+                    for (int j = 0; j < vCount; j++)
+                    {
+                        var point = InputVertices[j];
+                        if (initialPoints.Contains(point)) continue;
+
+                        var val = GetSimplexVolume(point, initialPoints);
+
+                        if (val > maximum)
+                        {
+                            maximum = val;
+                            maxPoint = point;
+                        }
+                    }
+
+                    if (maxPoint != null) initialPoints.Add(maxPoint);
+                    else ThrowSingular();
+                }
+            }
+            return initialPoints;
+        }
+
+        /// <summary>
+        /// Computes the volume of the (n=initialPoints.Count)D simplex defined by the
+        /// pivot and initialPoints.
+        /// This is computed as the determinant of the matrix | initialPoints[i] - pivot |
+        /// </summary>
+        /// <param name="pivot"></param>
+        /// <param name="initialPoints"></param>
+        /// <returns></returns>
+        double GetSimplexVolume(VertexWrap pivot, List<VertexWrap> initialPoints)
+        {
+            var dim = initialPoints.Count;
+            var m = nDMatrix;
+
+            for (int i = 0; i < dim; i++)
+            {
+                var pts = initialPoints[i];
+                for (int j = 0; j < dim; j++) m[i, j] = pts.PositionData[j] - pivot.PositionData[j];
+            }
+
+            return Math.Abs(StarMath.determinantDestructive(m, dim));
+        }
+
+        /// <summary>
+        /// Finds the extremes in all dimensions.
+        /// </summary>
+        /// <returns></returns>
+        private List<VertexWrap> FindExtremes()
+        {
+            var extremes = new List<VertexWrap>(2 * Dimension);
+
+            int vCount = InputVertices.Count;
+            for (int i = 0; i < Dimension; i++)
+            {
+                double min = double.MaxValue, max = double.MinValue;
+                int minInd = 0, maxInd = 0;
+                for (int j = 0; j < vCount; j++)
+                {
+                    var v = InputVertices[j].PositionData[i];
+                    if (v < min)
+                    {
+                        min = v;
+                        minInd = j;
+                    }
+                    if (v > max)
+                    {
+                        max = v;
+                        maxInd = j;
+                    }
+                }
+
+                if (minInd != maxInd)
+                {
+                    extremes.Add(InputVertices[minInd]);
+                    extremes.Add(InputVertices[maxInd]);
+                }
+                else extremes.Add(InputVertices[minInd]);
+            }
+            return extremes;
+        }
+
+        /// <summary>
+        /// The exception thrown if singular input data detected.
+        /// </summary>
+        void ThrowSingular()
+        {
+            throw new InvalidOperationException(
+                    "ConvexHull: Singular input data (i.e. trying to triangulate a data that contain a regular lattice of points).\n"
+                    + "Introducing some noise to the data might resolve the issue.");
+        }
+
+        /// <summary>
+        /// Fins the convex hull.
+        /// </summary>
+        void FindConvexHull()
+        {
+            // Find the (dimension+1) initial points and create the simplexes.
+            InitConvexHull();
+
+            // Expand the convex hull and faces.
+            while (UnprocessedFaces.First != null)
+            {
+                var currentFace = UnprocessedFaces.First;
+                CurrentVertex = currentFace.FurthestVertex;
+                ConvexHull.Add(CurrentVertex);
+                UpdateCenter();
+
+                // The affected faces get tagged
+                TagAffectedFaces(currentFace);
+
+                // Create the cone from the currentVertex and the affected faces horizon.
+                CreateCone();
+
+                // Need to reset the tags
+                int count = AffectedFaceBuffer.Count;
+                for (int i = 0; i < count; i++) AffectedFaceBuffer[i].Tag = 0;
+            }
+        }
+
+        /// <summary>
+        /// Wraps the vertices and determines the dimension if it's unknown.
+        /// </summary>
+        /// <param name="vertices"></param>
+        /// <param name="dim"></param>
+        private ConvexHullInternal(IEnumerable<IVertex> vertices)
+        {
+            InputVertices = new List<VertexWrap>(vertices.Select((v, i) => new VertexWrap { Vertex = v, PositionData = v.Position, Index = i }));
+            Dimension = DetermineDimension();
+            Initialize();
+        }
+
+        /// <summary>
+        /// Finds the vertices on the convex hull and optionally converts them to the TVertex array.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <param name="onlyCompute"></param>
+        /// <returns></returns>
+        private IEnumerable<TVertex> GetConvexHullInternal<TVertex>(bool onlyCompute = false) where TVertex : IVertex
+        {
+            if (Computed) return onlyCompute ? null : ConvexHull.Select(v => (TVertex)v.Vertex).ToArray();
+
+            if (Dimension < 2) throw new ArgumentException("Dimension of the input must be 2 or greater.");
+
+            FindConvexHull();
+            Computed = true;
+            return onlyCompute ? null : ConvexHull.Select(v => (TVertex)v.Vertex).ToArray();
+        }
+
+        /// <summary>
+        /// Finds the convex hull and creates the TFace objects.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TFace"></typeparam>
+        /// <returns></returns>
+        private IEnumerable<TFace> GetConvexFacesInternal<TVertex, TFace>()
+            where TFace : ConvexFace<TVertex, TFace>, new()
+            where TVertex : IVertex
+        {
+            if (!Computed) GetConvexHullInternal<TVertex>(true);
+
+            var faces = ConvexFaces;
+            int cellCount = faces.Count;
+            var cells = new TFace[cellCount];
+
+            for (int i = 0; i < cellCount; i++)
+            {
+                var face = faces[i];
+                var vertices = new TVertex[Dimension];
+                for (int j = 0; j < Dimension; j++) vertices[j] = (TVertex)face.Vertices[j].Vertex;
+                cells[i] = new TFace
+                {
+                    Vertices = vertices,
+                    Adjacency = new TFace[Dimension],
+                    Normal = face.Normal
+                };
+                face.Tag = i;
+            }
+
+            for (int i = 0; i < cellCount; i++)
+            {
+                var face = faces[i];
+                var cell = cells[i];
+                for (int j = 0; j < Dimension; j++)
+                {
+                    if (face.AdjacentFaces[j] == null) continue;
+                    cell.Adjacency[j] = cells[face.AdjacentFaces[j].Tag];
+                }
+
+                // Fix the vertex orientation.
+                if (face.IsNormalFlipped)
+                {
+                    var tempVert = cell.Vertices[0];
+                    cell.Vertices[0] = cell.Vertices[Dimension - 1];
+                    cell.Vertices[Dimension - 1] = tempVert;
+
+                    var tempAdj = cell.Adjacency[0];
+                    cell.Adjacency[0] = cell.Adjacency[Dimension - 1];
+                    cell.Adjacency[Dimension - 1] = tempAdj;
+                }
+            }
+
+            return cells;
+        }
+
+        /// <summary>
+        /// This is used by the Delaunay triangulation code.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TFace"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        internal static List<ConvexFaceInternal> GetConvexFacesInternal<TVertex, TFace>(IEnumerable<TVertex> data)
+            where TFace : ConvexFace<TVertex, TFace>, new()
+            where TVertex : IVertex
+        {
+            ConvexHullInternal ch = new ConvexHullInternal(data.Cast<IVertex>());
+            ch.GetConvexHullInternal<TVertex>(true);
+            return ch.ConvexFaces;
+        }
+
+        /// <summary>
+        /// This is called by the "ConvexHull" class.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TFace"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        internal static Tuple<IEnumerable<TVertex>, IEnumerable<TFace>> GetConvexHullAndFaces<TVertex, TFace>(IEnumerable<IVertex> data)
+            where TFace : ConvexFace<TVertex, TFace>, new()
+            where TVertex : IVertex
+        {
+            ConvexHullInternal ch = new ConvexHullInternal(data);
+            return Tuple.Create(
+                ch.GetConvexHullInternal<TVertex>(),
+                ch.GetConvexFacesInternal<TVertex, TFace>());
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/IVertex.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/IVertex.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/ConvexHull/IVertex.cs	(revision 9730)
@@ -0,0 +1,26 @@
+﻿
+namespace MIConvexHull
+{
+    /// <summary>
+    /// An interface for a structure with nD position.
+    /// </summary>
+    public interface IVertex
+    {
+        /// <summary>
+        /// Position of the vertex.
+        /// </summary>
+        double[] Position { get; set; }
+    }
+
+    /// <summary>
+    /// "Default" vertex.
+    /// </summary>
+    public class DefaultVertex : IVertex
+    {
+        /// <summary>
+        /// Position of the vertex.
+        /// </summary>
+        public double[] Position { get; set; }
+    }
+
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/MIConvexHull.csproj
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/MIConvexHull.csproj	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/MIConvexHull.csproj	(revision 9730)
@@ -0,0 +1,80 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{2337776D-7D0C-40AA-A439-C26C3CE24FAB}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MIConvexHull</RootNamespace>
+    <AssemblyName>MIConvexHullPlugin</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\MIConvexHullPlugin.xml</DocumentationFile>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\..\trunk\sources\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConvexHull\Collections.cs" />
+    <Compile Include="ConvexHull\ConvexFace.cs" />
+    <Compile Include="ConvexHull\ConvexFaceInternal.cs" />
+    <Compile Include="ConvexHull\ConvexHull.cs" />
+    <Compile Include="ConvexHull\ConvexHullInternal.cs" />
+    <Compile Include="ConvexHull\IVertex.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="StarMath\StarMathLibrary.cs" />
+    <Compile Include="Triangulation\DelaunayTriangulation.cs" />
+    <Compile Include="Triangulation\Triangulation.cs" />
+    <Compile Include="Triangulation\TriangulationCell.cs" />
+    <Compile Include="Triangulation\VoronoiEdge.cs" />
+    <Compile Include="Triangulation\VoronoiMesh.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="HeuristicLab.snk" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Properties/AssemblyInfo.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Properties/AssemblyInfo.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Properties/AssemblyInfo.cs	(revision 9730)
@@ -0,0 +1,35 @@
+﻿using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MIConvexHull")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("UT-ADLab")]
+[assembly: AssemblyProduct("MIConvexHull")]
+[assembly: AssemblyCopyright("Copyright © UT-ADLab 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d24b97d6-7b40-4bb5-b831-806d40106a83")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.10.1021")]
+[assembly: AssemblyFileVersion("1.0.10.1021")]
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/StarMath/StarMathLibrary.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/StarMath/StarMathLibrary.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/StarMath/StarMathLibrary.cs	(revision 9730)
@@ -0,0 +1,707 @@
+﻿/*************************************************************************
+ *     This file & class is part of the StarMath Project
+ *     Copyright 2010, 2011 Matthew Ira Campbell, PhD.
+ *
+ *     StarMath is free software: you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation, either version 3 of the License, or
+ *     (at your option) any later version.
+ *  
+ *     StarMath is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *  
+ *     You should have received a copy of the GNU General Public License
+ *     along with StarMath.  If not, see <http://www.gnu.org/licenses/>.
+ *     
+ *     Please find further details and contact information on StarMath
+ *     at http://starmath.codeplex.com/.
+ *************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+
+namespace MIConvexHull
+{
+    public static class StarMath
+    {
+        #region Printing
+        private const int cellWidth = 10;
+        private const int numDecimals = 3;
+
+        /// <summary>
+        /// Makes the print string.
+        /// </summary>
+        /// <param name = "A">The A.</param>
+        public static string MakePrintString(double[,] A)
+        {
+            if (A == null) return "<null>";
+            var format = "{0:F" + numDecimals + "}";
+            var p = "";
+            for (var i = 0; i < A.GetLength(0); i++)
+            {
+                p += "| ";
+                for (var j = 0; j < A.GetLength(1); j++)
+                    p += formatCell(format, A[i, j]) + ",";
+                p = p.Remove(p.Length - 1);
+                p += " |\n";
+            }
+            p = p.Remove(p.Length - 1);
+            return p;
+        }
+
+        private static object formatCell(string format, double p)
+        {
+            var numStr = string.Format(format, p);
+            numStr = numStr.TrimEnd('0');
+            numStr = numStr.TrimEnd('.');
+            var padAmt = ((double)(cellWidth - numStr.Length)) / 2;
+            numStr = numStr.PadLeft((int)Math.Floor(padAmt + numStr.Length));
+            numStr = numStr.PadRight(cellWidth);
+            return numStr;
+        }
+        #endregion
+
+        #region Solve
+        /// <summary>
+        /// Solves the specified A matrix.
+        /// </summary>
+        /// <param name="A">The A.</param>
+        /// <param name="b">The b.</param>
+        /// <returns></returns>
+        public static double[] solve(double[,] A, IList<double> b)
+        {
+            var aLength = A.GetLength(0);
+            if (aLength != A.GetLength(1))
+                throw new Exception("Matrix, A, must be square.");
+            if (aLength != b.Count)
+                throw new Exception("Matrix, A, must be have the same number of rows as the vector, b.");
+
+            /****** need code to determine when to switch between *****
+             ****** this analytical approach and the SOR approach *****/
+            return multiply(inverse(A, aLength), b, aLength, aLength);
+        }
+
+        public static void solveDestructiveInto(double[,] A, double[] b, double[] target)
+        {
+            var aLength = A.GetLength(0);
+            if (aLength != A.GetLength(1))
+                throw new Exception("Matrix, A, must be square.");
+            if (aLength != b.Length)
+                throw new Exception("Matrix, A, must be have the same number of rows as the vector, b.");
+
+            /****** need code to determine when to switch between *****
+             ****** this analytical approach and the SOR approach *****/
+            inverseInPlace(A, aLength);
+            multiplyInto(A, b, aLength, aLength, target);
+        }
+
+        /// <summary>
+        /// does gaussian elimination.
+        /// </summary>
+        /// <param name="nDim"></param>
+        /// <param name="pfMatr"></param>
+        /// <param name="pfVect"></param>
+        /// <param name="pfSolution"></param>
+        public static void gaussElimination(int nDim, double[][] pfMatr, double[] pfVect, double[] pfSolution)
+        {
+            double fMaxElem;
+            double fAcc;
+
+            int i, j, k, m;
+            
+            for (k = 0; k < (nDim - 1); k++) // base row of matrix
+            {
+                var rowK = pfMatr[k];
+
+                // search of line with max element
+                fMaxElem = Math.Abs(rowK[k]);
+                m = k;
+                for (i = k + 1; i < nDim; i++)
+                {
+                    if (fMaxElem < Math.Abs(pfMatr[i][k]))
+                    {
+                        fMaxElem = pfMatr[i][k];
+                        m = i;
+                    }
+                }
+
+                // permutation of base line (index k) and max element line(index m)                
+                if (m != k)
+                {
+                    var rowM = pfMatr[m];
+                    for (i = k; i < nDim; i++)
+                    {                        
+                        fAcc = rowK[i];
+                        rowK[i] = rowM[i];
+                        rowM[i] = fAcc;
+                    }
+                    fAcc = pfVect[k];
+                    pfVect[k] = pfVect[m];
+                    pfVect[m] = fAcc;
+                }
+
+                //if( pfMatr[k*nDim + k] == 0.0) return 1; // needs improvement !!!
+
+                // triangulation of matrix with coefficients
+                for (j = (k + 1); j < nDim; j++) // current row of matrix
+                {
+                    var rowJ = pfMatr[j];
+                    fAcc = -rowJ[k] / rowK[k];
+                    for (i = k; i < nDim; i++)
+                    {
+                        rowJ[i] = rowJ[i] + fAcc * rowK[i];
+                    }
+                    pfVect[j] = pfVect[j] + fAcc * pfVect[k]; // free member recalculation
+                }
+            }
+
+            for (k = (nDim - 1); k >= 0; k--)
+            {
+                var rowK = pfMatr[k];
+                pfSolution[k] = pfVect[k];
+                for (i = (k + 1); i < nDim; i++)
+                {
+                    pfSolution[k] -= (rowK[i] * pfSolution[i]);
+                }
+                pfSolution[k] = pfSolution[k] / rowK[k];
+            }
+        }
+
+        #endregion
+
+        #region inverse transpose
+
+        /// <summary>
+        /// Inverses the matrix A only if the diagonal is all non-zero.
+        /// A[i,i] != 0.0
+        /// </summary>
+        /// <param name = "A">The matrix to invert. This matrix is unchanged by this function.</param>
+        /// <param name="length">The length of the number of rows/columns in the square matrix, A.</param>
+        /// <returns>The inverted matrix, A^-1.</returns>
+        public static double[,] inverse(double[,] A, int length)
+        {
+            if (length == 1) return new[,] { { 1 / A[0, 0] } };
+            return inverseWithLUResult(LUDecomposition(A, length), length);
+        }
+
+        public static void inverseInPlace(double[,] A, int length)
+        {
+            if (length == 1)
+            {
+                A[0, 0] = 1 / A[0, 0];
+                return;
+            }
+            LUDecompositionInPlace(A, length);
+            inverseWithLUResult(A, length);
+        }
+
+
+        /// <summary>
+        /// Returns the LU decomposition of A in a new matrix.
+        /// </summary>
+        /// <param name = "A">The matrix to invert. This matrix is unchanged by this function.</param>
+        /// <param name="length">The length of the number of rows/columns in the square matrix, A.</param>
+        /// <returns>A matrix of equal size to A that combines the L and U. Here the diagonals belongs to L and the U's diagonal elements are all 1.</returns>
+        public static double[,] LUDecomposition(double[,] A, int length)
+        {
+            var B = (double[,])A.Clone();
+            // normalize row 0
+            for (var i = 1; i < length; i++) B[0, i] /= B[0, 0];
+
+            for (var i = 1; i < length; i++)
+            {
+                for (var j = i; j < length; j++)
+                {
+                    // do a column of L
+                    var sum = 0.0;
+                    for (var k = 0; k < i; k++)
+                        sum += B[j, k] * B[k, i];
+                    B[j, i] -= sum;
+                }
+                if (i == length - 1) continue;
+                for (var j = i + 1; j < length; j++)
+                {
+                    // do a row of U
+                    var sum = 0.0;
+                    for (var k = 0; k < i; k++)
+                        sum += B[i, k] * B[k, j];
+                    B[i, j] =
+                        (B[i, j] - sum) / B[i, i];
+                }
+            }
+            return B;
+        }
+
+        public static void LUDecompositionInPlace(double[,] A, int length)
+        {
+            var B = A;
+            // normalize row 0
+            for (var i = 1; i < length; i++) B[0, i] /= B[0, 0];
+
+            for (var i = 1; i < length; i++)
+            {
+                for (var j = i; j < length; j++)
+                {
+                    // do a column of L
+                    var sum = 0.0;
+                    for (var k = 0; k < i; k++)
+                        sum += B[j, k] * B[k, i];
+                    B[j, i] -= sum;
+                }
+                if (i == length - 1) continue;
+                for (var j = i + 1; j < length; j++)
+                {
+                    // do a row of U
+                    var sum = 0.0;
+                    for (var k = 0; k < i; k++)
+                        sum += B[i, k] * B[k, j];
+                    B[i, j] =
+                        (B[i, j] - sum) / B[i, i];
+                }
+            }
+        }
+
+        private static double[,] inverseWithLUResult(double[,] B, int length)
+        {
+            // this code is adapted from http://users.erols.com/mdinolfo/matrix.htm
+            // one constraint/caveat in this function is that the diagonal elts. cannot
+            // be zero.
+            // if the matrix is not square or is less than B 2x2, 
+            // then this function won't work
+            #region invert L
+
+            for (var i = 0; i < length; i++)
+                for (var j = i; j < length; j++)
+                {
+                    var x = 1.0;
+                    if (i != j)
+                    {
+                        x = 0.0;
+                        for (var k = i; k < j; k++)
+                            x -= B[j, k] * B[k, i];
+                    }
+                    B[j, i] = x / B[j, j];
+                }
+
+            #endregion
+
+            #region invert U
+
+            for (var i = 0; i < length; i++)
+                for (var j = i; j < length; j++)
+                {
+                    if (i == j) continue;
+                    var sum = 0.0;
+                    for (var k = i; k < j; k++)
+                        sum += B[k, j] * ((i == k) ? 1.0 : B[i, k]);
+                    B[i, j] = -sum;
+                }
+
+            #endregion
+
+            #region final inversion
+
+            for (var i = 0; i < length; i++)
+                for (var j = 0; j < length; j++)
+                {
+                    var sum = 0.0;
+                    for (var k = ((i > j) ? i : j); k < length; k++)
+                        sum += ((j == k) ? 1.0 : B[j, k]) * B[k, i];
+                    B[j, i] = sum;
+                }
+
+            #endregion
+
+            return B;
+        }
+        /// <summary>
+        /// Returns the determinant of matrix, A.
+        /// </summary>
+        /// <param name = "A">The input argument matrix. This matrix is unchanged by this function.</param>
+        /// <exception cref = "Exception"></exception>
+        /// <returns>a single value representing the matrix's determinant.</returns>
+        public static double determinant(double[,] A)
+        {
+            if (A == null) throw new Exception("The matrix, A, is null.");
+            var length = A.GetLength(0);
+            if (length != A.GetLength(1))
+                throw new Exception("The determinant is only possible for square matrices.");
+            if (length == 0) return 0.0;
+            if (length == 1) return A[0, 0];
+            if (length == 2) return (A[0, 0] * A[1, 1]) - (A[0, 1] * A[1, 0]);
+            if (length == 3)
+                return (A[0, 0] * A[1, 1] * A[2, 2])
+                       + (A[0, 1] * A[1, 2] * A[2, 0])
+                       + (A[0, 2] * A[1, 0] * A[2, 1])
+                       - (A[0, 0] * A[1, 2] * A[2, 1])
+                       - (A[0, 1] * A[1, 0] * A[2, 2])
+                       - (A[0, 2] * A[1, 1] * A[2, 0]);
+            return determinantBig(A, length);
+        }
+
+        /// <summary>
+        /// Modifies the matrix during the computation if the dimension > 3.
+        /// </summary>
+        /// <param name="A"></param>
+        /// <returns></returns>
+        public static double determinantDestructive(double[,] A, int dimension)
+        {
+            if (A == null) throw new Exception("The matrix, A, is null.");
+            var length = dimension;
+            //if (length != A.GetLength(1))
+            //    throw new Exception("The determinant is only possible for square matrices.");
+            if (length == 0) return 0.0;
+            if (length == 1) return A[0, 0];
+            if (length == 2) return (A[0, 0] * A[1, 1]) - (A[0, 1] * A[1, 0]);
+            if (length == 3)
+                return (A[0, 0] * A[1, 1] * A[2, 2])
+                       + (A[0, 1] * A[1, 2] * A[2, 0])
+                       + (A[0, 2] * A[1, 0] * A[2, 1])
+                       - (A[0, 0] * A[1, 2] * A[2, 1])
+                       - (A[0, 1] * A[1, 0] * A[2, 2])
+                       - (A[0, 2] * A[1, 1] * A[2, 0]);
+            return determinantBigDestructive(A, length);
+        }
+
+        static double determinantBigDestructive(double[,] A, int length)
+        {
+            LUDecompositionInPlace(A, length);
+            var result = 1.0;
+            for (var i = 0; i < length; i++)
+                if (double.IsNaN(A[i, i]))
+                    return 0;
+                else result *= A[i, i];
+            return result;
+        }
+
+        /// <summary>
+        /// Returns the determinant of matrix, A. Only used internally for matrices larger than 3.
+        /// </summary>
+        /// <param name="A">The input argument matrix. This matrix is unchanged by this function.</param>
+        /// <param name="length">The length of the side of the square matrix.</param>
+        /// <returns>
+        /// a single value representing the matrix's determinant.
+        /// </returns>
+        public static double determinantBig(double[,] A, int length)
+        {
+            double[,] L, U;
+            LUDecomposition(A, out L, out U, length);
+            var result = 1.0;
+            for (var i = 0; i < length; i++)
+                if (double.IsNaN(L[i, i]))
+                    return 0;
+                else result *= L[i, i];
+            return result;
+        }
+        /// <summary>
+        /// Returns the LU decomposition of A in a new matrix.
+        /// </summary>
+        /// <param name = "A">The matrix to invert. This matrix is unchanged by this function.</param>
+        /// <param name = "L">The L matrix is output where the diagonal elements are included and not (necessarily) equal to one.</param>
+        /// <param name = "U">The U matrix is output where the diagonal elements are all equal to one.</param>
+        /// <param name="length">The length of the number of rows/columns in the square matrix, A.</param>
+        public static void LUDecomposition(double[,] A, out double[,] L, out double[,] U, int length)
+        {
+            L = LUDecomposition(A, length);
+            U = new double[length, length];
+            for (var i = 0; i < length; i++)
+            {
+                U[i, i] = 1.0;
+                for (var j = i + 1; j < length; j++)
+                {
+                    U[i, j] = L[i, j];
+                    L[i, j] = 0.0;
+                }
+            }
+        }
+
+        #endregion
+
+        #region norm
+        /// <summary>
+        /// Returns to 2-norm (square root of the sum of squares of all terms)
+        /// of the vector, x.
+        /// </summary>
+        /// <param name="x">The vector, x.</param>
+        /// <param name="dontDoSqrt">if set to <c>true</c> [don't take the square root].</param>
+        /// <returns>Scalar value of 2-norm.</returns>
+        public static double norm2(double[] x, int dim, Boolean dontDoSqrt = false)
+        {
+            double norm = 0;
+            for (int i = 0; i < dim; i++)
+            {
+                var t = x[i];
+                norm += t * t;
+            }
+            return dontDoSqrt ? norm : Math.Sqrt(norm);
+        }
+        /// <summary>
+        /// Returns to normalized vector (has lenght or 2-norm of 1))
+        /// of the vector, x.
+        /// </summary>
+        /// <param name="x">The vector, x.</param>
+        /// <param name="length">The length of the vector.</param>
+        /// <returns>unit vector.</returns>
+        public static double[] normalize(double[] x, int length)
+        {
+            return divide(x, norm2(x, length), length);
+        }
+
+        public static void normalizeInPlace(double[] x, int length)
+        {
+            double f = 1.0 / norm2(x, length);
+            for (int i = 0; i < length; i++) x[i] *= f;
+        }
+        #endregion
+
+        #region make extract
+        /// <summary>
+        /// Gets a row of matrix, A.
+        /// </summary>
+        /// <param name = "rowIndex">The row index.</param>
+        /// <param name = "A">The matrix, A.</param>
+        /// <returns>A double array that contains the requested row</returns>
+        public static double[] GetRow(int rowIndex, double[,] A)
+        {
+            var numRows = A.GetLength(0);
+            var numCols = A.GetLength(1);
+            if ((rowIndex < 0) || (rowIndex >= numRows))
+                throw new Exception("MatrixMath Size Error: An index value of "
+                                    + rowIndex
+                                    + " for getRow is not in required range from 0 up to (but not including) "
+                                    + numRows + ".");
+            var v = new double[numCols];
+            for (var i = 0; i < numCols; i++)
+                v[i] = A[rowIndex, i];
+            return v;
+        }
+        /// <summary>
+        /// Sets/Replaces the given column of matrix A with the vector v.
+        /// </summary>
+        /// <param name = "colIndex">Index of the col.</param>
+        /// <param name = "A">The A.</param>
+        /// <param name = "v">The v.</param>
+        public static void SetColumn(int colIndex, double[,] A, IList<double> v)
+        {
+            var numRows = A.GetLength(0);
+            var numCols = A.GetLength(1);
+            if ((colIndex < 0) || (colIndex >= numCols))
+                throw new Exception("MatrixMath Size Error: An index value of "
+                                    + colIndex
+                                    + " for getColumn is not in required range from 0 up to (but not including) "
+                                    + numCols + ".");
+            for (var i = 0; i < numRows; i++)
+                A[i, colIndex] = v[i];
+        }
+        /// <summary>
+        /// Sets/Replaces the given row of matrix A with the vector v.
+        /// </summary>
+        /// <param name = "rowIndex">The index of the row, rowIndex.</param>
+        /// <param name = "A">The matrix, A.</param>
+        /// <param name = "v">The vector, v.</param>
+        public static void SetRow(int rowIndex, double[,] A, IList<double> v)
+        {
+            var numRows = A.GetLength(0);
+            var numCols = A.GetLength(1);
+            if ((rowIndex < 0) || (rowIndex >= numRows))
+                throw new Exception("MatrixMath Size Error: An index value of "
+                                    + rowIndex
+                                    + " for getRow is not in required range from 0 up to (but not including) "
+                                    + numRows + ".");
+            for (var i = 0; i < numCols; i++)
+                A[rowIndex, i] = v[i];
+        }
+        /// <summary>
+        /// Makes the zero vector.
+        /// </summary>
+        /// <param name = "p">The p.</param>
+        /// <returns></returns>
+        public static double[] makeZeroVector(int p)
+        {
+            if (p <= 0) throw new Exception("The size, p, must be a positive integer.");
+            return new double[p];
+        }
+
+        #endregion
+
+        #region add subtract multiply
+        /// <summary>
+        /// The cross product of two double vectors, A and B, which are of length, 2.
+        /// In actuality, there is no cross-product for 2D. This is shorthand for 2D systems 
+        /// that are really simplifications of 3D. The returned scalar is actually the value in 
+        /// the third (read: z) direction.
+        /// </summary>
+        /// <param name = "A">1D double Array, A</param>
+        /// <param name = "B">1D double Array, B</param>
+        /// <returns></returns>
+        public static double crossProduct2(IList<double> A, IList<double> B)
+        {
+            if (((A.Count() == 2) && (B.Count() == 2))
+                || ((A.Count() == 3) && (B.Count() == 3) && A[2] == 0.0 && B[2] == 0.0))
+                return A[0] * B[1] - B[0] * A[1];
+            throw new Exception("This cross product \"shortcut\" is only used with 2D vectors to get the single value in the,"
+                                + "would be, Z-direction.");
+        }
+
+        /// <summary>
+        /// The dot product of the two 1D double vectors A and B
+        /// </summary>
+        /// <param name="A">1D double Array, A</param>
+        /// <param name="B">1D double Array, B</param>
+        /// <param name="length">The length of both vectors A and B. This is an optional argument, but if it is already known 
+        /// - there is a slight speed advantage to providing it.</param>
+        /// <returns>
+        /// A double value that contains the dot product
+        /// </returns>
+        public static double dotProduct(IList<double> A, IList<double> B, int length)
+        {
+            var c = 0.0;
+            for (var i = 0; i != length; i++)
+                c += A[i] * B[i];
+            return c;
+        }
+        /// <summary>
+        /// The dot product of the one 1D int vector and one 1D double vector
+        /// </summary>
+        /// <param name="A">1D int Array, A</param>
+        /// <param name="B">1D double Array, B</param>
+        /// <param name="length">The length of both vectors A and B. This is an optional argument, but if it is already known 
+        /// - there is a slight speed advantage to providing it.</param>
+        /// <returns>
+        /// A double value that contains the dot product
+        /// </returns>
+        public static double dotProduct(IList<int> A, IList<double> B, int length)
+        {
+            var c = 0.0;
+            for (var i = 0; i != length; i++)
+                c += A[i] * B[i];
+            return c;
+        }
+        /// <summary>
+        /// Subtracts one vector (B) from the other (A). C = A - B.
+        /// </summary>
+        /// <param name = "A">The minuend vector, A (1D double)</param>
+        /// <param name = "B">The subtrahend vector, B (1D double)</param>
+        /// <param name="length">The length of the vectors.</param>
+        /// <returns>Returns the difference vector, C (1D double)</returns>
+        public static double[] subtract(IList<double> A, IList<double> B, int length)
+        {
+            var c = new double[length];
+            for (var i = 0; i != length; i++)
+                c[i] = A[i] - B[i];
+            return c;
+        }
+        /// <summary>
+        /// Adds arrays A and B
+        /// </summary>
+        /// <param name = "A">1D double array 1</param>
+        /// <param name = "B">1D double array 2</param>
+        /// <param name="length">The length of the array.</param>
+        /// <returns>1D double array that contains sum of vectros A and B</returns>
+        public static double[] add(IList<double> A, IList<double> B, int length)
+        {
+            var c = new double[length];
+            for (var i = 0; i != length; i++)
+                c[i] = A[i] + B[i];
+            return c;
+        }
+        /// <summary>
+        /// Divides all elements of a 1D double array by the double value.
+        /// </summary>
+        /// <param name="B">The vector to be divided</param>
+        /// <param name="a">The double value to be divided by, the divisor.</param>
+        /// <param name="length">The length of the vector B. This is an optional argument, but if it is already known 
+        /// - there is a slight speed advantage to providing it.</param>
+        /// <returns>
+        /// A 1D double array that contains the product
+        /// </returns>
+        public static double[] divide(IList<double> B, double a, int length)
+        { return multiply((1 / a), B, length); }
+        /// <summary>
+        /// Multiplies all elements of a 1D double array with the double value.
+        /// </summary>
+        /// <param name="a">The double value to be multiplied</param>
+        /// <param name="B">The double vector to be multiplied with</param>
+        /// <param name="length">The length of the vector B. This is an optional argument, but if it is already known 
+        /// - there is a slight speed advantage to providing it.</param>
+        /// <returns>
+        /// A 1D double array that contains the product
+        /// </returns>
+        public static double[] multiply(double a, IList<double> B, int length)
+        {
+            // scale vector B by the amount of scalar a
+            var c = new double[length];
+            for (var i = 0; i != length; i++)
+                c[i] = a * B[i];
+            return c;
+        }
+
+        /// <summary>
+        /// Product of a matrix and a vector (2D double and 1D double)
+        /// </summary>
+        /// <param name = "A">2D double Array</param>
+        /// <param name = "B">1D double array - column vector (1 element row)</param>
+        /// <param name="numRows">The number of rows.</param>
+        /// <param name="numCols">The number of columns.</param>
+        /// <returns>A 1D double array that is the product of the two matrices A and B</returns>
+        public static double[] multiply(double[,] A, IList<double> B, int numRows, int numCols)
+        {
+            var C = new double[numRows];
+
+            for (var i = 0; i != numRows; i++)
+            {
+                C[i] = 0.0;
+                for (var j = 0; j != numCols; j++)
+                    C[i] += A[i, j] * B[j];
+            }
+            return C;
+        }
+
+        public static void multiplyInto(double[,] A, double[] B, int numRows, int numCols, double[] target)
+        {
+            var C = target;
+
+            for (var i = 0; i != numRows; i++)
+            {
+                C[i] = 0.0;
+                for (var j = 0; j != numCols; j++)
+                    C[i] += A[i, j] * B[j];
+            }
+        }
+        /// <summary>
+        /// The cross product of two double vectors, A and B, which are of length, 3.
+        /// This is equivalent to calling crossProduct, but a slight speed advantage
+        /// may exist in skipping directly to this sub-function.
+        /// </summary>
+        /// <param name = "A">1D double Array, A</param>
+        /// <param name = "B">1D double Array, B</param>
+        /// <returns></returns>
+        public static double[] crossProduct3(IList<double> A, IList<double> B)
+        {
+            return new[]
+                       {
+                           A[1]*B[2] - B[1]*A[2],
+                           A[2]*B[0] - B[2]*A[0],
+                           A[0]*B[1] - B[0]*A[1]
+                       };
+        }
+
+        #endregion
+
+
+        public static double subtractAndDot(double[] n, double[] l, double[] r, int dim)
+        {
+            double acc = 0;
+            for (int i = 0; i < dim; i++)
+            {
+                double t = l[i] - r[i];
+                acc += n[i] * t;
+            }
+
+            return acc;
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/DelaunayTriangulation.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/DelaunayTriangulation.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/DelaunayTriangulation.cs	(revision 9730)
@@ -0,0 +1,120 @@
+﻿namespace MIConvexHull
+{
+    using System.Collections.Generic;
+    using System.Linq;
+    using System;
+
+    /// <summary>
+    /// Calculation and representation of Delaunay triangulation.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    /// <typeparam name="TCell"></typeparam>
+    public class DelaunayTriangulation<TVertex, TCell> : ITriangulation<TVertex, TCell>
+        where TCell : TriangulationCell<TVertex, TCell>, new()
+        where TVertex : IVertex
+    {
+        /// <summary>
+        /// Cells of the triangulation.
+        /// </summary>
+        public IEnumerable<TCell> Cells { get; private set; }
+
+        /// <summary>
+        /// Creates the Delaunay triangulation of the input data.
+        /// Be careful with concurrency, because during the computation, the vertex position arrays get resized.
+        /// </summary>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static DelaunayTriangulation<TVertex, TCell> Create(IEnumerable<TVertex> data)
+        {
+            if (data == null) throw new ArgumentException("data can't be null.");
+            if (!(data is IList<TVertex>)) data = data.ToArray();
+            if (data.Count() == 0) return new DelaunayTriangulation<TVertex, TCell> { Cells = Enumerable.Empty<TCell>() };
+
+            int dimension = data.First().Position.Length;
+
+            // Resize the arrays and lift the data.
+            foreach (var p in data)
+            {
+                double lenSq = StarMath.norm2(p.Position, dimension, true);
+                var v = p.Position;
+                Array.Resize(ref v, dimension + 1);
+                p.Position = v;
+                p.Position[dimension] = lenSq;
+            }
+
+            // Find the convex hull
+            var delaunayFaces = ConvexHullInternal.GetConvexFacesInternal<TVertex, TCell>(data);
+
+            // Resize the data back
+            foreach (var p in data)
+            {
+                var v = p.Position;
+                Array.Resize(ref v, dimension);
+                p.Position = v;
+            }
+            // Remove the "upper" faces
+            for (var i = delaunayFaces.Count - 1; i >= 0; i--)
+            {
+                var candidate = delaunayFaces[i];
+                if (candidate.Normal[dimension] >= 0)
+                {
+                    for (int fi = 0; fi < candidate.AdjacentFaces.Length; fi++)
+                    {
+                        var f = candidate.AdjacentFaces[fi];
+                        if (f != null)
+                        {
+                            for (int j = 0; j < f.AdjacentFaces.Length; j++)
+                            {
+                                if (object.ReferenceEquals(f.AdjacentFaces[j], candidate))
+                                {
+                                    f.AdjacentFaces[j] = null;
+                                }
+                            }
+                        }
+                    }
+                    var li = delaunayFaces.Count - 1;
+                    delaunayFaces[i] = delaunayFaces[li];
+                    delaunayFaces.RemoveAt(li);
+                }
+            }
+
+            // Create the "TCell" representation.
+            int cellCount = delaunayFaces.Count;
+            var cells = new TCell[cellCount];
+
+            for (int i = 0; i < cellCount; i++)
+            {
+                var face = delaunayFaces[i];
+                var vertices = new TVertex[dimension + 1];
+                for (int j = 0; j <= dimension; j++) vertices[j] = (TVertex)face.Vertices[j].Vertex;
+                cells[i] = new TCell
+                {
+                    Vertices = vertices,
+                    Adjacency = new TCell[dimension + 1]
+                };
+                face.Tag = i;
+            }
+
+            for (int i = 0; i < cellCount; i++)
+            {
+                var face = delaunayFaces[i];
+                var cell = cells[i];
+                for (int j = 0; j <= dimension; j++)
+                {
+                    if (face.AdjacentFaces[j] == null) continue;
+                    cell.Adjacency[j] = cells[face.AdjacentFaces[j].Tag];
+                }
+            }
+
+            return new DelaunayTriangulation<TVertex, TCell> { Cells = cells };
+        }
+
+        /// <summary>
+        /// Can only be created using a factory method.
+        /// </summary>
+        private DelaunayTriangulation()
+        {
+
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/Triangulation.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/Triangulation.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/Triangulation.cs	(revision 9730)
@@ -0,0 +1,60 @@
+﻿namespace MIConvexHull
+{
+    using System.Collections.Generic;
+    using System.Linq;
+
+    /// <summary>
+    /// Simple interface to unify different types of triangulations in the future.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    /// <typeparam name="TCell"></typeparam>
+    public interface ITriangulation<TVertex, TCell>
+        where TCell : TriangulationCell<TVertex, TCell>, new()
+        where TVertex : IVertex
+    {
+        IEnumerable<TCell> Cells { get; }
+    }
+
+    /// <summary>
+    /// Factory class for creating triangulations.
+    /// </summary>
+    public static class Triangulation
+    {
+        /// <summary>
+        /// Creates the Delaunay triangulation of the input data.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ITriangulation<TVertex, DefaultTriangulationCell<TVertex>> CreateDelaunay<TVertex>(IEnumerable<TVertex> data)
+            where TVertex : IVertex
+        {
+            return DelaunayTriangulation<TVertex, DefaultTriangulationCell<TVertex>>.Create(data);
+        }
+
+        /// <summary>
+        /// Creates the Delaunay triangulation of the input data.
+        /// </summary>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ITriangulation<DefaultVertex, DefaultTriangulationCell<DefaultVertex>> CreateDelaunay(IEnumerable<double[]> data)
+        {
+            var points = data.Select(p => new DefaultVertex { Position = p.ToArray() });
+            return DelaunayTriangulation<DefaultVertex, DefaultTriangulationCell<DefaultVertex>>.Create(points);
+        }
+
+        /// <summary>
+        /// Creates the Delaunay triangulation of the input data.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TFace"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static ITriangulation<TVertex, TFace> CreateDelaunay<TVertex, TFace>(IEnumerable<TVertex> data)
+            where TVertex : IVertex
+            where TFace : TriangulationCell<TVertex, TFace>, new()
+        {
+            return DelaunayTriangulation<TVertex, TFace>.Create(data);
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/TriangulationCell.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/TriangulationCell.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/TriangulationCell.cs	(revision 9730)
@@ -0,0 +1,25 @@
+﻿namespace MIConvexHull
+{
+    /// <summary>
+    /// Representation of the triangulation cell. Pretty much the same as ConvexFace,
+    /// just wanted to distinguish the two.
+    /// To declare your own face type, use class Face : DelaunayFace(of Vertex, of Face)
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    /// <typeparam name="TCell"></typeparam>
+    public abstract class TriangulationCell<TVertex, TCell> : ConvexFace<TVertex, TCell>
+        where TVertex : IVertex
+        where TCell : ConvexFace<TVertex, TCell>
+    {
+
+    }
+
+    /// <summary>
+    /// Default triangulation cell.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    public class DefaultTriangulationCell<TVertex> : TriangulationCell<TVertex, DefaultTriangulationCell<TVertex>>
+        where TVertex : IVertex
+    {
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/VoronoiEdge.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/VoronoiEdge.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/VoronoiEdge.cs	(revision 9730)
@@ -0,0 +1,72 @@
+﻿namespace MIConvexHull
+{
+    /// <summary>
+    /// A class representing an (undirected) edge of the Voronoi graph.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    /// <typeparam name="TCell"></typeparam>
+    public class VoronoiEdge<TVertex, TCell>
+        where TVertex : IVertex
+        where TCell : TriangulationCell<TVertex, TCell>
+    {
+        /// <summary>
+        /// Source of the edge.
+        /// </summary>
+        public TCell Source
+        {
+            get;
+            internal set;
+        }
+
+        /// <summary>
+        /// Target of the edge.
+        /// </summary>
+        public TCell Target
+        {
+            get;
+            internal set;
+        }
+
+        /// <summary>
+        /// ...
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        public override bool Equals(object obj)
+        {
+            var other = obj as VoronoiEdge<TVertex, TCell>;
+            if (other == null) return false;
+            if (object.ReferenceEquals(this, other)) return true;
+            return (Source == other.Source && Target == other.Target)
+                || (Source == other.Target && Target == other.Source);
+        }
+
+        /// <summary>
+        /// ...
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            int hash = 23;
+            hash = hash * 31 + Source.GetHashCode();
+            return hash * 31 + Target.GetHashCode();
+        }
+
+        /// <summary>
+        /// Create an instance of the edge.
+        /// </summary>
+        public VoronoiEdge()
+        {
+
+        }
+
+        /// <summary>
+        /// Create an instance of the edge.
+        /// </summary>
+        public VoronoiEdge(TCell source, TCell target)
+        {
+            this.Source = source;
+            this.Target = target;
+        }
+    }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/VoronoiMesh.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/VoronoiMesh.cs	(revision 9730)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/MIConvexHull/Triangulation/VoronoiMesh.cs	(revision 9730)
@@ -0,0 +1,144 @@
+﻿namespace MIConvexHull
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+
+    /// <summary>
+    /// A factory class for creating a Voronoi mesh.
+    /// </summary>
+    public static class VoronoiMesh
+    {
+        /// <summary>
+        /// Create the voronoi mesh.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TCell"></typeparam>
+        /// <typeparam name="TEdge"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static VoronoiMesh<TVertex, TCell, TEdge> Create<TVertex, TCell, TEdge>(IEnumerable<TVertex> data)
+            where TCell : TriangulationCell<TVertex, TCell>, new()
+            where TVertex : IVertex
+            where TEdge : VoronoiEdge<TVertex, TCell>, new()
+        {
+            return VoronoiMesh<TVertex, TCell, TEdge>.Create(data);
+        }
+
+        /// <summary>
+        /// Create the voronoi mesh.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static VoronoiMesh<TVertex, DefaultTriangulationCell<TVertex>, VoronoiEdge<TVertex, DefaultTriangulationCell<TVertex>>> Create<TVertex>(IEnumerable<TVertex> data)
+            where TVertex : IVertex
+        {
+            return VoronoiMesh<TVertex, DefaultTriangulationCell<TVertex>, VoronoiEdge<TVertex, DefaultTriangulationCell<TVertex>>>.Create(data);
+        }
+
+        /// <summary>
+        /// Create the voronoi mesh.
+        /// </summary>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static VoronoiMesh<DefaultVertex, DefaultTriangulationCell<DefaultVertex>, VoronoiEdge<DefaultVertex, DefaultTriangulationCell<DefaultVertex>>> 
+            Create(IEnumerable<double[]> data)
+        {
+            var points = data.Select(p => new DefaultVertex { Position = p.ToArray() });
+            return VoronoiMesh<DefaultVertex, DefaultTriangulationCell<DefaultVertex>, VoronoiEdge<DefaultVertex, DefaultTriangulationCell<DefaultVertex>>>.Create(points);
+        }
+
+        /// <summary>
+        /// Create the voronoi mesh.
+        /// </summary>
+        /// <typeparam name="TVertex"></typeparam>
+        /// <typeparam name="TCell"></typeparam>
+        /// <typeparam name="TEdge"></typeparam>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public static VoronoiMesh<TVertex, TCell, VoronoiEdge<TVertex, TCell>> Create<TVertex, TCell>(IEnumerable<TVertex> data)
+            where TVertex : IVertex
+            where TCell : TriangulationCell<TVertex, TCell>, new()
+        {
+            return VoronoiMesh<TVertex, TCell, VoronoiEdge<TVertex, TCell>>.Create(data);
+        }
+    }
+
+    /// <summary>
+    /// A representation of a voronoi mesh.
+    /// </summary>
+    /// <typeparam name="TVertex"></typeparam>
+    /// <typeparam name="TCell"></typeparam>
+    /// <typeparam name="TEdge"></typeparam>
+    public class VoronoiMesh<TVertex, TCell, TEdge>
+        where TCell : TriangulationCell<TVertex, TCell>, new()
+        where TVertex : IVertex
+        where TEdge : VoronoiEdge<TVertex, TCell>, new()
+    {
+        /// <summary>
+        /// This is probably not needed, but might make things a tiny bit faster.
+        /// </summary>
+        class EdgeComparer : IEqualityComparer<TEdge>
+        {
+            public bool Equals(TEdge x, TEdge y)
+            {
+                return (x.Source == y.Source && x.Target == y.Target) || (x.Source == y.Target && x.Target == y.Source);
+            }
+
+            public int GetHashCode(TEdge obj)
+            {
+                return obj.Source.GetHashCode() ^ obj.Target.GetHashCode();
+            }
+        }
+
+        /// <summary>
+        /// Vertices of the diagram.
+        /// </summary>
+        public IEnumerable<TCell> Vertices { get; private set; }
+
+        /// <summary>
+        /// Edges connecting the cells. 
+        /// The same information can be retrieved Cells' Adjacency.
+        /// </summary>
+        public IEnumerable<TEdge> Edges { get; private set; }
+
+        /// <summary>
+        /// Create a Voronoi diagram of the input data.
+        /// </summary>
+        /// <param name="data"></param>
+        public static VoronoiMesh<TVertex, TCell, TEdge> Create(IEnumerable<TVertex> data)
+        {
+            if (data == null) throw new ArgumentNullException("data can't be null");
+
+            if (!(data is IList<TVertex>)) data = data.ToArray();
+
+            var t = DelaunayTriangulation<TVertex, TCell>.Create(data);
+            var vertices = t.Cells;
+            var edges = new HashSet<TEdge>(new EdgeComparer());
+
+            foreach (var f in vertices)
+            {
+                for (int i = 0; i < f.Adjacency.Length; i++)
+                {
+                    var af = f.Adjacency[i];
+                    if (af != null) edges.Add(new TEdge { Source = f, Target = af });
+                }
+            }
+
+            return new VoronoiMesh<TVertex, TCell, TEdge>
+            {
+                Vertices = vertices,
+                Edges = edges.ToList()
+            };
+        }
+
+        /// <summary>
+        /// Can only be created using a factory method.
+        /// </summary>
+        private VoronoiMesh()
+        {
+
+        }
+    }
+}
