diff --git a/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java b/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java
index 0de5414dc250900339ad38ded8c12604b67faf91..1adce12f5c10f12798eddbb13e3809b29a6e5299 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java
@@ -7,7 +7,6 @@ import cz.fidentis.analyst.icp.IcpTransformer;
 import cz.fidentis.analyst.icp.UndersamplingStrategy;
 import cz.fidentis.analyst.kdtree.KdTree;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.symmetry.CurvatureAlg;
 import cz.fidentis.analyst.symmetry.SymmetryConfig;
 import cz.fidentis.analyst.symmetry.SymmetryEstimator;
 import java.io.File;
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java
index c7c6046db1cbaec2c5b75453f35f70d674b73bfe..961b880770a4998e736e20c2c8d7181f1f456dd6 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/RandomStrategy.java
@@ -18,7 +18,7 @@ public class RandomStrategy extends UndersamplingStrategy {
     /**
      * Constructor for PERCENTAGE undersampling type.
      * 
-     * @param perc Percentage - a value in (0.0, 1.0>
+     * @param perc Percentage - a value in (0.0, 1.0&gtl
      * @throws IllegalArgumentException if the input parameter is wrong
      */
     public RandomStrategy(double perc) {
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java
index 105d9ee8147ee7ca098bd02ab4afdc5803fd1ca9..e0d9b0692bafee98b6ee4335d78ae0ae910d0aec 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/UndersamplingStrategy.java
@@ -38,7 +38,7 @@ public abstract class UndersamplingStrategy {
     /**
      * Constructor for PERCENTAGE undersampling type.
      * 
-     * @param perc Percentage - a value in (0.0, 1.0>
+     * @param perc Percentage - a value in (0.0, 1.0>
      * @throws IllegalArgumentException if the input parameter is wrong
      */
     public UndersamplingStrategy(double perc) {
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java
index 26753fbdd348d09f060a2a9b5eb419d948496df5..a1800faed3997784b4edf99d243c6777cbdb30f9 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/MouseRotationListener.java
@@ -67,7 +67,7 @@ public class MouseRotationListener extends MouseAdapter {
 
     /**
      * Actualize mouse movement
-     * @param evt Mouse position info
+     * @param e Mouse position info
      */
     @Override
     public void mouseMoved(MouseEvent e) {
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java
index 618d50f314463ea7776b5086cb25ef00ae5e7145..1928b4347dd2d1eca876f47f2d8efe28cc87c559 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/RotationAnimator.java
@@ -38,7 +38,6 @@ public class RotationAnimator {
      * Constructor.
      * 
      * @param glCanvas OpenGL canvas
-     * @param camera Camera
      * @throws IllegalArgumentException if some argument is missing
      */
     public RotationAnimator(GLCanvas glCanvas) {
diff --git a/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java b/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java
index d1d4d488e4bb06f67a1cb7e04cdf06a946521f45..d803a9530c3ca85acfa34e8b98510a5cff88ca7e 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/distance/DistanceAction.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.distance;
 
+import com.jogamp.opengl.GL2;
 import cz.fidentis.analyst.canvas.Canvas;
 import cz.fidentis.analyst.core.LoadedActionEvent;
 import cz.fidentis.analyst.core.ControlPanelAction;
@@ -11,7 +12,6 @@ import cz.fidentis.analyst.visitors.face.HausdorffDistancePrioritized;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
-import java.util.DoubleSummaryStatistics;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -21,9 +21,10 @@ import javax.swing.JComboBox;
 import javax.swing.JTabbedPane;
 import javax.swing.JTextField;
 import javax.swing.JToggleButton;
+import javax.vecmath.Point3d;
 
 /**
- * Action listener for the curvature computation.
+ * Action listener for computation of the Hausdorff distance.
  * 
  * @author Radek Oslejsek
  * @author Daniel Schramm
@@ -34,14 +35,22 @@ public class DistanceAction extends ControlPanelAction {
      * Attributes handling the state
      */
     private HausdorffDistancePrioritized visitor = null;
-    private final Map<FeaturePointType, Double> featurePointTypes = new HashMap<>();
+    private final Map<FeaturePointType, Double> featurePointTypes;
     private String strategy = DistancePanel.STRATEGY_POINT_TO_POINT;
     private boolean relativeDist = false;
     private boolean weightedDist = false;
+    private boolean heatmapRender = false;
+    private boolean weightedFPsShow = true;
     
-    private Map<MeshFacet, List<Double>> hausdorffDistance = null;
+    private Map<MeshFacet, List<Double>> weightedHausdorffDistance = null;
+    private FeaturePointType hoveredFeaturePoint = null;
     
     private final DistancePanel controlPanel;
+    private final DrawableFeaturePoints weightedFeaturePoints;
+    
+    private static final Color WEIGHTED_FEATURE_POINT_DEFAULT_COLOR = Color.WHITE;
+    private static final Color FEATURE_POINT_HIGHLIGHT_COLOR = Color.MAGENTA;
+    private static final Color FEATURE_POINT_HOVER_COLOR = Color.CYAN;
     
     /**
      * Constructor.
@@ -51,7 +60,91 @@ public class DistanceAction extends ControlPanelAction {
      */
     public DistanceAction(Canvas canvas, JTabbedPane topControlPanel) {
         super(canvas, topControlPanel);
-        this.controlPanel = new DistancePanel(this, getSecondaryFeaturePoints().getFeaturePoints());
+        
+        // Calculate weighted Hausdorff distance for all feature points of the secondary face
+        calculateHausdorffDistance(
+                getSecondaryFeaturePoints().getFeaturePoints()
+                        .stream()
+                        .collect(Collectors.toMap(
+                                FeaturePoint::getFeaturePointType,
+                                featurePoint -> DrawableFeaturePoints.DEFAULT_SIZE))
+        );
+        
+        this.featurePointTypes = visitor.getFeaturePointWeights()
+                .get(getSecondaryDrawableFace().getHumanFace()) // Get FP weights for the secondary face
+                .entrySet()
+                .stream()
+                .map(fpWeights -> Map.entry(
+                        fpWeights.getKey(),  // For each FP type at the secondary face...
+                        fpWeights.getValue() // ... compute average FP weight over all its facets
+                                .values()
+                                .stream()
+                                .mapToDouble(weight -> weight)
+                                .average()
+                                .orElse(Double.NaN)))
+                .filter(fpWeight -> !Double.isNaN(fpWeight.getValue())) // Filter out feature points with Double.NaN weight
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        fpType -> DrawableFeaturePoints.DEFAULT_SIZE));
+        this.controlPanel = new DistancePanel(this, getSecondaryFeaturePoints().getFeaturePoints(), featurePointTypes.keySet());
+        this.visitor = null;
+        
+        // Add weighted feature points to the scene
+        this.weightedFeaturePoints = new DrawableFeaturePoints(getSecondaryFeaturePoints().getFeaturePoints());
+        weightedFeaturePoints.setRenderMode(GL2.GL_LINE);
+        weightedFeaturePoints.setColor(WEIGHTED_FEATURE_POINT_DEFAULT_COLOR);
+        getCanvas().getScene().addOtherDrawable(weightedFeaturePoints);
+        
+        // Place control panel to the topControlPanel
+        topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel);
+        topControlPanel.addChangeListener(e -> {
+            // If the distance panel is focused...
+            if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof DistancePanel) {
+                // ... display heatmap and feature points relevant to the Hausdorff distance
+                getCanvas().getScene().setDefaultColors();
+                weightedFeaturePoints.resetAllColorsToDefault();
+                if (weightedFPsShow) {
+                    weightedFeaturePoints.show();
+                }
+                
+                boolean secondaryFaceMoved = false;
+                final List<FeaturePoint> secondaryFPs = getSecondaryFeaturePoints().getFeaturePoints();
+                final List<FeaturePoint> weightedFPs = weightedFeaturePoints.getFeaturePoints();
+                for (int i = 0; i < secondaryFPs.size(); i++) {
+                    final FeaturePoint faceFP = secondaryFPs.get(i);
+                    final FeaturePoint weightedFP = weightedFPs.get(i);
+                    
+                    // Highlight feature point if selected
+                    if (featurePointTypes.containsKey(faceFP.getFeaturePointType())) {
+                        colorSecondaryFaceFeaturePoint(i, FEATURE_POINT_HIGHLIGHT_COLOR);
+                    }
+                    if (!faceFP.getPosition().equals(weightedFP.getPosition())) {
+                        secondaryFaceMoved = true;
+                    }
+                }
+                
+                // If the positin of secondary face has been changed
+                if (secondaryFaceMoved) {
+                    visitor = null; // recompute Hausdorff distance
+                    
+                    // Relocate weighted feature points
+                    for (int i = 0; i < secondaryFPs.size(); i++) {
+                        final Point3d faceFpPos = secondaryFPs.get(i).getPosition();
+                        final Point3d weightedFpPos = weightedFPs.get(i).getPosition();
+                        
+                        weightedFpPos.x = faceFpPos.x;
+                        weightedFpPos.y = faceFpPos.y;
+                        weightedFpPos.z = faceFpPos.z;
+                    }
+                }
+                
+                updateHausdorffDistanceInformation();
+                getSecondaryDrawableFace().setRenderHeatmap(heatmapRender);
+            } else {
+                weightedFeaturePoints.hide();
+            }
+        });
+        topControlPanel.setSelectedComponent(controlPanel); // Focus Hausdorff distance panel
     }
 
     @Override
@@ -59,41 +152,50 @@ public class DistanceAction extends ControlPanelAction {
         final String action = ae.getActionCommand();
         
         switch (action) {
-            case DistancePanel.ACTION_COMMAND_SHOW_HIDE_PANEL:
-                hideShowPanelActionPerformed(ae, this.controlPanel);
-                break;
             case DistancePanel.ACTION_COMMAND_SHOW_HIDE_HEATMAP:
-                if (((JToggleButton) ae.getSource()).isSelected()) {
-                    calculateHausdorffDistance();
-                    getSecondaryDrawableFace().setRenderHeatmap(true);
+                heatmapRender = ((JToggleButton) ae.getSource()).isSelected();
+                if (heatmapRender) {
+                    updateHausdorffDistanceInformation();
+                }
+                getSecondaryDrawableFace().setRenderHeatmap(heatmapRender);
+                break;
+            case DistancePanel.ACTION_COMMAND_SHOW_HIDE_WEIGHTED_FPOINTS:
+                weightedFPsShow = ((JToggleButton) ae.getSource()).isSelected();
+                if (weightedFPsShow) {
+                    weightedFeaturePoints.show();
                 } else {
-                    getSecondaryDrawableFace().setRenderHeatmap(false);
+                    weightedFeaturePoints.hide();
                 }
                 break;
             case DistancePanel.ACTION_COMMAND_SET_DISTANCE_STRATEGY:
                 strategy = (String) ((JComboBox) ae.getSource()).getSelectedItem();
                 this.visitor = null; // recompute
-                calculateHausdorffDistance();
+                updateHausdorffDistanceInformation();
                 break;
             case DistancePanel.ACTION_COMMAND_RELATIVE_ABSOLUTE_DIST:
                 this.relativeDist = ((JToggleButton) ae.getSource()).isSelected();
                 this.visitor = null; // recompute
-                calculateHausdorffDistance();
+                updateHausdorffDistanceInformation();
                 break;
             case DistancePanel.ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT:
                 highlightFeaturePoint((LoadedActionEvent) ae);
                 break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_HOVER_IN:
+                hoverFeaturePoint((LoadedActionEvent) ae, true);
+                break;
+            case DistancePanel.ACTION_COMMAND_FEATURE_POINT_HOVER_OUT:
+                hoverFeaturePoint((LoadedActionEvent) ae, false);
+                break;
             case DistancePanel.ACTION_COMMAND_FEATURE_POINT_RESIZE:
                 resizeFeaturePoint((LoadedActionEvent) ae);
                 break;
             case DistancePanel.ACTION_COMMAND_WEIGHTED_DISTANCE:
                 this.weightedDist = ((JToggleButton) ae.getSource()).isSelected();
-                this.hausdorffDistance = null; // recompute only priorities
-                calculateHausdorffDistance();
+                updateHausdorffDistanceInformation();
                 break;
-            case DistancePanel.ACTION_COMMAND_WEIGHTED_DIST_RECOMPUTE:
+            case DistancePanel.ACTION_COMMAND_DISTANCE_RECOMPUTE:
                 this.visitor = null; // recompute
-                calculateHausdorffDistance();
+                updateHausdorffDistanceInformation();
                 break;
             default:
                 // to nothing
@@ -105,7 +207,30 @@ public class DistanceAction extends ControlPanelAction {
      * (Re)calculates the Hausdorff distance and updates the heat map of the secondary face
      * as well as values of all appropriate GUI elements of {@link DistancePanel}.
      */
-    protected void calculateHausdorffDistance() {
+    private void updateHausdorffDistanceInformation() {
+        if (visitor == null) {
+            calculateHausdorffDistance(featurePointTypes);
+            
+            weightedHausdorffDistance = getWeightedDistance();
+            
+            // Update GUI elements that display the calculated Hausdorff distance metrics
+            setFeaturePointWeigths();
+            setHausdorffDistanceStatistics();
+        }
+        
+        getSecondaryDrawableFace().setHeatMap(weightedDist ? weightedHausdorffDistance : visitor.getDistances());
+    }
+    
+    /**
+     * (Re)calculates the Hausdorff distance.
+     * 
+     * @param featurePoints Types of feature points according to which the Hausdorff
+     *                      distances will be prioritized together with
+     *                      the radii of priority spheres around the feature
+     *                      points of the corresponding type.
+     *                      Must not be {@code null}.
+     */
+    private void calculateHausdorffDistance(Map<FeaturePointType, Double> featurePoints) {
         final Strategy useStrategy;
         switch (strategy) {
             case DistancePanel.STRATEGY_POINT_TO_POINT:
@@ -118,40 +243,25 @@ public class DistanceAction extends ControlPanelAction {
                 throw new UnsupportedOperationException(strategy);
         }
         
-        if (visitor == null) {
-            this.visitor = new HausdorffDistancePrioritized(getPrimaryDrawableFace().getModel(),
-                    featurePointTypes,
-                    useStrategy,
-                    relativeDist,
-                    true);
-            getSecondaryDrawableFace().getHumanFace().accept(visitor);
-            hausdorffDistance = null;
-        }
-        
-        // Update GUI elements that display the calculated Hausdorff distance
-        if (hausdorffDistance == null) {
-            hausdorffDistance = getWeightedDistance();
-            setHausdorffDistanceStatistics();
-            setFeaturePointWeigths();
-        }
-        getSecondaryDrawableFace().setHeatMap(hausdorffDistance);
+        this.visitor = new HausdorffDistancePrioritized(getPrimaryDrawableFace().getModel(),
+                featurePoints,
+                useStrategy,
+                relativeDist,
+                true);
+        getSecondaryDrawableFace().getHumanFace().accept(visitor);
     }
     
     /**
-     * Calculates weighted (or regular) Hausdorff distance of the face.
+     * Calculates weighted Hausdorff distance of the face.
      * 
      * @return weighted Hausdorff distance
      */
     private Map<MeshFacet, List<Double>> getWeightedDistance() {
-        if (!weightedDist) {
-            return visitor.getDistances();
-        }
-        
-        // Merge the map of distances with the map of priorities
         final Map<MeshFacet, List<Double>> weightedDistances = new HashMap<>(visitor.getDistances());
-
         final Map<MeshFacet, List<Double>> mergedPriorities = visitor.getMergedPriorities()
                 .get(getSecondaryDrawableFace().getHumanFace());
+
+        // Merge the map of distances with the map of priorities
         for (final Map.Entry<MeshFacet, List<Double>> facetPriorities: mergedPriorities.entrySet()) {
             weightedDistances.merge(
                     facetPriorities.getKey(),
@@ -165,35 +275,12 @@ public class DistanceAction extends ControlPanelAction {
 
         return weightedDistances;
     }
-
-    /**
-     * Updates the GUI elements of {@link DistancePanel} elements that display
-     * statistical data about the calculated Hausdorff distance.
-     */
-    private void setHausdorffDistanceStatistics() {
-        final DoubleSummaryStatistics distanceStats = hausdorffDistance.values()
-                .stream()
-                .flatMap(List::stream)
-                .mapToDouble(distance -> distance)
-                .summaryStatistics();
-        
-        controlPanel.updateHausdorffDistanceStats(
-                distanceStats.getAverage(),
-                distanceStats.getMax(),
-                distanceStats.getMin()
-        );
-    }
     
     /**
      * Updates the GUI elements of {@link DistancePanel} that display
      * the weights of feature points used to calculate the weighted Hausdorff distance.
      */
     private void setFeaturePointWeigths() {
-        if (!weightedDist) {
-            controlPanel.updateFeaturePointWeights(Map.of());
-            return;
-        }
-        
         controlPanel.updateFeaturePointWeights(
                 visitor.getFeaturePointWeights()
                         .get(getSecondaryDrawableFace().getHumanFace()) // Get FP weights for the secondary face
@@ -209,9 +296,32 @@ public class DistanceAction extends ControlPanelAction {
                                                 .average()
                                                 .orElse(Double.NaN))));
     }
+
+    /**
+     * Updates the GUI elements of {@link DistancePanel} elements that display
+     * statistical data about the calculated Hausdorff distance.
+     */
+    private void setHausdorffDistanceStatistics() {
+        controlPanel.updateHausdorffDistanceStats(
+                visitor.getDistances()
+                        .values()
+                        .stream()
+                        .flatMap(List::stream)
+                        .mapToDouble(distance -> distance)
+                        .summaryStatistics(),
+                weightedHausdorffDistance
+                        .values()
+                        .stream()
+                        .flatMap(List::stream)
+                        .mapToDouble(distance -> distance)
+                        .summaryStatistics()
+        );
+    }
     
     /**
-     * Changes the colour of the secondary face's feature point at the given index.
+     * Changes the color of the secondary face's feature point at the given index
+     * and of its weighted representation when the feature point is (de)selected
+     * for the computation of the weighted Hausdorff distance.
      * The index is received as the data payload of {@code actionEvent}.
      * 
      * @param actionEvent Action event with the index of the feature point as its payload data
@@ -219,16 +329,60 @@ public class DistanceAction extends ControlPanelAction {
     private void highlightFeaturePoint(LoadedActionEvent actionEvent) {
         final int index = (int) actionEvent.getData();
         final FeaturePointType fpType = getTypeOfFeaturePoint(index);
-        final DrawableFeaturePoints secondaryFeaturePoints = getSecondaryFeaturePoints();
         
         if (((JToggleButton) actionEvent.getSource()).isSelected()) {
-            secondaryFeaturePoints.setColor(index, Color.MAGENTA);
-            featurePointTypes.put(fpType, secondaryFeaturePoints.getSize(index));
+            colorSecondaryFaceFeaturePoint(index, FEATURE_POINT_HIGHLIGHT_COLOR);
+            featurePointTypes.put(fpType, weightedFeaturePoints.getSize(index));
         } else {
-            secondaryFeaturePoints.resetColorToDefault(index);
+            resetSecondaryFaceFeaturePointColor(index);
             featurePointTypes.remove(fpType);
         }
     }
+    
+    /**
+     * Changes the color of the secondary face's feature point at the given index
+     * and of its weighted representation when the cursor hovers over the feature point's name.
+     * The index is received as the data payload of {@code actionEvent}.
+     * 
+     * @param actionEvent Action event with the index of the feature point as its payload data
+     * @param entered {@code true} if the cursor entered the feature point,
+     *                {@code false} if the cursor left the feature point
+     */
+    private void hoverFeaturePoint(LoadedActionEvent actionEvent, boolean entered) {
+        final int index = (int) actionEvent.getData();
+        
+        if (entered) { // entering a feature point
+            colorSecondaryFaceFeaturePoint(index, FEATURE_POINT_HOVER_COLOR);
+            hoveredFeaturePoint = getTypeOfFeaturePoint(index);
+        } else if (featurePointTypes.containsKey(hoveredFeaturePoint)) { // leaving highlighted FP
+            colorSecondaryFaceFeaturePoint(index, FEATURE_POINT_HIGHLIGHT_COLOR);
+        } else { // leaving ordinary FP
+            resetSecondaryFaceFeaturePointColor(index);
+        }
+    }
+
+    /**
+     * Sets the color of the secondary face's feature point at the given index
+     * and of its weighted representation.
+     * 
+     * @param index Index of the feature point
+     * @param color New color of the feature point
+     */
+    private void colorSecondaryFaceFeaturePoint(int index, Color color) {
+        getSecondaryFeaturePoints().setColor(index, color);
+        weightedFeaturePoints.setColor(index, color);
+    }
+
+    /**
+     * Resets to default the color of the secondary face's feature point at the given index
+     * and of its weighted representation.
+     * 
+     * @param index Index of the feature point
+     */
+    private void resetSecondaryFaceFeaturePointColor(final int index) {
+        getSecondaryFeaturePoints().resetColorToDefault(index);
+        weightedFeaturePoints.resetColorToDefault(index);
+    }
 
     /**
      * Changes the size of the secondary face's feature point at the given index.
@@ -240,7 +394,7 @@ public class DistanceAction extends ControlPanelAction {
         final int index = (int) actionEvent.getData();
         final double size = Double.parseDouble(((JTextField) actionEvent.getSource()).getText());
         
-        getSecondaryFeaturePoints().setSize(index, size);
+        weightedFeaturePoints.setSize(index, size);
         featurePointTypes.replace(getTypeOfFeaturePoint(index), size);
     }
     
diff --git a/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java b/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java
index 035a8274f3f007166f1eb7cd11ae3ce9ce1a5796..057526561553eb5625a0962da723ff3cf00472fc 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/distance/DistancePanel.java
@@ -2,22 +2,26 @@ package cz.fidentis.analyst.distance;
 
 import cz.fidentis.analyst.core.ControlPanel;
 import cz.fidentis.analyst.core.ControlPanelBuilder;
+import cz.fidentis.analyst.core.LoadedActionEvent;
 import cz.fidentis.analyst.feature.FeaturePoint;
 import cz.fidentis.analyst.feature.FeaturePointType;
 import cz.fidentis.analyst.scene.DrawableFeaturePoints;
 import cz.fidentis.analyst.symmetry.SymmetryPanel;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.ArrayList;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.DoubleSummaryStatistics;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import javax.swing.AbstractAction;
 import javax.swing.BorderFactory;
 import javax.swing.ImageIcon;
-import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.JScrollPane;
 import javax.swing.JTextField;
 
 /**
@@ -41,9 +45,12 @@ public class DistancePanel extends ControlPanel {
     public static final String ACTION_COMMAND_SET_DISTANCE_STRATEGY = "set strategy";
     public static final String ACTION_COMMAND_RELATIVE_ABSOLUTE_DIST = "switch abosulte-relative distance";
     public static final String ACTION_COMMAND_WEIGHTED_DISTANCE = "switch weighted distance on/off";
+    public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_IN = "highlight hovered FP";
+    public static final String ACTION_COMMAND_FEATURE_POINT_HOVER_OUT = "set default color of hovered FP";
     public static final String ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT = "highlight feature point with color";
     public static final String ACTION_COMMAND_FEATURE_POINT_RESIZE = "set size of feature point";
-    public static final String ACTION_COMMAND_WEIGHTED_DIST_RECOMPUTE = "recompute weighted distance";
+    public static final String ACTION_COMMAND_DISTANCE_RECOMPUTE = "recompute the Hausdorff distance";
+    public static final String ACTION_COMMAND_SHOW_HIDE_WEIGHTED_FPOINTS = "show-hide weighted feature points";
     
     /*
      * Configuration of panel-specific GUI elements
@@ -51,14 +58,19 @@ public class DistancePanel extends ControlPanel {
     public static final String STRATEGY_POINT_TO_POINT = "Point to point";
     public static final String STRATEGY_POINT_TO_TRIANGLE = "Point to triangle";
     
-    private final JPanel featurePointsStats;
-    private final JLabel avgHD, maxHD, minHD;
+    private final Map<FeaturePointType, JLabel> featurePointStats;
+    private final JLabel avgHD, avgHDWeight, maxHD, maxHDWeight, minHD, minHDWeight;
     
     /**
      * Constructor.
+     * 
      * @param action Action listener
+     * @param featurePoints List of all feature points which can be used to calculate
+     *                      the weighted Hausdorff distance
+     * @param selectedFPs Set of feature point types which are initially selected
+     *                    to be used to calculate the weighted Hausdorff distance
      */
-    public DistancePanel(ActionListener action, List<FeaturePoint> featurePoints) {
+    public DistancePanel(ActionListener action, List<FeaturePoint> featurePoints, Set<FeaturePointType> selectedFPs) {
         this.setName(NAME);
         
         final ControlPanelBuilder builder = new ControlPanelBuilder(this);
@@ -82,37 +94,59 @@ public class DistancePanel extends ControlPanel {
         builder.addGap();
         builder.addLine();
         
-        final JCheckBox weightedDistChBx = builder.addCheckBoxOptionLine(
-                null,
-                "Weighted Hausdorff distance",
-                false,
-                createListener(action, ACTION_COMMAND_WEIGHTED_DISTANCE)
-        );
-        builder.addLine();
-        
         final JPanel featurePointsPanel = new JPanel();
         final ControlPanelBuilder fpBuilder = new ControlPanelBuilder(featurePointsPanel);
-        final List<JCheckBox> fpCheckBoxes = new ArrayList<>(featurePoints.size());
-        final List<JTextField> fpSliderInputs = new ArrayList<>(featurePoints.size());
+        featurePointStats = new HashMap<>(featurePoints.size());
         for (int i = 0; i < featurePoints.size(); i++) {
             final FeaturePoint featurePoint = featurePoints.get(i);
+            final FeaturePointType featurePointType = featurePoint.getFeaturePointType();
             
             final JCheckBox checkBox = fpBuilder.addCheckBox(
-                    false,
-                    createListener(action, ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT, i)
+                    selectedFPs.contains(featurePointType),
+                    createListener(action, ACTION_COMMAND_DISTANCE_RECOMPUTE)
             );
-            checkBox.setText(featurePoint.getFeaturePointType().getName());
-            fpCheckBoxes.add(checkBox);
+            checkBox.setText(featurePointType.getName());
+            checkBox.addActionListener(createListener(action, ACTION_COMMAND_FEATURE_POINT_HIGHLIGHT, i));
+            final int index = i;
+            checkBox.addMouseListener(new MouseAdapter() {
+                @Override
+                public void mouseEntered(MouseEvent e) {
+                    action.actionPerformed(new LoadedActionEvent(
+                            e.getSource(),
+                            ActionEvent.ACTION_PERFORMED,
+                            ACTION_COMMAND_FEATURE_POINT_HOVER_IN,
+                            index));
+                }
 
-            final JTextField sliderInput = fpBuilder.addSliderOptionLine(
-                    null,
-                    null,
-                    100,
-                    createListener(action, ACTION_COMMAND_FEATURE_POINT_RESIZE, i)
-            );
+                @Override
+                public void mouseExited(MouseEvent e) {
+                    action.actionPerformed(new LoadedActionEvent(
+                            e.getSource(),
+                            ActionEvent.ACTION_PERFORMED,
+                            ACTION_COMMAND_FEATURE_POINT_HOVER_OUT,
+                            index));
+                }
+            });
+
+            final JTextField sliderInput = fpBuilder.addSliderOptionLine(null, null, 100, null);
             sliderInput.setText(ControlPanelBuilder.doubleToStringLocale(DrawableFeaturePoints.DEFAULT_SIZE));
-            sliderInput.postActionEvent();
-            fpSliderInputs.add(sliderInput);
+            sliderInput.postActionEvent(); // Set correct position of slider
+            sliderInput.addActionListener(new AbstractAction() {
+                private final ActionListener listener = createListener(action, ACTION_COMMAND_DISTANCE_RECOMPUTE);
+                
+                @Override
+                public void actionPerformed(ActionEvent ae) {
+                    if (!checkBox.isSelected()) {
+                        return;
+                    }
+                    listener.actionPerformed(ae); // Recompute only if the feature point is selected
+                }
+            });
+            sliderInput.addActionListener(createListener(action, ACTION_COMMAND_FEATURE_POINT_RESIZE, i));
+            
+            fpBuilder.addGap();
+            featurePointStats.put(featurePointType, fpBuilder.addLabelLine(null));
+            fpBuilder.addGap();
             
             fpBuilder.addLine();
         }
@@ -120,39 +154,15 @@ public class DistancePanel extends ControlPanel {
                 .setBorder(BorderFactory.createTitledBorder("Feature points"));
         builder.addLine();
         
-        final JButton recomputeButton = builder.addButton(
-                "Recompute",
-                createListener(action, ACTION_COMMAND_WEIGHTED_DIST_RECOMPUTE)
-        );
-        recomputeButton.setEnabled(false);
-        recomputeButton.addActionListener((ActionEvent ae) -> 
-            recomputeButton.setEnabled(false)
-        );
-        weightedDistChBx.addActionListener((ActionEvent ae) -> {
-            if (!weightedDistChBx.isSelected()) {
-                recomputeButton.setEnabled(false);
-            }
-        });
-        for (final JCheckBox checkBox: fpCheckBoxes) {
-            checkBox.addActionListener((ActionEvent ae) -> {
-                if (weightedDistChBx.isSelected()) {
-                    recomputeButton.setEnabled(true);
-                }
-            });
-        }
-        for (int i = 0; i < fpSliderInputs.size(); i++) {
-            final JTextField sliderInput = fpSliderInputs.get(i);
-            final JCheckBox sliderCheckBox = fpCheckBoxes.get(i);
-            sliderInput.addActionListener((ActionEvent ae) -> {
-                if (weightedDistChBx.isSelected() && sliderCheckBox.isSelected()) {
-                    recomputeButton.setEnabled(true);
-                }
-            });
-        }
-        builder.addLine();
-        
         builder.addCaptionLine("Visualization options:");
         builder.addLine();
+        builder.addCheckBoxOptionLine(
+                null,
+                "Weighted feature points",
+                true,
+                createListener(action, ACTION_COMMAND_SHOW_HIDE_WEIGHTED_FPOINTS)
+        );
+        builder.addLine();
         builder.addCheckBoxOptionLine(
                 null, 
                 "Show Hausdorff distance", 
@@ -161,32 +171,39 @@ public class DistancePanel extends ControlPanel {
         ); 
         builder.addLine();
         
+        builder.addCheckBoxOptionLine(
+                null,
+                "Weighted Hausdorff distance",
+                false,
+                createListener(action, ACTION_COMMAND_WEIGHTED_DISTANCE)
+        );
+        builder.addLine();
+        
         builder.addCaptionLine("Hausdorff distance:");
         builder.addLine();
         
+        builder.addOptionText("");
+        builder.addOptionText("Hausdorff distance");
+        builder.addOptionText("Weighted Hasudorff distance");
+        builder.addLine();
+        
         builder.addOptionText("Average");
-        builder.addGap();
         avgHD = builder.addLabelLine("");
         builder.addGap();
+        builder.addGap();
+        avgHDWeight = builder.addLabelLine("");
         builder.addLine();
         builder.addOptionText("Maximum");
-        builder.addGap();
         maxHD = builder.addLabelLine("");
         builder.addGap();
+        builder.addGap();
+        maxHDWeight = builder.addLabelLine("");
         builder.addLine();
         builder.addOptionText("Minimum");
-        builder.addGap();
         minHD = builder.addLabelLine("");
         builder.addGap();
-        builder.addLine();
-        
-        featurePointsStats = new JPanel();
-        final JScrollPane fpStatsScrollPanel = builder.addScrollPane(featurePointsStats);
-        fpStatsScrollPanel.setBorder(BorderFactory.createTitledBorder("Feature point weights"));
-        fpStatsScrollPanel.setVisible(false);
-        weightedDistChBx.addActionListener((ActionEvent ae) -> {
-            fpStatsScrollPanel.setVisible(weightedDistChBx.isSelected());
-        });
+        builder.addGap();
+        minHDWeight = builder.addLabelLine("");
         builder.addLine();
         
         builder.addVerticalStrut();
@@ -209,14 +226,19 @@ public class DistancePanel extends ControlPanel {
     /**
      * Updates GUI elements that display statistical data about the calculated Hausdorff distance.
      * 
-     * @param averageDist Average distance
-     * @param maxDist Maximum distance
-     * @param minDist Minimum distance
+     * @param hausdorffDistance Statistical data of the ordinary Hausdorff distance
+     * @param weightedHausdorffDistance Statistical data of the weighted Hausdorff distance
      */
-    public void updateHausdorffDistanceStats(double averageDist, double maxDist, double minDist) {
-        avgHD.setText(Double.toString(averageDist));
-        maxHD.setText(Double.toString(maxDist));
-        minHD.setText(Double.toString(minDist));
+    public void updateHausdorffDistanceStats(DoubleSummaryStatistics hausdorffDistance,
+            DoubleSummaryStatistics weightedHausdorffDistance) {
+        avgHD.setText(Double.toString(hausdorffDistance.getAverage()));
+        avgHDWeight.setText(Double.toString(weightedHausdorffDistance.getAverage()));
+        
+        maxHD.setText(Double.toString(hausdorffDistance.getMax()));
+        maxHDWeight.setText(Double.toString(weightedHausdorffDistance.getMax()));
+        
+        minHD.setText(Double.toString(hausdorffDistance.getMin()));
+        minHDWeight.setText(Double.toString(weightedHausdorffDistance.getMin()));
     }
     
     /**
@@ -226,17 +248,10 @@ public class DistancePanel extends ControlPanel {
      * @param featurePointWeights Map of feature point types and their weights
      */
     public void updateFeaturePointWeights(Map<FeaturePointType, Double> featurePointWeights) {
-        featurePointsStats.removeAll();
-        
-        final ControlPanelBuilder fpBuilder = new ControlPanelBuilder(featurePointsStats);
-        for (final Map.Entry<FeaturePointType, Double> fpStats: featurePointWeights.entrySet()) {
-            fpBuilder.addOptionText(fpStats.getKey().getName());
-            fpBuilder.addGap();
-            
-            fpBuilder.addLabelLine(Double.toString(fpStats.getValue()));
-            fpBuilder.addGap();
-            fpBuilder.addLine();
-        }
+        featurePointStats.forEach((fpType, fpWeightLabel) -> {
+            final Double fpWeight = featurePointWeights.get(fpType);
+            fpWeightLabel.setText(fpWeight == null ? "" : Double.toString(fpWeight));
+        });
     }
 
 }
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 3044b5613023b9e949ddbb5ae226f5a643e421b4..7cc5713639cd4392010b0f9fa7328a1a15ddbc11 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java
@@ -29,6 +29,7 @@ import javax.vecmath.Vector3d;
  * 
  * @author Richard Pajersky
  * @author Radek Oslejsek
+ * @author Daniel Schramm
  */
 public class RegistrationAction extends ControlPanelAction {
     
@@ -42,6 +43,7 @@ public class RegistrationAction extends ControlPanelAction {
     private HausdorffDistance hdVisitor = null;
     private String strategy = RegistrationPanel.STRATEGY_POINT_TO_POINT;
     private boolean relativeDist = false;
+    private boolean heatmapRender = false;
     
     /*
      * Coloring threshold and statistical values of feature point distances:
@@ -59,6 +61,21 @@ public class RegistrationAction extends ControlPanelAction {
     public RegistrationAction(Canvas canvas, JTabbedPane topControlPanel) {
         super(canvas, topControlPanel);
         this.controlPanel = new RegistrationPanel(this);
+        
+        // Place control panel to the topControlPanel
+        topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel);
+        topControlPanel.addChangeListener(e -> {
+            // If the registration panel is focused...
+            if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof RegistrationPanel) {
+                // ... display heatmap and feature points relevant to the registration
+                getCanvas().getScene().setDefaultColors();
+                calculateFeaturePoints();
+                setHeatmap();
+                getSecondaryDrawableFace().setRenderHeatmap(heatmapRender);
+            }
+        });
+        topControlPanel.setSelectedComponent(controlPanel); // Focus registration panel
+        calculateHausdorffDistance();
     }
     
     @Override
@@ -67,19 +84,12 @@ public class RegistrationAction extends ControlPanelAction {
         String action = ae.getActionCommand();
         
         switch (action) {
-            case RegistrationPanel.ACTION_COMMAND_SHOW_HIDE_PANEL:
-                hideShowPanelActionPerformed(ae, this.controlPanel);
-                if (((JToggleButton) ae.getSource()).isSelected()) {
-                    calculateFeaturePoints(); // color points 
-                    calculateHausdorffDistance();
-                } else {
-                    this.getCanvas().getScene().setDefaultColors();
-                }
-                break;
             case RegistrationPanel.ACTION_COMMAND_APPLY_ICP:
                 applyICP();
                 calculateFeaturePoints();
                 calculateHausdorffDistance();
+                this.hdVisitor = null; // recompute
+                setHeatmap();
                 break;
             case RegistrationPanel.ACTION_COMMAND_SHIFT_X:
                 value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
@@ -222,13 +232,12 @@ public class RegistrationAction extends ControlPanelAction {
                 }
                 break;
             case RegistrationPanel.ACTION_COMMAND_HD_HEATMAP:
-                if (((JToggleButton) ae.getSource()).isSelected()) {
+                heatmapRender = ((JToggleButton) ae.getSource()).isSelected();
+                if (heatmapRender) {
                     calculateHausdorffDistance();
                     setHeatmap();
-                    getSecondaryDrawableFace().setRenderHeatmap(true);
-                } else {
-                    getSecondaryDrawableFace().setRenderHeatmap(false);
                 }
+                getSecondaryDrawableFace().setRenderHeatmap(heatmapRender);
                 break;
             case RegistrationPanel.ACTION_COMMAND_HD_STRATEGY:
                 strategy = (String) ((JComboBox) ae.getSource()).getSelectedItem();
@@ -283,7 +292,7 @@ public class RegistrationAction extends ControlPanelAction {
     
     /**
      * Calculates feature points which are too far away
-     * and changes their color to red
+     * and changes their color to green
      * otherwise set color to default
      */
     private void calculateFeaturePoints() {
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 610477e27ff43eebd7aadcd47d0ab0eb4412ec04..f0e8978a33c0f467a9bd2d3f5d1f7030303ece26 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java
@@ -84,7 +84,7 @@ public class RegistrationPanel extends ControlPanel {
 
     /**
      * Listener which translates executed actions 
-     * into {@link cz.fidentis.analyst.gui.scene.DrawableMesh}
+     * into {@link cz.fidentis.analyst.scene.DrawableMesh}
      */
     private final ActionListener listener;
     
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java b/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java
index d011aa7b305d3848e8c1539f6ae6d19cbc5eb784..c6dbe3210bbd27e30b1630f2280cd12fe1e256e9 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/Drawable.java
@@ -195,7 +195,7 @@ public abstract class Drawable {
     /**
      * Sets render mode
      * @param renderMode Render mode
-     * @throws IllegalArgumentException if renderMode isn't {@code GL_FILL}, {@code GL_LINE} or {@coed GL_POINT}
+     * @throws IllegalArgumentException if renderMode isn't {@code GL_FILL}, {@code GL_LINE} or {@code GL_POINT}
      */
     public void setRenderMode(int renderMode) {
         if (renderMode != GL2.GL_FILL && 
diff --git a/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java
index d17f2c3936988a3ecc6e1bcad3fac2076849be04..3b9b93bc0aa94e658132cfff0613417203dc06ff 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/DrawableFeaturePoints.java
@@ -36,6 +36,11 @@ public class DrawableFeaturePoints extends Drawable {
      */
     private final Map<Integer, Double> specialSizes = new HashMap<>();
     
+    /**
+     * feature points rendered differently than the default render mode
+     */
+    private final Map<Integer, Integer> specialRenderModes = new HashMap<>();
+    
     /**
      * Constructor.
      * 
@@ -145,6 +150,65 @@ public class DrawableFeaturePoints extends Drawable {
     public void resetAllSizesToDefault() {
         specialSizes.clear();
     }
+    
+    /**
+     * Returns render mode of the feature point.
+     * 
+     * @param index Index of the feature point
+     * @return The render mode or {@code null}
+     */
+    public Integer getRenderMode(int index) {
+        if (index < 0 || index >= featurePoints.size()) {
+            return null;
+        }
+        if (specialRenderModes.containsKey(index)) {
+            return specialRenderModes.get(index);
+        } else {
+            return getRenderMode();
+        }
+    }
+    
+    /**
+     * Sets render mode of the feature point.
+     * The render mode must be {@link GL2#GL_FILL}, {@link GL2#GL_LINE}
+     * or {@link GL2#GL_POINT}.
+     * 
+     * @param index Index of the feature point
+     * @param renderMode New render mode of the feature point
+     * @throws IllegalArgumentException if renderMode isn't {@code GL_FILL},
+     *         {@code GL_LINE} or {@code GL_POINT}
+     */
+    public void setRenderMode(int index, int renderMode) {
+        if (renderMode != GL2.GL_FILL &&
+                renderMode != GL2.GL_LINE &&
+                renderMode != GL2.GL_POINT) {
+            throw new IllegalArgumentException("renderMode");
+        }
+        if (index < 0 || index >= featurePoints.size()) {
+            return;
+        }
+        if (renderMode == getRenderMode()) {
+            specialRenderModes.remove(index);
+        } else {
+            specialRenderModes.put(index, renderMode);
+        }
+    }
+    
+    /**
+     * Removes (possible) special render mode of the feature point.
+     * 
+     * @param index Index of the feature point
+     */
+    public void resetRenderModeToDefault(int index) {
+        setRenderMode(index, getRenderMode());
+    }
+    
+    /**
+     * Removes all individual render modes of feature points.
+     */
+    public void resetAllRenderModesToDefault() {
+        specialRenderModes.clear();
+    }
 
     @Override
     protected void renderObject(GL2 gl) {
@@ -158,12 +222,18 @@ public class DrawableFeaturePoints extends Drawable {
         
         for (int i = 0; i < featurePoints.size(); i++) {
             FeaturePoint fp = featurePoints.get(i);
+            
             Color specialColor = specialColors.get(i);
             if (specialColor != null) {
                 float[] tmpRGB = {specialColor.getRed() / 255f, specialColor.getGreen() / 255f, specialColor.getBlue() / 255f, getTransparency()};
                 gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, tmpRGB, 0);
             }
             
+            Integer specialRenderMode = specialRenderModes.get(i);
+            if (specialRenderMode != null) {
+                gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, specialRenderMode);
+            }
+            
             gl.glPushMatrix(); 
             gl.glTranslated(fp.getX(), fp.getY(), fp.getZ());
             GLUquadric center = GLU_CONTEXT.gluNewQuadric();
@@ -177,6 +247,9 @@ public class DrawableFeaturePoints extends Drawable {
             if (specialColor != null) {
                 gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, rgba, 0); // set default color
             }
+            if (specialRenderMode != null) {
+                gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, getRenderMode()); // set default render mode
+            }
         }
     }
     
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 ab19624d5e94aab63bc1796d6c4d606ea7a8c86d..7f14cee8e275a139ba89f18b008486b629e2a0ed 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/scene/Scene.java
@@ -16,6 +16,7 @@ public class Scene {
     private final List<DrawableFace> drawableFaces = new ArrayList<>();
     private final List<DrawableFeaturePoints> drawableFeaturePoints = new ArrayList<>();
     private final List<DrawablePlane> drawableSymmetryPlanes = new ArrayList<>();
+    private final List<Drawable> otherDrawables = new ArrayList<>();
     
     /**
      * Constructor for single face analysis.
@@ -153,6 +154,20 @@ public class Scene {
         }
     }
     
+    /**
+     * Adds new drawable object to the scene.
+     * 
+     * <p>
+     * Note: This drawable object is ignored in the {@link setDefaultColors} method.
+     * The caller must take care of the colors of the object themself.
+     * </p>
+     * 
+     * @param otherDrawable Drawable object to be added to the scene
+     */
+    public void addOtherDrawable(Drawable otherDrawable) {
+        otherDrawables.add(otherDrawable);
+    }
+    
     /**
      * Returns all drawable objects.
      * 
@@ -163,6 +178,7 @@ public class Scene {
         ret.addAll(this.drawableFaces);
         ret.addAll(this.drawableFeaturePoints);
         ret.addAll(this.drawableSymmetryPlanes);
+        ret.addAll(this.otherDrawables);
         while (ret.remove(null)) {}
         return ret;
     }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java b/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java
index 9df7b46ba231f59ed54401e0ea5db6a08a0f2ef6..337bfc75fc04bfa128f9244e2fe78541f47b9598 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/toolbar/FaceToFaceToolBar.java
@@ -1,19 +1,15 @@
 package cz.fidentis.analyst.toolbar;
 
 import cz.fidentis.analyst.canvas.Canvas;
-import cz.fidentis.analyst.core.ControlPanel;
 import cz.fidentis.analyst.distance.DistanceAction;
-import cz.fidentis.analyst.distance.DistancePanel;
 import cz.fidentis.analyst.registration.RegistrationAction;
-import cz.fidentis.analyst.registration.RegistrationPanel;
 import javax.swing.JTabbedPane;
-import javax.swing.JToggleButton;
-import org.openide.util.NbBundle;
 
 /**
  * A toolbar extension for the analysis of two faces.
  * 
  * @author Radek Oslejsek
+ * @author Daniel Schramm
  */
 public class FaceToFaceToolBar extends RenderingToolBar {
     
@@ -27,28 +23,14 @@ public class FaceToFaceToolBar extends RenderingToolBar {
         super(canvas);
         addPrimaryFaceButton();
         addSecondaryFaceButton();
-        addSeparator();
-        addDistanceButton(controlPanel);
-        addRegistrationButton(controlPanel);
-    }
-    
-    private void addDistanceButton(JTabbedPane controlPanel) {
-        JToggleButton button = new JToggleButton();
-        button.addActionListener(new DistanceAction(getCanvas(), controlPanel));
-        button.setActionCommand(ControlPanel.ACTION_COMMAND_SHOW_HIDE_PANEL);
-        button.setIcon(DistancePanel.getStaticIcon());
-        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "FaceToFaceToolBar.distance.text"));
-        add(button);
-        button.doClick(); // show
-    }
-    
-    private void addRegistrationButton(JTabbedPane controlPanel) {
-        JToggleButton button = new JToggleButton();
-        button.addActionListener(new RegistrationAction(getCanvas(), controlPanel));
-        button.setActionCommand(ControlPanel.ACTION_COMMAND_SHOW_HIDE_PANEL);
-        button.setIcon(RegistrationPanel.getStaticIcon());
-        button.setToolTipText(NbBundle.getMessage(RenderingToolBar.class, "FaceToFaceToolBar.registration.text"));
-        add(button);
-        button.doClick(); // show
+        
+        // (Re)render scene after all change listeners have been called
+        // (the first added listener is called last)
+        controlPanel.addChangeListener(e -> getCanvas().renderScene());
+        
+        // Add distance panel to the control panel
+        new DistanceAction(getCanvas(), controlPanel);
+        // Add registration panel to the control panel
+        new RegistrationAction(getCanvas(), controlPanel);
     }
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
index 9176377791fcd07abdc079952050863843ef8d4a..3e0328d96ec801a9583918c2cfc9fdb79aa92671 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
@@ -31,9 +31,7 @@ public class MeshTriangle implements Iterable<MeshPoint> {
     /**
      * Creates new triangle
      * 
-     * @param v1 first vertex 
-     * @param v2 second vertex
-     * @param v3 third vertex
+     * @param facet Mesh facet
      * @param i1 which index is the first vertex stored in the mesh facet
      * @param i2 which index is the second vertex stored in the mesh facet
      * @param i3 which index is the third vertex stored in the mesh facet