diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
index c68e0f4e051c56fc1225b3efa130d435cb1a23b1..cb9cfaa3db6c98feb84d7b5b976d0c65f971f781 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
@@ -1,13 +1,15 @@
 package cz.fidentis.analyst.symmetry;
 
 import cz.fidentis.analyst.mesh.core.MeshFacet;
-import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
+import javax.vecmath.Vector3d;
 
 /**
  *
  * @author Natália Bebjaková
  * 
- * Representation of the plane 
+ * Representation of the symmetry plane 
  */
 public class Plane {
     public double a;
@@ -52,36 +54,38 @@ public class Plane {
      * @param scale distance of points given by bounding box
      * @return plane represented as mesh 
      */
-    public static SymmetryEstimator createPlaneMesh(MeshPoint centroid, MeshPoint a, MeshPoint b, double scale) {
-        facet = new MeshFacet();
-        SymmetryEstimator planeMesh = new SymmetryEstimator(facet, Config.getDefault());
-        
-        MeshPoint[] points = new MeshPoint[4];
+    public static SymmetryEstimator createPlaneMesh(Vector3d centroid, Vector3d a, Vector3d b, double scale) {
+        Vector3d[] points = new Vector3d[4];
         
-        points[0] = centroid.subtractPosition(a.multiplyPosition(scale)).subtractPosition(b.multiplyPosition(scale));
-        points[1] = centroid.subtractPosition(a.multiplyPosition(scale)).addPosition(b.multiplyPosition(scale));
-        points[2] = centroid.addPosition(a.multiplyPosition(scale)).addPosition(b.multiplyPosition(scale));
-        points[3] = centroid.addPosition(a.multiplyPosition(scale)).subtractPosition(b.multiplyPosition(scale));
+        Vector3d aScaled = new Vector3d(a);
+        Vector3d bScaled = new Vector3d(b);
+        aScaled.scale(scale);
+        bScaled.scale(scale);
         
-        for (MeshPoint point : points) {
-            facet.addVertex(point);
-        }
-
-        Triangle[] triangles = new Triangle[4];
+        points[0] = new Vector3d(centroid);
+        points[0].sub(aScaled);
+        points[0].sub(bScaled);
         
-        triangles[0] = new Triangle(0, 1, 2);
-        triangles[1] = new Triangle(0, 2, 3);
-        triangles[2] = new Triangle(0, 2, 1);
-        triangles[3] = new Triangle(0, 3, 2);
-        planeMesh.setTriangles(triangles);
+        points[1] = new Vector3d(centroid);
+        points[1].sub(aScaled);
+        points[1].add(bScaled);
         
-        MeshPoint[] normals = planeMesh.calculateNormals();
+        points[2] = new Vector3d(centroid);
+        points[2].add(aScaled);
+        points[2].add(bScaled);
         
-        facet.getVertices().clear();
+        points[3] = new Vector3d(centroid);
+        points[3].add(aScaled);
+        points[3].sub(bScaled);
         
-        for (int i = 0; i < points.length; i++) {
-            facet.addVertex(new MeshPoint(points[i].getPosition(),normals[i].getPosition(),null));
+        facet = new MeshFacetImpl();
+        for (Vector3d point : points) {
+            facet.addVertex(new MeshPointImpl(point, null, null));
         }
+        facet.calculateVertexNormals();
+
+        SymmetryEstimator planeMesh = new SymmetryEstimator(facet, Config.getDefault());
+        
         return planeMesh;
     }
     
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 e42754f6b17476f8e63a68baead6b8d8464de4f5..50e9f043b3d572ea22ce7d7ac486c295fcabd574 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
@@ -3,9 +3,15 @@ package cz.fidentis.analyst.symmetry;
 import cz.fidentis.analyst.mesh.core.CornerTableRow;
 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.BoundingBox;
+import cz.fidentis.analyst.mesh.core.MeshTriangle;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import javax.swing.ImageIcon;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
@@ -39,7 +45,8 @@ public class SymmetryEstimator {
     /**
      * Helping array of triangles computed from corner table 
      */
-    protected Triangle[] triangles;
+    private List<MeshTriangle> triangles;
+    
     /**
      * panel for configuration of symmetry counting 
      */
@@ -90,10 +97,14 @@ public class SymmetryEstimator {
         this.facet = f;
         this.config = config;
         
-        initTriangles();
-        initArrayOfTriangleVertexAreas();
+        this.triangles = f.asTriangles();
+        
+        this.areas = new TriangleVertexAreas[triangles.size()];
+        for (int i = 0; i < areas.length; i++) {
+            areas[i] = computeTriangleVertexAreas(triangles.get(i));
+        }
 
-        boundingBox = new BoundingBox(facet.getVertices());
+        boundingBox = facet.getBoundingBox();
     }
     
     /**
@@ -103,35 +114,11 @@ public class SymmetryEstimator {
      */
     public BoundingBox getBoundingBox() {
         if (boundingBox == null) {
-            boundingBox = new BoundingBox(facet.getVertices());               
+            boundingBox = facet.getBoundingBox();
         }
         return boundingBox; 
     }
 
-    /**
-     * 
-     * @param boundingBox new min-max box of the boundries of the model. 
-     */
-    public void setBoundingBox(BoundingBox boundingBox) {
-        this.boundingBox = boundingBox;
-    }
-    
-    /**
-     * 
-     * @return array of triangles 
-     */
-    public Triangle[] getTriangles() {
-        return triangles;
-    }
-    
-    /**
-     * 
-     * @param triangles new array of triangles 
-     */
-    public void setTriangles(Triangle[] triangles) {
-        this.triangles = triangles;
-    }
-    
     /**
      * Representation of areas of Voronoi region of triangles
      * used for computing Gaussian curvature 
@@ -144,52 +131,13 @@ public class SymmetryEstimator {
             public double v3Area;
     }
    
-    /**
-     * Computes triangles of facet from corner table
-     */
-    public void initTriangles() {
-        triangles = new Triangle[facet.getCornerTable().getSize() / 3];
-        for (int i = 0; i < facet.getCornerTable().getSize(); i += 3) {
-            Triangle t = new Triangle(facet.getCornerTable().getRow(i).getVertexIndex(),
-                    facet.getCornerTable().getRow(i + 1).getVertexIndex(),
-                    facet.getCornerTable().getRow(i + 2).getVertexIndex());
-            triangles[(i / 3)] = t;
-        }
-    }
-    
-    /**
-     * Calculates new normals of the points for models that do not have normals
-     * 
-     * @return new normals represented as mesh points so that math operations can be done 
-     */
-    public MeshPoint[] calculateNormals() {
-        MeshPoint[] newNormals = new MeshPoint[facet.getNumberOfVertices()];
-        for (int i = 0; i < facet.getNumberOfVertices(); i++) {
-            newNormals[i] = new MeshPoint(new Vector3d(0, 0, 0), null, null);
-        }
-        for (Triangle t : triangles) {
-            MeshPoint triangleNormal = (facet.getVertices().get(t.vertex3).subtractPosition
-        (facet.getVertices().get(t.vertex1))).crossProduct(facet.getVertices().get(t.vertex2).subtractPosition(facet.getVertices().get(t.vertex1)));
-            newNormals[t.vertex1] = newNormals[t.vertex1].addPosition(new MeshPoint(triangleNormal.getPosition(), null, null));
-            newNormals[t.vertex2] = newNormals[t.vertex2].addPosition(new MeshPoint(triangleNormal.getPosition(), null, null));
-            newNormals[t.vertex3] = newNormals[t.vertex3].addPosition(new MeshPoint(triangleNormal.getPosition(), null, null));
-        }
-        for (int i = 0; i < newNormals.length; i++){ 
-            if (newNormals[i].getPosition().x != 0 && newNormals[i].getPosition().y != 0 && newNormals[i].getPosition().z != 0) {
-                newNormals[i] = newNormals[i].dividePosition(newNormals[i].abs());
-            }   
-        }
-        return newNormals;
-    }
-    
     /**
      * 
      * @param pointIndex index of point for which we are searching traingles in its neighborhood
      * @return triangle neighbours of given index of vertex
      */
-    public List<Integer> getNeighbours(int pointIndex) {
-        List<Integer> neighbours = facet.getCornerTable().getTriangleIndexesByVertexIndex(pointIndex);
-        return neighbours;
+    protected List<Integer> getNeighbours(int pointIndex) {
+        return facet.getCornerTable().getTriangleIndexesByVertexIndex(pointIndex);
     }
     
     /**
@@ -198,16 +146,10 @@ public class SymmetryEstimator {
      * @param t triangle of which area is computed
      * @return area of Voronoi region
      */
-    private TriangleVertexAreas computeTriangleVertexAreas(Triangle t) {
-        MeshPoint circumcenter;
-                
-        MeshPoint tVertex1 = facet.getVertices().get(t.vertex1);
-        MeshPoint tVertex2 = facet.getVertices().get(t.vertex2);
-        MeshPoint tVertex3 = facet.getVertices().get(t.vertex3);
-        
-        double a = (tVertex2.subtractPosition(tVertex3)).abs();
-        double b = (tVertex3.subtractPosition(tVertex1)).abs();
-        double c = (tVertex2.subtractPosition(tVertex1)).abs();
+    private TriangleVertexAreas computeTriangleVertexAreas(MeshTriangle t) {
+        double a = (t.vertex2.subtractPosition(t.vertex3)).abs();
+        double b = (t.vertex3.subtractPosition(t.vertex1)).abs();
+        double c = (t.vertex2.subtractPosition(t.vertex1)).abs();
         
         double d1 = a * a * (b * b + c * c - a * a);
         double d2 = b * b * (c * c + a * a - b * b);
@@ -218,94 +160,79 @@ public class SymmetryEstimator {
         d2 /= dSum;
         d3 /= dSum;
 
-        MeshPoint v1Half = (tVertex2.addPosition(tVertex3)).dividePosition(2);
-        MeshPoint v2Half = (tVertex1.addPosition(tVertex3)).dividePosition(2);
-        MeshPoint v3Half = (tVertex2.addPosition(tVertex1)).dividePosition(2);
+        MeshPoint v1Half = (t.vertex2.addPosition(t.vertex3)).dividePosition(2);
+        MeshPoint v2Half = (t.vertex1.addPosition(t.vertex3)).dividePosition(2);
+        MeshPoint v3Half = (t.vertex2.addPosition(t.vertex1)).dividePosition(2);
 
         
         TriangleVertexAreas area = new TriangleVertexAreas();
 
         if (d1 < 0) {           
-            area.v3Area = ((v2Half.subtractPosition(tVertex3)).crossProduct(v1Half.subtractPosition(tVertex3))).abs() / 2;
-            area.v2Area = ((v3Half.subtractPosition(tVertex2)).crossProduct(v1Half.subtractPosition(tVertex2))).abs() / 2;
-            area.v1Area = (((v1Half.subtractPosition(tVertex1)).crossProduct(v3Half.subtractPosition(tVertex1))).abs() / 2) + 
-                    (((v1Half.subtractPosition(tVertex1)).crossProduct(v2Half.subtractPosition(tVertex1))).abs() / 2);
+            area.v3Area = ((v2Half.subtractPosition(t.vertex3)).crossProduct(v1Half.subtractPosition(t.vertex3))).abs() / 2.0;
+            area.v2Area = ((v3Half.subtractPosition(t.vertex2)).crossProduct(v1Half.subtractPosition(t.vertex2))).abs() / 2.0;
+            area.v1Area = (((v1Half.subtractPosition(t.vertex1)).crossProduct(v3Half.subtractPosition(t.vertex1))).abs() / 2.0) + 
+                    (((v1Half.subtractPosition(t.vertex1)).crossProduct(v2Half.subtractPosition(t.vertex1))).abs() / 2.0);
             return area;
         }
         if (d2 < 0) {
-            area.v1Area = ((v3Half.subtractPosition(tVertex1)).crossProduct(v2Half.subtractPosition(tVertex1))).abs() / 2;
-            area.v3Area = ((v1Half.subtractPosition(tVertex3)).crossProduct(v2Half.subtractPosition(tVertex3))).abs() / 2;
-            area.v2Area = (((v2Half.subtractPosition(tVertex2)).crossProduct(v1Half.subtractPosition(tVertex2))).abs() / 2) + 
-                    (((v2Half.subtractPosition(tVertex2)).crossProduct(v3Half.subtractPosition(tVertex2))).abs() / 2);
+            area.v1Area = ((v3Half.subtractPosition(t.vertex1)).crossProduct(v2Half.subtractPosition(t.vertex1))).abs() / 2.0;
+            area.v3Area = ((v1Half.subtractPosition(t.vertex3)).crossProduct(v2Half.subtractPosition(t.vertex3))).abs() / 2.0;
+            area.v2Area = (((v2Half.subtractPosition(t.vertex2)).crossProduct(v1Half.subtractPosition(t.vertex2))).abs() / 2.0) + 
+                    (((v2Half.subtractPosition(t.vertex2)).crossProduct(v3Half.subtractPosition(t.vertex2))).abs() / 2.0);
             return area;
         }
         if (d3 < 0) {
-            area.v2Area = ((v1Half.subtractPosition(tVertex2)).crossProduct(v3Half.subtractPosition(tVertex2))).abs() / 2;
-            area.v1Area = ((v2Half.subtractPosition(tVertex1)).crossProduct(v3Half.subtractPosition(tVertex1))).abs() / 2;
-            area.v3Area = (((v3Half.subtractPosition(tVertex3)).crossProduct(v2Half.subtractPosition(tVertex3))).abs() / 2) + 
-                    (((v3Half.subtractPosition(tVertex3)).crossProduct(v1Half.subtractPosition(tVertex3))).abs() / 2);
+            area.v2Area = ((v1Half.subtractPosition(t.vertex2)).crossProduct(v3Half.subtractPosition(t.vertex2))).abs() / 2.0;
+            area.v1Area = ((v2Half.subtractPosition(t.vertex1)).crossProduct(v3Half.subtractPosition(t.vertex1))).abs() / 2.0;
+            area.v3Area = (((v3Half.subtractPosition(t.vertex3)).crossProduct(v2Half.subtractPosition(t.vertex3))).abs() / 2.0) + 
+                    (((v3Half.subtractPosition(t.vertex3)).crossProduct(v1Half.subtractPosition(t.vertex3))).abs() / 2.0);
             return area;
         }
         
-        circumcenter = tVertex1.multiplyPosition(d1).addPosition(tVertex2.multiplyPosition(d2).addPosition(tVertex3.multiplyPosition(d3)));
+        MeshPoint circumcenter = t.vertex1.multiplyPosition(d1).addPosition(t.vertex2.multiplyPosition(d2).addPosition(t.vertex3.multiplyPosition(d3)));
         
-        area.v1Area = (((v2Half.subtractPosition(tVertex1)).crossProduct(circumcenter.subtractPosition(tVertex1))).abs() / 2) + 
-                (((v3Half.subtractPosition(tVertex1)).crossProduct(circumcenter.subtractPosition(tVertex1))).abs() / 2);
+        area.v1Area = (((v2Half.subtractPosition(t.vertex1)).crossProduct(circumcenter.subtractPosition(t.vertex1))).abs() / 2.0) + 
+                (((v3Half.subtractPosition(t.vertex1)).crossProduct(circumcenter.subtractPosition(t.vertex1))).abs() / 2.0);
         
-        area.v2Area = (((v3Half.subtractPosition(tVertex2)).crossProduct(circumcenter.subtractPosition(tVertex2))).abs() / 2) +
-                (((v1Half.subtractPosition(tVertex2)).crossProduct(circumcenter.subtractPosition(tVertex2))).abs() / 2);
+        area.v2Area = (((v3Half.subtractPosition(t.vertex2)).crossProduct(circumcenter.subtractPosition(t.vertex2))).abs() / 2.0) +
+                (((v1Half.subtractPosition(t.vertex2)).crossProduct(circumcenter.subtractPosition(t.vertex2))).abs() / 2.0);
         
-        area.v3Area = (((v1Half.subtractPosition(tVertex3)).crossProduct(circumcenter.subtractPosition(tVertex3))).abs() / 2) +
-                (((v2Half.subtractPosition(tVertex3)).crossProduct(circumcenter.subtractPosition(tVertex3))).abs() / 2);
+        area.v3Area = (((v1Half.subtractPosition(t.vertex3)).crossProduct(circumcenter.subtractPosition(t.vertex3))).abs() / 2.0) +
+                (((v2Half.subtractPosition(t.vertex3)).crossProduct(circumcenter.subtractPosition(t.vertex3))).abs() / 2.0);
         return area;
     }
     
     /**
-     * Computes area of Voronoi region for all triangles
-     */
-    private void initArrayOfTriangleVertexAreas() {
-        areas = new TriangleVertexAreas[triangles.length];
-        for (int i = 0; i < areas.length; i++) {
-            areas[i] = computeTriangleVertexAreas(triangles[i]);
-        }
-    }
- 
-    /**
-     * Calculates angle of the triangle according to centerIndex
+     * Calculates angle of the triangle according to center point
      * 
-     * @param centerIndex centerIndex
+     * @param centerPoint center point
      * @param t triangle
      * @return angle
      */
-    private double calculateTriangleAlfa(int centerIndex, Triangle t) {        
-        MeshPoint tVertex1 = facet.getVertices().get(t.vertex1);
-        MeshPoint tVertex2 = facet.getVertices().get(t.vertex2);
-        MeshPoint tVertex3 = facet.getVertices().get(t.vertex3);
-        
+    private double calculateTriangleAlfa(MeshPoint centerPoint, MeshTriangle t) {        
         double alfaCos = 0;
         
-        if (t.vertex1 == centerIndex) {
-            MeshPoint e1 = tVertex1.subtractPosition(tVertex3);
+        if (t.vertex1 == centerPoint) {
+            MeshPoint e1 = t.vertex1.subtractPosition(t.vertex3);
             e1 = e1.dividePosition(e1.abs());
             
-            MeshPoint e2 = tVertex2.subtractPosition(tVertex3);
+            MeshPoint e2 = t.vertex2.subtractPosition(t.vertex3);
             e2 = e2.dividePosition(e2.abs());
             
             alfaCos = e1.dotProduct(e2);
-        } else if (t.vertex2 == centerIndex) {
-            
-            MeshPoint e1 = tVertex2.subtractPosition(tVertex1);
+        } else if (t.vertex2 == centerPoint) {
+            MeshPoint e1 = t.vertex2.subtractPosition(t.vertex1);
             e1 = e1.dividePosition(e1.abs());
             
-            MeshPoint e2 = tVertex3.subtractPosition(tVertex1);
+            MeshPoint e2 = t.vertex3.subtractPosition(t.vertex1);
             e2 = e2.dividePosition(e2.abs());
             
             alfaCos = e1.dotProduct(e2);
-        } else if (t.vertex3 == centerIndex){
-            MeshPoint e1 = tVertex3.subtractPosition(tVertex2);
+        } else if (t.vertex3 == centerPoint){
+            MeshPoint e1 = t.vertex3.subtractPosition(t.vertex2);
             e1 = e1.dividePosition(e1.abs());
                 
-            MeshPoint e2 = tVertex1.subtractPosition(tVertex2);
+            MeshPoint e2 = t.vertex1.subtractPosition(t.vertex2);
             e2 = e2.dividePosition(e2.abs());
             
             alfaCos = e1.dotProduct(e2);
@@ -315,41 +242,36 @@ public class SymmetryEstimator {
     }
 
     /**
-     * Calculates angle of the triangle according to centerIndex
+     * Calculates angle of the triangle according to center point
      * 
-     * @param centerIndex centerIndex
+     * @param centerPoint center point
      * @param t triangle
      * @return angle
      */
-    private double calculateTriangleBeta(int centerIndex, Triangle t) {
-        MeshPoint tVertex1 = facet.getVertices().get(t.vertex1);
-        MeshPoint tVertex2 = facet.getVertices().get(t.vertex2);
-        MeshPoint tVertex3 = facet.getVertices().get(t.vertex3);
-        
+    private double calculateTriangleBeta(MeshPoint centerPoint, MeshTriangle t) {
         double betaCos = 0;
             
-        if (t.vertex1 == centerIndex) {
-            MeshPoint e1 = tVertex1.subtractPosition(tVertex2);
+        if (t.vertex1 == centerPoint) {
+            MeshPoint e1 = t.vertex1.subtractPosition(t.vertex2);
             e1 = e1.dividePosition(e1.abs());
             
-            MeshPoint e2 = tVertex3.subtractPosition(tVertex2);
+            MeshPoint e2 = t.vertex3.subtractPosition(t.vertex2);
             e2 = e2.dividePosition(e2.abs());
             
             betaCos = e1.dotProduct(e2);
-        } else if (t.vertex2 == centerIndex) {
-            
-            MeshPoint e1 = tVertex2.subtractPosition(tVertex3);
+        } else if (t.vertex2 == centerPoint) {
+            MeshPoint e1 = t.vertex2.subtractPosition(t.vertex3);
             e1 = e1.dividePosition(e1.abs());
             
-            MeshPoint e2 = tVertex1.subtractPosition(tVertex3);
+            MeshPoint e2 = t.vertex1.subtractPosition(t.vertex3);
             e2 = e2.dividePosition(e2.abs());
             
             betaCos = e1.dotProduct(e2);
-        } else if (t.vertex3 == centerIndex){
-            MeshPoint e1 = tVertex3.subtractPosition(tVertex1);
+        } else if (t.vertex3 == centerPoint){
+            MeshPoint e1 = t.vertex3.subtractPosition(t.vertex1);
             e1 = e1.dividePosition(e1.abs());
                 
-            MeshPoint e2 = tVertex2.subtractPosition(tVertex1);
+            MeshPoint e2 = t.vertex2.subtractPosition(t.vertex1);
             e2 = e2.dividePosition(e2.abs());
             
             betaCos = e1.dotProduct(e2);
@@ -364,41 +286,43 @@ public class SymmetryEstimator {
      * @param centerIndex centerIndex
      * @return laplacian 
      */
-    private MeshPoint calculateLaplacian(int centerIndex) {
+    private Vector3d calculateLaplacian(int centerIndex) {
         List<Integer> trianglesNeighbours = getNeighbours(centerIndex);
 
         if (trianglesNeighbours.isEmpty()) {
-            return new MeshPoint(new Vector3d(), new Vector3d(), new Vector3d());
+            return new Vector3d();
         }
+        
         double areaSum = 0;
-        MeshPoint pointSum = new MeshPoint(new Vector3d(), new Vector3d(), new Vector3d());
+        Vector3d pointSum = new Vector3d();
         for (int i = 0; i < trianglesNeighbours.size(); i++) {
-            Triangle t = triangles[trianglesNeighbours.get(i)];
-            Triangle tNext = triangles[trianglesNeighbours.get((i + 1) % trianglesNeighbours.size())];
+            MeshTriangle t = triangles.get(trianglesNeighbours.get(i));
+            MeshTriangle tNext = triangles.get(trianglesNeighbours.get((i + 1) % trianglesNeighbours.size()));
             double area = 0;
             
-            MeshPoint tVertex1 = facet.getVertices().get(t.vertex1);
-            MeshPoint tVertex2 = facet.getVertices().get(t.vertex2);
-            MeshPoint tVertex3 = facet.getVertices().get(t.vertex3);
+            //MeshPoint tVertex1 = facet.getVertices().get(t.vertex1);
+            //MeshPoint tVertex2 = facet.getVertices().get(t.vertex2);
+            //MeshPoint tVertex3 = facet.getVertices().get(t.vertex3);
             MeshPoint centerPoint = facet.getVertices().get(centerIndex);
-                    
-            if (t.vertex1 == centerIndex) {
+
+            Vector3d aux = new Vector3d();
+            if (t.vertex1 == facet.getVertex(centerIndex)) {
                 area = areas[trianglesNeighbours.get(i)].v1Area;
-                pointSum = pointSum.addPosition((tVertex2.subtractPosition(centerPoint)).multiplyPosition((calculateTriangleAlfa(centerIndex, t)
-                        + calculateTriangleBeta(centerIndex, tNext)) / 2));
-                       
-            } else if (t.vertex2 == centerIndex) {
+                aux = new Vector3d(t.vertex2.getPosition());
+            } else if (t.vertex2 == facet.getVertex(centerIndex)) {
                 area = areas[trianglesNeighbours.get(i)].v2Area;
-                pointSum = pointSum.addPosition((tVertex3.subtractPosition(centerPoint)).multiplyPosition((calculateTriangleAlfa(centerIndex, t)
-                        + calculateTriangleBeta(centerIndex, tNext)) / 2));
-            } else if (t.vertex3 == centerIndex) {
+                aux = new Vector3d(t.vertex3.getPosition());
+            } else if (t.vertex3 == facet.getVertex(centerIndex)) {
                 area = areas[trianglesNeighbours.get(i)].v3Area;
-                pointSum = pointSum.addPosition((tVertex1.subtractPosition(centerPoint)).multiplyPosition((calculateTriangleAlfa(centerIndex, t)
-                        + calculateTriangleBeta(centerIndex, tNext)) / 2));
+                aux = new Vector3d(t.vertex1.getPosition());
             }
+            aux.sub(centerPoint.getPosition());
+            aux.scale((calculateTriangleAlfa(centerPoint, t) + calculateTriangleBeta(centerPoint, tNext)) / 2.0);
+            pointSum.add(aux);
             areaSum += area;
         }
-        return pointSum.multiplyPosition(1 / areaSum);
+        pointSum.scale(1.0/areaSum);
+        return pointSum;
     }
     
     /**
@@ -420,37 +344,39 @@ public class SymmetryEstimator {
         double areaSum = 0;
 
         for (int i = 0; i < triangleNeighbours.size(); i++) {
-            MeshPoint v1 = new MeshPoint(new Vector3d(), new Vector3d(), new Vector3d());
-            MeshPoint v2 = new MeshPoint(new Vector3d(), new Vector3d(), new Vector3d());
-            Triangle t = triangles[triangleNeighbours.get(i)];
-            
-            MeshPoint tVertex1 = facet.getVertices().get(t.vertex1);
-            MeshPoint tVertex2 = facet.getVertices().get(t.vertex2);
-            MeshPoint tVertex3 = facet.getVertices().get(t.vertex3);
+            Vector3d v1 = new Vector3d();
+            Vector3d v2 = new Vector3d();
+            MeshTriangle t = triangles.get(triangleNeighbours.get(i));
             
             double area = 0;
-            if (t.vertex1 == centerIndex) {
-                v1 = tVertex2.subtractPosition(tVertex1);
-                v2 = tVertex3.subtractPosition(tVertex1);
+            if (t.vertex1 ==  facet.getVertex(centerIndex)) {
+                v1 = new Vector3d(t.vertex2.getPosition());
+                v2 = new Vector3d(t.vertex3.getPosition());
+                v1.sub(t.vertex1.getPosition());
+                v2.sub(t.vertex1.getPosition());
 
                 area = areas[triangleNeighbours.get(i)].v1Area;
-            } else if (t.vertex2 == centerIndex) {
-                v1 = tVertex1.subtractPosition(tVertex2);
-                v2 = tVertex3.subtractPosition(tVertex2);
+            } else if (t.vertex2 == facet.getVertex(centerIndex)) {
+                v1 = new Vector3d(t.vertex1.getPosition());
+                v2 = new Vector3d(t.vertex3.getPosition());
+                v1.sub(t.vertex2.getPosition());
+                v2.sub(t.vertex2.getPosition());
                 
                 area = areas[triangleNeighbours.get(i)].v2Area;
-            } else if (t.vertex3 == centerIndex) {
-                v1 = tVertex2.subtractPosition(tVertex3);
-                v2 = tVertex1.subtractPosition(tVertex3);
+            } else if (t.vertex3 == facet.getVertex(centerIndex)) {
+                v1 = new Vector3d(t.vertex2.getPosition());
+                v2 = new Vector3d(t.vertex1.getPosition());
+                v1.sub(t.vertex3.getPosition());
+                v2.sub(t.vertex3.getPosition());
 
                 area = areas[triangleNeighbours.get(i)].v3Area;
             }
             
             areaSum += area;
-            v1 = v1.dividePosition(v1.abs());
-            v2 = v2.dividePosition(v2.abs());
+            v1.normalize();
+            v2.normalize();
             
-            sum -= Math.acos(v1.dotProduct(v2));
+            sum -= Math.acos(v1.dot(v2));
         } 
         double value = sum * (1.0 / areaSum);
         return value;
@@ -462,7 +388,7 @@ public class SymmetryEstimator {
      * @return mean curvature
      */
     private double getMeanCurvature(int centerIndex) {
-        return calculateLaplacian(centerIndex).abs();
+        return calculateLaplacian(centerIndex).length();
     }
     
     /**
@@ -505,42 +431,43 @@ public class SymmetryEstimator {
         
         plane.normalize();
         
-        MeshPoint normal = new MeshPoint((new Vector3d(plane.a, plane.b, plane.c)),new Vector3d(), new Vector3d());
+        Vector3d normal = new Vector3d(plane.a, plane.b, plane.c);
         double d = plane.d;
         double maxCurvRatio = 1.0 / minCurvRatio;
         int votes = 0;
-        MeshPoint[] normals = calculateNormals();
+        //List<Vector3d> normals = calculateNormals();
+        
+        if (!facet.hasVertexNormals()) {
+            facet.calculateVertexNormals();
+        }
 
         for (int i = 0; i < curvatures.size(); i++) {
             for (int j = 0; j < curvatures.size(); j++) {
                 if (i != j && (curvatures.get(i) / curvatures.get(j) >= minCurvRatio
                         && curvatures.get(i) / curvatures.get(j) <= maxCurvRatio)) {
                     
-                    MeshPoint vec = facet.getVertices().get(points.get(i)).subtractPosition(facet.getVertices().get(points.get(j)));
-                    vec = vec.dividePosition(vec.abs());
-                    double cos = vec.dotProduct(normal);
- 
-                    MeshPoint ni;
-            
-                    ni = new MeshPoint (new Vector3d(normals[points.get(i)].getPosition().x,normals[points.get(i)].getPosition().y,
-                           normals[points.get(i)].getPosition().z), new Vector3d(), new Vector3d());
-                        
-                    ni = ni.dividePosition(ni.abs());
-                        
-                    MeshPoint nj;
-                    nj = new MeshPoint (new Vector3d(normals[points.get(j)].getPosition().x,normals[points.get(j)].getPosition().y,
-                               normals[points.get(j)].getPosition().z), new Vector3d(), new Vector3d());
-                    nj = nj.dividePosition(nj.abs());
-
-                    MeshPoint normVec = ni.subtractPosition(nj);
-                    normVec = normVec.dividePosition(normVec.abs());
-                    double normCos = normVec.dotProduct(normal);
+                    Vector3d vec = new Vector3d(facet.getVertices().get(points.get(i)).getPosition());
+                    vec.sub(facet.getVertices().get(points.get(j)).getPosition());
+                    vec.normalize();
+                    double cos = vec.dot(normal);
                     
+                    Vector3d ni = new Vector3d(facet.getVertex(points.get(i)).getNormal());
+                    Vector3d nj = new Vector3d(facet.getVertex(points.get(j)).getNormal());
+                    ni.normalize();
+                    nj.normalize();
+                    
+                    Vector3d normVec = ni;
+                    normVec.sub(nj);
+                    normVec.normalize();
+                    double normCos = normVec.dot(normal);
+ 
                     if (Math.abs(cos) >= minAngleCos && Math.abs(normCos) >= minNormAngleCos) {
-                        MeshPoint avrg = (facet.getVertices().get(points.get(i)).addPosition(facet.getVertices().get(points.get(j)))).dividePosition(2.0);
-
-                        double dist = normal.getPosition().x * avrg.getPosition().x +
-                                normal.getPosition().y * avrg.getPosition().y + normal.getPosition().z * avrg.getPosition().z + d;
+                        Vector3d avrg = new Vector3d(facet.getVertices().get(points.get(i)).getPosition());
+                        Vector3d aux = new Vector3d(facet.getVertices().get(points.get(i)).getPosition());
+                        avrg.add(aux);
+                        avrg.scale(0.5);
+                        
+                        double dist = normal.x * avrg.x + normal.y * avrg.y + normal.z * avrg.z + d;
                         
                         dist = Math.abs(dist);
                         
@@ -564,7 +491,10 @@ public class SymmetryEstimator {
         UIManager.put("ProgressMonitor.progressText", "Counting symmetry...");
  
         ArrayList<AproxSymmetryPlane> planes = new ArrayList<>();
-        MeshPoint[] normals = calculateNormals();
+        //List<Vector3d> normals = calculateNormals();
+        if (!facet.hasVertexNormals()) {
+            facet.calculateVertexNormals();
+        }
         double[] curvatures = new double[facet.getNumberOfVertices()];
         for (int i = 0; i < facet.getNumberOfVertices(); i++) {
             if (facet.getNumberOfVertices() == 2500) {
@@ -614,38 +544,31 @@ public class SymmetryEstimator {
                     if (significantCurvatures.get(i) / significantCurvatures.get(j) >= minRatio && significantCurvatures.get(i) /
                             significantCurvatures.get(j) <= maxRatio) {
                         
-                        MeshPoint p1 = facet.getVertex(significantPoints.get(i));
-                        MeshPoint p2 = facet.getVertex(significantPoints.get(j));
-                        MeshPoint avrg = (p1.addPosition(p2)).dividePosition(2.0);
-                        MeshPoint normal = (p1.subtractPosition(p2));
+                        Vector3d p1 = new Vector3d(facet.getVertex(significantPoints.get(i)).getPosition());
+                        Vector3d p2 = new Vector3d(facet.getVertex(significantPoints.get(j)).getPosition());
                         
-                        normal = normal.dividePosition(normal.abs());
-                        double d = -(normal.getPosition().x * avrg.getPosition().x) -
-                                (normal.getPosition().y * avrg.getPosition().y) - (normal.getPosition().z * avrg.getPosition().z);
-                       
-                        MeshPoint ni;
-                        ni = new MeshPoint (new Vector3d(normals[significantPoints.get(i)].getPosition().x,
-                                normals[significantPoints.get(i)].getPosition().y,
-                                normals[significantPoints.get(i)].getPosition().z),
-                                new Vector3d(), new Vector3d());
+                        Vector3d avrg = new Vector3d(p1);
+                        avrg.add(p2);
+                        avrg.scale(0.5);
                         
-                        ni = ni.dividePosition(ni.abs());
+                        Vector3d normal = new Vector3d(p1);
+                        normal.sub(p2);
+                        normal.normalize();
                         
-                        MeshPoint nj;
-                        nj = new MeshPoint (new Vector3d(normals[significantPoints.get(j)].getPosition().x,
-                                normals[significantPoints.get(j)].getPosition().y,
-                                normals[significantPoints.get(j)].getPosition().z),
-                                new Vector3d(), new Vector3d());
+                        double d = -(normal.x * avrg.x) - (normal.y * avrg.y) - (normal.z * avrg.z);
                        
-                        nj = nj.dividePosition(nj.abs());
-                        
-                        MeshPoint normVec = ni.subtractPosition(nj);
-                        normVec = normVec.dividePosition(normVec.abs());
-                        double normCos = normVec.dotProduct(normal);
+                        Vector3d ni = new Vector3d(facet.getVertex(significantPoints.get(i)).getNormal());
+                        Vector3d nj = new Vector3d(facet.getVertex(significantPoints.get(j)).getNormal());
+                        ni.normalize();
+                        nj.normalize();
+
+                        Vector3d normVec = ni;
+                        normVec.sub(nj);
+                        normVec.normalize();
+                        double normCos = normVec.dot(normal);
 
                         if (Math.abs(normCos) >= config.getMinNormAngleCos()) {
-                            
-                            Plane newPlane = new Plane(normal.getPosition().x, normal.getPosition().y, normal.getPosition().z, d);
+                            Plane newPlane = new Plane(normal.x, normal.y, normal.z, d);
                             int currentVotes = getVotes(newPlane, 
                                 significantCurvatures, 
                                 significantPoints, 
@@ -653,7 +576,6 @@ public class SymmetryEstimator {
                                 config.getMinAngleCos(), 
                                 config.getMinNormAngleCos(), 
                                 boundingBox.getMaxDiag() * config.getMaxRelDistance());
-                            
 
                             planes.add(new AproxSymmetryPlane(newPlane, currentVotes));
                             
@@ -678,10 +600,10 @@ public class SymmetryEstimator {
             }
         }
         Plane finalPlane = new Plane(0, 0, 0, 0);
-        MeshPoint refDir = new MeshPoint(new Vector3d(finalPlanes.get(0).a, finalPlanes.get(0).b, finalPlanes.get(0).c), new Vector3d(), new Vector3d());
+        Vector3d refDir = new Vector3d(finalPlanes.get(0).a, finalPlanes.get(0).b, finalPlanes.get(0).c);
         for (int i = 0; i < finalPlanes.size(); i++) {
-            MeshPoint normDir = new MeshPoint(new Vector3d(finalPlanes.get(i).a, finalPlanes.get(i).b, finalPlanes.get(i).c), new Vector3d(), new Vector3d());
-            if (normDir.dotProduct(refDir) < 0) {
+            Vector3d normDir = new Vector3d(finalPlanes.get(i).a, finalPlanes.get(i).b, finalPlanes.get(i).c);
+            if (normDir.dot(refDir) < 0) {
                 finalPlane.a -= finalPlanes.get(i).a;
                 finalPlane.b -= finalPlanes.get(i).b;
                 finalPlane.c -= finalPlanes.get(i).c;
@@ -710,32 +632,34 @@ public class SymmetryEstimator {
      * @return mesh that represents facet with computed plane of approximate symmetry
      */
     public SymmetryEstimator mergeWithPlane(Plane plane) {
-        MeshPoint normal = new MeshPoint(new Vector3d(plane.a, plane.b, plane.c), new Vector3d(), new Vector3d());
-        MeshPoint midPoint = boundingBox.getMidPoint();
-
-        double alpha = -((plane.a * midPoint.getPosition().x) + 
-                (plane.b * midPoint.getPosition().y) + (plane.c * midPoint.getPosition().z) +
-                plane.d) / (normal.dotProduct(normal));
+        Vector3d normal = new Vector3d(plane.a, plane.b, plane.c);
+        Vector3d midPoint = boundingBox.getMidPoint().getPosition();
 
-        MeshPoint midPointOnPlane = midPoint.addPosition(normal.multiplyPosition(alpha));
-
-        double val = plane.a * midPointOnPlane.getPosition().x + plane.b *
-                midPointOnPlane.getPosition().y + plane.c *
-                midPointOnPlane.getPosition().z + plane.d;
-
-        MeshPoint a;
-        if (Math.abs(normal.dotProduct(new MeshPoint(new Vector3d(0.0, 1.0, 0.0), new Vector3d(), new Vector3d()))) 
-                > Math.abs(normal.dotProduct(new MeshPoint(new Vector3d (1.0, 0.0, 0.0), new Vector3d(), new Vector3d())))) {
-                a = normal.crossProduct(new MeshPoint(new Vector3d(1.0, 0.0, 0.0), new Vector3d(), new Vector3d()));
+        double alpha = -((plane.a * midPoint.x) + 
+                (plane.b * midPoint.y) + (plane.c * midPoint.z) +
+                plane.d) / (normal.dot(normal));
+        
+        Vector3d midPointOnPlane = new Vector3d(midPoint);
+        Vector3d nn = new Vector3d(normal);
+        nn.scale(alpha);
+        midPointOnPlane.add(nn);
+
+        double val = plane.a * midPointOnPlane.x + plane.b *
+                midPointOnPlane.y + plane.c *
+                midPointOnPlane.z + plane.d;
+
+        Vector3d a = new Vector3d();
+        if (Math.abs(normal.dot(new Vector3d(0.0, 1.0, 0.0))) > Math.abs(normal.dot(new Vector3d (1.0, 0.0, 0.0)))) {
+            a.cross(normal, new Vector3d(1.0, 0.0, 0.0));
         } else {
-            a = normal.crossProduct(new MeshPoint(new Vector3d(0.0, 1.0, 0.0), new Vector3d(), new Vector3d()));
+            a.cross(normal, new Vector3d(0.0, 1.0, 0.0));
         }
-        a = a.dividePosition(a.abs());
+        a.normalize();
 
-        MeshPoint b = normal.crossProduct(a);
-        b = b.dividePosition(b.abs());
+        Vector3d b = new Vector3d();
+        b.cross(normal,a);
+        b.normalize();
        
-
         SymmetryEstimator planeMesh = Plane.createPlaneMesh(midPointOnPlane, a, b,
                 (boundingBox.getMaxPoint().subtractPosition(boundingBox.getMinPoint())).getPosition().x);
 
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Triangle.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Triangle.java
deleted file mode 100644
index 23d919447263b794a86bec721e16724bc4fc48fe..0000000000000000000000000000000000000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Triangle.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package cz.fidentis.analyst.symmetry;
-
-/**
- *
- * @author Natália Bebjaková
- * 
- * Helping representation of triangle in symmetry estimate 
- */
-
-public class Triangle { 
-    protected int vertex1;
-    protected int vertex2;
-    protected int vertex3;
-    
-    /**
-     * Creates new triangle
-     * 
-     * @param v1 first vertex 
-     * @param v2 second vertex
-     * @param v3 third vertex
-     */        
-    public Triangle(int v1, int v2, int v3) {
-        this.vertex1 = v1;
-        this.vertex2 = v2; 
-        this.vertex3 = v3;
-    }
-    /**
-     * 
-     * @return first vertex of triangle
-     */
-    public int getVertex1() {
-        return vertex1;
-    }
-
-    /**
-     * 
-     * @param vertex1 new vertex
-     */
-    public void setVertex1(int vertex1) {
-        this.vertex1 = vertex1;
-    }
-
-    /**
-     * 
-     * @return second vertex of triangle
-     */
-    public int getVertex2() {
-        return vertex2;
-    }
-
-    /**
-     * 
-     * @param vertex2 new vertex 
-     */
-    public void setVertex2(int vertex2) {
-        this.vertex2 = vertex2;
-    }
-
-    /**
-     * 
-     * @return third vertex of triangle
-     */
-    public int getVertex3() {
-        return vertex3;
-    }
-
-    /**
-     * 
-     * @param vertex3 new vertex 
-     */
-    public void setVertex3(int vertex3) {
-        this.vertex3 = vertex3;
-    }
-
-    /**
-     * Triangles are same if they have same vertices
-     * 
-     * @param obj other triangle 
-     * @return true if two triangles are same 
-     */        
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof Triangle) {
-            Triangle t = (Triangle)obj;
-            if (((this.vertex1 == t.vertex1) || (this.vertex1 == t.vertex2) || (this.vertex1 == t.vertex3)) &&
-                ((this.vertex2 == t.vertex1) || (this.vertex2 == t.vertex2) || (this.vertex2 == t.vertex3)) &&
-                ((this.vertex3 == t.vertex1) || (this.vertex3 == t.vertex2) || (this.vertex3 == t.vertex3))) {
-                return (true);
-            }
-        }
-        return (false);
-    }
-       
-    /**
-     * 
-     * @return hascode of the triangle
-     */
-    @Override 
-    public int hashCode() {
-        return (this.vertex1 * 100 ^ this.vertex2 * 100 ^ this.vertex3);
-    }
-}
diff --git a/MeshModel/pom.xml b/MeshModel/pom.xml
index 917a9b069f39ce2502e9b5557c54e48632db87d4..d440dda45e4d3592806c68ae9d97b0a38f7be3f2 100644
--- a/MeshModel/pom.xml
+++ b/MeshModel/pom.xml
@@ -19,6 +19,8 @@
                     <publicPackages> <!-- expose API/packages to other modules -->
                        <publicPackage>cz.fidentis.analyst.mesh.core.*</publicPackage>
                        <publicPackage>cz.fidentis.analyst.mesh.io.*</publicPackage>
+                       <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshFacet</publicPackage>-->
+                       <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshPoint</publicPackage>-->
                    </publicPackages>
                 </configuration>
             </plugin>
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/BoundingBox.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
similarity index 58%
rename from Comparison/src/main/java/cz/fidentis/analyst/symmetry/BoundingBox.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
index dabb5a6fd0d54bd642f2119de2d54d9a71c604a1..97d990ef85e49d4e64dc6cc81f199cdccabf9091 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/BoundingBox.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
@@ -1,6 +1,5 @@
-package cz.fidentis.analyst.symmetry;
+package cz.fidentis.analyst.mesh.core;
 
-import cz.fidentis.analyst.mesh.core.MeshPoint;
 import java.util.List;
 import javax.vecmath.Vector3d;
 
@@ -13,13 +12,24 @@ import javax.vecmath.Vector3d;
  */
 
 public class BoundingBox {
-    private boolean isMinMaxValid;
     private MeshPoint maxPoint;
     private MeshPoint minPoint;
     private MeshPoint midPoint;
     private double maxDiag;
-    private final List<MeshPoint> points;
     
+    /** 
+     * Creates bounding box that is automatically maintained with respect to given array.
+     * @param points array of points, must not be null or pempty
+     * @throws IllegalArgumentException if the @code{points} param is null or empty
+     */
+    public BoundingBox(List<MeshPoint> points) {
+        if (points == null || points.isEmpty()) {
+            throw new IllegalArgumentException("points");
+        }
+        this.computeMinMax(points);
+        this.computeMidDiag();
+    }        
+
     /**
      * 
      * @return max point of the bounding box
@@ -28,14 +38,6 @@ public class BoundingBox {
         return maxPoint;
     }
     
-    /**
-     * 
-     * @param point new max point of the bounding box
-     */
-    public void setMaxPoint(MeshPoint point) {
-        this.maxPoint = point;
-    }
-    
     /**
      * 
      * @return middle point of the bounding box
@@ -44,14 +46,6 @@ public class BoundingBox {
         return midPoint;
     }
     
-    /**
-     * 
-     * @param point new middle point of the bounding box
-     */
-    public void setMidPoint(MeshPoint point) {
-        this.midPoint = point;
-    }
-    
     /**
      * 
      * @return min point of the bounding box
@@ -61,36 +55,19 @@ public class BoundingBox {
     }
     
     /**
-     * 
-     * @param point new min point of the bounding box
-     */
-    public void setMinPoint(MeshPoint point) {
-        this.minPoint = point;
-    }
-    
-    /** 
-     * Creates bounding box that is automatically maintained with respect to given array.
-     * @param points array of points
+     * Return volume diagonal of the bounding box.
+     * @return maximal diagonal of bounding box
      */
-    public BoundingBox(List<MeshPoint> points) {
-        this.points = points;
-        this.validateMinMax();
-        this.validateMidDiag();
-    }        
-
-    /**
-     * @return point array that is managed by curent bounding box.
-    */
-    public List<MeshPoint> getPoints() {
-        return points;
+    public double getMaxDiag() {
+        return maxDiag;
     }
     
     /**
      * Recomputes the BoundingBox from all points
-    */
-    private void validateMinMax() {
-        minPoint = new MeshPoint(new Vector3d(Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE), null, null);
-        maxPoint = new MeshPoint(new Vector3d(-100000.0,-100000.0,-100000.0), null, null);
+     */
+    private void computeMinMax(List<MeshPoint> points) {
+        minPoint = new MeshPointImpl(new Vector3d(Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE), null, null);
+        maxPoint = new MeshPointImpl(new Vector3d(-100000.0,-100000.0,-100000.0), null, null);
  
         for (int i = 0; i < points.size(); i++) {
             MeshPoint point = points.get(i);
@@ -103,30 +80,17 @@ public class BoundingBox {
             maxPoint.getPosition().y = Math.max(maxPoint.getPosition().y, point.getPosition().y);
             maxPoint.getPosition().z = Math.max(maxPoint.getPosition().z, point.getPosition().z);                    
         }
-	isMinMaxValid = true;
-	this.validateMidDiag();
     }
 
     /**
      * Recompute mid-point and max diagonal length.
      */   
-    private void validateMidDiag() {
+    private void computeMidDiag() {
         midPoint = (minPoint.addPosition(maxPoint)).multiplyPosition(0.5);
         MeshPoint diag = maxPoint.subtractPosition(minPoint);
         this.maxDiag = diag.abs();
     }
 
-    /**
-     * Return volume diagonal of the bounding box.
-     * @return maximal diagonal of bounding box
-     */
-    public double getMaxDiag() {
-        if (!isMinMaxValid) {
-            this.validateMinMax();
-        }
-        return maxDiag;
-    }
-    
     /**
      * Returns description of BoundignBox.
      * 
@@ -135,14 +99,11 @@ public class BoundingBox {
     @Override
     public String toString() {
         String str = "BoundingBox: ";
-        if (this.minPoint == null || this.maxPoint == null || this.midPoint == null) {
-            return str += "undefined (there are no points)";
-        }
-        str += "\n";
-        str += "\t" + "- min point : " + this.minPoint + "\n";
-        str += "\t" + "- max point : " + this.maxPoint + "\n";
-        str += "\t" + "- mid point : " + this.midPoint + "\n";
-        str += "\t" + "- max diag  : " + this.maxDiag + "\n";
+        str += System.lineSeparator();
+        str += "\t" + "- min point : " + this.minPoint + System.lineSeparator();
+        str += "\t" + "- max point : " + this.maxPoint + System.lineSeparator();
+        str += "\t" + "- mid point : " + this.midPoint + System.lineSeparator();
+        str += "\t" + "- max diag  : " + this.maxDiag + System.lineSeparator();
         return str;
     }      
 }  
\ No newline at end of file
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
index f7960da57ffca8b9cc5f6530b2bcf2afe3528fe7..7fac0315a81a591edd26aaea2a8d95b68cd54beb 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
@@ -5,7 +5,8 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 /**
- * Representation of mesh in memory using corner table
+ * Representation of mesh in memory using corner table. 
+ * Face = triangle.
  *
  * @author Matej Lukes
  */
@@ -201,9 +202,10 @@ public class CornerTable {
                 .map(corner -> getIndexOfFace(rows.indexOf(corner)))
                 .collect(Collectors.toList());
     }
-
+    
     /**
      * returns indexes of vertices of triangle
+     *
      * @param triangleIndex index of triangle
      * @return list of indexes
      */
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 a9c59105ee017853cc37270a86e9b41885f6a1e9..3a70047917c3b62a2c4d31d76a81b2c5ddf36a8f 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,81 +1,70 @@
-package cz.fidentis.analyst.mesh.core;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * MashFacet
- *
- * @author Matej Lukes
- */
-public class MeshFacet {
-    private List<MeshPoint> vertices = new ArrayList<>();
-    private CornerTable cornerTable;
-
-    /**
-     * Constructor of MeshFacet
-     */
-    public MeshFacet() {
-        cornerTable = new CornerTable();
-    }
-
-    /**
-     * Copy constructor of MeshFacet
-     *
-     * @param facet copied MeshFacet
-     */
-    public MeshFacet(MeshFacet facet) {
-        for (MeshPoint vertex :
-                facet.vertices) {
-            vertices.add(new MeshPoint(vertex));
-        }
-        cornerTable = new CornerTable(facet.cornerTable);
-    }
-
-    /**
-     * returns vertex of specified index
-     *
-     * @param index index of vertex
-     * @return vertex
-     */
-    public MeshPoint getVertex(int index) {
-        return vertices.get(index);
-    }
-
-    /**
-     * adds vertex to MeshFacet
-     *
-     * @param point new vertex
-     */
-    public void addVertex(MeshPoint point) {
-        vertices.add(point);
-    }
-
-    /**
-     * returns number of vertices in MeshFacet
-     *
-     * @return number of vertices
-     */
-    public int getNumberOfVertices() {
-        return vertices.size();
-    }
-
-    /**
-     * returns list of vertices in MeshFacet
-     *
-     * @return list if vertices
-     */
-    public List<MeshPoint> getVertices() {
-        return vertices;
-    }
-
-    /**
-     * returns Corner Table representing MeshFacet
-     *
-     * @return corner table
-     */
-    public CornerTable getCornerTable() {
-        return cornerTable;
-    }
-}
-
+package cz.fidentis.analyst.mesh.core;
+
+import java.util.List;
+
+/**
+ * An ancapsulated mesh plate (with shared vertices).
+ *
+ * @author Matej Lukes
+ */
+public interface MeshFacet {
+    
+    /**
+     * returns vertex of specified index
+     *
+     * @param index index of vertex
+     * @return vertex
+     */
+    MeshPoint getVertex(int index);
+
+    /**
+     * adds vertex to MeshFacet
+     *
+     * @param point new vertex
+     */
+    void addVertex(MeshPoint point);
+
+    /**
+     * returns number of vertices in MeshFacet
+     *
+     * @return number of vertices
+     */
+    int getNumberOfVertices();
+
+    /**
+     * returns list of vertices in MeshFacet
+     *
+     * @return list if vertices
+     */
+    List<MeshPoint> getVertices();
+
+    /**
+     * returns Corner Table representing MeshFacet
+     *
+     * @return corner table
+     */
+    CornerTable getCornerTable();
+    
+    /**
+     * Returns the mesh as a list of individial triangles.
+     * @return the list of individial triangles.
+     */
+    List<MeshTriangle> asTriangles();
+    
+    /**
+     * Computes and returns bounding box of the mesh facet.
+     * @return bounding box of the mesh facet.
+     */
+    BoundingBox getBoundingBox();
+    
+    /**
+     * Returns true if normals of vertices are calculated.
+     * @return true if normals of vertices are calculated.
+     */
+    boolean hasVertexNormals();
+    
+    /**
+     * Calculates normals of vertices from normals of triangles.
+     */
+    void calculateVertexNormals();
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..f0c12ab8bbd2aeb0b9b790d89a46a91b79acccaf
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
@@ -0,0 +1,115 @@
+package cz.fidentis.analyst.mesh.core;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.vecmath.Vector3d;
+
+/**
+ * MashFacet
+ *
+ * @author Matej Lukes
+ */
+public class MeshFacetImpl implements MeshFacet {
+    
+    private List<MeshPoint> vertices = new ArrayList<>();
+    private CornerTable cornerTable;
+
+    /**
+     * Constructor of MeshFacet
+     */
+    public MeshFacetImpl() {
+        cornerTable = new CornerTable();
+    }
+
+    /**
+     * Copy constructor of MeshFacet
+     *
+     * @param facet copied MeshFacet
+     */
+    public MeshFacetImpl(MeshFacet facet) {
+        vertices.addAll(facet.getVertices()); // encapsulation preserved - vertices MeshPoints are immutable)
+        cornerTable = new CornerTable(facet.getCornerTable());
+    }
+
+    @Override
+    public MeshPoint getVertex(int index) {
+        return vertices.get(index);
+    }
+
+    @Override
+    public void addVertex(MeshPoint point) {
+        vertices.add(point);
+    }
+
+    @Override
+    public int getNumberOfVertices() {
+        return vertices.size();
+    }
+
+    @Override
+    public List<MeshPoint> getVertices() {
+        return Collections.unmodifiableList(vertices);
+    }
+
+    @Override
+    public CornerTable getCornerTable() {
+        return cornerTable;
+    }
+    
+    @Override
+    public List<MeshTriangle> asTriangles() {
+        List<MeshTriangle> ret = new ArrayList<>();
+        for (int i = 0; i < cornerTable.getSize(); i += 3) {
+            ret.add(new MeshTriangle(
+                    vertices.get(cornerTable.getRow(i + 0).getVertexIndex()),
+                    vertices.get(cornerTable.getRow(i + 1).getVertexIndex()),
+                    vertices.get(cornerTable.getRow(i + 2).getVertexIndex())));
+        }
+        return ret;
+    }
+    
+    @Override
+    public BoundingBox getBoundingBox() {
+        return new BoundingBox(this.vertices);
+    }
+    
+    @Override
+    public boolean hasVertexNormals() {
+        return !this.vertices.isEmpty() && this.vertices.get(0).getNormal() != null;
+    }
+    
+    /**
+     * REPLACE WITH BETTER IMPLEMENTATION
+     * @throws RuntimeException if there are duplicate meth points in the mesh facet
+     */
+    @Override
+    public void calculateVertexNormals() {
+        Map<Vector3d, Vector3d> normalMap = new HashMap<>(); // key = mesh point, value = normal
+        
+        // init normals:
+        for (MeshPoint point: vertices) { 
+            if (normalMap.put(point.getPosition(), new Vector3d(0, 0, 0)) != null) {
+                throw new RuntimeException("Duplicate mesh point in the MeshFacet: " + point);
+            }
+        }
+        
+        // calculate normals from corresponding triangles
+        for (MeshTriangle t : asTriangles()) { 
+            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);
+        }
+        
+        // normalize normals:
+        for (Vector3d normal: normalMap.values()) { 
+            normal.normalize();
+        }
+    }
+
+}
+
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 1f22bb850298923e44df81fef96a40ffb33cfd71..9ab6d00ce755367b76da0f4562f8d298021c0d6d 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
@@ -24,9 +24,8 @@ public class MeshModel {
      * @param meshModel copied MeshModel
      */
     public MeshModel(MeshModel meshModel) {
-        for (MeshFacet facet :
-                meshModel.facets) {
-            facets.add(new MeshFacet(facet));
+        for (MeshFacet facet: meshModel.facets) {
+            facets.add(new MeshFacetImpl(facet));
         }
     }
 
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
index 6ba54c95d91e4243ca93418205f715a10f932135..8b5b6252de21eaf5ce27b630311959441b5a9e1d 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
@@ -1,266 +1,130 @@
-package cz.fidentis.analyst.mesh.core;
-
-import javax.vecmath.Vector3d;
-
-/**
- * MeshPoint represents a point with position, normal, and texture coordinates
- *
- * @author Matej Lukes
- */
-public class MeshPoint {
-    private final Vector3d position, normal, texCoord;
-
-    /**
-     * constructor of meshPoint
-     *
-     * @param position position of MeshPoint
-     * @param normal   normal of MeshPoint
-     * @param texCoord coordinates in texture
-     */
-    public MeshPoint(Vector3d position, Vector3d normal, Vector3d texCoord) {
-        if (position == null) {
-            throw new NullPointerException("position cannot be null");
-        }
-
-        this.position = position;
-        this.normal = normal;
-        this.texCoord = texCoord;
-    }
-
-    /**
-     * copy constructor of meshPoint
-     * @param meshPoint copied meshPoint
-     */
-    public MeshPoint(MeshPoint meshPoint) {
-        this.position = new Vector3d(meshPoint.position);
-        this.normal = new Vector3d(meshPoint.normal);
-        this.texCoord = new Vector3d(meshPoint.texCoord);
-
-    }
-
-    /**
-     * @return normal
-     */
-    public Vector3d getNormal() {
-        return normal;
-    }
-
-    /**
-     * @return position
-     */
-    public Vector3d getPosition() {
-        return position;
-    }
-
-    /**
-     * @return texture coordinates
-     */
-    public Vector3d getTexCoord() {
-        return texCoord;
-    }
-
-    /**
-     * returns new instance of MeshPoint with subtracted position
-     *
-     * @param subtrahend position to be subtracted
-     * @return subtracted MeshPoint
-     */
-    public MeshPoint subtractPosition(MeshPoint subtrahend) {
-        return subtractPosition(subtrahend.position);
-    }
-
-    /**
-     * returns new instance of MeshPoint with subtracted position
-     *
-     * @param subtrahend position to be subtracted
-     * @return subtracted MeshPoint
-     */
-    public MeshPoint subtractPosition(Vector3d subtrahend) {
-        Vector3d newPosition = new Vector3d(position);
-        newPosition.sub(subtrahend);
-        return new MeshPoint(new Vector3d(newPosition), normal, new Vector3d(texCoord));
-    }
-
-    /**
-     * returns new instance of MeshPoint with added position
-     *
-     * @param addend position to be added
-     * @return added MeshPoint
-     */
-    public MeshPoint addPosition(MeshPoint addend) {
-        return addPosition(addend.position);
-    }
-
-    /**
-     * returns new instance of MeshPoint with added position
-     *
-     * @param addend position to be added
-     * @return added MeshPoint
-     */
-    public MeshPoint addPosition(Vector3d addend) {
-        Vector3d newPosition = new Vector3d(position);
-        newPosition.add(addend);
-        return new MeshPoint(new Vector3d(newPosition), normal, new Vector3d(texCoord));
-    }
-
-    /**
-     * returns new instance of MeshPoint with multiplied position by number
-     * 
-     * @param number Number for multiplying
-     * @return multiplied MeshPoint
-     */
-    public MeshPoint multiplyPosition(double number) {
-        if (normal != null) {
-            if (texCoord != null) 
-                return new MeshPoint(new Vector3d(this.getPosition().x * number,
-                        this.getPosition().y * number, this.getPosition().z * number),
-                        new Vector3d(normal), new Vector3d(texCoord));
-            else
-                return new MeshPoint(new Vector3d(this.getPosition().x * number,
-                        this.getPosition().y * number, this.getPosition().z * number),
-                        new Vector3d(normal), null);
-        }
-        return new MeshPoint(new Vector3d(this.getPosition().x * number,
-                        this.getPosition().y * number, this.getPosition().z * number),
-                        null, null);        
-    }
-
-    /**
-     * returns new instance of MeshPoint with divided position by number
-     * 
-     * @param number Number for division
-     * @return divided MeshPoint
-     */
-    public MeshPoint dividePosition(double number) {
-        if (normal != null) {
-            if (texCoord != null) 
-                return new MeshPoint(new Vector3d(this.getPosition().x / number, this.getPosition().y / number,
-                        this.getPosition().z / number), new Vector3d(normal), new Vector3d(texCoord));
-            else
-                return new MeshPoint(new Vector3d(this.getPosition().x / number, this.getPosition().y / number,
-                        this.getPosition().z / number), new Vector3d(normal), null);
-        }
-        return new MeshPoint(new Vector3d(this.getPosition().x / number, this.getPosition().y / number,
-                this.getPosition().z / number), null, null);
-    }
-    
-    /**
-     * Returns the cross product of two points.
-     * 
-     * @param meshPoint Second argument of the cross product operation.
-     * @return MeshPoint representing the resulting vector.
-     */
-    public MeshPoint crossProduct(MeshPoint meshPoint) {
-        if (normal != null) {
-            if (texCoord != null) 
-                return new MeshPoint(new Vector3d
-                (this.position.y * meshPoint.position.z - this.position.z * meshPoint.position.y,
-                this.position.z * meshPoint.position.x - this.position.x * meshPoint.position.z,
-                this.position.x * meshPoint.position.y - this.position.y * meshPoint.position.x),
-                new Vector3d(normal), new Vector3d(texCoord));
-            else
-                return new MeshPoint(new Vector3d
-                (this.position.y * meshPoint.position.z - this.position.z * meshPoint.position.y,
-                this.position.z * meshPoint.position.x - this.position.x * meshPoint.position.z,
-                this.position.x * meshPoint.position.y - this.position.y * meshPoint.position.x),
-                new Vector3d(normal), null);
-        }
-        return new MeshPoint(new Vector3d
-                (this.position.y * meshPoint.position.z - this.position.z * meshPoint.position.y,
-                this.position.z * meshPoint.position.x - this.position.x * meshPoint.position.z,
-                this.position.x * meshPoint.position.y - this.position.y * meshPoint.position.x),
-                null, null);
-    }
-
-    /**
-     * returns the dot product of two points
-     * 
-     * @param meshPoint Second argument of the dot product operation
-     * @return dot product of two instances of MeshPoint 
-     */
-    public double dotProduct(MeshPoint meshPoint) {
-        return (this.position.x * meshPoint.position.x + this.position.y * meshPoint.position.y + this.position.z * meshPoint.position.z);
-    }
-    
-    /**
-     * returns absolute value of MeshPoint
-     * 
-     * @return absolute value of MeshPoint
-     */
-    public double abs() {
-        return Math.sqrt(this.getPosition().x * this.getPosition().x + 
-                this.getPosition().y * this.getPosition().y + this.getPosition().z * this.getPosition().z);
-    }
-
-    /**
-     * returns new instance of MeshPoint with subtracted normal
-     *
-     * @param subtrahend normal to be subtracted
-     * @return subtracted MeshPoint
-     */
-    public MeshPoint subtractNormal(MeshPoint subtrahend) {
-        return subtractNormal(subtrahend.normal);
-    }
-
-    /**
-     * returns new instance of MeshPoint with subtracted normal
-     *
-     * @param subtrahend normal to be subtracted
-     * @return subtracted MeshPoint
-     */
-    public MeshPoint subtractNormal(Vector3d subtrahend) {
-        Vector3d newNormal = new Vector3d(normal);
-        newNormal.sub(subtrahend);
-        newNormal.normalize();
-        return new MeshPoint(new Vector3d(position), newNormal, new Vector3d(texCoord));
-    }
-
-    /**
-     * returns new instance of MeshPoint with added normal
-     *
-     * @param addend normal to be added
-     * @return added MeshPoint
-     */
-    public MeshPoint addNormal(MeshPoint addend) {
-        return addNormal(addend.normal);
-    }
-
-    /**
-     * returns new instance of MeshPoint with added normal
-     *
-     * @param addend normal to be added
-     * @return added MeshPoint
-     */
-    public MeshPoint addNormal(Vector3d addend) {
-        Vector3d newNormal = new Vector3d(normal);
-        newNormal.add(addend);
-        newNormal.normalize();
-        return new MeshPoint(new Vector3d(position), newNormal, new Vector3d(texCoord));
-    }
-
-    /**
-     * @param obj compared object
-     * @return true if positions, normals and texture coordinates are equal, false otherwise
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof MeshPoint)) {
-            return false;
-        }
-
-        MeshPoint meshPointObj = (MeshPoint) obj;
-        return this.position.equals(meshPointObj.position)
-                && this.normal.equals(meshPointObj.normal)
-                && this.texCoord.equals(meshPointObj.texCoord);
-    }
-
-    /**
-     * returns hash of MeshPoint
-     *
-     * @return hash
-     */
-    @Override
-    public int hashCode() {
-        return position.hashCode() + normal.hashCode() + texCoord.hashCode();
-    }
-}
+package cz.fidentis.analyst.mesh.core;
+
+import javax.vecmath.Vector3d;
+
+/**
+ * MeshPoint represents a point with position, normal, and texture coordinates
+ *
+ * @author Matej Lukes
+ */
+public interface MeshPoint {
+    
+    /**
+     * @return normal
+     */
+    Vector3d getNormal();
+
+    /**
+     * @return position
+     */
+    Vector3d getPosition();
+
+    /**
+     * @return texture coordinates
+     */
+    Vector3d getTexCoord();
+
+    /**
+     * returns new instance of MeshPoint with subtracted position
+     *
+     * @param subtrahend position to be subtracted
+     * @return subtracted MeshPoint
+     */
+    MeshPoint subtractPosition(MeshPoint subtrahend);
+
+    /**
+     * returns new instance of MeshPoint with subtracted position
+     *
+     * @param subtrahend position to be subtracted
+     * @return subtracted MeshPoint
+     */
+    MeshPoint subtractPosition(Vector3d subtrahend);
+
+    /**
+     * returns new instance of MeshPoint with added position
+     *
+     * @param addend position to be added
+     * @return added MeshPoint
+     */
+    MeshPoint addPosition(MeshPoint addend);
+
+    /**
+     * returns new instance of MeshPoint with added position
+     *
+     * @param addend position to be added
+     * @return added MeshPoint
+     */
+    MeshPoint addPosition(Vector3d addend);
+
+    /**
+     * returns new instance of MeshPoint with multiplied position by number
+     * 
+     * @param number Number for multiplying
+     * @return multiplied MeshPoint
+     */
+    MeshPoint multiplyPosition(double number);
+
+    /**
+     * returns new instance of MeshPoint with divided position by number
+     * 
+     * @param number Number for division
+     * @return divided MeshPoint
+     */
+    MeshPoint dividePosition(double number);
+    
+    /**
+     * Returns the cross product of two points.
+     * 
+     * @param meshPoint Second argument of the cross product operation.
+     * @return MeshPoint representing the resulting vector.
+     */
+    MeshPoint crossProduct(MeshPoint meshPoint);
+
+    /**
+     * returns the dot product of two points
+     * 
+     * @param meshPoint Second argument of the dot product operation
+     * @return dot product of two instances of MeshPoint 
+     */
+    double dotProduct(MeshPoint meshPoint);
+    
+    /**
+     * returns absolute value of MeshPoint
+     * 
+     * @return absolute value of MeshPoint
+     */
+    double abs();
+
+    /**
+     * returns new instance of MeshPoint with subtracted normal
+     *
+     * @param subtrahend normal to be subtracted
+     * @return subtracted MeshPoint
+     */
+    MeshPoint subtractNormal(MeshPoint subtrahend);
+
+    /**
+     * returns new instance of MeshPoint with subtracted normal
+     *
+     * @param subtrahend normal to be subtracted
+     * @return subtracted MeshPoint
+     */
+    MeshPoint subtractNormal(Vector3d subtrahend);
+
+    /**
+     * returns new instance of MeshPoint with added normal
+     *
+     * @param addend normal to be added
+     * @return added MeshPoint
+     */
+    MeshPoint addNormal(MeshPoint addend);
+
+    /**
+     * returns new instance of MeshPoint with added normal
+     *
+     * @param addend normal to be added
+     * @return added MeshPoint
+     */
+    MeshPoint addNormal(Vector3d addend);
+
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..8284ac9a209f679198abdfdff8ce2a645b09c270
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
@@ -0,0 +1,200 @@
+package cz.fidentis.analyst.mesh.core;
+
+import javax.vecmath.Vector3d;
+
+/**
+ * MeshPoint represents a point with position, normal, and texture coordinates.
+ *
+ * @author Matej Lukes
+ */
+public class MeshPointImpl implements MeshPoint {
+    
+    private final Vector3d position, normal, texCoord;
+
+    /**
+     * constructor of meshPoint
+     *
+     * @param position position of MeshPoint
+     * @param normal   normal of MeshPoint
+     * @param texCoord coordinates in texture
+     */
+    public MeshPointImpl(Vector3d position, Vector3d normal, Vector3d texCoord) {
+        if (position == null) {
+            throw new NullPointerException("position cannot be null");
+        }
+
+        this.position = new Vector3d(position);
+        this.normal = new Vector3d(normal);
+        this.texCoord = new Vector3d(texCoord);
+    }
+
+    /**
+     * copy constructor of meshPoint
+     * 
+     * @param meshPoint copied meshPoint
+     */
+    public MeshPointImpl(MeshPoint meshPoint) {
+        this(meshPoint.getPosition(), meshPoint.getNormal(), meshPoint.getTexCoord());
+
+    }
+
+    @Override
+    public Vector3d getNormal() {
+        return normal;
+    }
+
+    @Override
+    public Vector3d getPosition() {
+        return position;
+    }
+
+    @Override
+    public Vector3d getTexCoord() {
+        return texCoord;
+    }
+
+    @Override
+    public MeshPoint subtractPosition(MeshPoint subtrahend) {
+        return subtractPosition(subtrahend.getPosition());
+    }
+
+    @Override
+    public MeshPoint subtractPosition(Vector3d subtrahend) {
+        Vector3d newPosition = new Vector3d(position);
+        newPosition.sub(subtrahend);
+        return new MeshPointImpl(new Vector3d(newPosition), normal, new Vector3d(texCoord));
+    }
+
+    @Override
+    public MeshPoint addPosition(MeshPoint addend) {
+        return addPosition(addend.getPosition());
+    }
+
+    @Override
+    public MeshPoint addPosition(Vector3d addend) {
+        Vector3d newPosition = new Vector3d(position);
+        newPosition.add(addend);
+        return new MeshPointImpl(new Vector3d(newPosition), normal, new Vector3d(texCoord));
+    }
+
+    @Override
+    public MeshPoint multiplyPosition(double number) {
+        if (normal != null) {
+            if (texCoord != null) {
+                return new MeshPointImpl(new Vector3d(this.getPosition().x * number,
+                        this.getPosition().y * number, this.getPosition().z * number),
+                        new Vector3d(normal), new Vector3d(texCoord));
+            } else {
+                return new MeshPointImpl(new Vector3d(this.getPosition().x * number,
+                        this.getPosition().y * number, this.getPosition().z * number),
+                        new Vector3d(normal), null);
+            }
+        }
+        return new MeshPointImpl(new Vector3d(this.getPosition().x * number,
+                        this.getPosition().y * number, this.getPosition().z * number),
+                        null, null);        
+    }
+
+    @Override
+    public MeshPoint dividePosition(double number) {
+        if (normal != null) {
+            if (texCoord != null) {
+                return new MeshPointImpl(new Vector3d(this.getPosition().x / number, this.getPosition().y / number,
+                        this.getPosition().z / number), new Vector3d(normal), new Vector3d(texCoord));
+            } else {
+                return new MeshPointImpl(new Vector3d(this.getPosition().x / number, this.getPosition().y / number,
+                        this.getPosition().z / number), new Vector3d(normal), null);
+            }
+        }
+        return new MeshPointImpl(new Vector3d(this.getPosition().x / number, this.getPosition().y / number,
+                this.getPosition().z / number), null, null);
+    }
+    
+    @Override
+    public MeshPoint crossProduct(MeshPoint meshPoint) {
+        if (normal != null) {
+            if (texCoord != null) {
+                return new MeshPointImpl(new Vector3d
+                (this.position.y * meshPoint.getPosition().z - this.position.z * meshPoint.getPosition().y,
+                this.position.z * meshPoint.getPosition().x - this.position.x * meshPoint.getPosition().z,
+                this.position.x * meshPoint.getPosition().y - this.position.y * meshPoint.getPosition().x),
+                new Vector3d(normal), new Vector3d(texCoord));
+            } else {
+                return new MeshPointImpl(new Vector3d
+                (this.position.y * meshPoint.getPosition().z - this.position.z * meshPoint.getPosition().y,
+                this.position.z * meshPoint.getPosition().x - this.position.x * meshPoint.getPosition().z,
+                this.position.x * meshPoint.getPosition().y - this.position.y * meshPoint.getPosition().x),
+                new Vector3d(normal), null);
+            }
+        }
+        return new MeshPointImpl(new Vector3d
+                (this.position.y * meshPoint.getPosition().z - this.position.z * meshPoint.getPosition().y,
+                this.position.z * meshPoint.getPosition().x - this.position.x * meshPoint.getPosition().z,
+                this.position.x * meshPoint.getPosition().y - this.position.y * meshPoint.getPosition().x),
+                null, null);
+    }
+
+    @Override
+    public double dotProduct(MeshPoint meshPoint) {
+        return (this.position.x * meshPoint.getPosition().x + this.position.y * meshPoint.getPosition().y + this.position.z * meshPoint.getPosition().z);
+    }
+    
+    @Override
+    public double abs() {
+        return Math.sqrt(this.getPosition().x * this.getPosition().x + 
+                this.getPosition().y * this.getPosition().y + this.getPosition().z * this.getPosition().z);
+    }
+
+    @Override
+    public MeshPoint subtractNormal(MeshPoint subtrahend) {
+        return subtractNormal(subtrahend.getNormal());
+    }
+
+    @Override
+    public MeshPoint subtractNormal(Vector3d subtrahend) {
+        Vector3d newNormal = new Vector3d(normal);
+        newNormal.sub(subtrahend);
+        newNormal.normalize();
+        return new MeshPointImpl(new Vector3d(position), newNormal, new Vector3d(texCoord));
+    }
+
+    @Override
+    public MeshPoint addNormal(MeshPoint addend) {
+        return addNormal(addend.getNormal());
+    }
+
+    @Override
+    public MeshPoint addNormal(Vector3d addend) {
+        Vector3d newNormal = new Vector3d(normal);
+        newNormal.add(addend);
+        newNormal.normalize();
+        return new MeshPointImpl(new Vector3d(position), newNormal, new Vector3d(texCoord));
+    }
+
+    /**
+     * @param obj compared object
+     * @return true if positions, normals and texture coordinates are equal, false otherwise
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof MeshPointImpl)) {
+            return false;
+        }
+
+        MeshPointImpl meshPointObj = (MeshPointImpl) obj;
+        return this.position.equals(meshPointObj.position)
+                && this.normal.equals(meshPointObj.normal)
+                && this.texCoord.equals(meshPointObj.texCoord);
+    }
+
+    /**
+     * returns hash of MeshPoint
+     *
+     * @return hash
+     */
+    @Override
+    public int hashCode() {
+        return position.hashCode() + normal.hashCode() + texCoord.hashCode();
+    }
+
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..ce92a48824f25a7198a025dfd7773ab8077e93e2
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
@@ -0,0 +1,30 @@
+package cz.fidentis.analyst.mesh.core;
+
+/**
+ *
+ * @author Natália Bebjaková
+ * 
+ * Adapter for the corner table representing a single triangle of the @code{MeshFacet}.
+ */
+
+public class MeshTriangle { 
+    
+    public final MeshPoint vertex1;
+    public final MeshPoint vertex2;
+    public final MeshPoint vertex3;
+    
+    /**
+     * Creates new triangle
+     * 
+     * @param v1 first vertex 
+     * @param v2 second vertex
+     * @param v3 third vertex
+     */        
+    public MeshTriangle(MeshPoint v1, MeshPoint v2, MeshPoint v3) {
+        this.vertex1 = v1;
+        this.vertex2 = v2; 
+        this.vertex3 = v3;
+    }
+    
+    
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjExporter.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjExporter.java
index d3bed5084fa65398b8e1931b5d14ff4d69413968..e518c9adee25c1e061d031795743492c7e5dcf10 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjExporter.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjExporter.java
@@ -19,7 +19,7 @@ public class MeshObjExporter {
     /**
      * Model to be exported
      */
-    MeshModel model;
+    private MeshModel model;
     
     /**
      *
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java
index 12ef65c44b81a258c918368b250925240a628e94..210616d4f472673037af0ce2d981ee75a514a5bd 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java
@@ -12,8 +12,10 @@ import com.mokiat.data.front.parser.OBJTexCoord;
 import com.mokiat.data.front.parser.OBJVertex;
 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.MeshModel;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 
 import javax.vecmath.Vector3d;
 import java.io.File;
@@ -90,7 +92,7 @@ public class MeshObjLoader {
      * @throws IOException Data are corrupted
      */
     private static MeshFacet parseMeshToFacet(OBJModel model, OBJMesh mesh) throws IOException {
-        MeshFacet meshFacet = new MeshFacet();
+        MeshFacet meshFacet = new MeshFacetImpl();
         Map<MeshPoint, Integer> vertices = new HashMap();
         Map<Edge, Integer> edges = new HashMap();
 
@@ -178,7 +180,7 @@ public class MeshObjLoader {
                 final OBJTexCoord texCoord = model.getTexCoord(reference);
                 texCoords = new Vector3d(texCoord.u, texCoord.v, texCoord.w);
             }
-            result.add(new MeshPoint(coords, norm, texCoords));
+            result.add(new MeshPointImpl(coords, norm, texCoords));
         }
         if (result.size() != 3) {
             throw new IOException("Mesh contains non-triangular face");
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java
index 2507d8778dab9612a6cb0901d279105c2392b021..17a5f729bcf869daaa0225876d6c3d57a31d9f44 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/ModelFileFilter.java
@@ -18,8 +18,7 @@ public class ModelFileFilter extends FileFilter {
      * @param extension Extentions of files
      * @param description Description
      */
-    public ModelFileFilter(String[] extension, String description)
-    {
+    public ModelFileFilter(String[] extension, String description) {
         this.extension = extension;
         this.description = description;
     }
@@ -30,8 +29,7 @@ public class ModelFileFilter extends FileFilter {
      * @return Whether file has chosen extension or not 
      */
     @Override
-    public boolean accept(File f)
-    {
+    public boolean accept(File f) {
         boolean accepted = false;
         for (String extension1 : extension) {
             if (f.isDirectory() || f.getName().endsWith(extension1)) {
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java
index 96295a00a3df442f23a41367b27780d8f1856586..c6df9b5ad44b3f161bad6ec8b5fb1f61c39b5091 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java
@@ -13,6 +13,7 @@ import com.mokiat.data.front.parser.OBJVertex;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshModel;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -20,9 +21,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 import javax.vecmath.Vector3d;
 
@@ -191,7 +190,7 @@ public class MeshObjLoaderTest {
                         final OBJTexCoord texCoord = model.getTexCoord(reference);
                         texCoords = new Vector3d(texCoord.u, texCoord.v, texCoord.w);
                     }
-                    points.add(new MeshPoint(coords, norm, texCoords));
+                    points.add(new MeshPointImpl(coords, norm, texCoords));
                 }
             }
         }
diff --git a/codestyle.xml b/codestyle.xml
index 87b2b9619253a2ca3fc4951cb9964015f524b802..e8cd9d82de24f5f0053519da0e7aef771b8bba9a 100644
--- a/codestyle.xml
+++ b/codestyle.xml
@@ -13,10 +13,14 @@
     <module name="TreeWalker">
         <!-- Checks for Javadoc comments.                     -->
         <!-- See http://checkstyle.sf.net/config_javadoc.html -->
-        <module name="JavadocMethod">
+	<module name="MissingJavadocMethodCheck">
+            <property name="scope" value="public"/>
+	    <property name="allowMissingPropertyJavadoc" value="true"/>
+	</module>
+        <!--<module name="JavadocMethod">
             <property name="scope" value="public"/>
             <property name="allowMissingPropertyJavadoc" value="true"/>
-        </module>
+        </module>-->
         <module name="JavadocType">
             <property name="scope" value="public"/>
         </module>
@@ -54,9 +58,9 @@
 
         <!-- Checks for Size Violations.                    -->
         <!-- See http://checkstyle.sf.net/config_sizes.html -->
-        <module name="LineLength">
+        <!--<module name="LineLength">
             <property name="max" value="220"/>
-        </module>
+        </module>-->
         <module name="MethodLength">
             <property name="max" value="50"/>
             <property name="countEmpty" value="false"/>
@@ -91,7 +95,9 @@
         <!-- See http://checkstyle.sf.net/config_design.html -->
         <module name="FinalClass"/>
         <module name="InterfaceIsType"/>
-        <module name="VisibilityModifier"/>
+        <module name="VisibilityModifier">
+	  <property name="allowPublicFinalFields" value="true"/>
+        </module>
 
         <!-- Miscellaneous other checks.                   -->
         <!-- See http://checkstyle.sf.net/config_misc.html -->
diff --git a/pom.xml b/pom.xml
index f76915168359ea9014848a6ed2d6a73e6b9080e3..659231044d85fbb99cb7fb5b1685fbbf2eaf27c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
     <properties>
         <netbeans.version>RELEASE113</netbeans.version>
         <brandingToken>fidentisanalyst</brandingToken>
-        <version.maven.plugin.checkstyle>2.17</version.maven.plugin.checkstyle>
+        <version.maven.plugin.checkstyle>3.1.1</version.maven.plugin.checkstyle>
         <version.plugin.checkstyle>8.5</version.plugin.checkstyle>
         <version.plugin.source>2.4</version.plugin.source>
         <version.javax.vecmath>1.5.2</version.javax.vecmath>