diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java
index b11761b08dea8c7b55fe7a5baedff09ecaed1fd4..022861ed796af59bdf5d128b0b3d823f846c6178 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java
@@ -284,9 +284,11 @@ public class IcpTransformer extends MeshVisitor   {
             transformation = computeIcpTransformation(nearestPoints, distances, reducedFacet.getVertices());
             transformations.get(transformedFacet).add(transformation);
             applyTransformation(transformedFacet, transformation);
-            if (!samplingStrategy.isBackedByOrigMesh()) { // transform samples as well
+            
+            if (!samplingStrategy.isBackedByOrigMesh()) { // samples have to be transfomed as well
                 applyTransformation(reducedFacet, transformation);
             }
+            
             currentIteration ++;
         }
     }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/NoSampling.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/NoSampling.java
index e248620eab2ae7181cbbcb575dc76ed18d02cd1c..45e399b3e3697d68e11b48244dd203596b231179 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/NoSampling.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/NoSampling.java
@@ -29,7 +29,7 @@ public class NoSampling extends PointSampling {
     
     @Override
     public String toString() {
-        return "none";
+        return "no downsampling = " + this.getNumDownsampledPoints(allVertices.size()) + " real points";
     }
 
     
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/PointSampling.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/PointSampling.java
index 8199fc634fb87023a56047fbe878299ede1a84ec..12202b757e2b2eef05e13e772aa2eaa94a28a89d 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/PointSampling.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/PointSampling.java
@@ -32,8 +32,8 @@ public abstract class PointSampling extends MeshVisitor {
      * Constructor for no point sampling.
      */
     public PointSampling() {
-        this.samplingType = null;
-        this.samplingLimit = 0.0;
+        this.samplingType = PointSamplingType.PERCENTAGE;
+        this.samplingLimit = 1.0;
     }
     
     /**
@@ -70,7 +70,7 @@ public abstract class PointSampling extends MeshVisitor {
     /**
      * If {@code true}, then the returned points samples are points
      * from the original mesh. Therefore, any change changes the original mesh!
-     * If {@code}, then new points are returned.
+     * If {@code false}, then new points are returned that are independent on the original mesh.
      * 
      * @return {@code true} if the point samples include points of the original mesh
      */
@@ -78,6 +78,21 @@ public abstract class PointSampling extends MeshVisitor {
         return true;
     }
     
+    /**
+     * If {@code true}, then the returned points samples are stored a space-ordering
+     * structure. Therefore, their 3D transformation requires to re-arrange the
+     * ordering structure (i.e., to reg-generate samples by calling {@link #getSamples()}
+     * again.
+     * 
+     * from the original mesh. Therefore, any change changes the original mesh!
+     * If {@code}, then new points are returned.
+     * 
+     * @return {@code true} if the point samples include points of the original mesh
+     */
+    public boolean usesSpaceOrdering() {
+        return false;
+    }
+    
     /**
      * Changes the number of required samples.
      * 
@@ -107,9 +122,9 @@ public abstract class PointSampling extends MeshVisitor {
     @Override
     public String toString() {
         if (this.samplingType == PointSamplingType.PERCENTAGE) {
-            return "sampling to " + (int) (samplingLimit * 100) + "%";
+            return "downsampling to " + (int) (samplingLimit * 100) + "%";
         } else {
-            return "sampling of " + (int) samplingLimit + " points";
+            return "downsampling to " + (int) samplingLimit + " points";
         }
     }
     
@@ -132,4 +147,11 @@ public abstract class PointSampling extends MeshVisitor {
         }
     }
     
+    protected PointSamplingType getSamplingType() {
+        return this.samplingType;
+    }
+    
+    protected double getSamplingLimit() {
+        return this.samplingLimit;
+    }
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/RandomSampling.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/RandomSampling.java
index 67d75c4455ca59f021f614d6ae91fcb5841fb4dc..31ccf49a0d5b99b0a36f1558b7ed93e36d2900d4 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/RandomSampling.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/RandomSampling.java
@@ -97,7 +97,7 @@ public class RandomSampling extends PointSampling {
 
     @Override
     public String toString() {
-        return "random " + super.toString();
+        return "random " + super.toString() + ". Current state: " + this.getNumDownsampledPoints(allVertices.size()) + " samples";
     }
 
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSpaceSampling.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSpaceSampling.java
index 95facf9c2689580bbdda6d27d8376dd4891ff598..c4cbcfd464166789518b75578f04114cfd6a4b79 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSpaceSampling.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSpaceSampling.java
@@ -6,7 +6,6 @@ import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 import javax.vecmath.Point3d;
@@ -60,6 +59,11 @@ public class UniformSpaceSampling extends PointSampling {
     public boolean isBackedByOrigMesh() {
         return false;
     }
+    
+    @Override
+    public boolean usesSpaceOrdering() {
+        return true;
+    }
      
     @Override
     public void visitMeshFacet(MeshFacet facet) {
@@ -70,18 +74,54 @@ public class UniformSpaceSampling extends PointSampling {
     
     @Override
     public List<MeshPoint> getSamples() {
-        int numReducedVertices = getNumDownsampledPoints(allVertices.size());
-        if (allVertices.size() == numReducedVertices) {
-            return Collections.unmodifiableList(allVertices);
+        // no downsampling:
+        if (allVertices.size() == getNumDownsampledPoints(allVertices.size())) { 
+            // this sampling method is NOT backed by the original mesh. Therefore, meke a copy.
+            return allVertices.stream()
+                    .map(p -> new MeshPointImpl(p))                    
+                    .collect(Collectors.toList());
         }
         
-        MeshPoint centroid = new MeshPointImpl(allVertices);
-        double avgDist = getAvgDist(allVertices, centroid.getPosition());
-        
+        // compute controid of cell's points:
+        return createGrid().getNonEmptyCells().stream()
+                .map(list -> new MeshPointImpl(list)) 
+                .collect(Collectors.toList());
+    }
+    
+    @Override
+    public String toString() {
+        return "uniform space " + super.toString();
+    }
+    
+    protected List<MeshPoint> getOrigPoints() {
+        return this.allVertices;
+    }
+    
+    /**
+     * Computes the average distance between vertices and their centroid.
+     * 
+     * @param vertices vertices
+     * @param centroid their centroid
+     * @return the average distance between vertices and their centroid.
+     */
+    protected double getAvgDist(Collection<MeshPoint> vertices, Point3d centroid) {
+        return vertices.stream()
+                .map(p -> p.getPosition())
+                .mapToDouble(p -> centroid.distance(p))
+                .average()
+                .orElse(0);
+    }
+    
+    protected UniformGrid3d<MeshPoint> createGrid() {
+        int numReducedVertices = getNumDownsampledPoints(allVertices.size());
         double k = CELL_RESIZE_INIT_VALUE;
         double step = CELL_RESIZE_INIT_STEP;
         int numCells = 0;
         UniformGrid3d<MeshPoint> grid;
+        
+        MeshPoint centroid = new MeshPointImpl(allVertices);
+        double avgDist = getAvgDist(allVertices, centroid.getPosition());
+        
         int counter = 0;
         do {
             double cellSize = avgDist / k;
@@ -100,28 +140,6 @@ public class UniformSpaceSampling extends PointSampling {
             k += step;
         } while (numCells < numReducedVertices || numCells > numReducedVertices + DOWNSAMPLING_TOLERANCE);
         
-        return grid.getNonEmptyCells().stream()
-                        .map(list -> new MeshPointImpl(list)) // compute controid of cell's points
-                        .collect(Collectors.toList());
-    }
-    
-    @Override
-    public String toString() {
-        return "uniform space " + super.toString();
-    }
-    
-    /**
-     * Computes the average distance between vertices and their centroid.
-     * 
-     * @param vertices vertices
-     * @param centroid their centroid
-     * @return the average distance between vertices and their centroid.
-     */
-    protected double getAvgDist(Collection<MeshPoint> vertices, Point3d centroid) {
-        return vertices.stream()
-                .map(p -> p.getPosition())
-                .mapToDouble(p -> centroid.distance(p))
-                .average()
-                .orElse(0);
+        return grid;
     }
 }
\ No newline at end of file
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSurfaceSampling.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSurfaceSampling.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae87803083413a907fa3bdcc03c1307b781c7427
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/sampling/UniformSurfaceSampling.java
@@ -0,0 +1,72 @@
+package cz.fidentis.analyst.visitors.mesh.sampling;
+
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+/**
+ * Similar downsampling strategy to the {@link UniformSpaceSampling}.
+ * However, a random vertex from the mesh is selected from each non-empty cell instead 
+ * of computing a new average point. Therefore, the samples lie on the mesh surface.
+ * 
+ * @author Radek Oslejsek
+ */
+public class UniformSurfaceSampling extends UniformSpaceSampling {
+    
+    /** 
+     * Constructor for no point sampling (100 %).
+     */
+    public UniformSurfaceSampling() {
+        this(1.0);
+    }
+    
+    /**
+     * Constructor for PERCENTAGE point sampling type.
+     * 
+     * @param perc Percentage - a value in (0.0, 1.0&gt;
+     * @throws IllegalArgumentException if the input parameter is wrong
+     */
+    public UniformSurfaceSampling(double perc) {
+        super(perc);
+    }
+    
+    /**
+     * Constructor for MAX_VERTICES point sampling type.
+     * 
+     * @param max Required number of samples. Must be bigger than zero
+     * @throws IllegalArgumentException if the input parameter is wrong
+     */
+    public UniformSurfaceSampling(int max) {
+        super(max);
+    }
+    
+    @Override
+    public boolean isBackedByOrigMesh() {
+        return true;
+    }
+    
+    @Override
+    public List<MeshPoint> getSamples() {
+         // no downsampling:
+        if (getOrigPoints().size() == getNumDownsampledPoints(getOrigPoints().size())) {
+            return Collections.unmodifiableList(getOrigPoints());
+        }
+        
+        // Get a random vertex of the cell:
+        Random rand = new Random();
+        return createGrid().getNonEmptyCells().stream()
+                .map(list -> list.get(rand.nextInt(list.size()))) 
+                .collect(Collectors.toList());
+    }
+    
+    @Override
+    public String toString() {
+        if (getSamplingType() == PointSamplingType.PERCENTAGE) {
+            return "uniform surface downsampling to " + (int) (getSamplingLimit() * 100) + "%";
+        } else {
+            return "uniform surface downsampling to " + (int) getSamplingLimit() + " points";
+        }
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java
index a7d3211c6e2a1e25c4e9f79b718a1a87f492da74..2358895bf7f0abd6682d483496cc1bc452776dba 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java
@@ -119,7 +119,7 @@ public class BatchAction extends ControlPanelAction implements HumanFaceListener
         HumanFace selectedFace = controlPanel.getSelectedFace();
         if (controlPanel.showIcpPreview() && selectedFace != null) {
             getScene().clearScene(); // scene is recovered automatically - see the event handler above
-            faceSceneSlot = getScene().getFreeSlot();
+            faceSceneSlot = getScene().getFreeSlotForFace();
             
             // Add inital face to the scene:
             getScene().setDrawableFace(faceSceneSlot, selectedFace);
@@ -168,7 +168,7 @@ public class BatchAction extends ControlPanelAction implements HumanFaceListener
         HumanFace face = controlPanel.getSelectedFace();
         if (face != null) {
             if (faceSceneSlot == -1) {
-                faceSceneSlot = getScene().getFreeSlot();
+                faceSceneSlot = getScene().getFreeSlotForFace();
             }
             getScene().setDrawableFace(faceSceneSlot, face); 
             getScene().setFaceAsPrimary(faceSceneSlot);
diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.form b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.form
index a3f2757eb1431749c6705183e983d9c8032c80f1..d6d0cdf5811b8538298e929b37404865e8d52675 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.form
+++ b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.form
@@ -80,7 +80,7 @@
                       </Group>
                       <Component id="jCheckBox4" alignment="0" min="-2" max="-2" attributes="0"/>
                   </Group>
-                  <EmptySpace pref="96" max="32767" attributes="0"/>
+                  <EmptySpace max="32767" attributes="0"/>
               </Group>
           </Group>
         </DimensionLayout>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java
index 37fd2e6e1360d037e6e47ad386834cd5b24794c3..be2eaeb35119355b61a7672e6378c8a53a642fd5 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java
@@ -45,12 +45,6 @@ public class BatchPanel extends ControlPanel {
     private final HumanFaceFactory factory = new HumanFaceFactory();
     private boolean haveAvgFace = false;
     
-    /**
-     * ICP undersampling. 100 = none
-     */
-    private int undersampling = 100;
-    
-
     /**
      * Constructor.
      * @param action Action listener
@@ -72,10 +66,7 @@ public class BatchPanel extends ControlPanel {
         
         jButton1.addActionListener(createListener(action, ACTION_COMMAND_COMPUTE_ICP));
         
-        spinSlider1.initPercentage(this.undersampling);
-        spinSlider1.addSpinnerListener((ActionEvent ae) -> { // update slider when the input field changed
-            this.undersampling = (Integer) spinSlider1.getValue();
-        });
+        spinSlider1.initInteger(2000, 0, 5000, 1);
         
         jComboBox2.addItem(SIMILARITY_APPROX_HD);
         jComboBox2.addItem(SIMILARITY_COMPLETE_HD);
@@ -202,11 +193,11 @@ public class BatchPanel extends ControlPanel {
     }
     
     /**
-     * Returns ICP undersampling parameter
-     * @return ICP undersampling parameter
+     * Returns the number of desired points, 0 for no downsampling
+     * @return the number of desired points, 0 for no downsampling
      */
     public int getIcpUndersampling() {
-        return undersampling;
+        return (int) spinSlider1.getValue();
     }
     
     /**
@@ -395,7 +386,7 @@ public class BatchPanel extends ControlPanel {
                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                         .addComponent(spinSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                     .addComponent(jCheckBox4))
-                .addContainerGap(96, Short.MAX_VALUE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
         );
         jPanel1Layout.setVerticalGroup(
             jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java b/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java
index f62bf7e5f15183b1515a78423f14592b708ad4b6..67d6cf51a44497be34a84d5e271cee51043c6fb9 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java
@@ -10,6 +10,8 @@ import cz.fidentis.analyst.mesh.core.MeshModel;
 import cz.fidentis.analyst.mesh.io.MeshObjExporter;
 import cz.fidentis.analyst.scene.DrawableFace;
 import cz.fidentis.analyst.visitors.kdtree.AvgFaceConstructor;
+import cz.fidentis.analyst.visitors.mesh.sampling.NoSampling;
+import cz.fidentis.analyst.visitors.mesh.sampling.PointSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.RandomSampling;
 import java.io.File;
 import java.io.IOException;
@@ -114,6 +116,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> {
                     //////////////////////
                     */
                     
+                    PointSampling sampling = (undersampling == 0)? new NoSampling() : new RandomSampling(undersampling);
                     icpComputationTime.start();
                     HumanFaceUtils.alignMeshes(
                             initFace,
@@ -121,10 +124,11 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> {
                             100,  // max iterations
                             controlPanel.scaleIcp(),
                             0.3,  // error
-                            new RandomSampling(undersampling),
+                            sampling,
                             false // drop k-d tree, if exists
                     );
                     icpComputationTime.stop();
+                    System.out.println(sampling);
                 }
                 
                 if (computeAvgFace) { // AVG template face
@@ -184,7 +188,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> {
             }
             if (controlPanel.showIcpPreview()) {
                 if (faceSceneSlot == -1) {
-                    faceSceneSlot = canvas.getScene().getFreeSlot();
+                    faceSceneSlot = canvas.getScene().getFreeSlotForFace();
                 }
                 canvas.getScene().setDrawableFace(faceSceneSlot, f);
                 canvas.getScene().getDrawableFace(faceSceneSlot).setTransparency(0.5f);
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
index 053f750f4a12ea28922e26108cad818f32054828..5f03fde1027eb03b669b85464e807456b72fbf39 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
@@ -89,7 +89,7 @@ public class Canvas extends JPanel implements HumanFaceListener {
     public int addPrimaryFace(HumanFace face) {
         if (face != null) {
             faces.add(face);
-            int index = scene.getFreeSlot();
+            int index = scene.getFreeSlotForFace();
             scene.setHumanFace(index, face);
             scene.setFaceAsPrimary(index);
             face.registerListener(this);
@@ -107,7 +107,7 @@ public class Canvas extends JPanel implements HumanFaceListener {
     public int addSecondaryFace(HumanFace face) {
         if (face != null) {
             faces.add(face);
-            int index = scene.getFreeSlot();
+            int index = scene.getFreeSlotForFace();
             scene.setHumanFace(index, face);
             scene.setFaceAsSecondary(index);
             face.registerListener(this);
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/toolbar/RenderingModeToolbox.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/toolbar/RenderingModeToolbox.java
index 8ae8cd93716df9c13839f5ba38561bafac378a42..83565e8278c9fe9cabc249a8c1e447d3ed68f44d 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/canvas/toolbar/RenderingModeToolbox.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/toolbar/RenderingModeToolbox.java
@@ -2,7 +2,6 @@ package cz.fidentis.analyst.canvas.toolbar;
 
 import com.jogamp.opengl.GL2;
 import cz.fidentis.analyst.canvas.Canvas;
-import cz.fidentis.analyst.scene.DrawableFace;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import javax.swing.AbstractAction;
@@ -64,68 +63,9 @@ public class RenderingModeToolbox extends JPopupMenu {
             }
         });
         
-        JMenuItem menuItem4 = new JMenuItem(new AbstractAction() { // Random sampling
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                canvas.getScene().getFaceSlots().forEach(i -> {
-                   canvas.getScene().getDrawableFace(i).setRenderMode(DrawableFace.RANDOM_SAMPLING);
-                });
-                canvas.renderScene();
-            }
-        });
-        
-        JMenuItem menuItem5 = new JMenuItem(new AbstractAction() { // Curvature sampling
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                canvas.getScene().getFaceSlots().forEach(i -> {
-                   canvas.getScene().getDrawableFace(i).setRenderMode(DrawableFace.CURVATURE_SAMPLING_MIN);
-                });
-                canvas.renderScene();
-            }
-        });
-        
-        JMenuItem menuItem6 = new JMenuItem(new AbstractAction() { // Curvature sampling
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                canvas.getScene().getFaceSlots().forEach(i -> {
-                   canvas.getScene().getDrawableFace(i).setRenderMode(DrawableFace.CURVATURE_SAMPLING_MAX);
-                });
-                canvas.renderScene();
-            }
-        });
-        
-        JMenuItem menuItem7 = new JMenuItem(new AbstractAction() { // Curvature sampling
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                canvas.getScene().getFaceSlots().forEach(i -> {
-                   canvas.getScene().getDrawableFace(i).setRenderMode(DrawableFace.CURVATURE_SAMPLING_MEAN);
-                });
-                canvas.renderScene();
-            }
-        });
-        
-        JMenuItem menuItem8 = new JMenuItem(new AbstractAction() { // Curvature sampling
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                canvas.getScene().getFaceSlots().forEach(i -> {
-                   canvas.getScene().getDrawableFace(i).setRenderMode(DrawableFace.CURVATURE_SAMPLING_GAUSSIAN);
-                });
-                canvas.renderScene();
-            }
-        });
-        
         menuItem1.setIcon(new ImageIcon(getClass().getResource("/" + RenderingModeToolbox.SMOOT_BUTTON_ICON)));
         menuItem2.setIcon(new ImageIcon(getClass().getResource("/" + RenderingModeToolbox.WIREFRAME_BUTTON_ICON)));
         menuItem3.setIcon(new ImageIcon(getClass().getResource("/" + RenderingModeToolbox.POINTS_BUTTON_ICON)));
-        
-        menuItem1.setText("Shading");
-        menuItem2.setText("Wire-frame");
-        menuItem3.setText("Points Cloud");
-        menuItem4.setText("Random Sampling");
-        menuItem5.setText("Min. Curvature");
-        menuItem6.setText("Max. Curvature");
-        menuItem7.setText("Mean Curvature");
-        menuItem8.setText("Gaussian Curvature");
 
         menuItem1.setToolTipText(NbBundle.getMessage(RenderingModeToolbox.class, "RenderingModeToolbox.smooth.text"));
         menuItem2.setToolTipText(NbBundle.getMessage(RenderingModeToolbox.class, "RenderingModeToolbox.wireframe.text"));
@@ -134,14 +74,7 @@ public class RenderingModeToolbox extends JPopupMenu {
         add(menuItem1);
         add(menuItem2);
         add(menuItem3);
-        addSeparator();
-        add(menuItem4);
-        add(menuItem5);
-        add(menuItem6);
-        add(menuItem7);
-        add(menuItem8);
         
-        //setLayout(new GridLayout(1,0));        
-        setLayout(new GridLayout(0,1));        
+        setLayout(new GridLayout(1,0));
     }
 }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ProgressDialog.java b/GUI/src/main/java/cz/fidentis/analyst/core/ProgressDialog.java
index 746b897162797c0172aab63afaea1afbabe42c77..3ffcc1a6dfafebbada78eeb3a39afcaeacb47351 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/core/ProgressDialog.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ProgressDialog.java
@@ -107,7 +107,7 @@ public class ProgressDialog<T,V> extends JDialog {
         setSize(450, 100);
         
         cancelButton.addActionListener((ActionEvent e) -> {
-            System.out.println("ZZZ " + task.cancel(true));
+            task.cancel(true);
             dispose();
         });
     }    
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalComboBoxListener.java b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalComboBoxListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee4e42c5a269d57bff9fe99640896126bdd86949
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalComboBoxListener.java
@@ -0,0 +1,38 @@
+package cz.fidentis.analyst.core.combobox;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * A listener responsible for selecting an enabled combo box item 
+ * when a disabled item is selected.
+ * 
+ * @author Radek Oslejsek
+ */
+public class ConditionalComboBoxListener implements ActionListener {
+
+    private final SelectableComboBox combobox;
+    private Object oldItem;
+
+    /**
+     * Constructor.
+     * 
+     * @param combobox A selectable combo box.
+     */
+    public ConditionalComboBoxListener(SelectableComboBox combobox) {
+        this.combobox = combobox;
+        combobox.setSelectedIndex(combobox.firstTrueItem());
+        oldItem = combobox.getSelectedItem();
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        Object selectedItem = combobox.getSelectedItem();
+        if (!((ConditionalItem) selectedItem).isEnabled()) {
+            combobox.setSelectedItem(oldItem);
+        } else {
+            oldItem = selectedItem;
+        }
+    }
+
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalComboBoxRenderer.java b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalComboBoxRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..dadb58826cce12a38676776145be5d1d702610b0
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalComboBoxRenderer.java
@@ -0,0 +1,44 @@
+package cz.fidentis.analyst.core.combobox;
+
+import java.awt.Color;
+import java.awt.Component;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+import javax.swing.border.EmptyBorder;
+import javax.swing.plaf.basic.BasicComboBoxRenderer;
+
+/**
+ * A combo box renderer adapted for displaying disabled items in gray color.
+ * 
+ * @author Radek Oslejsek
+ */
+public class ConditionalComboBoxRenderer extends BasicComboBoxRenderer implements ListCellRenderer<Object> {
+    
+    private static final Color DISABLED_COLOR = Color.LIGHT_GRAY;
+
+    @Override
+    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+        setBorder(new EmptyBorder(5,5,5,5));
+        
+        if (isSelected) {
+            setBackground(list.getSelectionBackground());
+            setForeground(list.getSelectionForeground());
+        } else {
+            setBackground(list.getBackground());
+            setForeground(list.getForeground());
+        }
+
+        try {
+            if (value != null && !((ConditionalItem) value).isEnabled()) {
+                setBackground(list.getBackground());
+                setForeground(DISABLED_COLOR);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            setFont(list.getFont());
+            setText((value == null) ? "" : value.toString());
+        }
+        return this;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalItem.java b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..cead4e4799ef149211d6fdadbdef701b3aa87348
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/ConditionalItem.java
@@ -0,0 +1,55 @@
+package cz.fidentis.analyst.core.combobox;
+
+/**
+ * A combo box item with "is enabled" state.
+ * 
+ * @author Radek Oslejsek
+ */
+public class ConditionalItem {
+
+    private Object object;
+    private boolean isEnabled;
+
+    /**
+     * Constructor.
+     * 
+     * @param object Item content
+     * @param isEnabled The state
+     */
+    public ConditionalItem(Object object, boolean isEnabled) {
+        this.object = object;
+        this.isEnabled = isEnabled;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param object Item content
+     */
+    public ConditionalItem(Object object) {
+        this(object, true);
+    }
+
+    /**
+     * Returns the state.
+     * 
+     * @return the state
+     */
+    public boolean isEnabled() {
+        return isEnabled;
+    }
+
+    /**
+     * Sets the state.
+     * 
+     * @param isEnabled Desired state.
+     */
+    public void setEnabled(boolean isEnabled) {
+        this.isEnabled = isEnabled;
+    }
+
+    @Override
+    public String toString() {
+        return object.toString();
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/combobox/SelectableComboBox.java b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/SelectableComboBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..2055d849c647f375063799448096c1dbe97361f3
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/combobox/SelectableComboBox.java
@@ -0,0 +1,107 @@
+package cz.fidentis.analyst.core.combobox;
+
+import java.awt.Component;
+import java.awt.event.ActionListener;
+import javax.swing.JComboBox;
+
+/**
+ * A combobox adapted to show enabled/disabled items.
+ * 
+ * @author Radek Oslejsek
+ */
+public class SelectableComboBox extends JComboBox<Object> {
+
+    private ActionListener listener;
+
+    /**
+     * Constructor.
+     */
+    public SelectableComboBox() {
+        this.setRenderer(new ConditionalComboBoxRenderer());
+        listener = new ConditionalComboBoxListener(this);
+        this.addActionListener(listener);
+    }
+
+    /**
+     * Adds an enabled item into the combo box
+     * 
+     * @param str Text of the item
+     */
+    public void addItem(String str) {
+        addItem(new ConditionalItem(str, true));
+    }
+
+    /**
+     * Adds an item into the combobox in either enabled or disabled state,
+     * 
+     * @param str Text of the item
+     * @param enabled The state 
+     */
+    public void addItem(String str, boolean enabled) {
+        addItem(new ConditionalItem(str, enabled));
+    }
+
+    /**
+     * Add an existing item into the combobox.
+     * 
+     * @param ci An existing item
+     */
+    public void addItem(Component ci) {
+        this.add(ci);
+        this.setRenderer(new ConditionalComboBoxRenderer());
+        this.addActionListener(new ConditionalComboBoxListener(this));
+    }
+
+    /**
+     * If the combobox contains {@code str}, sets its state to [@code bool}.
+     * If it's not yet an item, ignores it. The method also re-sets the selected item to the first
+     * one shown in the list as "true", and disables the listeners in this
+     * process to avoid firing an action when reorganizing the list.
+     * 
+     * @param str Text of the existing item
+     * @param enabled New state
+     */
+    public void setItem(String str, boolean enabled) {
+        int n = this.getItemCount();
+        for (int i = 0; i < n; i++) {
+            if (this.getItemAt(i).toString().equals(str)) {
+
+                this.removeActionListener(listener);
+                this.removeItemAt(i);
+                this.insertItemAt(new ConditionalItem(str, enabled), i);
+                int k = this.firstTrueItem();
+                if (k < 0) {
+                    k = 0; // default index 0 if no true item is shown as true
+                }
+                this.setSelectedIndex(k);
+                this.addActionListener(listener);
+
+                return;
+            }
+        }
+        System.err.println("Warning: item " + str + " is not a member of this combobox: ignoring it...");
+    }
+
+    protected Object[] getItems() {
+        int n = this.getItemCount();
+        Object[] obj = new Object[n];
+        for (int i = 0; i < n; i++) {
+            obj[i] = this.getItemAt(i);
+        }
+        return obj;
+    }
+
+    /**
+     * @return -1 if no item is true
+     */
+    protected int firstTrueItem() {
+        int i = 0;
+        for (Object obj : this.getItems()) {
+            if (((ConditionalItem) obj).isEnabled()) {
+                return i;
+            }
+            i++;
+        }
+        return -1;
+    }
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/Installer.java b/GUI/src/main/java/cz/fidentis/analyst/gui/Installer.java
index cb50c9a7a8baa92590d8d0f7d6f4d215d93d605e..6be0f44fba8d11ad22784701ae18b3aa8984d19a 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/gui/Installer.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/gui/Installer.java
@@ -32,8 +32,10 @@ public class Installer extends ModuleInstall {
     
     @Override
     public void restored() {
+        /*
         try {
             for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+                //System.out.println(info.getName());
                 if ("Nimbus".equals(info.getName())) {
                     javax.swing.UIManager.setLookAndFeel(info.getClassName());
                     break;
@@ -42,6 +44,7 @@ public class Installer extends ModuleInstall {
         } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
             java.util.logging.Logger.getLogger(Installer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         }
+        */
         java.awt.EventQueue.invokeLater(() -> {
             //old JFrame, disabled
             /*frameMain = new UserInterface();
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
index b0bace831f0823479e7429871cd04ecf236d0cff..b143d24c2a0b3822f1de3b3bf2a9c936bce14ca0 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
@@ -17,6 +17,7 @@ import cz.fidentis.analyst.visitors.mesh.sampling.NoSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.PointSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.RandomSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.UniformSpaceSampling;
+import cz.fidentis.analyst.visitors.mesh.sampling.UniformSurfaceSampling;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
 import javax.swing.JFormattedTextField;
@@ -106,12 +107,12 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
         getPrimaryDrawableFace().getHumanFace().registerListener(this);
         getSecondaryDrawableFace().getHumanFace().registerListener(this);
         
-        controlPanel.setEnabledPlanesButton(
+        controlPanel.setEnabledPlanes(
                 getCanvas().getPrimaryFace().hasSymmetryPlane() &&
                         getCanvas().getSecondaryFace().hasSymmetryPlane()
         );
         
-        controlPanel.setEnabledProcrustesButton(
+        controlPanel.setEnabledProcrustes(
                 getCanvas().getPrimaryFace().hasFeaturePoints() &&
                         getCanvas().getSecondaryFace().hasFeaturePoints()
         );
@@ -122,13 +123,23 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
         String action = ae.getActionCommand();
 
         switch (action) {
-            case RegistrationPanel.ACTION_COMMAND_APPLY_ICP:
-                applyICP();
+            case RegistrationPanel.ACTION_COMMAND_REGISTER:
+                String alg = controlPanel.getRegistrationAlgorihm();
+                if (RegistrationPanel.AUTO_ALIGNMENT_ALGORITHM[0].equals(alg)) { // ICP
+                    applyICP();
+                } else if (RegistrationPanel.AUTO_ALIGNMENT_ALGORITHM[1].equals(alg)) { // Procrustes
+                    applyProcrustes();
+                } else if (RegistrationPanel.AUTO_ALIGNMENT_ALGORITHM[2].equals(alg)) { // Symmetry
+                    alignSymmetryPlanes();
+                }
                 highlightCloseFeaturePoints();
-                getCanvas().getSecondaryFace().announceEvent(new HumanFaceTransformedEvent(
-                        getCanvas().getSecondaryFace(), "", this)
-                );
-                pointCloudSlot = drawPointSamples(getCanvas().getScene().getSecondaryFaceSlot(), pointCloudSlot, controlPanel.getIcpUndersamplingStrength());
+                if (RegistrationPanel.AUTO_ALIGNMENT_ALGORITHM[1].equals(alg)) { // Procrustes also transforms the primary face
+                    getCanvas().getPrimaryFace().announceEvent(new HumanFaceTransformedEvent(getCanvas().getPrimaryFace(), "", this));
+                }
+                getCanvas().getSecondaryFace().announceEvent(new HumanFaceTransformedEvent(getCanvas().getSecondaryFace(), "", this));
+                pointCloudSlot = drawPointSamples(getCanvas().getScene().getSecondaryFaceSlot(), 
+                        pointCloudSlot, controlPanel.getIcpUndersamplingStrength());
+                
                 break;
             case RegistrationPanel.ACTION_COMMAND_MANUAL_TRANSFORMATION_IN_PROGRESS:
                 HumanFaceUtils.transformFace(
@@ -153,25 +164,6 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
                 fpThreshold = ((Number) (((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                 highlightCloseFeaturePoints();
                 break;
-            case RegistrationPanel.ACTION_COMMAND_PROCRUSTES_APPLY:
-                applyProcrustes();
-                highlightCloseFeaturePoints();
-                getCanvas().getPrimaryFace().announceEvent(new HumanFaceTransformedEvent(
-                        getCanvas().getPrimaryFace(), "", this)
-                );
-                getCanvas().getSecondaryFace().announceEvent(new HumanFaceTransformedEvent(
-                        getCanvas().getSecondaryFace(), "", this)
-                );
-                pointCloudSlot = drawPointSamples(getCanvas().getScene().getSecondaryFaceSlot(), pointCloudSlot, controlPanel.getIcpUndersamplingStrength());
-                break;
-            case RegistrationPanel.ACTION_COMMAND_ALIGN_SYMMETRY_PLANES:
-                alignSymmetryPlanes();
-                highlightCloseFeaturePoints();
-                getCanvas().getSecondaryFace().announceEvent(new HumanFaceTransformedEvent(
-                        getCanvas().getSecondaryFace(), "", this)
-                );
-                pointCloudSlot = drawPointSamples(getCanvas().getScene().getSecondaryFaceSlot(), pointCloudSlot, controlPanel.getIcpUndersamplingStrength());
-                break;
             case RegistrationPanel.ACTION_COMMAND_POINT_SAMPLING_STRENGTH:
                 int numSamples = (Integer) ((SpinSlider) ae.getSource()).getValue();
                 pointCloudSlot = drawPointSamples(getCanvas().getScene().getSecondaryFaceSlot(), pointCloudSlot, numSamples);
@@ -201,7 +193,7 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
         }
         
         if (event instanceof SymmetryPlaneChangedEvent) {
-            controlPanel.setEnabledPlanesButton(
+            controlPanel.setEnabledPlanes(
                     getCanvas().getPrimaryFace().hasSymmetryPlane() &&
                             getCanvas().getSecondaryFace().hasSymmetryPlane()
             );
@@ -331,6 +323,8 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
             return new CurvatureSampling(CurvatureSampling.CurvatureAlg.MIN, strength);
         } else if (st.equals(RegistrationPanel.POINT_SAMPLING_STRATEGIES[6])) {
             return new UniformSpaceSampling(strength);
+        } else if (st.equals(RegistrationPanel.POINT_SAMPLING_STRATEGIES[7])) {
+            return new UniformSurfaceSampling(strength);
         } else {
             return null;
         }
@@ -348,14 +342,16 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
         
         if (sampling.getClass() == NoSampling.class) { // don't show
             if (cloudSlot != -1) {
-                getScene().setOtherDrawable(cloudSlot, null);
+                getScene().setOtherDrawable(cloudSlot, null); // hide existing points
             }
             return -1;
         } else {
-            if (cloudSlot == -1) {
-                cloudSlot = getCanvas().getScene().getFreeSlot();
+            synchronized (this) {
+                if (cloudSlot == -1) {
+                    cloudSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+                }
+                getScene().setOtherDrawable(cloudSlot, new DrawablePointCloud(sampling.getSamples()));
             }
-            getScene().setOtherDrawable(cloudSlot, new DrawablePointCloud(sampling.getSamples()));
             return cloudSlot;
         }
     }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form
index 87d48cc6d40d438ec318420751b14863223031bf..6bfe69798a65fee022d88c8d4464ced6b97c2531 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.form
@@ -931,18 +931,16 @@
                           </Group>
                       </Group>
                       <Group type="102" alignment="0" attributes="0">
-                          <Group type="103" groupAlignment="1" attributes="0">
+                          <Group type="103" groupAlignment="0" attributes="0">
                               <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
-                              <Group type="102" attributes="0">
+                              <Group type="102" alignment="0" attributes="0">
+                                  <Component id="selectableComboBox1" min="-2" max="-2" attributes="0"/>
+                                  <EmptySpace max="-2" attributes="0"/>
                                   <Component id="jButton1" min="-2" max="-2" attributes="0"/>
                                   <EmptySpace max="-2" attributes="0"/>
-                                  <Component id="jButton2" min="-2" max="-2" attributes="0"/>
+                                  <Component id="jButtonInfo1" min="-2" max="-2" attributes="0"/>
                               </Group>
                           </Group>
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="jButton3" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                          <Component id="jButtonInfo1" min="-2" max="-2" attributes="0"/>
                           <EmptySpace max="32767" attributes="0"/>
                       </Group>
                   </Group>
@@ -956,12 +954,11 @@
                   <Group type="103" groupAlignment="0" max="-2" attributes="0">
                       <Group type="103" groupAlignment="3" attributes="0">
                           <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
-                          <Component id="jButton2" alignment="3" min="-2" max="-2" attributes="0"/>
-                          <Component id="jButton3" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="selectableComboBox1" alignment="3" min="-2" max="-2" attributes="0"/>
                       </Group>
                       <Component id="jButtonInfo1" pref="0" max="32767" attributes="0"/>
                   </Group>
-                  <EmptySpace type="separate" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
                   <Group type="103" groupAlignment="0" attributes="0">
                       <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
                       <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
@@ -1060,32 +1057,6 @@
             <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
           </Events>
         </Component>
-        <Component class="javax.swing.JButton" name="jButton2">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Ubuntu" size="15" style="1"/>
-            </Property>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jButton2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jButton2.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-          <Events>
-            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/>
-          </Events>
-        </Component>
-        <Component class="javax.swing.JButton" name="jButton3">
-          <Properties>
-            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-              <Font name="Ubuntu" size="15" style="1"/>
-            </Property>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="cz/fidentis/analyst/registration/Bundle.properties" key="RegistrationPanel.jButton3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-        </Component>
         <Component class="javax.swing.JButton" name="jButtonInfo1">
           <Properties>
             <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
@@ -1132,6 +1103,8 @@
         </Component>
         <Component class="cz.fidentis.analyst.core.SpinSlider" name="spinSlider1">
         </Component>
+        <Component class="cz.fidentis.analyst.core.combobox.SelectableComboBox" name="selectableComboBox1">
+        </Component>
       </SubComponents>
     </Container>
     <Container class="javax.swing.JPanel" name="jPanel4">
diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
index e40d77b13ddddfb4eea3452b2be224de7a6d24bd..d019d3c7e526bb0042afb833af540fb00e11cfe4 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
@@ -27,22 +27,18 @@ public class RegistrationPanel extends ControlPanel {
     /*
      * External actions
      */
-    public static final String ACTION_COMMAND_APPLY_ICP = "apply ICP";
-    
     public static final String ACTION_COMMAND_MANUAL_TRANSFORMATION_FINISHED = "manual transformation";
     public static final String ACTION_COMMAND_MANUAL_TRANSFORMATION_IN_PROGRESS = "manual transformation in progress";
     
     public static final String ACTION_COMMAND_FP_CLOSENESS_THRESHOLD = "fp closeness treshold";
     
-    public static final String ACTION_COMMAND_PROCRUSTES_APPLY = "Procrustes apply";
-    
-    public static final String ACTION_COMMAND_ALIGN_SYMMETRY_PLANES = "align symmetry planes";
-    
     public static final String ACTION_COMMAND_POINT_SAMPLING_STRATEGY = "Point sampling strategy";
     
     public static final String ACTION_COMMAND_POINT_SAMPLING_STRENGTH = "Point sampling strength";
     
-        /*
+    public static final String ACTION_COMMAND_REGISTER = "Register";
+    
+    /*
      * Configuration of panel-specific GUI elements
      */
     public static final String STRATEGY_POINT_TO_POINT = "Point to point";
@@ -55,7 +51,14 @@ public class RegistrationPanel extends ControlPanel {
         "Gaussian Curvature",
         "Max Curvature",
         "Min Curvature",
-        "Uniform Space Sampling"
+        "Uniform Space Sampling",
+        "Uniform Mesh Sampling",
+    };
+    
+    public static final String[] AUTO_ALIGNMENT_ALGORITHM = new String[] {
+        "Align meshes (ICP)",
+        "Align feature points (Procrustes)",
+        "Align symmetry planes"
     };
     
     
@@ -86,10 +89,7 @@ public class RegistrationPanel extends ControlPanel {
         initComponents();
         this.action = action;
         
-        // connect GUI element with RegistrationAction listener:
-        jButton1.addActionListener(createListener(action, ACTION_COMMAND_APPLY_ICP));
-        jButton2.addActionListener(createListener(action, ACTION_COMMAND_PROCRUSTES_APPLY));
-        jButton3.addActionListener(createListener(action, ACTION_COMMAND_ALIGN_SYMMETRY_PLANES));
+        jButton1.addActionListener(createListener(action, ACTION_COMMAND_REGISTER));
         
         thersholdFTF.setValue(5.0);
         thersholdFTF.addActionListener(createListener(action, ACTION_COMMAND_FP_CLOSENESS_THRESHOLD));
@@ -114,6 +114,11 @@ public class RegistrationPanel extends ControlPanel {
         Arrays.stream(POINT_SAMPLING_STRATEGIES).forEach(v -> jComboBox1.addItem(v));
         jComboBox1.setSelectedIndex(0);
         jComboBox1.addActionListener(createListener(action, ACTION_COMMAND_POINT_SAMPLING_STRATEGY));
+        
+        selectableComboBox1.addItem(AUTO_ALIGNMENT_ALGORITHM[0], true);
+        selectableComboBox1.addItem(AUTO_ALIGNMENT_ALGORITHM[1], true);
+        selectableComboBox1.addItem(AUTO_ALIGNMENT_ALGORITHM[2], true);
+        //selectableComboBox1.setSelectedIndex(0);
     }
     
     /**
@@ -154,6 +159,14 @@ public class RegistrationPanel extends ControlPanel {
         return undersamplingStrength;
     }
     
+    /**
+     * Returns actually selected algorithm
+     * @return actually selected algorithm
+     */
+    public String getRegistrationAlgorihm() {
+        return this.selectableComboBox1.getSelectedItem().toString();
+    }
+    
     /**
      * Return selected point sampling strategy
      * @return selected point sampling strategy
@@ -163,21 +176,19 @@ public class RegistrationPanel extends ControlPanel {
     }
     
     /**
-     * Turns ob or off the plane alignment button
+     * Turns on or off the plane alignment 
      * @param on on-off value
      */
-    public void setEnabledPlanesButton(boolean on) {
-        jButton3.setEnabled(on);
-        jButton3.setFont(new java.awt.Font("Ubuntu", (on) ? 1 : 0, 15)); // NOI18N
+    public void setEnabledPlanes(boolean on) {
+        selectableComboBox1.setItem(AUTO_ALIGNMENT_ALGORITHM[2], on);
     }
     
     /**
-     * Turns ob or off the plane alignment button
+     * Turns on or off the plane alignment 
      * @param on on-off value
      */
-    public void setEnabledProcrustesButton(boolean on) {
-        jButton2.setEnabled(on);
-        jButton2.setFont(new java.awt.Font("Ubuntu", (on) ? 1 : 0, 15)); // NOI18N
+    public void setEnabledProcrustes(boolean on) {
+        selectableComboBox1.setItem(AUTO_ALIGNMENT_ALGORITHM[1], on);
     }
     
     /**
@@ -283,16 +294,16 @@ public class RegistrationPanel extends ControlPanel {
         JOptionPane.showMessageDialog(
                 this, 
                 "<html>"
-                        + "<strong>Mesh</strong>: <br/>"
+                        + "<strong>Align meshes (ICP)</strong>: <br/>"
                         + "Superimposition of two faces by applying iterative closest points (ICP) algorithm<br/>" 
                         + "on their triangular meshes. This approach is slow, unsharp, but universal.<br/>"
                         + "<br/>"
-                        + "<strong>Feature points</strong>: <br/>"
+                        + "<strong>Align feature points (Procrustes)</strong>: <br/>"
                         + "Superimposition of two faces by applying Procrustes algorithm<br/>" 
                         + "on feature points. It is fast, precise, but feature points of the same types<br/>"
                         + "have to be presented for both faces.<br/>"
                         + "<br/>"
-                        + "<strong>Symmetry planes</strong>: <br/>"
+                        + "<strong>Align symmetry planes</strong>: <br/>"
                         + "Superimposition of two faces by aligning their symmetry planes.<br/>" 
                         + "Symmetry planes have to be computed on the \"<i>Symmetry</i>\" tab first<br/>"
                         + "to enable this feature.<br/>"
@@ -350,13 +361,12 @@ public class RegistrationPanel extends ControlPanel {
         jFormattedTextField2 = new javax.swing.JFormattedTextField();
         jLabel8 = new javax.swing.JLabel();
         jButton1 = new javax.swing.JButton();
-        jButton2 = new javax.swing.JButton();
-        jButton3 = new javax.swing.JButton();
         jButtonInfo1 = new javax.swing.JButton();
         jLabel9 = new javax.swing.JLabel();
         jComboBox1 = new javax.swing.JComboBox<>();
         jLabel3 = new javax.swing.JLabel();
         spinSlider1 = new cz.fidentis.analyst.core.SpinSlider();
+        selectableComboBox1 = new cz.fidentis.analyst.core.combobox.SelectableComboBox();
         jPanel4 = new javax.swing.JPanel();
         featurePointsLabel = new javax.swing.JLabel();
         thersholdFTF = new javax.swing.JFormattedTextField();
@@ -833,18 +843,6 @@ public class RegistrationPanel extends ControlPanel {
             }
         });
 
-        jButton2.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jButton2.text")); // NOI18N
-        jButton2.setToolTipText(org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jButton2.toolTipText")); // NOI18N
-        jButton2.addActionListener(new java.awt.event.ActionListener() {
-            public void actionPerformed(java.awt.event.ActionEvent evt) {
-                jButton2ActionPerformed(evt);
-            }
-        });
-
-        jButton3.setFont(new java.awt.Font("Ubuntu", 1, 15)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(jButton3, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jButton3.text")); // NOI18N
-
         jButtonInfo1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
         org.openide.awt.Mnemonics.setLocalizedText(jButtonInfo1, org.openide.util.NbBundle.getMessage(RegistrationPanel.class, "RegistrationPanel.jButtonInfo1.text")); // NOI18N
         jButtonInfo1.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
@@ -888,16 +886,14 @@ public class RegistrationPanel extends ControlPanel {
                                 .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                     .addGroup(jPanel1Layout.createSequentialGroup()
-                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                            .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING)
+                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(jLabel3)
                             .addGroup(jPanel1Layout.createSequentialGroup()
+                                .addComponent(selectableComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                 .addComponent(jButton1)
                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                                .addComponent(jButton2)))
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                        .addComponent(jButton3)
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                        .addComponent(jButtonInfo1)
+                                .addComponent(jButtonInfo1)))
                         .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
         );
         jPanel1Layout.setVerticalGroup(
@@ -907,10 +903,9 @@ public class RegistrationPanel extends ControlPanel {
                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                     .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                         .addComponent(jButton1)
-                        .addComponent(jButton2)
-                        .addComponent(jButton3))
+                        .addComponent(selectableComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                     .addComponent(jButtonInfo1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
-                .addGap(18, 18, 18)
+                .addGap(21, 21, 21)
                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                     .addComponent(jCheckBox1)
                     .addComponent(jLabel3))
@@ -922,13 +917,10 @@ public class RegistrationPanel extends ControlPanel {
                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                     .addComponent(jFormattedTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
                     .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addGap(18, 18, 18)
                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(jPanel1Layout.createSequentialGroup()
-                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                        .addComponent(spinSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addGroup(jPanel1Layout.createSequentialGroup()
-                        .addGap(18, 18, 18)
-                        .addComponent(jLabel8)))
+                    .addComponent(spinSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jLabel8))
                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                     .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
@@ -1107,10 +1099,6 @@ public class RegistrationPanel extends ControlPanel {
         thersholdFTF.postActionEvent();
     }//GEN-LAST:event_thersholdUpButtonActionPerformed
 
-    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
-        // TODO add your handling code here:
-    }//GEN-LAST:event_jButton2ActionPerformed
-
     private void scaleMinusButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_scaleMinusButtonMouseReleased
         animator.stopModelAnimation(this);
         action.actionPerformed(new ActionEvent(
@@ -1297,8 +1285,6 @@ public class RegistrationPanel extends ControlPanel {
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private javax.swing.JLabel featurePointsLabel;
     private javax.swing.JButton jButton1;
-    private javax.swing.JButton jButton2;
-    private javax.swing.JButton jButton3;
     private javax.swing.JButton jButtonInfo1;
     private javax.swing.JCheckBox jCheckBox1;
     private javax.swing.JComboBox<String> jComboBox1;
@@ -1342,6 +1328,7 @@ public class RegistrationPanel extends ControlPanel {
     private javax.swing.JPanel scalePanel;
     private javax.swing.JButton scalePlusButton;
     private javax.swing.ButtonGroup secondaryRenerModeGroup;
+    private cz.fidentis.analyst.core.combobox.SelectableComboBox selectableComboBox1;
     private javax.swing.JPanel shiftPanel;
     private cz.fidentis.analyst.core.SpinSlider spinSlider1;
     private javax.swing.JFormattedTextField thersholdFTF;
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java b/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
index c8ef2126571a5a71a8fd3e4ba18b960ec5f74149..0645d1bc72b7f813e487cf904b3de76924e5bec6 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
@@ -41,10 +41,12 @@ public class Scene {
     }
     
     /**
-     * Finds and returns a first free slot for human face and its drawables.
-     * @return a first free slot for human face and its drawables.
+     * Finds and returns a first free slot <b>for human face and its feature points and symmetry plane</b>.
+     * Use {@link #getFreeSlotForOtherDrawables()} to get free slot of other objects.
+     * 
+     * @return a first free slot for human face and its feature points and symmetry plane.
      */
-    public int getFreeSlot() {
+    public int getFreeSlotForFace() {
         int slot = -1;
         for (int i = 0; i < getArraySize(); i++) {
             if (this.drawableFaces.get(i) == null) {
@@ -62,7 +64,7 @@ public class Scene {
      * Finds and returns a first free slot for other drawable objects.
      * @return a first free slot for other drawable objects.
      */
-    public int getFreeSlotForOtherDrawables() {
+    public synchronized int getFreeSlotForOtherDrawables() {
         int slot = -1;
         for (int i = 0; i < this.otherDrawables.size(); i++) {
             if (this.otherDrawables.get(i) == null) {
@@ -73,7 +75,7 @@ public class Scene {
         if (slot == -1) {
             slot = otherDrawables.size();
         }
-        return (slot < Scene.MAX_FACES_IN_SCENE) ? slot : -1;
+        return slot;
     }
     
     /**
diff --git a/GUI/src/main/java/cz/fidentis/analyst/symmetry/ProfilesAction.java b/GUI/src/main/java/cz/fidentis/analyst/symmetry/ProfilesAction.java
index 224e0ce48c7cb9d30468314d21ff6c0fa9badb68..a2bab1cd9ae5fa7034d66457a97c037d1516c72a 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/symmetry/ProfilesAction.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/symmetry/ProfilesAction.java
@@ -175,7 +175,7 @@ public class ProfilesAction extends ControlPanelAction implements HumanFaceListe
             } else {
                 computeVerticalCuttingPlanes();
             }
-            getDrawableCuttingPlane(priCuttingPlaneSlot).show(false); // will be shown on the panel focus
+            getDrawableCuttingPlane(priCuttingPlaneSlot).show(false); // will be shown when the panel is focused
             if (getDrawableCuttingPlane(secCuttingPlaneSlot) != null) {
                 getDrawableCuttingPlane(secCuttingPlaneSlot).show(false);
             }
@@ -277,20 +277,24 @@ public class ProfilesAction extends ControlPanelAction implements HumanFaceListe
         Plane plane = new Plane(new Vector3d(1,0,0), bbox.getMidPoint().x);
         DrawableCuttingPlane cuttingPlane = new DrawableCuttingPlane(plane, bbox, true);
         cuttingPlane.setTransparency(0.5f);
-        if (priCuttingPlaneSlot == -1) {
-            priCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+        synchronized (this) {
+            if (priCuttingPlaneSlot == -1) {
+                priCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+            }
+            getCanvas().getScene().setOtherDrawable(priCuttingPlaneSlot, cuttingPlane);
         }
-        getCanvas().getScene().setOtherDrawable(priCuttingPlaneSlot, cuttingPlane);
         
         if (getSecondaryDrawableFace() != null) {
             bbox = getCanvas().getSecondaryFace().getBoundingBox(); 
             plane = new Plane(new Vector3d(1,0,0), bbox.getMidPoint().x);
             cuttingPlane = new DrawableCuttingPlane(plane, bbox, true);
             cuttingPlane.setTransparency(0.5f);
-            if (secCuttingPlaneSlot == -1) {
-                secCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+            synchronized (this) {
+                if (secCuttingPlaneSlot == -1) {
+                    secCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+                }
+                getCanvas().getScene().setOtherDrawable(secCuttingPlaneSlot, new DrawableCuttingPlane(cuttingPlane));
             }
-            getCanvas().getScene().setOtherDrawable(secCuttingPlaneSlot, new DrawableCuttingPlane(cuttingPlane));
         }
         
         cuttingPlaneFromSymmetry = false;
@@ -310,10 +314,12 @@ public class ProfilesAction extends ControlPanelAction implements HumanFaceListe
                 false
         );
         cuttingPlane.setTransparency(0.5f);
-        if (priCuttingPlaneSlot == -1) {
-            priCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+        synchronized (this) {
+            if (priCuttingPlaneSlot == -1) {
+                priCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+            }
+            getCanvas().getScene().setOtherDrawable(priCuttingPlaneSlot, cuttingPlane);
         }
-        getCanvas().getScene().setOtherDrawable(priCuttingPlaneSlot, cuttingPlane);
         recomputePrimaryProfile();
         
         if (getCanvas().getSecondaryFace() != null) {
@@ -327,10 +333,12 @@ public class ProfilesAction extends ControlPanelAction implements HumanFaceListe
                     false
             );
             cuttingPlane.setTransparency(0.5f);
-            if (secCuttingPlaneSlot == -1) {
-                secCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+            synchronized (this) {
+                if (secCuttingPlaneSlot == -1) {
+                    secCuttingPlaneSlot = getCanvas().getScene().getFreeSlotForOtherDrawables();
+                }
+                getCanvas().getScene().setOtherDrawable(secCuttingPlaneSlot, cuttingPlane);
             }
-            getCanvas().getScene().setOtherDrawable(secCuttingPlaneSlot, cuttingPlane);
             recomputeSecondaryProfile();
         }
         cuttingPlaneFromSymmetry = true;
@@ -348,8 +356,8 @@ public class ProfilesAction extends ControlPanelAction implements HumanFaceListe
         curve.projectFeaturePointsToCurve(close);
     }
     
-    protected DrawableCuttingPlane getDrawableCuttingPlane(int index) {
-        return (DrawableCuttingPlane) getScene().getOtherDrawable(index);
+    protected DrawableCuttingPlane getDrawableCuttingPlane(int slot) {
+        return (DrawableCuttingPlane) getScene().getOtherDrawable(slot);
     }
     
     protected void showCuttingPlanes(boolean show, boolean showMirrors) {
diff --git a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java
index 680748a1315558a92581dcebd2286d7e30d13808..12021420a64dc9e5ea95e5d7f01f5ccd5fb52ba1 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryAction.java
@@ -177,8 +177,8 @@ public class SymmetryAction extends ControlPanelAction implements HumanFaceListe
         face.announceEvent(new SymmetryPlaneChangedEvent(face, "", this));
     }
     
-    protected void recomputeFromFeaturePoints(int index) {
-        HumanFace face = getCanvas().getHumanFace(index);
+    protected void recomputeFromFeaturePoints(int slot) {
+        HumanFace face = getCanvas().getHumanFace(slot);
         if (face == null) {
             return;
         }
@@ -215,16 +215,16 @@ public class SymmetryAction extends ControlPanelAction implements HumanFaceListe
         }
         
         face.setSymmetryPlane(new Plane(planes)); // creates an average plane
-        setDrawablePlane(face, index);
+        setDrawablePlane(face, slot);
         face.announceEvent(new SymmetryPlaneChangedEvent(face, "", this));
     }
     
-    protected void setDrawablePlane(HumanFace face, int index) {
-        getCanvas().getScene().setDrawableSymmetryPlane(index, face); // add or remove
+    protected void setDrawablePlane(HumanFace face, int slot) {
+        getCanvas().getScene().setDrawableSymmetryPlane(slot, face); // add or remove
         if (face.hasSymmetryPlane()) {
-            getCanvas().getScene().getDrawableSymmetryPlane(index).setTransparency(0.5f);
-            getCanvas().getScene().getDrawableSymmetryPlane(index).setColor(
-                    (index == 0) ? DrawableFace.SKIN_COLOR_PRIMARY.darker() : DrawableFace.SKIN_COLOR_SECONDARY.darker()
+            getCanvas().getScene().getDrawableSymmetryPlane(slot).setTransparency(0.5f);
+            getCanvas().getScene().getDrawableSymmetryPlane(slot).setColor(
+                    (slot == 0) ? DrawableFace.SKIN_COLOR_PRIMARY.darker() : DrawableFace.SKIN_COLOR_SECONDARY.darker()
             );
         }
     }
@@ -271,7 +271,7 @@ public class SymmetryAction extends ControlPanelAction implements HumanFaceListe
             return -1;
         } else {
             if (cloudSlot == -1) {
-                cloudSlot = getCanvas().getScene().getFreeSlot();
+                cloudSlot = getCanvas().getScene().getFreeSlotForFace();
             }
             getScene().setOtherDrawable(cloudSlot, new DrawablePointCloud(sampling.getSamples()));
             return cloudSlot;
diff --git a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.form b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.form
index af111187b812a982823711c5f46daf7d8d116c5f..7e2685bc5c8b4978ae1a8842630d2244e34a87c9 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.form
+++ b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.form
@@ -330,8 +330,8 @@
           <Group type="103" groupAlignment="0" attributes="0">
               <Group type="102" alignment="0" attributes="0">
                   <EmptySpace max="-2" attributes="0"/>
-                  <Component id="jComboBox1" min="-2" max="-2" attributes="0"/>
-                  <EmptySpace type="separate" max="-2" attributes="0"/>
+                  <Component id="selectableComboBox1" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
                   <Component id="jButton2" min="-2" max="-2" attributes="0"/>
                   <EmptySpace max="32767" attributes="0"/>
               </Group>
@@ -342,8 +342,8 @@
               <Group type="102" alignment="0" attributes="0">
                   <EmptySpace max="-2" attributes="0"/>
                   <Group type="103" groupAlignment="3" attributes="0">
-                      <Component id="jComboBox1" alignment="3" min="-2" max="-2" attributes="0"/>
                       <Component id="jButton2" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="selectableComboBox1" alignment="3" min="-2" max="-2" attributes="0"/>
                   </Group>
                   <EmptySpace max="32767" attributes="0"/>
               </Group>
@@ -351,16 +351,6 @@
         </DimensionLayout>
       </Layout>
       <SubComponents>
-        <Component class="javax.swing.JComboBox" name="jComboBox1">
-          <Properties>
-            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
-              <StringArray count="0"/>
-            </Property>
-          </Properties>
-          <AuxValues>
-            <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
-          </AuxValues>
-        </Component>
         <Component class="javax.swing.JButton" name="jButton2">
           <Properties>
             <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
@@ -374,6 +364,8 @@
             <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/>
           </Events>
         </Component>
+        <Component class="cz.fidentis.analyst.core.combobox.SelectableComboBox" name="selectableComboBox1">
+        </Component>
       </SubComponents>
     </Container>
   </SubComponents>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java
index 33d9732550950b0501c11b7133fd7b3cae16cfcb..8c60eda639c8297f7818428d8934078dec4952a0 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/symmetry/SymmetryPanel.java
@@ -65,7 +65,7 @@ public class SymmetryPanel extends ControlPanel  {
             action.actionPerformed(new ActionEvent( // recompute
                     e.getSource(), 
                     ActionEvent.ACTION_PERFORMED,
-                    jComboBox1.getSelectedItem().toString()
+                    selectableComboBox1.getSelectedItem().toString()
             )); 
         });
         
@@ -81,9 +81,9 @@ public class SymmetryPanel extends ControlPanel  {
             this.showAlgorithmHelp();
         });
         
-        jComboBox1.addItem(SymmetryPanel.ACTION_COMMAND_RECOMPUTE_FROM_MESH);
-        //jComboBox1.addItem(SymmetryPanel.ACTION_COMMAND_COMPUTE_FROM_FPS);
-        jComboBox1.setSelectedIndex(0);
+        selectableComboBox1.addItem(SymmetryPanel.ACTION_COMMAND_RECOMPUTE_FROM_MESH, true);
+        selectableComboBox1.addItem(SymmetryPanel.ACTION_COMMAND_COMPUTE_FROM_FPS, true);
+        selectableComboBox1.setSelectedIndex(0);
         
         jComboBox3.addActionListener((ActionEvent e) -> {  // set default values
             setDefaultValues(action);
@@ -143,13 +143,7 @@ public class SymmetryPanel extends ControlPanel  {
      * @param on {@code true} = enable
      */
     public void setComputeFromFPs(boolean on) {
-        if (on && jComboBox1.getItemCount() == 1) {
-            jComboBox1.addItem(SymmetryPanel.ACTION_COMMAND_COMPUTE_FROM_FPS);
-        }
-        
-        if (!on && jComboBox1.getItemCount() == 2) {
-            jComboBox1.removeItemAt(1);
-        }
+        selectableComboBox1.setItem(SymmetryPanel.ACTION_COMMAND_COMPUTE_FROM_FPS, on);
     }
     
     /**
@@ -271,8 +265,8 @@ public class SymmetryPanel extends ControlPanel  {
         jLabel8 = new javax.swing.JLabel();
         jTextField2 = new javax.swing.JTextField();
         jPanel3 = new javax.swing.JPanel();
-        jComboBox1 = new javax.swing.JComboBox<>();
         jButton2 = new javax.swing.JButton();
+        selectableComboBox1 = new cz.fidentis.analyst.core.combobox.SelectableComboBox();
 
         jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(SymmetryPanel.class, "SymmetryPanel.jPanel1.border.title_1"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 1, 14))); // NOI18N
 
@@ -427,8 +421,8 @@ public class SymmetryPanel extends ControlPanel  {
             jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
             .addGroup(jPanel3Layout.createSequentialGroup()
                 .addContainerGap()
-                .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(18, 18, 18)
+                .addComponent(selectableComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(jButton2)
                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
         );
@@ -437,8 +431,8 @@ public class SymmetryPanel extends ControlPanel  {
             .addGroup(jPanel3Layout.createSequentialGroup()
                 .addContainerGap()
                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addComponent(jButton2))
+                    .addComponent(jButton2)
+                    .addComponent(selectableComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
         );
 
@@ -493,7 +487,6 @@ public class SymmetryPanel extends ControlPanel  {
     private javax.swing.JButton jButtonInfo1;
     private javax.swing.JButton jButtonInfo2;
     private javax.swing.JButton jButtonInfo3;
-    private javax.swing.JComboBox<String> jComboBox1;
     private javax.swing.JComboBox<String> jComboBox2;
     private javax.swing.JComboBox<String> jComboBox3;
     private javax.swing.JLabel jLabel1;
@@ -507,6 +500,7 @@ public class SymmetryPanel extends ControlPanel  {
     private javax.swing.JPanel jPanel3;
     private javax.swing.JTextField jTextField1;
     private javax.swing.JTextField jTextField2;
+    private cz.fidentis.analyst.core.combobox.SelectableComboBox selectableComboBox1;
     private cz.fidentis.analyst.core.SpinSlider spinSlider1;
     private cz.fidentis.analyst.core.SpinSlider spinSlider2;
     // End of variables declaration//GEN-END:variables
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/IcpDownsampling.java b/GUI/src/main/java/cz/fidentis/analyst/tests/IcpDownsampling.java
index 50e9c25d45fb14ab24e1dfa18848df4bec1e80a7..216a461cc2b1fd2914156fc8a882f2c631bcb1f8 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/IcpDownsampling.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/IcpDownsampling.java
@@ -3,17 +3,22 @@ package cz.fidentis.analyst.tests;
 import cz.fidentis.analyst.batch.Stopwatch;
 import cz.fidentis.analyst.face.HumanFace;
 import cz.fidentis.analyst.face.HumanFaceUtils;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.symmetry.Plane;
+import cz.fidentis.analyst.symmetry.SymmetryEstimator;
+import cz.fidentis.analyst.symmetry.SymmetryEstimatorRobust;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
 import cz.fidentis.analyst.visitors.mesh.sampling.CurvatureSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.NoSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.PointSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.RandomSampling;
 import cz.fidentis.analyst.visitors.mesh.sampling.UniformSpaceSampling;
+import cz.fidentis.analyst.visitors.mesh.sampling.UniformSurfaceSampling;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.SortedMap;
@@ -29,7 +34,7 @@ import java.util.stream.Collectors;
 public class IcpDownsampling {
     
     private static final String DATA_DIR = "../../analyst-data-antropologie/_ECA";
-    private static final int MAX_SAMPLES = 100;
+    private static final int MAX_SAMPLES = 500;
     
     /**
      * Main method 
@@ -43,18 +48,20 @@ public class IcpDownsampling {
                 .limit(MAX_SAMPLES)
                 .collect(Collectors.toList());
         
-        SortedMap<Double, Stopwatch> efficiency = new TreeMap<>();
-        SortedMap<Double, List<Double>> precision = new TreeMap<>();
+        SortedMap<Integer, Stopwatch> efficiency = new TreeMap<>();
+        SortedMap<Integer, List<Double>> precision = new TreeMap<>();
         
-        String alg = "random";
+        //String alg = "random";
         //String alg = "gaussian";
         //String alg = "uniform space";
+        String alg = "uniform mesh";
         
         int counter = 1;
-        for (int i = 0; i < faces.size(); i++) {
-            for (int j = i; j < faces.size(); j++) { // starts with "i"!
+        for (int i = 0; i < faces.size(); i += 5) {
+            for (int j = i; j < faces.size(); j += 5) { // starts with "i"!
                 if (i != j) { // register only different faces
-                    System.out.println(counter + " / " + (faces.size()*faces.size()/2));
+                    System.out.println();
+                    System.out.println("Iteration: " + counter);
                     compareFaces(faces.get(i), faces.get(j), efficiency, precision, alg);
                     printResults(efficiency, precision, counter, alg);
                     counter++;
@@ -63,36 +70,54 @@ public class IcpDownsampling {
         }
     }
     
-    protected static void printResults(SortedMap<Double, Stopwatch> efficiency, SortedMap<Double, List<Double>> precision, double counter, String sampling) {
+    protected static void printResults(SortedMap<Integer, Stopwatch> efficiency, SortedMap<Integer, List<Double>> precision, double counter, String sampling) {
         System.out.println();
         System.out.println("Avg. Time (ms) - " + sampling + " sampling:");
         efficiency.entrySet().forEach(e -> {
             System.out.println(e.getKey() + ";" + (e.getValue().getTotalTime() / counter));
         });
         System.out.println();
-        System.out.println("Avg. Precision - " + sampling + "  sampling:");
+        System.out.println("Avg. Precision - " + sampling + " sampling:");
+        System.out.println("# samples;average similarity;variance");
         precision.entrySet().forEach(e -> {
-            System.out.println(e.getKey() + ";" 
-                    + e.getValue().get(0) + ";" // min
-                    + e.getValue().get(1) + ";" // max
-                    + (e.getValue().get(2) / counter)); // avg
+            double avg = e.getValue().stream()
+                    .mapToDouble(val -> val)
+                    .summaryStatistics()
+                    .getAverage();
+            double variance = e.getValue().stream()
+                    .mapToDouble(val -> Math.pow(Math.abs(val - avg), 2))
+                    .average()
+                    .orElse(-1);
+            System.out.println(e.getKey() + ";" + avg + ";" + variance);
         });
     }
 
     protected static void compareFaces(
             Path priFacePath, Path secFacePath, 
-            Map<Double, Stopwatch> efficiency, Map<Double, List<Double>> precision,
+            Map<Integer, Stopwatch> efficiency, Map<Integer, List<Double>> precision,
             String samp) throws IOException {
         
         //double[] percs = new double[]{0.5,1,2,4,6,8,10,15,20,30,40,50,60,70,80,85,90,92,94,96,98,100};
-        double[] percs = new double[]{100,90,80,70,60,50,40,30,20,15,10,8,6,4,2,1,0.5};
+        //double[] percs = new double[]{100,90,80,70,60,50,40,30,20,15,10,8,6,4,2,1,0.5};
+        //int[] samples = new int[]{0,200,500,1000,2000,3000,5000,10000,20000,30000,40000};
+        int[] samples = new int[]{0,200,500,1000,2000,3000,5000};
         
         HumanFace priFace = new HumanFace(priFacePath.toFile());
         priFace.computeKdTree(false);
+        SymmetryEstimator seVisitor = new SymmetryEstimatorRobust(new UniformSpaceSampling(), 100, 1000);
+        priFace.getMeshModel().compute(seVisitor);
+        priFace.setSymmetryPlane(seVisitor.getSymmetryPlane());
         
-        for (double i: percs) {
-            System.out.println("" + i);
-            HumanFace secFace = new HumanFace(secFacePath.toFile());
+        HumanFace secFaceFromFile = new HumanFace(secFacePath.toFile());
+        seVisitor = new SymmetryEstimatorRobust(new UniformSpaceSampling(), 100, 1000);
+        secFaceFromFile.getMeshModel().compute(seVisitor);
+        secFaceFromFile.setSymmetryPlane(seVisitor.getSymmetryPlane());
+        
+        
+        System.out.println(secFaceFromFile.getShortName());
+        for (int i: samples) {
+            HumanFace secFace = new HumanFace(new MeshModel(secFaceFromFile.getMeshModel()), secFaceFromFile.getId());
+            secFace.setSymmetryPlane(new Plane(secFaceFromFile.getSymmetryPlane()));
             
             PointSampling sampling;
             switch (samp) {
@@ -105,24 +130,35 @@ public class IcpDownsampling {
                 case "uniform space":
                     sampling = new UniformSpaceSampling();
                     break;
+                case "uniform mesh":
+                    sampling = new UniformSurfaceSampling();
+                    break;
                 default:
                     return;
             }
             
-            sampling.setRequiredSamples(i/100.0);
+            if (i == 0) {
+                sampling = new NoSampling();
+            } else {
+                //sampling.setRequiredSamples(i/100.0);
+                sampling.setRequiredSamples(i);
+            }
             
             efficiency.computeIfAbsent(i, k-> new Stopwatch("")).start();
+            HumanFaceUtils.alignSymmetryPlanes(priFace, secFace, false, true);
             HumanFaceUtils.alignMeshes(
                             priFace,
                             secFace, // is transformed
                             100,  // max iterations
                             false,// scale
                             0.3,  // error
-                            (i == 100) ? new NoSampling() : sampling,  // no undersampling
+                            sampling, 
                             false // drop k-d tree, if exists
             );
             efficiency.get(i).stop();
             
+            System.out.println("" + sampling);
+
             HausdorffDistance hd = new HausdorffDistance(
                     priFace.getKdTree(),
                     HausdorffDistance.Strategy.POINT_TO_POINT,
@@ -131,11 +167,7 @@ public class IcpDownsampling {
                     true    // crop
             );
             secFace.getMeshModel().compute(hd);
-            
-            List<Double> val = precision.computeIfAbsent(i, k -> Arrays.asList(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0));
-            val.set(0, Math.min(val.get(0), hd.getStats().getAverage()));
-            val.set(1, Math.max(val.get(1), hd.getStats().getAverage()));
-            val.set(2, val.get(2) + hd.getStats().getAverage());
+            precision.computeIfAbsent(i, k -> new ArrayList<>()).add(hd.getStats().getAverage());
         }
         System.out.println();
     }
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/batch/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/batch/Bundle.properties
index 1d136de071aad207a972bc9db6984fb79eca211c..bff63b85fe181fe816e13be215422a48b5993bbc 100644
--- a/GUI/src/main/resources/cz/fidentis/analyst/batch/Bundle.properties
+++ b/GUI/src/main/resources/cz/fidentis/analyst/batch/Bundle.properties
@@ -8,7 +8,7 @@ BatchPanel.jCheckBox4.text=ICP scaling
 BatchPanel.jCheckBox3.text=Show ICP transformations in the 3D preview
 BatchPanel.jCheckBox2.text=Transform faces towards the selected one using ICP
 BatchPanel.jCheckBox1.text_1=Compute an average face from the selected  one
-BatchPanel.jLabel2.text=ICP undersampling :
+BatchPanel.jLabel2.text=ICP samples (0 = no downsampling) :
 BatchPanel.jButton1.text=Compute
 BatchPanel.jButtonInfo1.text=
 BatchPanel.jButton6.text=Export results
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties
index 15a33f9b70ec84ac7586897bc4bc97b6c06bdb79..0392f11b8a3037d4e5fd8cbf962a09f15afa06df 100644
--- a/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties
+++ b/GUI/src/main/resources/cz/fidentis/analyst/registration/Bundle.properties
@@ -1,4 +1,4 @@
-RegistrationPanel.jButton1.text=Mesh
+RegistrationPanel.jButton1.text=Compute
 RegistrationPanel.jCheckBox1.text=
 RegistrationPanel.jFormattedTextField1.text=0,3
 RegistrationPanel.jLabel5.text=ICP min error:
@@ -9,9 +9,7 @@ RegistrationPanel.thersholdUpButton.text=
 RegistrationPanel.thresholdDownButton.text=
 RegistrationPanel.featurePointsLabel.text=Highlight feature point pairs closer than:
 2
-RegistrationPanel.jButton2.text=Feature points
 RegistrationPanel.jButton1.toolTipText=Apply ICP
-RegistrationPanel.jButton2.toolTipText=Apply Procrustes
 RegistrationPanel.jPanel1.border.title=Auto-alignment
 RegistrationPanel.jPanel4.border.title=View:
 RegistrationPanel.jLabel1.text=Hausdorff distance:
@@ -22,7 +20,6 @@ RegistrationPanel.jTextField1.text=
 BatchRegistrationPanel.jPanel2.border.title=Dataset
 BatchRegistrationPanel.jCheckBox1.text=compute average face from
 BatchRegistrationPanel.jPanel3.border.title=Similarity
-RegistrationPanel.jButton3.text=Symmetry planes
 RegistrationPanel.scaleMinusButton.text=
 RegistrationPanel.scalePlusButton.text=
 RegistrationPanel.scalePanel.border.title=scale