From 8228dedef99708903646cc31c415399d21f335d6 Mon Sep 17 00:00:00 2001
From: Radek Oslejsek <oslejsek@fi.muni.cz>
Date: Tue, 6 Apr 2021 20:44:52 +0200
Subject: [PATCH] Fixed curvature calculations

---
 .../analyst/visitors/mesh/Curvature.java      | 202 ++++++++++++++----
 .../analyst/tests/EfficiencyTests.java        |  36 ++--
 .../fidentis/analyst/mesh/core/MeshFacet.java |  13 +-
 .../analyst/mesh/core/MeshFacetImpl.java      |  22 +-
 .../analyst/mesh/core/TriangleFan.java        |  69 +++---
 5 files changed, 236 insertions(+), 106 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 d83e846f..b42c398b 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
@@ -4,6 +4,7 @@ import cz.fidentis.analyst.mesh.MeshVisitor;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.mesh.core.MeshTriangle;
+import cz.fidentis.analyst.mesh.core.TriangleFan;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -60,7 +61,7 @@ public class Curvature extends MeshVisitor {
     }
     
     /**
-     * Returns maximu principal curvatures for all inspected mesh facets. The order corresponds to
+     * Returns maximum principal curvatures for all inspected mesh facets. The order corresponds to
      * the order of vertices, i.e., i-th value represents the curvature of i-th mesh vertex.
      * 
      * @return Maximum principal curvatures of inspected mesh facets.
@@ -81,12 +82,13 @@ public class Curvature extends MeshVisitor {
             maxPrincipal.put(facet, new ArrayList<>());
         }
         
-        //final List<MeshTriangle> triangles = facet.getTriangles();
+        Cache cache = new Cache(facet);
+        
         final List<CurvTriangle> triangles = precomputeTriangles(facet);
         for (int vertA = 0; vertA < facet.getNumberOfVertices(); vertA++) {
-            List<Integer> neighbouringTriangles = facet.getCornerTable().getTriangleIndexesByVertexIndex(vertA);
+            TriangleFan oneRing = facet.getOneRingNeighborhood(vertA);
             
-            if (facet.vertexIsBoundary(vertA)) {
+            if (oneRing.isBoundary()) {
                 this.gaussian.get(facet).add(0.0);
                 this.mean.get(facet).add(0.0);
                 this.minPrincipal.get(facet).add(0.0);
@@ -94,30 +96,52 @@ public class Curvature extends MeshVisitor {
                 continue;
             }
         
-            if (neighbouringTriangles.isEmpty()) {
-                this.gaussian.get(facet).add(Double.NaN);
-                this.mean.get(facet).add(Double.NaN);
-                this.minPrincipal.get(facet).add(Double.NaN);
-                this.maxPrincipal.get(facet).add(Double.NaN);
-                continue;
-            }
-        
-            double sumArea = 0.0;
             double sumAngles = 0.0;
+            double sumArea = 0.0;
             Vector3d pointSum = new Vector3d();
-        
-            // for all surrounding triangles:
-            for (int i = 0; i < neighbouringTriangles.size(); i++) {
-                CurvTriangle ctri = triangles.get(neighbouringTriangles.get(i));
-                CurvTriangle tNext = triangles.get(neighbouringTriangles.get((i + 1) % neighbouringTriangles.size()));
-            
-                sumArea += computeArea(ctri, facet.getVertex(vertA));
-                sumAngles +=  ctri.alpha(facet.getVertex(vertA));
             
-                Vector3d aux = new Vector3d(ctri.vertC(facet.getVertex(vertA)));
-                aux.sub(ctri.vertA(facet.getVertex(vertA)));
-                aux.scale(ctri.betaCotan(facet.getVertex(vertA)) + tNext.gammaCotan(facet.getVertex(vertA)));
-                pointSum.add(aux);
+            for (int i = 0; i < oneRing.getVertices().size()-1; i++) {
+                int vertB = oneRing.getVertices().get(i);
+                int vertC = oneRing.getVertices().get(i+1);
+                int tri = oneRing.getTriangles().get(i);
+                
+                // Angles:
+                sumAngles += cache.getAngle(vertA, vertB, vertC, tri);
+                
+                // Area:
+                double alpha = cache.getAngle(vertA, vertB, vertC, tri);
+                double beta = cache.getAngle(vertB, vertA, vertC, tri);
+                double gamma = cache.getAngle(vertC, vertA, vertB, tri);
+                
+                Vector3d ab = new Vector3d(facet.getVertex(vertB).getPosition());
+                ab.sub(facet.getVertex(vertA).getPosition());
+        
+                Vector3d ac = new Vector3d(facet.getVertex(vertC).getPosition());
+                ac.sub(facet.getVertex(vertA).getPosition());
+        
+                double lenSqrtAB = ab.lengthSquared();
+                double lenSqrtAC = ac.lengthSquared();
+                
+                double piHalf = Math.PI / 2.0; // 90 degrees
+                if (alpha >= piHalf || beta >= piHalf || gamma >= piHalf) { // check for obtuse angle
+                    double area = 0.5 * lenSqrtAB * lenSqrtAC * Math.sin(alpha);
+                    sumArea += (alpha > piHalf) ? area / 2.0 : area / 4.0;
+                } else {
+                    double cotGamma = 1.0 / Math.tan(gamma);
+                    double cotBeta = 1.0 / Math.tan(beta);
+                    sumArea += (lenSqrtAB * cotGamma + lenSqrtAC * cotBeta) / 8.0;
+                }
+                
+                // Laplace:
+                int triNext = oneRing.getTriangles().get((i + 1) % oneRing.getTriangles().size());
+                int vertD;
+                if (i == (oneRing.getVertices().size() - 2)) { // last triangle
+                    vertD = oneRing.getVertices().get(1);
+                } else {
+                    vertD = oneRing.getVertices().get(i + 2);
+                }
+                ac.scale(cache.getCtan(vertA, vertB, vertC, tri) + cache.getCtan(vertA, vertC, vertD, triNext));
+                pointSum.add(ac);
             }
         
             double gaussVal = (2.0 * Math.PI - sumAngles) / sumArea;
@@ -139,23 +163,6 @@ public class Curvature extends MeshVisitor {
         return ret;
     }
     
-    protected double computeArea(CurvTriangle ctri, MeshPoint vertA) {
-        double alpha = ctri.alpha(vertA);
-        double beta = ctri.beta(vertA);
-        double gamma = ctri.gamma(vertA);
-            
-        double piHalf = Math.PI / 2.0; // 90 degrees
-        if (alpha >= piHalf || beta >= piHalf || gamma >= piHalf) { // check for obtuse angle
-            return (alpha > piHalf) ? ctri.area() / 2.0 : ctri.area() / 4.0;
-        } else {
-            double cotBeta = ctri.betaCotan(vertA);
-            double cotGamma = ctri.gammaCotan(vertA);
-            double ab = ctri.lengthSquaredAB(vertA);
-            double ac = ctri.lengthSquaredAC(vertA);
-            return (ab * cotGamma + ac * cotBeta) / 8.0;
-        }
-    }
-    
     /**
      * Helper class that caches triangle characteristics used multiples times during the curvature computation.
      * <ul>
@@ -437,4 +444,115 @@ public class Curvature extends MeshVisitor {
         }
     }
 
+    /**
+     * Cache key.
+     * @author Radek Oslejsek
+     */
+    private class CacheKey {
+
+        private final int vertIndex;
+        private final int triIndex;
+        
+        /**
+         * Constructor.
+         * @param v vertex
+         * @param i triangle
+         */
+        CacheKey(int v, int i) {
+            this.vertIndex = v;
+            this.triIndex = i;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 61 * hash + this.vertIndex;
+            hash = 61 * hash + this.triIndex;
+            return hash;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            final CacheKey other = (CacheKey) obj;
+            if (this.vertIndex != other.vertIndex) {
+                return false;
+            }
+            if (this.triIndex != other.triIndex) {
+                return false;
+            }
+            return true;
+        }
+    }
+    
+    /**
+     * Cache.
+     * @author Radek Oslejsek
+     */
+    private class Cache {
+        
+        private final MeshFacet facet;
+        private final Map<CacheKey, Double> cache = new HashMap<>();
+
+        Cache(MeshFacet facet) {
+            this.facet = facet;
+        }
+        
+        public double getAngle(int vertA, int vertB, int vertC, int tri) {
+            CacheKey key = new CacheKey(vertA, tri);
+            if (cache.containsKey(key)) {
+                return cache.get(key);
+            }
+            
+            //System.out.println("XXX"+vertA+"|"+vertB+"|"+vertC);
+            //System.out.println("YYY"+facet.getVertex(vertA).getPosition()+"|"+facet.getVertex(vertB).getPosition()+"|"+facet.getVertex(vertC).getPosition());
+            
+            Vector3d ab = new Vector3d(facet.getVertex(vertB).getPosition());
+            ab.sub(facet.getVertex(vertA).getPosition());
+            ab.normalize();
+            
+            Vector3d ac = new Vector3d(facet.getVertex(vertC).getPosition());
+            ac.sub(facet.getVertex(vertA).getPosition());
+            ac.normalize();
+            
+            Vector3d bc = new Vector3d(facet.getVertex(vertC).getPosition());
+            bc.sub(facet.getVertex(vertB).getPosition());
+            bc.normalize();
+            
+            //System.out.println("AAA"+ac+"|"+ab+"|"+bc);
+            
+            double cosAlpha = ab.dot(ac);
+            
+            ab.scale(-1.0);
+            double cosBeta = ab.dot(bc);
+            
+            bc.scale(-1.0);
+            ac.scale(-1.0);
+            double cosGamma = bc.dot(ac);
+            
+            //System.out.println("BBB"+cosAlpha+"|"+cosBeta+"|"+cosGamma);
+            
+            double ret = Math.acos(cosAlpha);
+            
+            cache.put(new CacheKey(vertA, tri), ret);
+            cache.put(new CacheKey(vertB, tri), Math.acos(cosBeta));
+            cache.put(new CacheKey(vertC, tri), Math.acos(cosGamma));
+            
+            return ret;
+        }
+        
+        public double getCtan(int vertA, int vertB, int vertC, int tri) {
+            return 1.0 / Math.tan(getAngle(vertA, vertB, vertC, tri));
+        }
+    }
+    
+
 }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
index 64a50054..aa40e41d 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
@@ -40,32 +40,32 @@ public class EfficiencyTests {
         face2 = new HumanFace(boyFile);
         
         boolean relativeDist = false;
-        boolean printDetails = true;
+        boolean printDetails = false;
         
         //face1.getMeshModel().compute(new GaussianCurvature()); // initialize everything, then measure
         
-        //System.out.println("Symmetry plane calculation:");
-        //printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.MEAN);
-        //printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.GAUSSIAN);
-        //printSymmetryPlane(face1, false, SignificantPoints.CurvatureAlg.MEAN);
-        //printSymmetryPlane(face1, false, SignificantPoints.CurvatureAlg.GAUSSIAN);
+        System.out.println("Symmetry plane calculation:");
+        printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.MEAN);
+        printSymmetryPlane(face1, true, SignificantPoints.CurvatureAlg.GAUSSIAN);
+        printSymmetryPlane(face1, false, SignificantPoints.CurvatureAlg.MEAN);
+        printSymmetryPlane(face1, false, SignificantPoints.CurvatureAlg.GAUSSIAN);
         
-        //System.out.println();
-        //System.out.println(measureKdTreeCreation(face1) + "\tmsec:\tKd-tree creation of first face");
-        //System.out.println(measureKdTreeCreation(face2) + "\tmsec:\tKd-tree creation of second face");
+        System.out.println();
+        System.out.println(measureKdTreeCreation(face1) + "\tmsec:\tKd-tree creation of first face");
+        System.out.println(measureKdTreeCreation(face2) + "\tmsec:\tKd-tree creation of second face");
         
         System.out.println();
         System.out.println("Hausdorff distance sequentially:");
-        testAndPrint(face2, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT, relativeDist, false), printDetails);
-        //testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT_DISTANCE_ONLY, false, false), printDetails);
-        //testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT, relativeDist, false), printDetails);
-        //testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_TRIANGLE_APPROXIMATE, relativeDist, false), printDetails);
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT, relativeDist, false), printDetails);
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT_DISTANCE_ONLY, false, false), printDetails);
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT, relativeDist, false), printDetails);
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_TRIANGLE_APPROXIMATE, relativeDist, false), printDetails);
 
-        //System.out.println();
-        //System.out.println("Hausdorff distance concurrently:");
-        //testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT_DISTANCE_ONLY, false, true), printDetails);
-        //testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT, relativeDist, true), printDetails);
-        //testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_TRIANGLE_APPROXIMATE, relativeDist, true), printDetails);
+        System.out.println();
+        System.out.println("Hausdorff distance concurrently:");
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT_DISTANCE_ONLY, false, true), printDetails);
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_POINT, relativeDist, true), printDetails);
+        testAndPrint(face1, new HausdorffDistance(face2.getMeshModel(), Strategy.POINT_TO_TRIANGLE_APPROXIMATE, relativeDist, true), printDetails);
     }
     
     protected static void testAndPrint(HumanFace face, HausdorffDistance vis, boolean printDetails) {
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 c9dcefae..27cfd798 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
@@ -5,7 +5,7 @@ import cz.fidentis.analyst.mesh.MeshVisitor;
 import javax.vecmath.Vector3d;
 
 /**
- * An ancapsulated mesh plate, i.e., multiple triangles sharing vertices.
+ * An encapsulated mesh plate, i.e., multiple triangles sharing vertices.
  * Mesh facet is iterable (triangle as returned) and visitable by 
  * {@link cz.fidentis.analyst.mesh.MeshVisitor}s.
  *
@@ -114,8 +114,8 @@ public interface MeshFacet extends Iterable<MeshTriangle> {
     void accept(MeshVisitor visitor);   
     
     /**
-     * Computes centers of circumcircle of all triaqngles.
-     * These points represent the point of Voronoi area used for Delaunay triangulation, for instenace.
+     * Computes centers of circumcircle of all triangles.
+     * These points represent the point of Voronoi area used for Delaunay triangulation, for instance.
      * The list is computed only once (during the first call) and than cached.
      * The order corresponds to the order of triangles, i.e., the i-th point
      * is the Voronoi point of i-th triangle.
@@ -125,9 +125,10 @@ public interface MeshFacet extends Iterable<MeshTriangle> {
     List<Vector3d> calculateVoronoiPoints();
     
     /**
-     * Returns {@code true} if the given vertex lie at the facet boundary.
+     * Returns 1-ring neighborhood, i.e., triangles around the given mesh point.
+     * 
      * @param vertexIndex Index of mesh vertex
-     * @return {@code true} if the given vertex lie at the facet boundary.
+     * @return Triangles around the vertex or {@code null}
      */
-    boolean vertexIsBoundary(int vertexIndex);
+    TriangleFan getOneRingNeighborhood(int vertexIndex);
 }
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 b009ee71..6511eb24 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
@@ -7,10 +7,8 @@ import java.util.List;
 import java.util.Map;
 import javax.vecmath.Vector3d;
 import cz.fidentis.analyst.mesh.MeshVisitor;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import java.util.Set;
 
 /**
  * Mash facet is a compact triangular mesh without duplicated vertices.
@@ -146,18 +144,6 @@ public class MeshFacetImpl implements MeshFacet {
         return ret;
     }
     
-    @Override
-    public boolean vertexIsBoundary(int vertexIndex) {
-        List<MeshTriangle> tris = getAdjacentTriangles(vertexIndex);
-        Set<Vector3d> vset = new HashSet<>();
-        for (MeshTriangle tri: tris) {
-            for (MeshPoint p: tri) {
-                vset.add(p.getPosition());
-            }
-        }
-        return (tris.size()+1) != vset.size();
-    }
-    
     @Override
     public Vector3d getClosestAdjacentPoint(Vector3d point, int vertexIndex) {
         double dist = Double.POSITIVE_INFINITY;
@@ -236,5 +222,13 @@ public class MeshFacetImpl implements MeshFacet {
         } 
         return Collections.unmodifiableList(voronoiPoints);
     }
+    
+    @Override
+    public TriangleFan getOneRingNeighborhood(int vertexIndex) {
+        if (vertexIndex < 0 || vertexIndex >= this.getNumberOfVertices()) {
+            return null;
+        }
+        return new TriangleFan(this, vertexIndex);
+    }
 }
 
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 c8df70d9..9536cbbb 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
@@ -16,56 +16,83 @@ public class TriangleFan {
     private final List<Integer> vertices = new LinkedList<>();
     private final List<Integer> triangles = new LinkedList<>();
     
+    /**
+     * Constructor.
+     * 
+     * @param facet Mesh facet
+     * @param vert Central vertex for the triangle fan
+     * @throws IllegalArgumentException if some parameter is missing or wrong
+     */
     public TriangleFan(MeshFacet facet, int vert) {
         if (facet == null) {
             throw new IllegalArgumentException("facet");
         }
         
-        //System.out.println(facet.getVertices());
-        
-        CornerTable ct = facet.getCornerTable();
-        
-        int vertRow = getVertexRow(ct, vert);
-        //System.out.println("DDD " + vert + " " + vertRow + " " + ct.getRow(vertRow).getVertexIndex());
+        int vertRow = -1;
+        for (int i = 0; i < facet.getCornerTable().getSize(); i++) {
+            if (facet.getCornerTable().getRow(i).getVertexIndex() == vert) {
+                vertRow = i;
+                break;
+            }
+        }
         if (vertRow == -1) {
             throw new IllegalArgumentException("vert");
         }
         
-        computeOneRingData(ct, vertRow, vertices, triangles);
+        computeOneRingData(facet, vertRow);
     }
     
+    /**
+     * Returns {@code true} if the triangle fan is enclosed (i.e., is not boundary).
+     * 
+     * @return {@code true} if the triangle fan is enclosed (i.e., is not boundary).
+     */
     public boolean isEnclosed() {
         return Objects.equals(vertices.get(0), vertices.get(vertices.size()-1));
     }
     
-    public boolean isBoundery() {
+    /**
+     * Returns {@code true} if the triangle fan is boundary (i.e., is not enclosed).
+     * 
+     * @return {@code true} if the triangle fan is enclosed (i.e., is not boundary).
+     */
+    public boolean isBoundary() {
         return !isEnclosed();
     }
     
+    /**
+     * Vertex indices of the 1-ring neighborhood. If the triangle fan is enclosed
+     * then the first and last vertices are the same.
+     * 
+     * @return Vertex indices of the 1-ring neighborhood.
+     */
     public List<Integer> getVertices() {
         return Collections.unmodifiableList(vertices);
     }
     
+    /**
+     * Triangle indices of the 1-ring neighborhood. The first triangle is related to
+     * the edge delimited by first and second vertex, etc. The number of triangles 
+     * corresponds to the number of vertices minus one.
+     * 
+     * @return Triangle indices of the 1-ring neighborhood.
+     */
     public List<Integer> getTriangles() {
         return Collections.unmodifiableList(triangles);
     }
     
-    private void computeOneRingData(CornerTable ct, int vertRow, List<Integer> vertices, List<Integer> triangles) {
-        //System.out.println(ct);
-        //System.out.println("AAA " + ct.getRow(vertRow).getVertexIndex());
+    private void computeOneRingData(MeshFacet facet, int vertRow) {
+        CornerTable ct = facet.getCornerTable();
         int ringVertRow = ct.getIndexOfNextCornerInFace(vertRow);
         while (true) {
-            //System.out.println("BBB " + ct.getRow(ringVertRow).getVertexIndex());
-            vertices.add(ct.getRow(ringVertRow).getVertexIndex());
+            vertices.add(facet.getCornerTable().getRow(ringVertRow).getVertexIndex());
             if (vertices.size() > 1 && isEnclosed()) {
                 return; // the ring is closed; we are done
             }
-            //System.out.println("CCC " + ct.getRow(ct.getIndexOfNextCornerInFace(ringVertRow)).getVertexIndex());
             ringVertRow = ct.getIndexOfOppositeCorner(ct.getIndexOfNextCornerInFace(ringVertRow));
             if (ringVertRow == -1) {
                 break; // we reached an open end
             }
-            //System.out.println("DDD " + ct.getRow(ringVertRow).getVertexIndex());
             triangles.add(ct.getIndexOfFace(ringVertRow));
         }
         
@@ -81,15 +108,5 @@ public class TriangleFan {
             }
             triangles.add(ct.getIndexOfFace(ringVertRow));
         }
-    }
-    
-    private int getVertexRow(CornerTable cornerTable, int vert) {
-        for (int i = 0; i < cornerTable.getSize(); i++) {
-            if (cornerTable.getRow(i).getVertexIndex() == vert) {
-                return i;
-            }
-        }
-        return -1;
-    }
-    
+    }    
 }
-- 
GitLab