From 8cdbcc8d298743ebe503be2db639396c1b6d1609 Mon Sep 17 00:00:00 2001
From: Radek Oslejsek <oslejsek@fi.muni.cz>
Date: Tue, 6 Apr 2021 21:29:18 +0200
Subject: [PATCH] MeshTriangle simplified

---
 .../analyst/visitors/mesh/Curvature.java      | 271 +-----------------
 .../analyst/mesh/core/MeshFacetImpl.java      |  14 +-
 .../analyst/mesh/core/MeshTriangle.java       |  71 +++--
 .../analyst/mesh/core/TriangleFan.java        |  48 +++-
 .../analyst/mesh/core/MeshTriangleTest.java   |   2 +
 5 files changed, 104 insertions(+), 302 deletions(-)

diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Curvature.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Curvature.java
index b42c398b..cba70946 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Curvature.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Curvature.java
@@ -84,7 +84,7 @@ public class Curvature extends MeshVisitor {
         
         Cache cache = new Cache(facet);
         
-        final List<CurvTriangle> triangles = precomputeTriangles(facet);
+        //final List<CurvTriangle> triangles = precomputeTriangles(facet);
         for (int vertA = 0; vertA < facet.getNumberOfVertices(); vertA++) {
             TriangleFan oneRing = facet.getOneRingNeighborhood(vertA);
             
@@ -155,6 +155,7 @@ public class Curvature extends MeshVisitor {
         }
     }
     
+    /*
     protected List<CurvTriangle> precomputeTriangles(MeshFacet facet) {
         List<CurvTriangle> ret = new ArrayList<>(facet.getNumTriangles());
         for (MeshTriangle tri: facet) {
@@ -162,6 +163,7 @@ public class Curvature extends MeshVisitor {
         }
         return ret;
     }
+    */
     
     /**
      * Helper class that caches triangle characteristics used multiples times during the curvature computation.
@@ -175,273 +177,6 @@ public class Curvature extends MeshVisitor {
      */
     protected class CurvTriangle {
         
-        private final MeshFacet facet;
-        private final MeshTriangle tri;
-        
-        private final double v1Angle;
-        private final double v2Angle;
-        private final double v3Angle;
-        
-        private final double v1AngleCotang;
-        private final double v2AngleCotang;
-        private final double v3AngleCotang;
-        
-        public CurvTriangle(MeshFacet facet, MeshTriangle tri) {
-            this.facet = facet;
-            this.tri = tri;
-            
-            Vector3d a = new Vector3d(facet.getVertex(tri.index3).getPosition());
-            a.sub(facet.getVertex(tri.index2).getPosition());
-            
-            Vector3d b = new Vector3d(facet.getVertex(tri.index1).getPosition());
-            b.sub(facet.getVertex(tri.index3).getPosition());
-            
-            Vector3d c = new Vector3d(facet.getVertex(tri.index2).getPosition());
-            c.sub(facet.getVertex(tri.index1).getPosition());
-            
-            a.normalize();
-            b.normalize();
-            c.normalize();
-            
-            b.scale(-1.0);
-            double cos1 = c.dot(b);
-            
-            c.scale(-1.0);
-            double cos2 = a.dot(c);
-            
-            a.scale(-1.0);
-            b.scale(-1.0);
-            double cos3 = a.dot(b);
-            
-            this.v1Angle = Math.acos(cos1);
-            this.v2Angle = Math.acos(cos2);
-            this.v3Angle = Math.acos(cos3);
-            
-            this.v1AngleCotang = 1.0 / Math.tan(v1Angle);
-            this.v2AngleCotang = 1.0 / Math.tan(v2Angle);
-            this.v3AngleCotang = 1.0 / Math.tan(v3Angle);
-        }
-        
-        public double area() {
-            return 0.5 * lengthSquaredAC(tri.vertex1) * lengthSquaredAB(tri.vertex1) * Math.sin(v1Angle);
-        }
-        
-        /**
-         * Returns vertex A. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return vertex A.
-         */
-        public Vector3d vertA(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return tri.vertex1.getPosition();
-            } else if (facetPoint == tri.vertex2) {
-                return tri.vertex2.getPosition();
-            } else if (facetPoint == tri.vertex3) {
-                return tri.vertex3.getPosition();
-            }
-            return null;
-        }
-
-        /**
-         * Returns vertex B. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return vertex B.
-         */
-        public Vector3d vertB(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return tri.vertex3.getPosition();
-            } else if (facetPoint == tri.vertex2) {
-                return tri.vertex1.getPosition();
-            } else if (facetPoint == tri.vertex3) {
-                return tri.vertex2.getPosition();
-            }
-            return null;
-        }
-
-        /**
-         * Returns vertex C. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return vertex C.
-         */
-        public Vector3d vertC(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return tri.vertex2.getPosition();
-            } else if (facetPoint == tri.vertex2) {
-                return tri.vertex3.getPosition();
-            } else if (facetPoint == tri.vertex3) {
-                return tri.vertex1.getPosition();
-            }
-            return null;
-        }
-
-        /**
-         * Returns cached angle in the vertex A. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Alpha angle.
-         */
-        public double alpha(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return v1Angle;
-            } else if (facetPoint == tri.vertex2) {
-                return v2Angle;
-            } else if (facetPoint == tri.vertex3) {
-                return v3Angle;
-            }
-            return Double.NaN;
-        }
-
-        /**
-         * Returns cached angle in the vertex B.
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Beta angle.
-         */
-        public double beta(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return v3Angle;
-            } else if (facetPoint == tri.vertex2) {
-                return v1Angle;
-            } else if (facetPoint == tri.vertex3) {
-                return v2Angle;
-            }
-            return Double.NaN;
-        }
-
-        /**
-         * Returns cached angle in the vertex C. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Gamma angle.
-         */
-        public double gamma(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return v2Angle;
-            } else if (facetPoint == tri.vertex2) {
-                return v3Angle;
-            } else if (facetPoint == tri.vertex3) {
-                return v1Angle;
-            }
-            return Double.NaN;
-        }
-
-        /**
-         * Returns cached cotangent of the angle in the vertex A. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Cotangent of the alpha angle.
-         */
-        public double alphaCotan(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return v1AngleCotang;
-            } else if (facetPoint == tri.vertex2) {
-                return v2AngleCotang;
-            } else if (facetPoint == tri.vertex3) {
-                return v3AngleCotang;
-            }
-            return Double.NaN;
-        }
-
-        /**
-         * Returns cached cotangent of the angle in the vertex B.
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Cotangent of the beta angle.
-         */
-        public double betaCotan(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return v3AngleCotang;
-            } else if (facetPoint == tri.vertex2) {
-                return v1AngleCotang;
-            } else if (facetPoint == tri.vertex3) {
-                return v2AngleCotang;
-            }
-            return Double.NaN;
-        }
-
-        /**
-         * Returns cached cotangent of the angle in the vertex C. 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Cotangent of the gamma angle.
-         */
-        public double gammaCotan(MeshPoint facetPoint) {
-            if (facetPoint == tri.vertex1) {
-                return v2AngleCotang;
-            } else if (facetPoint == tri.vertex2) {
-                return v3AngleCotang;
-            } else if (facetPoint == tri.vertex3) {
-                return v1AngleCotang;
-            }
-            return Double.NaN;
-        }
-        
-        /**
-         * Returns squared length of the edge AB (opposite to the vertex A). 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Squared length of the edge AB.
-         */
-        public double lengthSquaredAB(MeshPoint facetPoint) {
-            Vector3d v = null;
-            if (facetPoint == tri.vertex1) {
-                v = new Vector3d(facet.getVertex(tri.index3).getPosition());
-                v.sub(facet.getVertex(tri.index1).getPosition());
-            } else if (facetPoint == tri.vertex2) {
-                v = new Vector3d(facet.getVertex(tri.index1).getPosition());
-                v.sub(facet.getVertex(tri.index2).getPosition());
-            } else if (facetPoint == tri.vertex3) {
-                v = new Vector3d(facet.getVertex(tri.index2).getPosition());
-                v.sub(facet.getVertex(tri.index3).getPosition());
-            }
-            return v.lengthSquared();
-        }
-        
-        /**
-         * Returns squared length of the edge AC (opposite to the vertex B). 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Squared length of the edge AC.
-         */
-        public double lengthSquaredAC(MeshPoint facetPoint) {
-            Vector3d v = null;
-            if (facetPoint == tri.vertex1) {
-                v = new Vector3d(facet.getVertex(tri.index2).getPosition());
-                v.sub(facet.getVertex(tri.index1).getPosition());
-            } else if (facetPoint == tri.vertex2) {
-                v = new Vector3d(facet.getVertex(tri.index3).getPosition());
-                v.sub(facet.getVertex(tri.index2).getPosition());
-            } else if (facetPoint == tri.vertex3) {
-                v = new Vector3d(facet.getVertex(tri.index1).getPosition());
-                v.sub(facet.getVertex(tri.index3).getPosition());
-            }
-            return v.lengthSquared();
-        }
-        
-        /**
-         * Returns squared length of the edge BC (opposite to the vertex A). 
-         * 
-         * @param facetPoint Central point of the 1-ring neighborhood
-         * @return Squared length of the edge BC.
-         */
-        public double lengthSquaredBC(MeshPoint facetPoint) {
-            Vector3d v = null;
-            if (facetPoint == tri.vertex1) {
-                v = new Vector3d(facet.getVertex(tri.index3).getPosition());
-                v.sub(facet.getVertex(tri.index2).getPosition());
-                v.sub(facetPoint.getPosition());
-            } else if (facetPoint == tri.vertex2) {
-                v = new Vector3d(facet.getVertex(tri.index1).getPosition());
-                v.sub(facet.getVertex(tri.index3).getPosition());
-            } else if (facetPoint == tri.vertex3) {
-                v = new Vector3d(facet.getVertex(tri.index2).getPosition());
-                v.sub(facet.getVertex(tri.index1).getPosition());
-            }
-            return v.lengthSquared();
-        }
     }
 
     /**
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 6511eb24..b2d53377 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
@@ -98,10 +98,10 @@ public class MeshFacetImpl implements MeshFacet {
         // calculate normals from corresponding triangles
         for (MeshTriangle t : this) { 
             Vector3d triangleNormal = 
-                    (t.vertex3.subtractPosition(t.vertex1)).crossProduct(t.vertex2.subtractPosition(t.vertex1)).getPosition();
-            normalMap.get(t.vertex1.getPosition()).add(triangleNormal);
-            normalMap.get(t.vertex2.getPosition()).add(triangleNormal);
-            normalMap.get(t.vertex3.getPosition()).add(triangleNormal);
+                    (t.getPoint3().subtractPosition(t.getPoint1())).crossProduct(t.getPoint2().subtractPosition(t.getPoint1())).getPosition();
+            normalMap.get(t.getPoint1().getPosition()).add(triangleNormal);
+            normalMap.get(t.getPoint2().getPosition()).add(triangleNormal);
+            normalMap.get(t.getPoint3().getPosition()).add(triangleNormal);
         }
         
         // normalize normals:
@@ -132,9 +132,7 @@ public class MeshFacetImpl implements MeshFacet {
         for (Integer triI: adjacentTrianglesI) {
             List<Integer> triVerticesI = cornerTable.getIndexesOfVerticesByTriangleIndex(triI);
             MeshTriangle tri = new MeshTriangle(
-                    getVertex(triVerticesI.get(0)),
-                    getVertex(triVerticesI.get(1)),
-                    getVertex(triVerticesI.get(2)),
+                    this,
                     triVerticesI.get(0),
                     triVerticesI.get(1),
                     triVerticesI.get(2));
@@ -204,7 +202,7 @@ public class MeshFacetImpl implements MeshFacet {
                 int i2 = cornerTable.getRow(index + 1).getVertexIndex();
                 int i3 = cornerTable.getRow(index + 2).getVertexIndex();
         
-                MeshTriangle tri = new MeshTriangle(vertices.get(i1), vertices.get(i2), vertices.get(i3), i1, i2, i3);
+                MeshTriangle tri = new MeshTriangle(MeshFacetImpl.this, i1, i2, i3);
         
                 index += 3;        
                 return tri;
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 bcd476b7..75c24d04 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
@@ -16,9 +16,11 @@ public class MeshTriangle implements Iterable<MeshPoint> {
     
     public static final double EPS = 0.001; // tollerance
     
-    public final MeshPoint vertex1;
-    public final MeshPoint vertex2;
-    public final MeshPoint vertex3;
+    //public final MeshPoint vertex1;
+    //public final MeshPoint vertex2;
+    //public final MeshPoint vertex3;
+    
+    private final MeshFacet facet;
     
     /**
      * Under which index is the corresponding vertex stored in the mesh facet
@@ -39,13 +41,38 @@ public class MeshTriangle implements Iterable<MeshPoint> {
      * @param i2 which index is the second vertex stored in the mesh facet
      * @param i3 which index is the third vertex stored in the mesh facet
      */        
-    public MeshTriangle(MeshPoint v1, MeshPoint v2, MeshPoint v3, int i1, int i2, int i3) {
-        this.vertex1 = v1;
-        this.vertex2 = v2; 
-        this.vertex3 = v3;
+    public MeshTriangle(MeshFacet facet, int i1, int i2, int i3) {
+        if (facet == null) {
+            throw new IllegalArgumentException("facet");
+        }
         this.index1 = i1;
         this.index2 = i2;
         this.index3 = i3;
+        this.facet = facet;
+    }
+    
+    public Vector3d getVertex1() {
+        return facet.getVertex(index1).getPosition();
+    }
+    
+    public Vector3d getVertex2() {
+        return facet.getVertex(index2).getPosition();
+    }
+    
+    public Vector3d getVertex3() {
+        return facet.getVertex(index3).getPosition();
+    }
+    
+    public MeshPoint getPoint1() {
+        return facet.getVertex(index1);
+    }
+    
+    public MeshPoint getPoint2() {
+        return facet.getVertex(index2);
+    }
+    
+    public MeshPoint getPoint3() {
+        return facet.getVertex(index3);
     }
     
     /**
@@ -54,10 +81,10 @@ public class MeshTriangle implements Iterable<MeshPoint> {
      * @return normalized normal vector from the vertices.
      */
     public Vector3d computeNormal() {
-        Vector3d ab = new Vector3d(vertex1.getPosition());
-        ab.sub(vertex2.getPosition());
-        Vector3d ac = new Vector3d(vertex1.getPosition());
-        ac.sub(vertex3.getPosition());
+        Vector3d ab = new Vector3d(getVertex1());
+        ab.sub(getVertex2());
+        Vector3d ac = new Vector3d(getVertex1());
+        ac.sub(getVertex3());
         Vector3d normal = new Vector3d();
         normal.cross(ab, ac);
         normal.normalize();
@@ -101,11 +128,11 @@ public class MeshTriangle implements Iterable<MeshPoint> {
                 }
                 switch (counter++) {
                     case 0:
-                        return vertex1;
+                        return facet.getVertex(index1);
                     case 1:
-                        return vertex2;
+                        return facet.getVertex(index2);
                     case 2:
-                        return vertex3;
+                        return facet.getVertex(index3);
                     default:
                         return null;
                 }                
@@ -124,6 +151,10 @@ public class MeshTriangle implements Iterable<MeshPoint> {
             return voronoiPoint;
         }
         
+        MeshPoint vertex1 = facet.getVertex(index1);
+        MeshPoint vertex2 = facet.getVertex(index2);
+        MeshPoint vertex3 = facet.getVertex(index3);
+        
         double a = (vertex2.subtractPosition(vertex3)).abs();
         double b = (vertex3.subtractPosition(vertex1)).abs();
         double c = (vertex2.subtractPosition(vertex1)).abs();
@@ -202,7 +233,7 @@ public class MeshTriangle implements Iterable<MeshPoint> {
     protected Vector3d getProjectionToTrianglePlane(Vector3d point) {
         Vector3d normal = computeNormal();
         Vector3d helperVector = new Vector3d(point);
-        helperVector.sub(vertex1.getPosition());
+        helperVector.sub(getVertex1());
         double dist = helperVector.dot(normal);
 
         Vector3d projection = new Vector3d(point);
@@ -242,14 +273,10 @@ public class MeshTriangle implements Iterable<MeshPoint> {
      * @return perpendicular projection to the nearest edge
      */
     protected Vector3d getProjectionToClosestEdge(Vector3d point) {
-        Vector3d v1 = vertex1.getPosition();
-        Vector3d v2 = vertex2.getPosition();
-        Vector3d v3 = vertex3.getPosition();
-        
         double minDistance = Double.POSITIVE_INFINITY;
         Vector3d closestProjection = null;
 
-        Vector3d projection = getProjectionToEdge(point, v2, v1);
+        Vector3d projection = getProjectionToEdge(point, getVertex2(), getVertex1());
         Vector3d aux = new Vector3d(point);
         aux.sub(projection);
         double dist = aux.length();
@@ -258,7 +285,7 @@ public class MeshTriangle implements Iterable<MeshPoint> {
             closestProjection = projection;
         }
         
-        projection = getProjectionToEdge(point, v3, v2);
+        projection = getProjectionToEdge(point, getVertex3(), getVertex2());
         aux.sub(point, projection);
         dist = aux.length();
         if (dist < minDistance) {
@@ -266,7 +293,7 @@ public class MeshTriangle implements Iterable<MeshPoint> {
             closestProjection = projection;
         }
         
-        projection = getProjectionToEdge(point, v1, v3);
+        projection = getProjectionToEdge(point, getVertex1(), getVertex3());
         aux.sub(point, projection);
         dist = aux.length();
         if (dist < minDistance) {
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/TriangleFan.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/TriangleFan.java
index 9536cbbb..cbf29e2b 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/TriangleFan.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/TriangleFan.java
@@ -1,8 +1,10 @@
 package cz.fidentis.analyst.mesh.core;
 
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.Objects;
 
 /**
@@ -11,8 +13,10 @@ import java.util.Objects;
  * 
  * @author Radek Oslejsek
  */
-public class TriangleFan {
+public class TriangleFan implements Iterable<MeshTriangle> {
     
+    private final int centralVertex;
+    private final MeshFacet facet;
     private final List<Integer> vertices = new LinkedList<>();
     private final List<Integer> triangles = new LinkedList<>();
     
@@ -28,6 +32,9 @@ public class TriangleFan {
             throw new IllegalArgumentException("facet");
         }
         
+        centralVertex = vert;
+        this.facet = facet;
+        
         int vertRow = -1;
         for (int i = 0; i < facet.getCornerTable().getSize(); i++) {
             if (facet.getCornerTable().getRow(i).getVertexIndex() == vert) {
@@ -39,7 +46,7 @@ public class TriangleFan {
             throw new IllegalArgumentException("vert");
         }
         
-        computeOneRingData(facet, vertRow);
+        computeOneRingData(vertRow);
     }
     
     /**
@@ -81,7 +88,7 @@ public class TriangleFan {
         return Collections.unmodifiableList(triangles);
     }
     
-    private void computeOneRingData(MeshFacet facet, int vertRow) {
+    private void computeOneRingData(int vertRow) {
         CornerTable ct = facet.getCornerTable();
         int ringVertRow = ct.getIndexOfNextCornerInFace(vertRow);
         while (true) {
@@ -108,5 +115,38 @@ public class TriangleFan {
             }
             triangles.add(ct.getIndexOfFace(ringVertRow));
         }
-    }    
+    }
+    
+    /**
+     * Vertex 1 of the returned triangle always corresponds to the central vertex 
+     * around which the triangle fan is constructed.
+     * @return 
+     */
+    @Override
+    public Iterator<MeshTriangle> iterator() {
+        return new Iterator<MeshTriangle>() {
+            private int index;
+    
+            /**
+             * 
+             * @param facet Mesh facet to iterate
+             */
+            @Override
+            public boolean hasNext() {
+                return index < triangles.size();
+            }
+
+            @Override
+            public MeshTriangle next() {
+                if (!hasNext()) {
+                    throw new NoSuchElementException();
+                }
+                
+                MeshTriangle tri = new MeshTriangle(facet, centralVertex, index, index+1);
+                index++;
+                return tri;
+            }    
+        };
+    }
+    
 }
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/core/MeshTriangleTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/core/MeshTriangleTest.java
index 9abe112d..1fd03eec 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/core/MeshTriangleTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/core/MeshTriangleTest.java
@@ -12,6 +12,7 @@ import org.junit.jupiter.api.Test;
  */
 public class MeshTriangleTest {
     
+    /*
     protected MeshTriangle getTriangle() {
         MeshTriangle triangle = new MeshTriangle(
                 new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
@@ -36,5 +37,6 @@ public class MeshTriangleTest {
         Assertions.assertEquals(new Vector3d(1, 0, 0), tri.getClosestPoint(new Vector3d(1, 0, -1)));
         Assertions.assertEquals(new Vector3d(1.2, 0.2, 0), tri.getClosestPoint(new Vector3d(1.2, 0.2, -1)));
     }
+    */
 
 }
-- 
GitLab