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 b638bb6709e4f76f658e54eec475103e54804537..50e9f043b3d572ea22ce7d7ac486c295fcabd574 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
@@ -4,9 +4,14 @@ 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;
@@ -40,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 
      */
@@ -91,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();
     }
     
     /**
@@ -104,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 
@@ -145,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 MeshPointImpl(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 MeshPointImpl(triangleNormal.getPosition(), null, null));
-            newNormals[t.vertex2] = newNormals[t.vertex2].addPosition(new MeshPointImpl(triangleNormal.getPosition(), null, null));
-            newNormals[t.vertex3] = newNormals[t.vertex3].addPosition(new MeshPointImpl(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);
     }
     
     /**
@@ -199,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);
@@ -219,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);
@@ -316,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);
@@ -365,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 MeshPointImpl(new Vector3d(), new Vector3d(), new Vector3d());
+            return new Vector3d();
         }
+        
         double areaSum = 0;
-        MeshPoint pointSum = new MeshPointImpl(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;
     }
     
     /**
@@ -421,37 +344,39 @@ public class SymmetryEstimator {
         double areaSum = 0;
 
         for (int i = 0; i < triangleNeighbours.size(); i++) {
-            MeshPoint v1 = new MeshPointImpl(new Vector3d(), new Vector3d(), new Vector3d());
-            MeshPoint v2 = new MeshPointImpl(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;
@@ -463,7 +388,7 @@ public class SymmetryEstimator {
      * @return mean curvature
      */
     private double getMeanCurvature(int centerIndex) {
-        return calculateLaplacian(centerIndex).abs();
+        return calculateLaplacian(centerIndex).length();
     }
     
     /**
@@ -506,42 +431,43 @@ public class SymmetryEstimator {
         
         plane.normalize();
         
-        MeshPoint normal = new MeshPointImpl((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 MeshPointImpl(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 MeshPointImpl(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);
                         
@@ -565,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) {
@@ -615,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 MeshPointImpl(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 MeshPointImpl(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, 
@@ -654,7 +576,6 @@ public class SymmetryEstimator {
                                 config.getMinAngleCos(), 
                                 config.getMinNormAngleCos(), 
                                 boundingBox.getMaxDiag() * config.getMaxRelDistance());
-                            
 
                             planes.add(new AproxSymmetryPlane(newPlane, currentVotes));
                             
@@ -679,10 +600,10 @@ public class SymmetryEstimator {
             }
         }
         Plane finalPlane = new Plane(0, 0, 0, 0);
-        MeshPoint refDir = new MeshPointImpl(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 MeshPointImpl(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;
@@ -711,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 MeshPointImpl(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 MeshPointImpl(new Vector3d(0.0, 1.0, 0.0), new Vector3d(), new Vector3d()))) 
-                > Math.abs(normal.dotProduct(new MeshPointImpl(new Vector3d (1.0, 0.0, 0.0), new Vector3d(), new Vector3d())))) {
-                a = normal.crossProduct(new MeshPointImpl(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 MeshPointImpl(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);