diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/HumanFace.java
similarity index 96%
rename from MeshModel/src/main/java/cz/fidentis/analyst/mesh/HumanFace.java
rename to Comparison/src/main/java/cz/fidentis/analyst/HumanFace.java
index 044448d1edea8e513f0080ee75a8e185c0a9b1ce..e5ef7373be6a0c4732795ef40847621041ba5cb0 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/HumanFace.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/HumanFace.java
@@ -1,4 +1,4 @@
-package cz.fidentis.analyst.mesh;
+package cz.fidentis.analyst;
 
 import cz.fidentis.analyst.mesh.core.MeshModel;
 import cz.fidentis.analyst.mesh.io.MeshObjLoader;
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/comparison/ClosestVertices.java b/Comparison/src/main/java/cz/fidentis/analyst/comparison/ClosestVertices.java
deleted file mode 100644
index 7c9cc087308ed3fa95d3ed7c16fc943a735b5b0d..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/comparison/ClosestVertices.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package cz.fidentis.analyst.comparison;
-
-import cz.fidentis.analyst.mesh.core.MeshPoint;
-
-/**
- * 
- * @author Matej Lukes
- */
-public class ClosestVertices {
-    
-    private MeshPoint firstVertex;
-    private MeshPoint secondVertex;
-    private double distance;
-
-    /**
-     * Constructor.
-     * 
-     * @param firstVertex Firt vertex of the pair
-     * @param secondVertex Second vertex of the pair
-     * @param distance Distance
-     */
-    public ClosestVertices(MeshPoint firstVertex, MeshPoint secondVertex, double distance) {
-        this.firstVertex = firstVertex;
-        this.secondVertex = secondVertex;
-        this.distance = distance;
-    }
-
-    public MeshPoint getFirstVertex() {
-        return firstVertex;
-    }
-
-    public MeshPoint getSecondVertex() {
-        return secondVertex;
-    }
-
-    public double getDistance() {
-        return distance;
-    }
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/comparison/Comparison.java b/Comparison/src/main/java/cz/fidentis/analyst/comparison/Comparison.java
deleted file mode 100644
index a7ce1c307db8f155356eb51bcae6efbae9070a13..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/comparison/Comparison.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package cz.fidentis.analyst.comparison;
-
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.io.MeshObjLoader;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * @author Matej Lukes
- */
-public class Comparison {
-    private HausdorffDistance hausdorffDistance;
-
-    private MeshFacet mainFacet;
-    private MeshFacet comparedFacet;
-
-    /**
-     * Asynchronously loads main meshModel
-     *
-     * @param path path to meshModel file
-     * @return CompletableFuture
-     */
-    public CompletableFuture loadMainModel(String path) {
-
-        return CompletableFuture.runAsync(() -> {
-            try {
-                mainFacet = MeshObjLoader.read(new File(path)).getFacets().get(1);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        });
-    }
-
-    /**
-     * Asynchronously loads compared meshModel
-     *
-     * @param path path to meshModel file
-     * @return CompletableFuture
-     */
-    public CompletableFuture loadComparedModel(String path) {
-        return CompletableFuture.runAsync(() -> {
-            try {
-                comparedFacet = MeshObjLoader.read(new File(path)).getFacets().get(1);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        });
-    }
-
-    /**
-     * Asynchronously registers compared meshFacet to main meshFacet
-     *
-     * @param method registration method
-     * @return CompletableFuture
-     */
-    public CompletableFuture register(RegistrationMethod method) {
-        return CompletableFuture.runAsync(() -> comparedFacet = Registration
-                .register(mainFacet, comparedFacet, method));
-    }
-
-    /**
-     * Asynchronously compares MeshFacets from vertices to vertices
-     *
-     * @return list containing vertex from first facet, closest vertex to it from second facet, distance
-     */
-    public CompletableFuture<List<ClosestVertices>> compareHausdorffDistanceToVertices() {
-        hausdorffDistance = new HausdorffDistance(mainFacet, comparedFacet);
-        return CompletableFuture.supplyAsync(() -> hausdorffDistance.calculateHausdorffDistanceToVertices());
-    }
-
-    /**
-     * Asynchronously compares MeshFacets from vertices to any point on mesh
-     *
-     * @return list containing vertex from first facet, closest point to it from second facet, distance
-     */
-    public CompletableFuture<List<ClosestVertices>> compareHausdorffDistanceToMesh() {
-        hausdorffDistance = new HausdorffDistance(mainFacet, comparedFacet);
-        return CompletableFuture.supplyAsync(() -> hausdorffDistance.calculateHausdorffDistanceToMesh());
-    }
-
-    /**
-     * returns progress percentage
-     *
-     * @return progress percentage
-     */
-    public double getComparisonProgress() {
-        if (hausdorffDistance == null) {
-            return -1;
-        }
-        return hausdorffDistance.getProgressPercentage();
-    }
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/comparison/HausdorffDistance.java b/Comparison/src/main/java/cz/fidentis/analyst/comparison/HausdorffDistance.java
deleted file mode 100644
index f63122bd1372f3a976781cc617d305a6ee651f58..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/comparison/HausdorffDistance.java
+++ /dev/null
@@ -1,359 +0,0 @@
-package cz.fidentis.analyst.comparison;
-
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshPoint;
-import cz.fidentis.analyst.mesh.core.MeshPointImpl;
-import cz.fidentis.analyst.mesh.core.MeshTriangle;
-import cz.fidentis.analyst.mesh.visitors.TriangleListVisitor;
-
-import javax.vecmath.Vector3d;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-
-/**
- * @author Matej Lukes
- */
-public class HausdorffDistance {
-    
-    private MeshFacet mainFacet;
-    private MeshFacet comparedFacet;
-
-    private AtomicInteger progress = new AtomicInteger();
-    private int numberOfVertices;
-
-    /**
-     * @param mainFacet     main MeshFacet
-     * @param comparedFacet compared MeshFacet
-     */
-    public HausdorffDistance(MeshFacet mainFacet, MeshFacet comparedFacet) {
-        this.mainFacet = mainFacet;
-        this.comparedFacet = comparedFacet;
-        this.numberOfVertices = mainFacet.getNumberOfVertices();
-    }
-
-    /**
-     * returns progress percentage
-     *
-     * @return progress
-     */
-    public double getProgressPercentage() {
-        return ((double) progress.get() / numberOfVertices) * 100;
-    }
-
-    /**
-     * Finds the nearest vertex on the second facet.
-     *
-     * @param vertex vertex from
-     * @return vertex, nearest vertex from second facet, distance
-     */
-    private ClosestVertices getNearestVertex(MeshPoint vertex) {
-        Optional<Pair<MeshPoint, Double>> closestVertexAndDistance = comparedFacet.getVertices().parallelStream()
-                .map((meshPoint) -> new Pair<>(meshPoint, getDistanceBetweenPoints(vertex, meshPoint.getPosition())))
-                .max((Comparator.comparingDouble(Pair::getValue)));
-        return closestVertexAndDistance.map(vector3dDoublePair -> new ClosestVertices(vertex,
-                vector3dDoublePair.getKey(),
-                vector3dDoublePair.getValue())).orElse(null);
-    }
-
-    /**
-     * returns distance between two points
-     *
-     * @param point1 first point
-     * @param point2 second point
-     * @return distance
-     */
-    private double getDistanceBetweenPoints(MeshPoint point1, Vector3d point2) {
-        Vector3d helperVector = new Vector3d();
-        helperVector.sub(point1.getPosition(), point2);
-        return Math.signum(helperVector.dot(point1.getNormal())) * helperVector.length();
-    }
-
-    /**
-     * calculates Hausdorff Distance to the nearest vertex from second facet for each vertex in first facet
-     * this implementation uses executor
-     *
-     * @return list containing vertex from first facet, closest vertex to it from second facet, distance
-     */
-    public List<ClosestVertices> calculateHausdorffDistanceToVertices() {
-        progress.set(0);
-        int numberOfVertices = mainFacet.getNumberOfVertices();
-        List<Future<ClosestVertices>> closestVerticesFutures = new ArrayList<>(numberOfVertices);
-        ExecutorService executor = Executors.newCachedThreadPool();
-
-        for (final MeshPoint vertex : mainFacet.getVertices()) {
-            closestVerticesFutures.add(executor.submit(() -> {
-                ClosestVertices result = getNearestVertex(vertex);
-                progress.addAndGet(1);
-                return result;
-            }));
-        }
-
-        List<ClosestVertices> closestVertices = new ArrayList<>(numberOfVertices);
-        for (Future<ClosestVertices> future :
-                closestVerticesFutures) {
-            executor.submit(() -> {
-                try {
-                    ClosestVertices result = future.get();
-                    synchronized (closestVertices) {
-                        closestVertices.add(result);
-                    }
-                } catch (InterruptedException | ExecutionException e) {
-                    e.printStackTrace();
-                }
-            });
-        }
-
-        executor.shutdown();
-        return closestVertices;
-    }
-
-    /**
-     * calculates Hausdorff Distance to the nearest vertex from second facet for each vertex in first facet
-     * this implementation uses parallel streams
-     *
-     * @return list containing vertex from first facet, closest vertex to it from second facet, distance
-     */
-    public List<ClosestVertices> calculateHausdorffDistanceToVertices2() {
-        progress.set(0);
-        return mainFacet.getVertices().parallelStream()
-                .map((vertex) -> {
-                    ClosestVertices result = getNearestVertex(vertex);
-                    progress.addAndGet(1);
-                    return result;
-                })
-                .collect(Collectors.toList());
-    }
-
-    /**
-     * calculates Hausdorff Distance to the nearest point on second facet for each vertex
-     * this implementation uses executor
-     *
-     * @return list containing vertex from first facet, closest point to it from second facet, distance
-     */
-    public List<ClosestVertices> calculateHausdorffDistanceToMesh() {
-        progress.set(0);
-        int numberOfVertices = mainFacet.getNumberOfVertices();
-        List<Future<ClosestVertices>> closestPointsFutures = new ArrayList<>(numberOfVertices);
-        ExecutorService executor = Executors.newCachedThreadPool();
-
-        for (final MeshPoint vertex : mainFacet.getVertices()) {
-            closestPointsFutures.add(executor.submit(() -> {
-                ClosestVertices result = calculateNearestPointOnMesh(vertex,
-                        comparedFacet.getCornerTable()
-                                .getTriangleIndexesByVertexIndex(comparedFacet.getVertices()
-                                        .indexOf(getNearestVertex(vertex)
-                                                .getSecondVertex())));
-                progress.addAndGet(1);
-                return result;
-            }));
-        }
-
-        List<ClosestVertices> closestVertices = new ArrayList<>(numberOfVertices);
-        for (Future<ClosestVertices> future : closestPointsFutures) {
-            executor.submit(() -> {
-                try {
-                    ClosestVertices result = future.get();
-                    synchronized (closestVertices) {
-                        closestVertices.add(result);
-                    }
-                } catch (InterruptedException | ExecutionException e) {
-                    e.printStackTrace();
-                }
-            });
-        }
-
-        executor.shutdown();
-        return closestVertices;
-    }
-
-    /**
-     * calculates Hausdorff Distance to the nearest point on second facet for each vertex
-     * this implementation uses parallel streams
-     *
-     * @return list containing vertex from first facet, closest point to it from second facet, distance
-     */
-    public List<ClosestVertices> calculateHausdorffDistanceToMesh2() {
-        progress.set(0);
-        return mainFacet.getVertices().parallelStream()
-                .map((meshPoint) -> {
-                    ClosestVertices result = calculateNearestPointOnMesh(meshPoint,
-                            comparedFacet.getCornerTable()
-                                    .getTriangleIndexesByVertexIndex(comparedFacet.getVertices()
-                                            .indexOf(getNearestVertex(meshPoint)
-                                                    .getSecondVertex())));
-                    progress.addAndGet(1);
-                    return result;
-                }).collect(Collectors.toList());
-    }
-
-    /**
-     * calculates Hausdorff Distance to the nearest point on second facet for vertex
-     *
-     * @param vertex                     vertex from first facet
-     * @param indicesOfTrianglesOfVertex indices of triangles that contain the nearest vertex on second mesh
-     * @return vertex from first facet, closest point to it from second facet, distance
-     */
-    private ClosestVertices calculateNearestPointOnMesh(MeshPoint vertex, List<Integer> indicesOfTrianglesOfVertex) {
-        Vector3d vertexPosition = vertex.getPosition();
-        List<Pair<Vector3d, Double>> projections = new ArrayList<>(indicesOfTrianglesOfVertex.size());
-        Vector3d helperVector = new Vector3d();
-
-        TriangleListVisitor visitor = new TriangleListVisitor();
-        comparedFacet.accept(visitor);
-        List<MeshTriangle> trList = visitor.getTriangles();
-        for (int index : indicesOfTrianglesOfVertex) {
-            List<Vector3d> triangle = new ArrayList<>();
-            triangle.add(trList.get(index).vertex1.getPosition());
-            triangle.add(trList.get(index).vertex2.getPosition());
-            triangle.add(trList.get(index).vertex3.getPosition());
-            //List<Vector3d> triangle = comparedFacet.asTriangles()..getVerticesOfTriangle(index).stream()
-            //        .map(MeshPoint::getPosition)
-            //        .collect(Collectors.toList());
-            Vector3d projection = getProjectionToTrianglePlane(vertexPosition, triangle);
-            if (isPointInTriangle(projection, triangle)) {
-                helperVector.sub(vertexPosition, projection);
-                projections.add(new Pair<>(projection, helperVector.length()));
-            } else {
-                projection = getProjectionToClosestEdge(projection, triangle);
-                helperVector.sub(vertexPosition, projection);
-                projections.add(new Pair<>(projection, helperVector.length()));
-            }
-        }
-
-        Pair<Vector3d, Double> closestPosition = projections.stream()
-                .min(Comparator.comparingDouble(Pair::getValue)).orElseGet(() -> new Pair<>(null, Double.MAX_VALUE));
-        return new ClosestVertices(vertex,
-                new MeshPointImpl(closestPosition.getKey(), null, null),
-                closestPosition.getValue());
-    }
-
-    /**
-     * returns perpendicular projection from vertex to plane of triangle
-     *
-     * @param vertex   vertex from which the projection is created
-     * @param triangle triangle that defines the plane
-     * @return projection to plane of triangle
-     */
-    private Vector3d getProjectionToTrianglePlane(Vector3d vertex, List<Vector3d> triangle) {
-        Vector3d ab = new Vector3d();
-        ab.sub(triangle.get(0), triangle.get(1));
-        Vector3d ac = new Vector3d();
-        ac.sub(triangle.get(0), triangle.get(2));
-        Vector3d normal = new Vector3d();
-        normal.cross(ab, ac);
-        normal.normalize();
-
-        Vector3d helperVector = new Vector3d(vertex);
-        helperVector.sub(triangle.get(0));
-        double distance = helperVector.dot(normal);
-        helperVector.scaleAdd(-distance, normal, helperVector);
-        return helperVector;
-    }
-
-    /**
-     * checks if a point in plane of triangle lies within the triangle
-     *
-     * @param point    checked point
-     * @param triangle triangle
-     * @return true if point is in triangle, false otherwise
-     */
-    private boolean isPointInTriangle(Vector3d point, List<Vector3d> triangle) {
-        List<Vector3d> pointToVertices = triangle.stream()
-                .map((vertex) -> {
-                    Vector3d v = new Vector3d(vertex);
-                    v.sub(point);
-                    return v;
-                }).collect(Collectors.toList());
-
-        double angleSum = 0;
-        for (int i = 0; i < 3; i++) {
-            angleSum += pointToVertices.get(i).angle(pointToVertices.get((i + 1) % 3));
-        }
-        angleSum -= Math.PI;
-        return -0.01 < angleSum && angleSum < 0.01;
-    }
-
-    /**
-     * returns projection to to the nearest edge of triangle
-     *
-     * @param point    point in plane of triangle
-     * @param triangle triangle
-     * @return perpendicular projection to the nearest edge
-     */
-    private Vector3d getProjectionToClosestEdge(Vector3d point, List<Vector3d> triangle) {
-        Vector3d[] projections = new Vector3d[3];
-        for (int i = 0; i < 3; i++) {
-            projections[i] = getProjectionToEdge(point, triangle.get(i), triangle.get((i + 1) % 3));
-        }
-
-        double minDistance = Double.MAX_VALUE;
-        Vector3d closestProjection = null;
-        Vector3d helperVector = new Vector3d();
-        for (Vector3d projection :
-                projections) {
-            helperVector.sub(point, projection);
-            double distance = helperVector.length();
-            if (distance < minDistance) {
-                minDistance = distance;
-                closestProjection = projection;
-            }
-        }
-        return closestProjection;
-    }
-
-    /**
-     * returns projection to edge
-     *
-     * @param point       point in plane of triangle
-     * @param edgeVertex1 first vertex of edge
-     * @param edgeVertex2 second vertex of edge
-     * @return projection to edge
-     */
-    private Vector3d getProjectionToEdge(Vector3d point, Vector3d edgeVertex1, Vector3d edgeVertex2) {
-        Vector3d ab = new Vector3d();
-        ab.sub(edgeVertex1, edgeVertex2);
-        Vector3d ap = new Vector3d();
-        ap.sub(edgeVertex1, point);
-        double t = ab.dot(ap) / ab.lengthSquared();
-        return new Vector3d(edgeVertex1.x + t * ab.x, edgeVertex1.y + t * ab.y, edgeVertex1.z + t * ab.z);
-    }
-    
-    
-    /**
-     * Helper class for pairs.
-     * 
-     * @param <K> key 
-     * @param <V> value
-     * @author Radek Oslejsek
-     */
-    private final class Pair<K,V> {
-        private final K key;
-        private final V value;
-       
-        /**
-         * Constructor.
-         * @param key key
-         * @param value value
-         */
-        private Pair(K key, V value) {
-            this.key = key;
-            this.value = value;
-        }
-        
-        public K getKey() {
-            return key;
-        }
-        
-        public V getValue() {
-            return value;
-        }
-    }
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/comparison/Registration.java b/Comparison/src/main/java/cz/fidentis/analyst/comparison/Registration.java
deleted file mode 100644
index dc681e550c9a874deb2cbff8adb7b4c89bea5b3c..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/comparison/Registration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package cz.fidentis.analyst.comparison;
-
-import cz.fidentis.analyst.mesh.core.MeshFacet;
-
-/**
- * 
- * @author Matej Lukes
- */
-public class Registration {
-
-    /**
-     * Heler method - TO DO
-     * 
-     * @param facet main facet
-     * @param registeredFacet refistered facet
-     * @param method registration method
-     * @return TO DO
-     */
-    public static MeshFacet register(MeshFacet facet, MeshFacet registeredFacet, RegistrationMethod method) {
-        switch (method) {
-            case NO_REGISTRATION:
-                return registeredFacet;
-            default:
-                return null;
-        }
-    }
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/comparison/RegistrationMethod.java b/Comparison/src/main/java/cz/fidentis/analyst/comparison/RegistrationMethod.java
deleted file mode 100644
index 730fcf274e47849e2ef3b8bd6b19d04ecc446201..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/comparison/RegistrationMethod.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package cz.fidentis.analyst.comparison;
-
-/**
- * @author Matej Lukes
- */
-public enum RegistrationMethod {
-    NO_REGISTRATION
-}
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
index 918c50881ef78e172b3a2e47f65f23ccc5b7e111..9b62883410673cff9658cd27dd383cae083c8d74 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
@@ -8,7 +8,6 @@ import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import cz.fidentis.analyst.mesh.core.MeshTriangle;
 import cz.fidentis.analyst.mesh.visitors.BoundingBoxVisitor;
-import cz.fidentis.analyst.mesh.visitors.TriangleListVisitor;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -49,13 +48,10 @@ public class SymmetryEstimator {
         this.facet = f;
         this.config = config;
         
-        TriangleListVisitor visitor = new TriangleListVisitor();
-        f.accept(visitor);
-        this.triangles = visitor.getTriangles();
-        
-        this.areas = new TriangleVertexAreas[triangles.size()];
-        for (int i = 0; i < areas.length; i++) {
-            areas[i] = computeTriangleVertexAreas(triangles.get(i));
+        this.areas = new TriangleVertexAreas[f.getNumTriangles()];
+        int i = 0;
+        for (MeshTriangle tri: f) {
+            areas[i++] = computeTriangleVertexAreas(tri);
         }
     }
     
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
index 7156633509af9673c2361f202a89c187c898005e..47be30f520cfe01f86b13a307612c93112ef6742 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
@@ -1,7 +1,6 @@
 package cz.fidentis.analyst.kdtree;
 
 import cz.fidentis.analyst.mesh.core.MeshFacet;
-import java.util.Collection;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -104,6 +103,10 @@ public class KdNode {
         return depth;
     }
 
+    /**
+     * Returns 3D location of vertices stored in this node
+     * @return 3D location of vertices stored in this node
+     */
     public Vector3d get3dLocation() {
         Map.Entry<MeshFacet, Integer> entry = facets.entrySet().iterator().next();
         return entry.getKey().getVertex(entry.getValue()).getPosition();
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
index 1db7603be5d26ea5f17d69f5f5c6162bf3a0642a..35694362ac33ba6dccbb5adea38a48fdab159ad3 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
@@ -1,14 +1,14 @@
 package cz.fidentis.analyst.mesh.core;
 
-import cz.fidentis.analyst.mesh.visitors.Visitor;
 import java.util.List;
+import cz.fidentis.analyst.mesh.visitors.MeshVisitor;
 
 /**
  * An ancapsulated mesh plate (with shared vertices).
  *
  * @author Matej Lukes
  */
-public interface MeshFacet {
+public interface MeshFacet extends Iterable<MeshTriangle> {
     
     /**
      * returns vertex of specified index
@@ -57,10 +57,17 @@ public interface MeshFacet {
      */
     void calculateVertexNormals();
     
+    /**
+     * Returns number of triangles.
+     * 
+     * @return number of triangles
+     */
+    int getNumTriangles();
+    
     /**
      * Entry point for visitors. 
      * 
      * @param visitor Visitor
      */
-    void accept(Visitor visitor);
+    void accept(MeshVisitor visitor);
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
index d50797953e3789ec245dd6c85a6bb0825c0ea6cd..2c9ce081e517abb57c97cbd4669888a11a227081 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
@@ -1,13 +1,14 @@
 package cz.fidentis.analyst.mesh.core;
 
-import cz.fidentis.analyst.mesh.visitors.TriangleListVisitor;
-import cz.fidentis.analyst.mesh.visitors.Visitor;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import javax.vecmath.Vector3d;
+import cz.fidentis.analyst.mesh.visitors.MeshVisitor;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 /**
  * MashFacet
@@ -37,7 +38,7 @@ public class MeshFacetImpl implements MeshFacet {
     }
     
     @Override
-    public void accept(Visitor visitor) {
+    public void accept(MeshVisitor visitor) {
         visitor.visitMeshFacet(this);
     }
 
@@ -87,14 +88,12 @@ public class MeshFacetImpl implements MeshFacet {
         }
         
         // calculate normals from corresponding triangles
-        TriangleListVisitor visitor = new TriangleListVisitor();
-        this.accept(visitor);
-        for (MeshTriangle t : visitor.getTriangles()) { 
+        for (MeshTriangle t : this) { 
             Vector3d triangleNormal = 
                     (t.vertex3.subtractPosition(t.vertex1)).crossProduct(t.vertex2.subtractPosition(t.vertex1)).getPosition();
-            normalMap.get(t.vertex1).add(triangleNormal);
-            normalMap.get(t.vertex2).add(triangleNormal);
-            normalMap.get(t.vertex3).add(triangleNormal);
+            normalMap.get(t.vertex1.getPosition()).add(triangleNormal);
+            normalMap.get(t.vertex2.getPosition()).add(triangleNormal);
+            normalMap.get(t.vertex3.getPosition()).add(triangleNormal);
         }
         
         // normalize normals:
@@ -102,6 +101,41 @@ public class MeshFacetImpl implements MeshFacet {
             normal.normalize();
         }
     }
+    
+    public int getNumTriangles() {
+        return cornerTable.getSize();
+    }
+    
+    @Override
+    public Iterator<MeshTriangle> iterator() {
+        return new Iterator<MeshTriangle>() {
+            private int index;
+    
+            /**
+             * 
+             * @param facet Mesh facet to iterate
+             */
+            @Override
+            public boolean hasNext() {
+                return index < cornerTable.getSize();
+            }
+
+            @Override
+            public MeshTriangle next() {
+                if (!hasNext()) {
+                    throw new NoSuchElementException();
+                }
+        
+                MeshTriangle tri = new MeshTriangle(
+                        vertices.get(cornerTable.getRow(index + 0).getVertexIndex()),
+                        vertices.get(cornerTable.getRow(index + 1).getVertexIndex()),
+                        vertices.get(cornerTable.getRow(index + 2).getVertexIndex()));
+        
+                index += 3;        
+                return tri;
+            }    
+        };
+    }
 
 }
 
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
index eaa796cf2f24cf15d03a742f246b8fa432f5d7df..01b745ba6c1ffa414fc1822ba52330c414b6f9db 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
@@ -1,8 +1,8 @@
 package cz.fidentis.analyst.mesh.core;
 
-import cz.fidentis.analyst.mesh.visitors.Visitor;
 import java.util.ArrayList;
 import java.util.List;
+import cz.fidentis.analyst.mesh.visitors.MeshVisitor;
 
 /**
  * MeshModel is a root node of the hierarchy
@@ -53,7 +53,7 @@ public class MeshModel {
      * 
      * @param visitor Visitor
      */
-    public void accept(Visitor visitor) {
+    public void accept(MeshVisitor visitor) {
         visitor.visitMeshModel(this);
     }
 }
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 ce92a48824f25a7198a025dfd7773ab8077e93e2..234f9376b629837f8ef954c37b3db51b94c5b48d 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
@@ -1,5 +1,8 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
 /**
  *
  * @author Natália Bebjaková
@@ -7,7 +10,7 @@ package cz.fidentis.analyst.mesh.core;
  * Adapter for the corner table representing a single triangle of the @code{MeshFacet}.
  */
 
-public class MeshTriangle { 
+public class MeshTriangle implements Iterable<MeshPoint> { 
     
     public final MeshPoint vertex1;
     public final MeshPoint vertex2;
@@ -25,6 +28,34 @@ public class MeshTriangle {
         this.vertex2 = v2; 
         this.vertex3 = v3;
     }
-    
+
+    @Override
+    public Iterator<MeshPoint> iterator() {
+        return new Iterator<MeshPoint>() {
+            private int counter = 0;
+            
+            @Override
+            public boolean hasNext() {
+                return counter < 3;
+            }
+
+            @Override
+            public MeshPoint next() {
+                if (!hasNext()) {
+                    throw new NoSuchElementException();                    
+                }
+                switch (counter++) {
+                    case 0:
+                        return vertex1;
+                    case 1:
+                        return vertex2;
+                    case 2:
+                        return vertex3;
+                    default:
+                        return null;
+                }                
+            }
+        };
+    }
     
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitor.java
index 4e138d069d3fed48b8f4ec78d21e4837e49d7536..fa3f8b791bdd6df31355170d53a66ede40e74bb2 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitor.java
@@ -7,7 +7,7 @@ import cz.fidentis.analyst.mesh.core.MeshFacet;
  * 
  * @author Radek Oslejsek
  */
-public class BoundingBoxVisitor implements Visitor {
+public class BoundingBoxVisitor implements MeshVisitor {
 
     private BoundingBox bbox;
     
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshTriVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshTriVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..881a4bd72bae9c016e4620868da8404e4e27d108
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshTriVisitor.java
@@ -0,0 +1,60 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Visitor for Hausdorff distance. 
+ * This visitor is instantiated on a single mesh facet or multiple facets. 
+ * When applied to other facets, it computes Huasdorff distance to them.
+ * 
+ * Distances to triangles are computed, in constrast to the {@code HausdorffDistMeshTriVisitor}
+ * which calculated distances to mesh points.
+ * 
+ * @author Matej Lukes
+ * @author Radek Oslejsek
+ */
+public class HausdorffDistMeshTriVisitor extends HausdorffDistMeshVisitor {
+    
+    /**
+     * @param mainFacets Facets whose distance to other facets is computed. Must not be {@code null}
+     * @param relativeDistance If true, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present), 
+     * i.e., we can get negative distances.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public HausdorffDistMeshTriVisitor(Set<MeshFacet> mainFacets, boolean relativeDistance) {
+        super(mainFacets, relativeDistance);
+    }
+    
+    /**
+     * @param mainFacet Primary facet of which distance to others is to be computed. Must not be {@code null}
+     * @param relativeDistance If true, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present), 
+     * i.e., we can get negative distances.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public HausdorffDistMeshTriVisitor(MeshFacet mainFacet, boolean relativeDistance) {
+        super(mainFacet, relativeDistance);
+    }
+    
+    @Override
+    public void visitMeshFacet(MeshFacet comparedFacet) {
+        for (Map.Entry<MeshFacet, List<Double>> entry: getDistMap().entrySet()) {
+            List<MeshPoint> vertices = entry.getKey().getVertices();
+            List<Double> distList = entry.getValue();
+            
+            boolean firstComparison = distList.isEmpty();
+            
+            for (int i = 0; i < vertices.size(); i++) {
+                Point2MeshTriVisitor visitor = new Point2MeshTriVisitor(vertices.get(i), isRelativeDistance());
+                comparedFacet.accept(visitor);
+                double dist = visitor.getDistance();
+                updateDistances(distList, firstComparison, dist, i);
+            }
+        }
+    }
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..10f26a75ffbe426a455f0d49d2eb4a524f49fe31
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshVisitor.java
@@ -0,0 +1,110 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Visitor for Hausdorff distance. 
+ * This visitor is instantiated on a single mesh facet or multiple facets. 
+ * When applied to other facets, it computes Huasdorff distance to them.
+ * 
+ * @author Matej Lukes
+ * @author Radek Oslejsek
+ */
+public class HausdorffDistMeshVisitor implements MeshVisitor {
+    
+    private boolean relativeDistance;
+    private Map<MeshFacet, List<Double>> distances = new HashMap<>();
+    
+    /**
+     * @param mainFacets Facets whose distance to other facets is computed. Must not be {@code null}
+     * @param relativeDistance If true, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present), 
+     * i.e., we can get negative distances.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public HausdorffDistMeshVisitor(Set<MeshFacet> mainFacets, boolean relativeDistance) {
+        if (mainFacets == null) {
+            throw new IllegalArgumentException("mainFacets");
+        }
+        for (MeshFacet f: mainFacets) {
+            distances.put(f, new ArrayList<>());
+        }
+        this.relativeDistance = relativeDistance;
+    }
+    
+    /**
+     * @param mainFacet Primary facet of which distance to others is to be computed. Must not be {@code null}
+     * @param relativeDistance If true, then the visitor calculates the relative distances with respect 
+     * to the normal vectors of source facets (normal vectors have to present), 
+     * i.e., we can get negative distances.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public HausdorffDistMeshVisitor(MeshFacet mainFacet, boolean relativeDistance) {
+        this(new HashSet<>(Collections.singleton(mainFacet)), relativeDistance);
+        if (mainFacet == null) {
+            throw new IllegalArgumentException("mainFacet");
+        }
+    }
+    
+    @Override
+    public void visitMeshFacet(MeshFacet comparedFacet) {
+        for (Map.Entry<MeshFacet, List<Double>> entry: distances.entrySet()) {
+            List<MeshPoint> vertices = entry.getKey().getVertices();
+            List<Double> distList = entry.getValue();
+            
+            boolean firstComparison = distList.isEmpty();
+            
+            for (int i = 0; i < vertices.size(); i++) {
+                Point2MeshVisitor visitor = new Point2MeshVisitor(vertices.get(i), relativeDistance);
+                comparedFacet.accept(visitor);
+                double dist = visitor.getDistance();
+                updateDistances(distList, firstComparison, dist, i);
+            }
+        }
+    }
+    
+    /**
+     * Return Hausdorff distance for all points of the source mesh. 
+     * A list of distances is returned for each mesh separaptely. Index of the 
+     * list corresponds to the order of vertives in the mesh facet. 
+     * Therefore, i-t number corresponds to the distance of i-th vertex of the 
+     * source mesh.
+     * 
+     * @return Hausdorff distance for all points of the source mesh
+     */
+    public Map<MeshFacet, List<Double>> getDistances() {
+        return Collections.unmodifiableMap(distances);
+    }
+    
+    protected boolean isRelativeDistance() {
+        return relativeDistance;
+    }
+    
+    protected Map<MeshFacet, List<Double>> getDistMap() {
+        return distances;
+    }
+    
+    protected void updateDistances(List<Double> distList, boolean firstComparison, double dist, int index) {
+        if (firstComparison) {
+            distList.add(dist);
+            return;
+        } 
+        
+        if (dist >= 0 && dist < distList.get(index)) {
+            distList.set(index, dist);
+            return;
+        }
+        
+        if (dist < 0 && dist > distList.get(index)) { // for relative dist only
+            distList.set(index, dist);
+        }
+    }
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitor.java
index d703b91bfcc7f0f9ef45915fe9503fc36a03a76e..fe696ea2c1f6a6604ae15221c7b5f75186d9e1bf 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitor.java
@@ -13,7 +13,7 @@ import java.util.List;
  * @author Maria Kocurekova
  */
 
-public class KdTreeBuildVisitor implements Visitor {
+public class KdTreeBuildVisitor implements MeshVisitor {
     private List<MeshFacet> facets = new LinkedList<>();
 
     @Override
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Visitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/MeshVisitor.java
similarity index 52%
rename from MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Visitor.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/MeshVisitor.java
index 1453f172dcbf4d4b691110916726840a1df1d9ba..850ffeba6ab98d7830c82e4f510ee25d8f73f55c 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Visitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/MeshVisitor.java
@@ -4,15 +4,20 @@ import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshModel;
 
 /**
- * Visitor for the traversal of @see cz.fidentis.analyst.mesh.core.MeshModel
- * and @see cz.fidentis.analyst.mesh.core.MeshFacet.
+ * An object, when instatiated, can be applied to multiple meshes via
+ * @see cz.fidentis.analyst.mesh.core.MeshModel#accept() or
+ * @see cz.fidentis.analyst.mesh.core.MeshFacet#accept(). It inspects the state
+ * of these meshes one by one, and (cumulatevely) computes some results.
+ * 
+ * Implement this interface whenever you want to define new algorithm over a mesh.
  * 
  * @author Radek Oslejsek
  */
-public interface Visitor {
+public interface MeshVisitor {
     
     /**
-     * Visits a mesh model.
+     * Visits a mesh model. Ba default, this method visits 
+     * all facets of the model automatically.
      * 
      * @param model Mesh model to be visited.
      */
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c8ed4fa36c6e0ecffa68e1faa19d5582e8f9c75
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java
@@ -0,0 +1,175 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import cz.fidentis.analyst.mesh.core.MeshTriangle;
+import java.util.ArrayList;
+import java.util.List;
+import javax.vecmath.Vector3d;
+
+/**
+ * This visitor finds mesh points that are the closest to the given 3D point.
+ * In contrast to the {@code Point2MeshVisitor} visitor, 
+ * which computes pont-to-point distance, this implementation measures 
+ * the distance to the triangles. 
+ * 
+ * Because there can be multiple triangles with the same minimal distance, the visitor
+ * returns a list of mesh facets and a list of indices corresponding 
+ * to the facets.  
+ *
+ * Returned lists have the same size. 
+ * {@code n = getIndices().get(i)} returns the index of the closest triangle on the i-th facet.
+ * Then iterate into the n-th triangle of facet {@code getClosestFacets().get(i)} to get 
+ * the triangle instance.
+ * 
+ * @author Matej Lukes
+ * @author Radek Oslejsek
+ */
+public class Point2MeshTriVisitor extends Point2MeshVisitor {
+    
+    public static final double EPS = 0.001; // tollerance for double computations
+    
+    /**
+     * @param point Mesh point of which distance is computed. Must not be {@code null}
+     * @param relativeDistance If true, the visitor calculates the distances with respect 
+     * to the normals of the source point (the normal has to be present), 
+     * i.e., we can get negative distance.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public Point2MeshTriVisitor(MeshPoint point, boolean relativeDistance) {
+        super(point, relativeDistance);
+    }
+    
+    /**
+     * @param point 3D point of which distance is computed. Must not be {@code null}
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public Point2MeshTriVisitor(Vector3d point) {
+        this (new MeshPointImpl(point, null, null), true);
+    }
+    
+    @Override
+    public void visitMeshFacet(MeshFacet facet) {
+        Vector3d my = getMyPoint().getPosition();
+        int i = 0;
+        for (MeshTriangle tri: facet) {
+            Vector3d projection = getProjectionToTrianglePlane(my, tri);
+            if (!isPointInTriangle(projection, tri)) {
+                projection = getProjectionToClosestEdge(projection, tri);
+            }
+            checkAndUpdateDistance(projection, facet, i);
+        }        
+    }
+    
+    /**
+     * returns perpendicular projection from vertex to plane of triangle
+     *
+     * @param vertex   vertex from which the projection is created
+     * @param triangle triangle that defines the plane
+     * @return projection to plane of triangle
+     */
+    private Vector3d getProjectionToTrianglePlane(Vector3d vertex, MeshTriangle triangle) {
+        Vector3d ab = new Vector3d(triangle.vertex1.getPosition());
+        ab.sub(triangle.vertex2.getPosition());
+        Vector3d ac = new Vector3d(triangle.vertex1.getPosition());
+        ac.sub(triangle.vertex3.getPosition());
+        Vector3d normal = new Vector3d();
+        normal.cross(ab, ac);
+        normal.normalize();
+
+        Vector3d projection = new Vector3d(vertex);
+        Vector3d helperVector = new Vector3d(vertex);
+        helperVector.sub(triangle.vertex1.getPosition());
+        double dist = helperVector.dot(normal);
+
+        projection.scaleAdd(-dist, normal, projection);
+        return projection;
+    }
+
+    /**
+     * checks if a point in the plane of triangle lies within the triangle
+     *
+     * @param point    checked point
+     * @param triangle triangle
+     * @return true if point is in triangle, false otherwise
+     */
+    private boolean isPointInTriangle(Vector3d point, MeshTriangle triangle) {
+        List<Vector3d> pointToVertices = new ArrayList<>();
+        for (MeshPoint p: triangle) {
+            Vector3d v = new Vector3d(p.getPosition());
+            v.sub(point);
+            pointToVertices.add(v);
+        }
+        
+        double angleSum = 0;
+        for (int i = 0; i < 3; i++) {
+            angleSum += pointToVertices.get(i).angle(pointToVertices.get((i + 1) % 3));
+        }
+        angleSum -= 2 * Math.PI;
+        return -EPS < angleSum && angleSum < EPS;
+    }
+
+    /**
+     * returns projection to the nearest edge of the triangle
+     *
+     * @param point    point in plane of triangle
+     * @param triangle triangle
+     * @return perpendicular projection to the nearest edge
+     */
+    private Vector3d getProjectionToClosestEdge(Vector3d point, MeshTriangle triangle) {
+        Vector3d[] projections = new Vector3d[3];
+        projections[0] = getProjectionToEdge(point, triangle.vertex1.getPosition(), triangle.vertex2.getPosition());
+        projections[1] = getProjectionToEdge(point, triangle.vertex2.getPosition(), triangle.vertex3.getPosition());
+        projections[2] = getProjectionToEdge(point, triangle.vertex3.getPosition(), triangle.vertex1.getPosition());
+        
+        double minDistance = Double.MAX_VALUE;
+        Vector3d closestProjection = null;
+        Vector3d helperVector = new Vector3d();
+        for (Vector3d projection: projections) {
+            helperVector.sub(point, projection);
+            double dist = helperVector.length();
+            if (dist < minDistance) {
+                minDistance = dist;
+                closestProjection = projection;
+            }
+        }
+        return closestProjection;
+    }
+
+    /**
+     * returns projection to edge
+     *
+     * @param point       point in plane of triangle
+     * @param edgeVertex1 first vertex of edge
+     * @param edgeVertex2 second vertex of edge
+     * @return projection to edge
+     */
+    private Vector3d getProjectionToEdge(Vector3d point, Vector3d edgeVertex1, Vector3d edgeVertex2) {
+        Vector3d ab = new Vector3d();
+        ab.sub(edgeVertex2, edgeVertex1);
+        Vector3d ap = new Vector3d();
+        ap.sub(point, edgeVertex1);
+        double t = ab.dot(ap) / ab.lengthSquared();
+        Vector3d projection = new Vector3d(
+                edgeVertex1.x + t * ab.x,
+                edgeVertex1.y + t * ab.y,
+                edgeVertex1.z + t * ab.z);
+
+        Vector3d projectionToEdgeVertex1 = new Vector3d();
+        projectionToEdgeVertex1.sub(edgeVertex1, projection);
+        Vector3d projectionToEdgeVertex2 = new Vector3d();
+        projectionToEdgeVertex2.sub(edgeVertex2, projection);
+
+        if (Math.abs((projectionToEdgeVertex1.length() + projectionToEdgeVertex2.length()) - ab.length()) < EPS) {
+            return projection;
+        }
+
+        if (projectionToEdgeVertex1.length() < projectionToEdgeVertex2.length()) {
+            return edgeVertex1;
+        }
+
+        return edgeVertex2;
+    }
+
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0c718fa164e8f17fef55ac73bb9deb05f8b3945
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java
@@ -0,0 +1,129 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.vecmath.Vector3d;
+
+/**
+ * This visitor finds mesh points that are the closest to the given 3D point.
+ * Because there can be multiple points with the same minimal distance, the visitor
+ * returns a list of mesh facets and a list of indices corresponding 
+ * to the facets. 
+ * 
+* Returned lists have the same size. 
+ * {@code n = getIndices().get(i)} returns the index of the closest point on the i-th facet.
+ * Then call {@code getClosestFacets().get(i).getVertex(n))} to get the closest point.
+ * 
+ * @author Matej Lukes
+ * @author Radek Oslejsek
+ */
+public class Point2MeshVisitor implements MeshVisitor {
+    
+    private boolean relativeDist;
+    private MeshPoint myPoint;
+    private double distance = Double.POSITIVE_INFINITY;
+    private int sign = 1;
+    private final List<MeshFacet> closestFacets = new ArrayList<>();
+    private final List<Integer> indices = new ArrayList<>();
+    
+    /**
+     * @param point Mesh point of which distance is computed. Must not be {@code null}
+     * @param relativeDistance If true, the visitor calculates the distances with respect 
+     * to the normals of the source point (the normal has to be present), 
+     * i.e., we can get negative distance.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public Point2MeshVisitor(MeshPoint point, boolean relativeDistance) {
+        if (point == null) {
+            throw new IllegalArgumentException("point");
+        }
+        if (point.getNormal() == null && relativeDistance) {
+            throw new IllegalArgumentException("normal required for relative distance");
+        }
+        this.myPoint = point;
+        this.relativeDist = relativeDistance;
+    }
+    
+    /**
+     * @param point 3D point of which distance is computed. Must not be {@code null}
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public Point2MeshVisitor(Vector3d point) {
+        this (new MeshPointImpl(point, null, null), true);
+    }
+
+    @Override
+    public void visitMeshFacet(MeshFacet facet) {
+        List<MeshPoint> vertices = facet.getVertices();
+        for (int i = 0; i < vertices.size(); i++) {
+            checkAndUpdateDistance(vertices.get(i).getPosition(), facet, i);
+        }
+    }
+    
+    /**
+     * Returns distance to the closest mesh point.
+     * 
+     * @return distance to the closest mesh point, 
+     * {@code Double.POSITIVE_INFINITY} if no distance has been calculated
+     */
+    public double getDistance() {
+        return relativeDist ? sign * distance : distance;
+    }
+    
+    /**
+     * Returns indeces to the closest elements (points or triangles) of corresponding facet.
+     * 
+     * @return indeces to the closest elements (points or triangles) of corresponding facet,
+     * {@code null} if no search has been performed
+     */
+    public List<Integer> getIndices() {
+        return Collections.unmodifiableList(indices);
+    }
+    
+    /**
+     * Returns the closest mesh facets (containing the closest mesh points).
+     * 
+     * @return the closest mesh facets
+     */
+    public List<MeshFacet> getClosestFacets() {
+        return Collections.unmodifiableList(closestFacets);
+    }
+
+    protected boolean isRelativeDist() {
+        return relativeDist;
+    }
+
+    protected MeshPoint getMyPoint() {
+        return myPoint;
+    }
+
+    protected int getSign() {
+        return sign;
+    }
+
+    protected void checkAndUpdateDistance(Vector3d other, MeshFacet facet, int index) {
+        Vector3d aux = new Vector3d(other);
+        aux.sub(myPoint.getPosition());
+        sign = relativeDist ? (int) Math.signum(aux.dot(myPoint.getNormal())): 1;
+        double dist = aux.length();
+            
+        if (dist > distance) {
+            return;
+        }
+        
+        if (dist < distance) { // new closest point
+            distance = dist;
+            closestFacets.clear();
+            indices.clear();
+            closestFacets.add(facet);
+            indices.add(index);
+        } else { // the same distance
+            closestFacets.add(facet);
+            indices.add(index);
+        }
+    }
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitor.java
index 8acb8c8bc098689cff9746bd20a7092adddabe9a..2608f7009ad76d883a1a99e40803287125172a09 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitor.java
@@ -1,28 +1,26 @@
 package cz.fidentis.analyst.mesh.visitors;
 
-import cz.fidentis.analyst.mesh.core.CornerTable;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshTriangle;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Visitor that collects and returs list of triangles.
+ * A visitor that collects and returns a list of triangles. 
+ * It is usefull for collecting triangles of multiple mesh facets.
+ * For iterating through triangles of a single facet, use the iterator instead.
+ * Or iterate through the facet in a for-each cycle.
  * 
  * @author Radek Oslejsek
  */
-public class TriangleListVisitor implements Visitor {
+public class TriangleListVisitor implements MeshVisitor {
     
     private List<MeshTriangle> triangles = new ArrayList<>();
 
     @Override
     public void visitMeshFacet(MeshFacet facet) {
-        CornerTable ct = facet.getCornerTable();
-        for (int i = 0; i < ct.getSize(); i += 3) {
-            triangles.add(new MeshTriangle(
-                    facet.getVertex(ct.getRow(i + 0).getVertexIndex()),
-                    facet.getVertex(ct.getRow(i + 1).getVertexIndex()),
-                    facet.getVertex(ct.getRow(i + 2).getVertexIndex())));
+        for (MeshTriangle tri : facet) {
+            triangles.add(tri);
         }
     }
     
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java
index 74a58e63c6bfa825e4102a9aef6f24ecf461557b..87abc48d9a549247a797e304b34c9af5f3710c90 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.visitors;
 
+import cz.fidentis.analyst.mesh.visitors.BoundingBoxVisitor;
 import cz.fidentis.analyst.mesh.core.MeshModel;
 import cz.fidentis.analyst.mesh.io.MeshObjLoader;
 import java.io.File;
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshTriVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshTriVisitorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..73b6a884f3b9b6bde9f073c745a1ae134835d7f8
--- /dev/null
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshTriVisitorTest.java
@@ -0,0 +1,88 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.CornerTableRow;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import java.util.List;
+import java.util.Map;
+import javax.vecmath.Vector3d;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+
+public class HausdorffDistMeshTriVisitorTest {
+
+    private MeshFacet getTrivialFacet(double offset, double size) {
+        MeshFacet facet = new MeshFacetImpl();
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(size, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, size, offset), new Vector3d(0, 0, 1), new Vector3d()));
+
+        facet.getCornerTable().addRow(new CornerTableRow(0, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(1, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(2, -1));
+
+        return facet;
+    }
+
+    @Test
+    public void visitToVerticesTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(1.5, 1);
+
+        HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, false);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+        
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(0.5, results.get(i));
+        }
+    }
+
+    @Test
+    public void visitToVerticesBehindMeshTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(-1.5, 1);
+
+        HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, false);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(2.5, results.get(i));
+        }
+    }
+
+    @Test
+    public void visitToVerticesRelativeDistanceTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(1.5, 1);
+
+        HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, true);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(0.5, results.get(i));
+        }
+    }
+
+    @Test
+    public void visitToVerticesBehindMeshRelativeDistanceTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(-1.5, 1);
+
+        HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, true);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(-2.5, results.get(i));
+        }
+    }
+    
+}
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshVisitorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0e987fc88311855f963cf7f444a39c3644288ca
--- /dev/null
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/HausdorffDistMeshVisitorTest.java
@@ -0,0 +1,88 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.CornerTableRow;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import java.util.List;
+import java.util.Map;
+import javax.vecmath.Vector3d;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+
+public class HausdorffDistMeshVisitorTest {
+
+    private MeshFacet getTrivialFacet(double offset, double size) {
+        MeshFacet facet = new MeshFacetImpl();
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(size, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, size, offset), new Vector3d(0, 0, 1), new Vector3d()));
+
+        facet.getCornerTable().addRow(new CornerTableRow(0, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(1, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(2, -1));
+
+        return facet;
+    }
+
+    @Test
+    public void visitToVerticesTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(1.5, 1);
+
+        HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, false);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+        
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(0.5, results.get(i));
+        }
+    }
+
+    @Test
+    public void visitToVerticesBehindMeshTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(-1.5, 1);
+
+        HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, false);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(2.5, results.get(i));
+        }
+    }
+
+    @Test
+    public void visitToVerticesRelativeDistanceTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(1.5, 1);
+
+        HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, true);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(0.5, results.get(i));
+        }
+    }
+
+    @Test
+    public void visitToVerticesBehindMeshRelativeDistanceTest() {
+        MeshFacet mainFacet = getTrivialFacet(1, 1);
+        MeshFacet comparedFacet = getTrivialFacet(-1.5, 1);
+
+        HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, true);
+        hausdorffDistance.visitMeshFacet(comparedFacet);
+
+        Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances();
+        List<Double> results = map.get(mainFacet);
+        for (int i = 0; i < mainFacet.getNumberOfVertices(); i++) {
+            assertEquals(-2.5, results.get(i));
+        }
+    }
+
+}
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitorTest.java
index 1fead8af2d734a556b7de83354a421562cbdd022..8de5cebe908230b1ec465fcf8e505cbd593e36e3 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitorTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/KdTreeBuildVisitorTest.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.visitors;
 
+import cz.fidentis.analyst.mesh.visitors.KdTreeBuildVisitor;
 import cz.fidentis.analyst.kdtree.KdNode;
 import cz.fidentis.analyst.mesh.core.*;
 import cz.fidentis.analyst.mesh.io.MeshObjLoader;
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9fbaae3b7e50458416c6dc8e7a81cb5d4983a9fb
--- /dev/null
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java
@@ -0,0 +1,320 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.CornerTableRow;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import cz.fidentis.analyst.mesh.core.MeshTriangle;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import javax.vecmath.Vector3d;
+import org.junit.jupiter.api.Assertions;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * @author oslejsek
+ */
+public class Point2MeshTriVisitorTest {
+    private MeshFacet getTrivialFacet(double offset, double size) {
+        MeshFacet facet = new MeshFacetImpl();
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(size, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, size, offset), new Vector3d(0, 0, 1), new Vector3d()));
+
+        facet.getCornerTable().addRow(new CornerTableRow(0, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(1, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(2, -1));
+
+        return facet;
+    }
+
+    @Test
+    public void absoluteDistTest() {
+        MeshFacet facet = getTrivialFacet(1.5, 1);
+        MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d());
+        
+        Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false);
+        facet.accept(vis);
+        assertEquals(1.5, vis.getDistance());
+        
+        List<Integer> closestPoints = vis.getIndices();
+        List<MeshFacet> closestMeshes = vis.getClosestFacets();
+        assertNotNull(closestPoints);
+        assertNotNull(closestMeshes);
+        assertEquals(1, closestPoints.size());
+        assertEquals(1, closestMeshes.size());
+        assertEquals(facet, closestMeshes.get(0));
+        assertEquals(0, closestPoints.get(0));
+    }
+    
+    @Test
+    public void relativeDistTest() {
+        MeshFacet facet = getTrivialFacet(1.5, 1);
+        MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d());
+        
+        Point2MeshVisitor vis = new Point2MeshTriVisitor(point, true);
+        facet.accept(vis);
+        assertEquals(-1.5, vis.getDistance());
+        
+        List<Integer> closestPoints = vis.getIndices();
+        List<MeshFacet> closestMeshes = vis.getClosestFacets();
+        assertNotNull(closestPoints);
+        assertNotNull(closestMeshes);
+        assertEquals(1, closestPoints.size());
+        assertEquals(1, closestMeshes.size());
+        assertEquals(facet, closestMeshes.get(0));
+        assertEquals(0, closestPoints.get(0));
+    }
+    
+    @Test
+    public void exactMatchTest() {
+        MeshFacet facet = getTrivialFacet(1.5, 1);
+        MeshPoint point = new MeshPointImpl(new Vector3d(0, 0, 1.5), new Vector3d(0, 0, 1), new Vector3d());
+        
+        System.out.println(facet.getVertices());
+        
+        Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false);
+        facet.accept(vis);
+        assertEquals(0, vis.getDistance());
+        
+        System.out.println(facet.getVertices());
+        
+        List<Integer> closestPoints = vis.getIndices();
+        List<MeshFacet> closestMeshes = vis.getClosestFacets();
+        assertNotNull(closestPoints);
+        assertNotNull(closestMeshes);
+        assertEquals(1, closestPoints.size());
+        assertEquals(1, closestMeshes.size());
+        assertEquals(facet, closestMeshes.get(0));
+        assertEquals(0, closestPoints.get(0));
+    }
+    
+    @Test
+    public void getProjectionToTrianglePlaneTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[2];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = MeshTriangle.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToTrianglePlane", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[2];
+
+        args[0] = new Vector3d(0, 0.5, 1);
+        MeshTriangle triangle = new MeshTriangle(
+                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
+                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
+                new MeshPointImpl(new Vector3d(2, 0, 0), null, null)
+        );
+        args[1] = triangle;
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(0d, result.x);
+        Assertions.assertEquals(0.5d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+    @Test
+    public void getProjectionToTrianglePlaneBelowPLaneTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[2];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = MeshTriangle.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToTrianglePlane", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[2];
+
+        args[0] = new Vector3d(0, 0.5, 1);
+        MeshTriangle triangle = new MeshTriangle(
+                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
+                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
+                new MeshPointImpl(new Vector3d(2, 0, 0), null, null)
+        );
+        args[1] = triangle;
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(0d, result.x);
+        Assertions.assertEquals(0.5d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+    @Test
+    public void isPointInTriangleInsideTriangleTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[2];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = MeshTriangle.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("isPointInTriangle", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[2];
+
+        args[0] = new Vector3d(1.2, 0.2, 0);
+        MeshTriangle triangle = new MeshTriangle(
+                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
+                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
+                new MeshPointImpl(new Vector3d(2, 0, 0), null, null)
+        );
+        args[1] = triangle;
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        boolean result = (boolean) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertTrue(result);
+    }
+
+    @Test
+    public void isPointInTriangleOutsideTriangleTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[2];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = MeshTriangle.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("isPointInTriangle", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[2];
+
+        args[0] = new Vector3d(0, 0.5, 0);
+        MeshTriangle triangle = new MeshTriangle(
+                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
+                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
+                new MeshPointImpl(new Vector3d(2, 0, 0), null, null)
+        );
+        args[1] = triangle;
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        boolean result = (boolean) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertFalse(result);
+    }
+
+    @Test
+    public void getProjectionToClosestEdgeTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[2];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = MeshTriangle.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToClosestEdge", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[2];
+
+        args[0] = new Vector3d(0, 0.5, 0);
+        MeshTriangle triangle = new MeshTriangle(
+                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
+                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
+                new MeshPointImpl(new Vector3d(2, 0, 0), null, null)
+        );
+        args[1] = triangle;
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(1d, result.x);
+        Assertions.assertEquals(0.5d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+    @Test
+    public void getProjectionToClosestEdgeNormalProjectionOutsideEdgeTestTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[2];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = MeshTriangle.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToClosestEdge", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[2];
+
+        args[0] = new Vector3d(0, -0.5, 0);
+        MeshTriangle triangle = new MeshTriangle(
+                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
+                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
+                new MeshPointImpl(new Vector3d(2, 0, 0), null, null)
+        );
+        args[1] = triangle;
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(1d, result.x);
+        Assertions.assertEquals(0d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+    @Test
+    public void getProjectionToEdgeTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[3];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = Vector3d.class;
+        argClasses[2] = Vector3d.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToEdge", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[3];
+
+        args[0] = new Vector3d(0, 0.5, 0);
+        args[1] = new Vector3d(1, 2, 0);
+        args[2] = new Vector3d(1, 0, 0);
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(1d, result.x);
+        Assertions.assertEquals(0.5d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+    @Test
+    public void getProjectionToEdgeNormalProjectionOutsideEdgeTest()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[3];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = Vector3d.class;
+        argClasses[2] = Vector3d.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToEdge", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[3];
+
+        args[0] = new Vector3d(0, -0.5, 0);
+        args[1] = new Vector3d(1, 2, 0);
+        args[2] = new Vector3d(1, 0, 0);
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(1d, result.x);
+        Assertions.assertEquals(0d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+    @Test
+    public void getProjectionToEdgeNormalProjectionOutsideEdge2Test()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class<?>[] argClasses = new Class[3];
+        argClasses[0] = Vector3d.class;
+        argClasses[1] = Vector3d.class;
+        argClasses[2] = Vector3d.class;
+        Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToEdge", argClasses);
+        method.setAccessible(true);
+        Object[] args = new Object[3];
+
+        args[0] = new Vector3d(0, 2.5, 0);
+        args[1] = new Vector3d(1, 2, 0);
+        args[2] = new Vector3d(1, 0, 0);
+
+        Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false);
+        Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args);
+
+        Assertions.assertEquals(1d, result.x);
+        Assertions.assertEquals(2d, result.y);
+        Assertions.assertEquals(0d, result.z);
+    }
+
+}
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a53154a39821e1c2539e7dbfaebbef733f038b1
--- /dev/null
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java
@@ -0,0 +1,86 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.CornerTableRow;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import java.util.List;
+import javax.vecmath.Vector3d;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
+
+public class Point2MeshVisitorTest {
+    private MeshFacet getTrivialFacet(double offset, double size) {
+        MeshFacet facet = new MeshFacetImpl();
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(size, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
+        facet.addVertex(new MeshPointImpl(new Vector3d(0, size, offset), new Vector3d(0, 0, 1), new Vector3d()));
+
+        facet.getCornerTable().addRow(new CornerTableRow(0, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(1, -1));
+        facet.getCornerTable().addRow(new CornerTableRow(2, -1));
+
+        return facet;
+    }
+
+    @Test
+    public void absoluteDistTest() {
+        MeshFacet facet = getTrivialFacet(1.5, 1);
+        MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d());
+        
+        Point2MeshVisitor vis = new Point2MeshVisitor(point, false);
+        facet.accept(vis);
+        assertEquals(1.5, vis.getDistance());
+        
+        List<Integer> closestPoints = vis.getIndices();
+        List<MeshFacet> closestMeshes = vis.getClosestFacets();
+        assertNotNull(closestPoints);
+        assertNotNull(closestMeshes);
+        assertEquals(1, closestPoints.size());
+        assertEquals(1, closestMeshes.size());
+        assertEquals(facet, closestMeshes.get(0));
+        assertEquals(0, closestPoints.get(0));
+    }
+
+    @Test
+    public void relativeDistTest() {
+        MeshFacet facet = getTrivialFacet(1.5, 1);
+        MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d());
+        
+        Point2MeshVisitor vis = new Point2MeshVisitor(point, true);
+        facet.accept(vis);
+        assertEquals(-1.5, vis.getDistance());
+        
+        List<Integer> closestPoints = vis.getIndices();
+        List<MeshFacet> closestMeshes = vis.getClosestFacets();
+        assertNotNull(closestPoints);
+        assertNotNull(closestMeshes);
+        assertEquals(1, closestPoints.size());
+        assertEquals(1, closestMeshes.size());
+        assertEquals(facet, closestMeshes.get(0));
+        assertEquals(0, closestPoints.get(0));
+    }
+    
+    @Test
+    public void exactMatchTest() {
+        MeshFacet facet = getTrivialFacet(1.5, 1);
+        MeshPoint point = new MeshPointImpl(new Vector3d(0, 0, 1.5), new Vector3d(0, 0, 1), new Vector3d());
+        
+        System.out.println(facet.getVertices());
+        
+        Point2MeshVisitor vis = new Point2MeshVisitor(point, false);
+        facet.accept(vis);
+        assertEquals(0, vis.getDistance());
+        
+        List<Integer> closestPoints = vis.getIndices();
+        List<MeshFacet> closestMeshes = vis.getClosestFacets();
+        assertNotNull(closestPoints);
+        assertNotNull(closestMeshes);
+        assertEquals(1, closestPoints.size());
+        assertEquals(1, closestMeshes.size());
+        assertEquals(facet, closestMeshes.get(0));
+        assertEquals(0, closestPoints.get(0));
+    }
+}
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitorTest.java
index 9221bd871ff70ce22d8ecd6fd4edd652a1a51090..6f3dd6d8665ccdc96b926753d052160e62f2d925 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitorTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/TriangleListVisitorTest.java
@@ -1,6 +1,6 @@
 package cz.fidentis.analyst.mesh.visitors;
 
-import cz.fidentis.analyst.mesh.visitors.*;
+import cz.fidentis.analyst.mesh.visitors.TriangleListVisitor;
 import cz.fidentis.analyst.mesh.core.MeshModel;
 import cz.fidentis.analyst.mesh.io.MeshObjLoader;
 import cz.fidentis.analyst.mesh.io.MeshObjLoader;