Index: anches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/BinPacking3DProblemView.Designer.cs
===================================================================
--- /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/BinPacking3DProblemView.Designer.cs	(revision 15173)
+++ 	(revision )
@@ -1,172 +1,0 @@
-﻿namespace HeuristicLab.Problems.BinPacking.Views
-{
-    partial class BinPacking3DProblemView
-    {
-        /// <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.sortingComboBox = new System.Windows.Forms.ComboBox();
-            this.sortingLabel = new System.Windows.Forms.Label();
-            this.deltaLabel = new System.Windows.Forms.Label();
-            this.deltaTextBox = new System.Windows.Forms.TextBox();
-            this.heuristicLabel = new System.Windows.Forms.Label();
-            this.heuristicComboBox = new System.Windows.Forms.ComboBox();
-            ((System.ComponentModel.ISupportInitialize)(this.problemInstanceSplitContainer)).BeginInit();
-            this.problemInstanceSplitContainer.Panel1.SuspendLayout();
-            this.problemInstanceSplitContainer.Panel2.SuspendLayout();
-            this.problemInstanceSplitContainer.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
-            this.SuspendLayout();
-            // 
-            // problemInstanceSplitContainer
-            // 
-            this.problemInstanceSplitContainer.Location = new System.Drawing.Point(0, 71);
-            this.problemInstanceSplitContainer.Size = new System.Drawing.Size(511, 343);
-            // 
-            // problemInstanceProviderComboBox
-            // 
-            this.problemInstanceProviderComboBox.Location = new System.Drawing.Point(55, 2);
-            // 
-            // parameterCollectionView
-            // 
-            this.parameterCollectionView.Size = new System.Drawing.Size(501, 192);
-            // 
-            // nameTextBox
-            // 
-            this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
-            this.errorProvider.SetIconPadding(this.nameTextBox, 2);
-            // 
-            // sortingComboBox
-            // 
-            this.sortingComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.sortingComboBox.FormattingEnabled = true;
-            this.sortingComboBox.Items.AddRange(new object[] {
-            "Volume-Height",
-            "Height-Volume",
-            "Area-Height",
-            "Clustered Area-Height",
-            "Height-Area",
-            "Clustered Height-Area"});
-            this.sortingComboBox.Location = new System.Drawing.Point(55, 43);
-            this.sortingComboBox.Name = "sortingComboBox";
-            this.sortingComboBox.Size = new System.Drawing.Size(208, 21);
-            this.sortingComboBox.TabIndex = 15;
-            this.sortingComboBox.SelectedIndexChanged += new System.EventHandler(this.sortingComboBox_SelectedIndexChanged);
-            // 
-            // sortingLabel
-            // 
-            this.sortingLabel.AutoSize = true;
-            this.sortingLabel.Location = new System.Drawing.Point(3, 49);
-            this.sortingLabel.Name = "sortingLabel";
-            this.sortingLabel.Size = new System.Drawing.Size(43, 13);
-            this.sortingLabel.TabIndex = 16;
-            this.sortingLabel.Text = "Sorting:";
-            // 
-            // deltaLabel
-            // 
-            this.deltaLabel.AutoSize = true;
-            this.deltaLabel.Location = new System.Drawing.Point(278, 48);
-            this.deltaLabel.Name = "deltaLabel";
-            this.deltaLabel.Size = new System.Drawing.Size(35, 13);
-            this.deltaLabel.TabIndex = 17;
-            this.deltaLabel.Text = "Delta:";
-            this.deltaLabel.Visible = false;
-            // 
-            // deltaTextBox
-            // 
-            this.deltaTextBox.Location = new System.Drawing.Point(318, 44);
-            this.deltaTextBox.Name = "deltaTextBox";
-            this.deltaTextBox.Size = new System.Drawing.Size(73, 20);
-            this.deltaTextBox.TabIndex = 18;
-            this.deltaTextBox.Visible = false;
-            this.deltaTextBox.TextChanged += new System.EventHandler(this.deltaTextBox_TextChanged);
-            // 
-            // heuristicLabel
-            // 
-            this.heuristicLabel.AutoSize = true;
-            this.heuristicLabel.Location = new System.Drawing.Point(3, 19);
-            this.heuristicLabel.Name = "heuristicLabel";
-            this.heuristicLabel.Size = new System.Drawing.Size(51, 13);
-            this.heuristicLabel.TabIndex = 19;
-            this.heuristicLabel.Text = "Heuristic:";
-            // 
-            // heuristicComboBox
-            // 
-            this.heuristicComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.heuristicComboBox.FormattingEnabled = true;
-            this.heuristicComboBox.Items.AddRange(new object[] {
-            "First Fit",
-            "Best Fit (Free Volume)",
-            "Best Fit (Maximum Packing)",
-            "Best Fit (Level)",
-            "Best Fit (Residual Space)"});
-            this.heuristicComboBox.Location = new System.Drawing.Point(55, 14);
-            this.heuristicComboBox.Name = "heuristicComboBox";
-            this.heuristicComboBox.Size = new System.Drawing.Size(208, 21);
-            this.heuristicComboBox.TabIndex = 20;
-            //this.heuristicComboBox.SelectedIndexChanged += new System.EventHandler(this.heuristicComboBox_SelectedIndexChanged);
-            // 
-            // BinPacking3DProblemView
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.Controls.Add(this.heuristicComboBox);
-            this.Controls.Add(this.heuristicLabel);
-            this.Controls.Add(this.deltaTextBox);
-            this.Controls.Add(this.deltaLabel);
-            this.Controls.Add(this.sortingLabel);
-            this.Controls.Add(this.sortingComboBox);
-            this.Name = "BinPacking3DProblemView";
-            this.Size = new System.Drawing.Size(511, 414);
-            this.Controls.SetChildIndex(this.sortingComboBox, 0);
-            this.Controls.SetChildIndex(this.sortingLabel, 0);
-            this.Controls.SetChildIndex(this.deltaLabel, 0);
-            this.Controls.SetChildIndex(this.deltaTextBox, 0);
-            this.Controls.SetChildIndex(this.problemInstanceSplitContainer, 0);
-            this.Controls.SetChildIndex(this.heuristicLabel, 0);
-            this.Controls.SetChildIndex(this.heuristicComboBox, 0);
-            this.problemInstanceSplitContainer.Panel1.ResumeLayout(false);
-            this.problemInstanceSplitContainer.Panel1.PerformLayout();
-            this.problemInstanceSplitContainer.Panel2.ResumeLayout(false);
-            this.problemInstanceSplitContainer.Panel2.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.problemInstanceSplitContainer)).EndInit();
-            this.problemInstanceSplitContainer.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.ComboBox sortingComboBox;
-        private System.Windows.Forms.Label sortingLabel;
-        private System.Windows.Forms.Label deltaLabel;
-        private System.Windows.Forms.TextBox deltaTextBox;
-        private System.Windows.Forms.Label heuristicLabel;
-        private System.Windows.Forms.ComboBox heuristicComboBox;
-    }
-}
Index: anches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/BinPacking3DProblemView.cs
===================================================================
--- /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/BinPacking3DProblemView.cs	(revision 15173)
+++ 	(revision )
@@ -1,121 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using HeuristicLab.Optimization.Views;
-using HeuristicLab.MainForm;
-using HeuristicLab.MainForm.WindowsForms;
-using HeuristicLab.Core;
-using HeuristicLab.Problems.BinPacking3D;
-using HeuristicLab.Data;
-
-namespace HeuristicLab.Problems.BinPacking.Views {
-    [View("Permutation 3D Bin Packing Problem View")]
-    [Content(typeof(BinPacking3D.PermutationProblem), IsDefaultView = true)]
-    public partial class BinPacking3DProblemView : ProblemView {
-
-      public new BinPacking3D.PermutationProblem Content {
-        get { return (BinPacking3D.PermutationProblem)base.Content; }
-        set { base.Content = value; }
-      }
-
-      public BinPacking3DProblemView() {
-          InitializeComponent();
-      }
-
-      protected override void OnContentChanged() {
-        base.OnContentChanged();
-        sortingComboBox.SelectedIndex = 0;
-        heuristicComboBox.SelectedIndex = 0;
-      }
-
-      /*private void heuristicComboBox_SelectedIndexChanged(object sender, EventArgs e) {
-        if (Content == null) return;
-        if (heuristicComboBox.SelectedItem.ToString().CompareTo("Best Fit (Free Volume)") == 0) {
-        }
-      }*/
-
-      private void sortingComboBox_SelectedIndexChanged(object sender, EventArgs e) {
-        if (Content == null) return;
-        deltaLabel.Visible = false;
-        deltaTextBox.Visible = false;
-        var items = new ItemList<PackingItem>(Content.Items);
-
-         if (sortingComboBox.SelectedItem.ToString().CompareTo("Volume-Height") == 0) {
-           var sortedItems = new ItemList<PackingItem>(items.OrderByDescending(x => x.Depth * x.Width * x.Height).ThenByDescending(x => x.Height));
-           Content.Items = sortedItems.AsReadOnly();
-          }
-          else if (sortingComboBox.SelectedItem.ToString().CompareTo("Height-Volume") == 0) {
-            var sortedItems = new ItemList<PackingItem>(items.OrderByDescending(x => x.Height).ThenByDescending(x => x.Depth * x.Width * x.Height));
-            Content.Items = sortedItems.AsReadOnly();
-          }
-          else if (sortingComboBox.SelectedItem.ToString().CompareTo("Area-Height") == 0) {
-            var sortedItems = new ItemList<PackingItem>(items.OrderByDescending(x => x.Depth * x.Width).ThenByDescending(x => x.Height));
-            Content.Items = sortedItems.AsReadOnly();
-          }
-          else if (sortingComboBox.SelectedItem.ToString().CompareTo("Height-Area") == 0) {
-            var sortedItems = new ItemList<PackingItem>(items.OrderByDescending(x => x.Height).ThenByDescending(x => x.Depth * x.Width));
-            Content.Items = sortedItems.AsReadOnly();
-          }
-          else if (sortingComboBox.SelectedItem.ToString().CompareTo("Clustered Area-Height") == 0) {
-            deltaLabel.Visible = true;
-            deltaTextBox.Visible = true;
-            deltaTextBox.Clear();
-          }
-          else if (sortingComboBox.SelectedItem.ToString().CompareTo("Clustered Height-Area") == 0) {
-            deltaLabel.Visible = true;
-            deltaTextBox.Visible = true;
-            deltaTextBox.Clear();
-          }
-        }
-
-        private void deltaTextBox_TextChanged(object sender, EventArgs e) {
-          Dictionary<int, ItemList<PackingItem>> clusters = new Dictionary<int, ItemList<PackingItem>>();
-          var items = new ItemList<PackingItem>(Content.Items);
-
-          if (deltaTextBox.Text.Length > 0) {
-           int delta = Convert.ToInt32(deltaTextBox.Text);
-           
-           if (sortingComboBox.SelectedItem.ToString().CompareTo("Clustered Area-Height") == 0) {
-             // Cluster packing items with respect to area = width * depth
-             for (int i = 0; i < items.Count; i++) {
-               double clusterRange = items[i].TargetBin.Width * items[i].TargetBin.Depth * delta / 100.0;
-               int clusterId = (int)(Math.Ceiling(items[i].Width * items[i].Depth / clusterRange));
-
-               if (clusters.ContainsKey(clusterId)) clusters[clusterId].Add(items[i]);
-               else clusters.Add(clusterId, new ItemList<PackingItem> {items[i]});
-              }           
-
-              // Sort packing items inside the cluster where they belong with respect to height 
-              foreach (KeyValuePair<int, ItemList<PackingItem>> entry in clusters) {
-                clusters[entry.Key].OrderByDescending(x => x.Height);
-              }
-            }
-
-            else if (sortingComboBox.SelectedItem.ToString().CompareTo("Clustered Height-Area") == 0) {
-              // Cluster packing items with respect to height
-              for (int i = 0; i < items.Count; i++) {
-                double clusterRange = items[i].TargetBin.Height * delta / 100.0;
-                int clusterId = Convert.ToInt32(Math.Ceiling(items[i].Height / clusterRange));
-
-                if (clusters.ContainsKey(clusterId)) clusters[clusterId].Add(items[i]);
-                else clusters.Add(clusterId, new ItemList<PackingItem> {items[i]});
-              }           
-
-              // Sort packing items inside the cluster where they belong with respect to area = width * depth 
-              foreach (KeyValuePair<int, ItemList<PackingItem>> entry in clusters) {
-                  clusters[entry.Key].OrderByDescending(x => x.Width * x.Depth);
-              }
-            }
-            
-            // Insert all packing items into a single list 
-            var sortedItems = new ItemList<PackingItem>(clusters.OrderByDescending(x => x.Key).SelectMany(x => x.Value));
-            Content.Items = sortedItems.AsReadOnly();
-        }
-      }
-    }
-  }
Index: anches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/BinPacking3DProblemView.resx
===================================================================
--- /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/BinPacking3DProblemView.resx	(revision 15173)
+++ 	(revision )
@@ -1,129 +1,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>17, 17</value>
-  </metadata>
-  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>17, 17</value>
-  </metadata>
-  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>140, 17</value>
-  </metadata>
-</root>
Index: /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/HeuristicLab.Problems.BinPacking.Views-3.3.csproj
===================================================================
--- /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/HeuristicLab.Problems.BinPacking.Views-3.3.csproj	(revision 15173)
+++ /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking.Views/3.3/HeuristicLab.Problems.BinPacking.Views-3.3.csproj	(revision 15174)
@@ -139,10 +139,4 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="BinPacking3DProblemView.cs">
-      <SubType>UserControl</SubType>
-    </Compile>
-    <Compile Include="BinPacking3DProblemView.Designer.cs">
-      <DependentUpon>BinPacking3DProblemView.cs</DependentUpon>
-    </Compile>
     <Compile Include="Container3DView.xaml.cs">
       <DependentUpon>Container3DView.xaml</DependentUpon>
@@ -170,7 +164,4 @@
   </ItemGroup>
   <ItemGroup>
-    <EmbeddedResource Include="BinPacking3DProblemView.resx">
-      <DependentUpon>BinPacking3DProblemView.cs</DependentUpon>
-    </EmbeddedResource>
     <EmbeddedResource Include="PackingPlan2DView.resx">
       <DependentUpon>PackingPlan2DView.cs</DependentUpon>
Index: /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking/3.3/Algorithms/3D/ExtremePointAlgorithm.cs
===================================================================
--- /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking/3.3/Algorithms/3D/ExtremePointAlgorithm.cs	(revision 15174)
+++ /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking/3.3/Algorithms/3D/ExtremePointAlgorithm.cs	(revision 15174)
@@ -0,0 +1,230 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Joseph Helm and 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.BinPacking3D {
+  
+  public enum SortingMethod { All, Given, VolumeHeight, HeightVolume, AreaHeight, HeightArea, ClusteredAreaHeight, ClusteredHeightArea }
+  public enum FittingMethod { All, FirstFit, ResidualSpaceBestFit, FreeVolumeBestFit }
+
+  [Item("Extreme-point Packing (3D)", "An implementation of the extreme-point based packing described in Crainic, T. G., Perboli, G., & Tadei, R. (2008). Extreme point-based heuristics for three-dimensional bin packing. Informs Journal on computing, 20(3), 368-384.")]
+  [StorableClass]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public class ExtremePointAlgorithm : BasicAlgorithm {
+
+    public override Type ProblemType {
+      get { return typeof(PermutationProblem); }
+    }
+
+    public new PermutationProblem Problem {
+      get { return (PermutationProblem)base.Problem; }
+      set { base.Problem = value; }
+    }
+
+    public override bool SupportsPause {
+      get { return false; }
+    }
+
+    [Storable]
+    private IValueParameter<EnumValue<SortingMethod>> sortingMethodParameter;
+    public IValueParameter<EnumValue<SortingMethod>> SortingMethodParameter {
+      get { return sortingMethodParameter; }
+    }
+
+    [Storable]
+    private IValueParameter<EnumValue<FittingMethod>> fittingMethodParameter;
+    public IValueParameter<EnumValue<FittingMethod>> FittingMethodParameter {
+      get { return fittingMethodParameter; }
+    }
+
+    [Storable]
+    private IValueParameter<PercentValue> deltaParameter;
+    public IValueParameter<PercentValue> DeltaParameter {
+      get { return deltaParameter; }
+    }
+
+    [StorableConstructor]
+    protected ExtremePointAlgorithm(bool deserializing) : base(deserializing) { }
+    protected ExtremePointAlgorithm(ExtremePointAlgorithm original, Cloner cloner)
+      : base(original, cloner) {
+      sortingMethodParameter = cloner.Clone(original.sortingMethodParameter);
+      fittingMethodParameter = cloner.Clone(original.fittingMethodParameter);
+      deltaParameter = cloner.Clone(original.deltaParameter);
+    }
+    public ExtremePointAlgorithm() {
+      Parameters.Add(sortingMethodParameter = new ValueParameter<EnumValue<SortingMethod>>("SortingMethod", "In which order the items should be packed.", new EnumValue<SortingMethod>(SortingMethod.All)));
+      Parameters.Add(fittingMethodParameter = new ValueParameter<EnumValue<FittingMethod>>("FittingMethod", "Which method to fit should be used.", new EnumValue<FittingMethod>(FittingMethod.All)));
+      Parameters.Add(deltaParameter = new ValueParameter<PercentValue>("Delta", "[1;100]% Clustered sorting methods use a delta parameter to determine the clusters.", new PercentValue(.1)));
+      
+      Problem = new PermutationProblem();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExtremePointAlgorithm(this, cloner);
+    }
+    
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    protected override void Run(CancellationToken token) {
+      var items = Problem.Items;
+      var bin = Problem.BinShape;
+      var sorting = new[] { SortingMethodParameter.Value.Value };
+      if (sorting[0] == SortingMethod.All) {
+        sorting = Enum.GetValues(typeof(SortingMethod)).Cast<SortingMethod>().Where(x => x != SortingMethod.All).ToArray();
+      }
+      var fitting = new[] { fittingMethodParameter.Value.Value };
+      if (fitting[0] == FittingMethod.All) {
+        fitting = Enum.GetValues(typeof(FittingMethod)).Cast<FittingMethod>().Where(x => x != FittingMethod.All).ToArray();
+      }
+      var result = GetBest(bin, items, sorting, fitting, token);
+      if (result == null) throw new InvalidOperationException("No result obtained!");
+
+      Results.Add(new Result("Best Solution", result.Item1));
+      Results.Add(new Result("Best Solution Quality", new DoubleValue(result.Item2)));
+
+      var binUtil = new BinUtilizationEvaluator();
+      var packRatio = new PackingRatioEvaluator();
+      Results.Add(new Result("Best Solution BinCount", new IntValue(result.Item1.NrOfBins)));
+      Results.Add(new Result("Best Solution Bin Utilization", new PercentValue(Math.Round(binUtil.Evaluate(result.Item1), 2))));
+      Results.Add(new Result("Best Solution Packing Ratio", new PercentValue(Math.Round(packRatio.Evaluate(result.Item1), 2))));
+
+      if (result.Item3.HasValue && sorting.Length > 1)
+        Results.Add(new Result("Best Sorting Method", new EnumValue<SortingMethod>(result.Item3.Value)));
+      if (result.Item4.HasValue && fitting.Length > 1)
+        Results.Add(new Result("Best Fitting Method", new EnumValue<FittingMethod>(result.Item4.Value)));
+    }
+
+    private Tuple<Solution, double, SortingMethod?, FittingMethod?> GetBest(PackingShape bin, IList<PackingItem> items, SortingMethod[] sortings, FittingMethod[] fittings, CancellationToken token) {
+      SortingMethod? bestSorting = null;
+      FittingMethod? bestFitting = null;
+      var best = double.NaN;
+      Solution bestSolution = null;
+      foreach (var fit in fittings) {
+        foreach (var sort in sortings) {
+          var result = Optimize(bin, items, sort, fit, DeltaParameter.Value.Value, Problem.UseStackingConstraints, Problem.SolutionEvaluator, token);
+          if (double.IsNaN(result.Item2) || double.IsInfinity(result.Item2)) continue;
+          if (double.IsNaN(best)
+            || Problem.Maximization && result.Item2 > best
+            || !Problem.Maximization && result.Item2 < best) {
+            bestSolution = result.Item1;
+            best = result.Item2;
+            bestSorting = sort;
+            bestFitting = fit;
+          }
+          if (token.IsCancellationRequested) return Tuple.Create(bestSolution, best, bestSorting, bestFitting);
+        }
+      }
+      if (double.IsNaN(best)) return null;
+      return Tuple.Create(bestSolution, best, bestSorting, bestFitting);
+    }
+
+    private static Tuple<Solution, double> Optimize(PackingShape bin, IList<PackingItem> items, SortingMethod sorting, FittingMethod fitting, double delta, bool stackingConstraints, IEvaluator evaluator, CancellationToken token) {
+      Permutation sorted = null;
+      switch (sorting) {
+        case SortingMethod.Given:
+          sorted = new Permutation(PermutationTypes.Absolute, Enumerable.Range(0, items.Count).ToArray());
+          break;
+        case SortingMethod.VolumeHeight:
+          sorted = new Permutation(PermutationTypes.Absolute,
+                    items.Select((v, i) => new { Index = i, Item = v })
+                         .OrderByDescending(x => x.Item.Depth * x.Item.Width * x.Item.Height)
+                         .ThenByDescending(x => x.Item.Height)
+                         .Select(x => x.Index).ToArray());
+          break;
+        case SortingMethod.HeightVolume:
+          sorted = new Permutation(PermutationTypes.Absolute,
+                    items.Select((v, i) => new { Index = i, Item = v })
+                         .OrderByDescending(x => x.Item.Height)
+                         .ThenByDescending(x => x.Item.Depth * x.Item.Width * x.Item.Height)
+                         .Select(x => x.Index).ToArray());
+          break;
+        case SortingMethod.AreaHeight:
+          sorted = new Permutation(PermutationTypes.Absolute,
+                    items.Select((v, i) => new { Index = i, Item = v })
+                         .OrderByDescending(x => x.Item.Depth * x.Item.Width)
+                         .ThenByDescending(x => x.Item.Height)
+                         .Select(x => x.Index).ToArray());
+          break;
+        case SortingMethod.HeightArea:
+          sorted = new Permutation(PermutationTypes.Absolute,
+                    items.Select((v, i) => new { Index = i, Item = v })
+                         .OrderByDescending(x => x.Item.Height)
+                         .ThenByDescending(x => x.Item.Depth * x.Item.Width)
+                         .Select(x => x.Index).ToArray());
+          break;
+        case SortingMethod.ClusteredAreaHeight:
+          double clusterRange = bin.Width * bin.Depth * delta;
+          sorted = new Permutation(PermutationTypes.Absolute,
+                    items.Select((v, i) => new { Index = i, Item = v, ClusterId = (int)(Math.Ceiling(v.Width * v.Depth / clusterRange)) })
+                        .GroupBy(x => x.ClusterId)
+                        .Select(x => new { Cluster = x.Key, Items = x.OrderByDescending(y => y.Item.Height).ToList() })
+                        .OrderByDescending(x => x.Cluster)
+                        .SelectMany(x => x.Items)
+                        .Select(x => x.Index).ToArray());
+          break;
+        case SortingMethod.ClusteredHeightArea:
+          double clusterRange2 = bin.Height * delta;
+          sorted = new Permutation(PermutationTypes.Absolute,
+                    items.Select((v, i) => new { Index = i, Item = v, ClusterId = (int)(Math.Ceiling(v.Height / clusterRange2)) })
+                        .GroupBy(x => x.ClusterId)
+                        .Select(x => new { Cluster = x.Key, Items = x.OrderByDescending(y => y.Item.Depth * y.Item.Width).ToList() })
+                        .OrderByDescending(x => x.Cluster)
+                        .SelectMany(x => x.Items)
+                        .Select(x => x.Index).ToArray());
+          break;
+        default: throw new ArgumentException("Unknown sorting method: " + sorting);
+      }
+      
+      ExtremePointPermutationDecoderBase decoder = null;
+      switch (fitting) {
+        case FittingMethod.FirstFit:
+          decoder = new ExtremePointPermutationDecoder();
+          break;
+        case FittingMethod.FreeVolumeBestFit:
+          decoder = new FreeVolumeBestFitExtremePointPermutationDecoder();
+          break;
+        case FittingMethod.ResidualSpaceBestFit:
+          decoder = new ResidualSpaceBestFitExtremePointPermutationDecoder();
+          break;
+        default: throw new ArgumentException("Unknown fitting method: " + fitting);
+      }
+
+      var sol = decoder.Decode(sorted, bin, items, stackingConstraints);
+      var fit = evaluator.Evaluate(sol);
+
+      return Tuple.Create(sol, fit);
+    }
+  }
+}
Index: /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking/3.3/HeuristicLab.Problems.BinPacking-3.3.csproj
===================================================================
--- /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking/3.3/HeuristicLab.Problems.BinPacking-3.3.csproj	(revision 15173)
+++ /branches/BinPackingExtension/HeuristicLab.Problems.BinPacking/3.3/HeuristicLab.Problems.BinPacking-3.3.csproj	(revision 15174)
@@ -158,4 +158,5 @@
     <Compile Include="3D\Evaluators\BinUtilizationEvaluator.cs" />
     <Compile Include="3D\Evaluators\PackingRatioEvaluator.cs" />
+    <Compile Include="Algorithms\3D\ExtremePointAlgorithm.cs" />
     <Compile Include="3D\Instances\ThreeDInstanceDescriptor.cs" />
     <Compile Include="3D\Instances\BPPData.cs" />
