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 0507e945fc054d4d25c6fd66b35143618acadf20..2eb6eb4ecbcbb63424915ec6c7ad5fda50284b8c 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java
@@ -3,10 +3,11 @@ 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.BoundingBox;
+import cz.fidentis.analyst.mesh.visitors.BoundingBox;
 import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import cz.fidentis.analyst.mesh.core.MeshTriangle;
+import cz.fidentis.analyst.mesh.visitors.BoundingBoxVisitor;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -15,11 +16,6 @@ import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.ProgressMonitor;
 import javax.swing.UIManager;
-//import javax.swing.ImageIcon;
-//import javax.swing.JOptionPane;
-//import javax.swing.JPanel;
-//import javax.swing.ProgressMonitor;
-//import javax.swing.UIManager;
 import javax.vecmath.Vector3d;
 
 /**
@@ -40,8 +36,6 @@ public class SymmetryEstimator {
     
     private List<MeshTriangle> triangles; // Helping array of triangles computed from corner table 
     
-    //private JPanel panel; // panel for configuration of symmetry counting 
-    
     private final Config config;
     
     /**
@@ -60,8 +54,6 @@ public class SymmetryEstimator {
         for (int i = 0; i < areas.length; i++) {
             areas[i] = computeTriangleVertexAreas(triangles.get(i));
         }
-
-        boundingBox = facet.getBoundingBox();
     }
     
     /**
@@ -83,22 +75,6 @@ public class SymmetryEstimator {
         return config;
     }
 
-    /**
-     * 
-     * @return panel for configuration of symmetry counting 
-     */
-    //public JPanel getPanel() {
-    //    return panel;
-    //}
-
-    /**
-     * 
-     * @param panel new panel for configuration of symmetry counting 
-     */
-    //public void setPanel(JPanel panel) {
-    //    this.panel = panel;
-    //}
-    
     /**
      * 
      * @return Facet of the model on which symmetry is computed 
@@ -108,13 +84,15 @@ public class SymmetryEstimator {
     }
 
     /**
-     * If bounding box is not created yet, it creates new one. 
+     * If bounding box is not created yet, it's created now. 
      * 
      * @return Represent min-max box of the boundries of the model. 
      */
     public BoundingBox getBoundingBox() {
         if (boundingBox == null) {
-            boundingBox = facet.getBoundingBox();
+            BoundingBoxVisitor visitor = new BoundingBoxVisitor();
+            facet.accept(visitor);
+            boundingBox = visitor.getBoundingBox();
         }
         return boundingBox; 
     }
@@ -126,8 +104,6 @@ public class SymmetryEstimator {
      */
     public Plane getApproxSymmetryPlane(JPanel panel) {
         
-        ///UIManager.put("ProgressMonitor.progressText", "Counting symmetry...");
- 
         ArrayList<ApproxSymmetryPlane> planes = new ArrayList<>();
         //List<Vector3d> normals = calculateNormals();
         if (!facet.hasVertexNormals()) {
@@ -215,7 +191,7 @@ public class SymmetryEstimator {
                                 config.getMinCurvRatio(), 
                                 config.getMinAngleCos(), 
                                 config.getMinNormAngleCos(), 
-                                boundingBox.getMaxDiag() * config.getMaxRelDistance());
+                                getBoundingBox().getMaxDiag() * config.getMaxRelDistance());
 
                             planes.add(new ApproxSymmetryPlane(newPlane, currentVotes));
                             
@@ -241,7 +217,6 @@ public class SymmetryEstimator {
                 finalPlanes.add(planes.get(i));
             }
         }
-        //Plane finalPlane = new Plane(0, 0, 0, 0);
         double newA = 0, newB = 0, newC = 0, newD = 0;
         Vector3d refDir = finalPlanes.get(0).getNormal();
         for (int i = 0; i < finalPlanes.size(); i++) {
@@ -279,7 +254,7 @@ public class SymmetryEstimator {
      */
     public SymmetryEstimator mergeWithPlane(Plane plane) {
         Vector3d normal = plane.getNormal();
-        Vector3d midPoint = boundingBox.getMidPoint().getPosition();
+        Vector3d midPoint = getBoundingBox().getMidPoint().getPosition();
 
         double alpha = -((normal.x * midPoint.x) + 
                 (normal.y * midPoint.y) + (normal.z * midPoint.z) +
@@ -307,7 +282,7 @@ public class SymmetryEstimator {
         b.normalize();
         
         SymmetryEstimator planeMesh = new SymmetryEstimator(midPointOnPlane, a, b,
-                (boundingBox.getMaxPoint().subtractPosition(boundingBox.getMinPoint())).getPosition().x);
+                (getBoundingBox().getMaxPoint().subtractPosition(getBoundingBox().getMinPoint())).getPosition().x);
        
         return mergeMeshWith(planeMesh);
     }
diff --git a/MeshModel/pom.xml b/MeshModel/pom.xml
index d440dda45e4d3592806c68ae9d97b0a38f7be3f2..852d4a5ad2a12aa4a5ba11ea089af4248737b816 100644
--- a/MeshModel/pom.xml
+++ b/MeshModel/pom.xml
@@ -19,6 +19,7 @@
                     <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.visitors.*</publicPackage>
                        <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshFacet</publicPackage>-->
                        <!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshPoint</publicPackage>-->
                    </publicPackages>
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 3a70047917c3b62a2c4d31d76a81b2c5ddf36a8f..942f4a023385ce89ad98309159a01d3c24f6f5e1 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,5 +1,7 @@
 package cz.fidentis.analyst.mesh.core;
 
+import cz.fidentis.analyst.mesh.visitors.BoundingBox;
+import cz.fidentis.analyst.mesh.visitors.Visitor;
 import java.util.List;
 
 /**
@@ -51,12 +53,6 @@ public interface MeshFacet {
      */
     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.
@@ -67,4 +63,11 @@ public interface MeshFacet {
      * Calculates normals of vertices from normals of triangles.
      */
     void calculateVertexNormals();
+    
+    /**
+     * Entry point for visitors. 
+     * 
+     * @param visitor Visitor
+     */
+    public void accept(Visitor visitor);
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
index f0c12ab8bbd2aeb0b9b790d89a46a91b79acccaf..72873fc99e633629754b640b7343ac9b9e6348d8 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java
@@ -1,5 +1,7 @@
 package cz.fidentis.analyst.mesh.core;
 
+import cz.fidentis.analyst.mesh.visitors.BoundingBox;
+import cz.fidentis.analyst.mesh.visitors.Visitor;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -33,6 +35,11 @@ public class MeshFacetImpl implements MeshFacet {
         vertices.addAll(facet.getVertices()); // encapsulation preserved - vertices MeshPoints are immutable)
         cornerTable = new CornerTable(facet.getCornerTable());
     }
+    
+    @Override
+    public void accept(Visitor visitor) {
+        visitor.visitMeshFacet(this);
+    }
 
     @Override
     public MeshPoint getVertex(int index) {
@@ -71,11 +78,6 @@ public class MeshFacetImpl implements MeshFacet {
         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;
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 9ab6d00ce755367b76da0f4562f8d298021c0d6d..eaa796cf2f24cf15d03a742f246b8fa432f5d7df 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.core;
 
+import cz.fidentis.analyst.mesh.visitors.Visitor;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -9,7 +10,7 @@ import java.util.List;
  * @author Matej Lukes
  */
 public class MeshModel {
-    private List<MeshFacet> facets = new ArrayList<>();
+    private final List<MeshFacet> facets = new ArrayList<>();
 
     /**
      * Constructor of MeshModel
@@ -46,4 +47,13 @@ public class MeshModel {
     public void addFacet(MeshFacet facet) {
         facets.add(facet);
     }
+    
+    /**
+     * Entry point for visitors. 
+     * 
+     * @param visitor Visitor
+     */
+    public void accept(Visitor visitor) {
+        visitor.visitMeshModel(this);
+    }
 }
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
index 8284ac9a209f679198abdfdff8ce2a645b09c270..9d845de12bec745690266d34ee8e7b67e9f37da1 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPointImpl.java
@@ -9,7 +9,7 @@ import javax.vecmath.Vector3d;
  */
 public class MeshPointImpl implements MeshPoint {
     
-    private final Vector3d position, normal, texCoord;
+    private Vector3d position, normal, texCoord;
 
     /**
      * constructor of meshPoint
@@ -20,12 +20,18 @@ public class MeshPointImpl implements MeshPoint {
      */
     public MeshPointImpl(Vector3d position, Vector3d normal, Vector3d texCoord) {
         if (position == null) {
-            throw new NullPointerException("position cannot be null");
+            throw new IllegalArgumentException("position cannot be null");
+        } else {
+            this.position = new Vector3d(position);
         }
-
-        this.position = new Vector3d(position);
-        this.normal = new Vector3d(normal);
-        this.texCoord = new Vector3d(texCoord);
+        
+        if (normal != null) {
+            this.normal = new Vector3d(normal);
+        }
+        
+        if (texCoord != null) {
+            this.texCoord = new Vector3d(texCoord);
+        }        
     }
 
     /**
@@ -197,4 +203,10 @@ public class MeshPointImpl implements MeshPoint {
         return position.hashCode() + normal.hashCode() + texCoord.hashCode();
     }
 
+    @Override
+    public String toString() {
+        return "position " + position + ", " +
+                "normal " + normal + ", " +
+                "tex-coord " + texCoord;
+    }
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBox.java
similarity index 77%
rename from MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
rename to MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBox.java
index 733d5d844cdbf0b1a40279a28e5bfc4528d9a159..4f683737d34e1352ed16f72feeb80b162e3929e6 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBox.java
@@ -1,5 +1,7 @@
-package cz.fidentis.analyst.mesh.core;
+package cz.fidentis.analyst.mesh.visitors;
 
+import cz.fidentis.analyst.mesh.core.MeshPoint;
+import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import java.util.List;
 import javax.vecmath.Vector3d;
 
@@ -11,13 +13,12 @@ import javax.vecmath.Vector3d;
 
 public class BoundingBox {
     
-    private final MeshPoint maxPoint;
-    private final MeshPoint minPoint;
-    private final MeshPoint midPoint;
-    private final double maxDiag;
+    private MeshPoint maxPoint;
+    private MeshPoint minPoint;
     
     /** 
      * Creates bounding box from given mesh points.
+     * 
      * @param points List of mesh points, must not be null or empty
      * @throws IllegalArgumentException if the @code{points} param is null or empty
      */
@@ -26,9 +27,22 @@ public class BoundingBox {
             throw new IllegalArgumentException("points");
         }
         
-        minPoint = new MeshPointImpl(new Vector3d(Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY), null, null);
+        minPoint = new MeshPointImpl(new Vector3d(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY), null, null);
         maxPoint = new MeshPointImpl(new Vector3d(Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY), null, null);
- 
+        
+        compute(points);
+    }
+    
+    /** 
+     * Creates bounding box from given mesh points, possibly extends the existing BB.
+     * 
+     * @param points List of mesh points, must not be null or empty
+     */
+    public void compute(List<MeshPoint> points) {
+        if (points == null || points.isEmpty()) {
+            return;
+        }
+        
         for (int i = 0; i < points.size(); i++) {
             MeshPoint point = points.get(i);
             
@@ -40,10 +54,6 @@ 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);                    
         }
-        
-        midPoint = (minPoint.addPosition(maxPoint)).multiplyPosition(0.5);
-        MeshPoint diag = maxPoint.subtractPosition(minPoint);
-        this.maxDiag = diag.abs();
     }        
 
     /**
@@ -59,7 +69,7 @@ public class BoundingBox {
      * @return middle point of the bounding box
      */
     public MeshPoint getMidPoint() {
-        return midPoint;
+        return (minPoint.addPosition(maxPoint)).multiplyPosition(0.5);
     }
     
     /**
@@ -75,7 +85,7 @@ public class BoundingBox {
      * @return maximal diagonal of bounding box
      */
     public double getMaxDiag() {
-        return maxDiag;
+        return maxPoint.subtractPosition(minPoint).abs();
     }
     
     /**
@@ -89,8 +99,6 @@ public class BoundingBox {
         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/visitors/BoundingBoxVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..848848151917c1db524c0b10d16b2e8cef6d014a
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitor.java
@@ -0,0 +1,31 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+
+/**
+ * Computes a 3D bounding box (cube).
+ * 
+ * @author oslejsek
+ */
+public class BoundingBoxVisitor implements Visitor {
+
+    private BoundingBox bbox;
+    
+    @Override
+    public void visitMeshFacet(MeshFacet facet) {
+        if (bbox == null) {
+            bbox = new BoundingBox(facet.getVertices());
+        } else {
+            bbox.compute(facet.getVertices());
+        }
+    }
+    
+    /**
+     * Returns computed bounding box.
+     * @return Bounding box or null
+     */
+    public BoundingBox getBoundingBox() {
+        return bbox;
+    }
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Visitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Visitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf8401b9329240af765cca3055e76e18ae81b0f4
--- /dev/null
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Visitor.java
@@ -0,0 +1,31 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+
+/**
+ * Visitor for the traversal of @code{MeshModel} and @code{MeshFacet}.
+ * 
+ * @author oslejsek
+ */
+public interface Visitor {
+    
+    
+    /**
+     * Visits a mesh model.
+     * 
+     * @param model Mesh model to be visited.
+     */
+    default void visitMeshModel(MeshModel model) {
+        for (MeshFacet facet: model.getFacets()) {
+            facet.accept(this);
+        }
+    }
+   
+    /**
+     * Visits a mesh facet.
+     * 
+     * @param facet Mesh facet to be visited.
+     */
+    void visitMeshFacet(MeshFacet facet);
+}
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d693d11fc7e494e90c4e75dd40b57acc474e74f
--- /dev/null
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/BoundingBoxVisitorTest.java
@@ -0,0 +1,50 @@
+package cz.fidentis.analyst.mesh.visitors;
+
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.mesh.io.MeshObjLoader;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import javax.vecmath.Vector3d;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author Radek Oslejsek
+ */
+public class BoundingBoxVisitorTest {
+    
+    Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "mesh", "io");
+    
+    @Test
+    void moreObjectFileTest() { //TODO: Not testing in loader
+        File moreObjects = new File(testFileDirectory.toFile(), "MoreObjects.obj");
+        Exception ex = assertThrows(IOException.class, () -> MeshObjLoader.read(moreObjects));
+    }
+    
+    @Test
+    void icoSphereTest() throws IOException {
+        MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj"));
+        assertNotNull(m);
+        BoundingBoxVisitor visitor = new BoundingBoxVisitor();
+        m.accept(visitor);
+        assertEquals(new Vector3d(0.8944249749183655, 1.0, 0.8506399989128113), visitor.getBoundingBox().getMaxPoint().getPosition());
+        assertEquals(new Vector3d(-0.8944249749183655, -1.0, -0.8506399989128113), visitor.getBoundingBox().getMinPoint().getPosition());
+    }
+    
+    @Test
+    void combinedTest() throws IOException {
+        MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj"));
+        assertNotNull(m);
+        BoundingBoxVisitor visitor = new BoundingBoxVisitor();
+        m.accept(visitor);
+        
+        m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "Tetrahedron.obj"));
+        assertNotNull(m);
+        m.accept(visitor);
+        
+        assertEquals(new Vector3d(1.0, 1.0, 1.0), visitor.getBoundingBox().getMaxPoint().getPosition());
+        assertEquals(new Vector3d(-1.0, -1.0, -1.0), visitor.getBoundingBox().getMinPoint().getPosition());
+    }
+}