From bc5f6d81eac8aad7bd6a9b72681159e3c0051d08 Mon Sep 17 00:00:00 2001
From: Radek Oslejsek <oslejsek@fi.muni.cz>
Date: Sun, 24 May 2020 14:15:49 +0200
Subject: [PATCH] Adapted interface of MeshModel toward a component-based
 decomposition

---
 .../analyst/symmetry/TriangleOBSOLETE.java    | 102 ------------------
 .../analyst/mesh/core/BoundingBox.java        |  92 +++++-----------
 .../fidentis/analyst/mesh/core/MeshFacet.java |  23 ++++
 .../analyst/mesh/core/MeshFacetImpl.java      |  62 ++++++++++-
 .../fidentis/analyst/mesh/core/MeshModel.java |   3 +-
 .../analyst/mesh/core/MeshTriangle.java       |  92 ++--------------
 6 files changed, 118 insertions(+), 256 deletions(-)
 delete mode 100644 Comparison/src/main/java/cz/fidentis/analyst/symmetry/TriangleOBSOLETE.java

diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/TriangleOBSOLETE.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/TriangleOBSOLETE.java
deleted file mode 100644
index 23d91944..00000000
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/TriangleOBSOLETE.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/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
index 16be89d8..97d990ef 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/BoundingBox.java
@@ -1,7 +1,5 @@
-package cz.fidentis.analyst.symmetry;
+package cz.fidentis.analyst.mesh.core;
 
-import cz.fidentis.analyst.mesh.core.MeshPoint;
-import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import java.util.List;
 import javax.vecmath.Vector3d;
 
@@ -14,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
@@ -29,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
@@ -45,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
@@ -62,34 +55,17 @@ 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() {
+     */
+    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);
  
@@ -104,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.
      * 
@@ -136,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/MeshFacet.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
index 9f662046..3a700479 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
@@ -44,4 +44,27 @@ public interface 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
index 301548ec..10cd36d9 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,7 +1,11 @@
 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
@@ -26,9 +30,7 @@ public class MeshFacetImpl implements MeshFacet {
      * @param facet copied MeshFacet
      */
     public MeshFacetImpl(MeshFacet facet) {
-        for (MeshPoint vertex: facet.getVertices()) {
-            vertices.add(new MeshPointImpl(vertex));
-        }
+        vertices.addAll(facet.getVertices()); // encapsulation preserved - vertices MeshPoints are immutable)
         cornerTable = new CornerTable(facet.getCornerTable());
     }
 
@@ -49,12 +51,64 @@ public class MeshFacetImpl implements MeshFacet {
 
     @Override
     public List<MeshPoint> getVertices() {
-        return vertices;
+        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;
+    }
+    
+    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 38a7b9c6..9ab6d00c 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,8 +24,7 @@ public class MeshModel {
      * @param meshModel copied MeshModel
      */
     public MeshModel(MeshModel meshModel) {
-        for (MeshFacet facet :
-                meshModel.facets) {
+        for (MeshFacet facet: meshModel.facets) {
             facets.add(new MeshFacetImpl(facet));
         }
     }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
index 23d91944..ce92a488 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshTriangle.java
@@ -1,16 +1,17 @@
-package cz.fidentis.analyst.symmetry;
+package cz.fidentis.analyst.mesh.core;
 
 /**
  *
  * @author Natália Bebjaková
  * 
- * Helping representation of triangle in symmetry estimate 
+ * Adapter for the corner table representing a single triangle of the @code{MeshFacet}.
  */
 
-public class Triangle { 
-    protected int vertex1;
-    protected int vertex2;
-    protected int vertex3;
+public class MeshTriangle { 
+    
+    public final MeshPoint vertex1;
+    public final MeshPoint vertex2;
+    public final MeshPoint vertex3;
     
     /**
      * Creates new triangle
@@ -19,84 +20,11 @@ public class Triangle {
      * @param v2 second vertex
      * @param v3 third vertex
      */        
-    public Triangle(int v1, int v2, int v3) {
+    public MeshTriangle(MeshPoint v1, MeshPoint v2, MeshPoint 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);
-    }
+    
+    
 }
-- 
GitLab