commit f835cc5081cb9fb991b00f087b19c0ed21eae590
Author: leszek <leszek@koltunski.pl>
Date:   Tue Jul 18 23:44:00 2023 +0200

    Improve MeshMultigon (for the BandagedPyraminx case!)

diff --git a/src/main/java/org/distorted/library/mesh/MeshMultigon.java b/src/main/java/org/distorted/library/mesh/MeshMultigon.java
index 7e3f627..119010c 100644
--- a/src/main/java/org/distorted/library/mesh/MeshMultigon.java
+++ b/src/main/java/org/distorted/library/mesh/MeshMultigon.java
@@ -36,6 +36,8 @@ public class MeshMultigon extends MeshBase
   {
   private static final float MAX_ERROR = 0.000001f;
   private float[][] mOuterVertices;
+  private float[][] mOuterVectors;
+  private int mNumOuter;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -170,7 +172,28 @@ public class MeshMultigon extends MeshBase
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void computeOuter(float[][] vertices)
+  private void computeOuterVectors()
+    {
+    mOuterVectors = new float[mNumOuter][];
+
+    for(int curr=0; curr<mNumOuter; curr++)
+      {
+      int prev = curr==0 ? mNumOuter-1 : curr-1;
+      int next = curr==mNumOuter-1 ? 0 : curr+1;
+
+      float[] vP = mOuterVertices[prev];
+      float[] vN = mOuterVertices[next];
+
+      float dx = vP[0]-vN[0];
+      float dy = vP[1]-vN[1];
+
+      mOuterVectors[curr] = new float[] { dy,-dx };
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void computeOuterVertices(float[][] vertices)
     {
     ArrayList<float[]> tmp = new ArrayList<>();
 
@@ -188,27 +211,28 @@ public class MeshMultigon extends MeshBase
       }
     while( !isSame(next[0]-first[0],next[1]-first[1]) );
 
-    int num = tmp.size();
-    mOuterVertices = new float[num][];
-    for(int i=0; i<num; i++) mOuterVertices[i] = tmp.remove(0);
+    mNumOuter = tmp.size();
+    mOuterVertices = new float[mNumOuter][];
+    for(int i=0; i<mNumOuter; i++) mOuterVertices[i] = tmp.remove(0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean doesntBelongToOuter(float x, float y)
+  private int belongsToOuter(float x, float y)
     {
-    for( float[] v : mOuterVertices )
-      if( isSame(x-v[0],y-v[1]) ) return false;
+    for( int i=0; i<mNumOuter; i++ )
+      {
+      float[] v = mOuterVertices[i];
+      if( isSame(x-v[0],y-v[1]) ) return i;
+      }
 
-    return true;
+    return -1;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private boolean[][] computeVertsUp(float[][] vertices)
     {
-    computeOuter(vertices);
-
     int num = vertices.length;
     boolean[][] up = new boolean[num][];
 
@@ -217,7 +241,12 @@ public class MeshMultigon extends MeshBase
       float[] v = vertices[i];
       int len = v.length/2;
       up[i] = new boolean[len];
-      for(int j=0; j<len; j++) up[i][j] = doesntBelongToOuter(v[2*j],v[2*j+1]);
+
+      for(int j=0; j<len; j++)
+        {
+        int vert = belongsToOuter(v[2*j],v[2*j+1]);
+        up[i][j] = (vert==-1);
+        }
       }
 
     return up;
@@ -266,9 +295,6 @@ public class MeshMultigon extends MeshBase
 
     if( eupc<0 )
       {
-      int eupp = edges[prev];
-      int eupn = edges[next];
-
       vL[0] = v[2*curr];
       vL[1] = v[2*curr+1];
       vR[0] = v[2*next];
@@ -276,28 +302,16 @@ public class MeshMultigon extends MeshBase
       vT[0] = centers[component][0];
       vT[1] = centers[component][1];
 
-      if( eupp<0 )
-        {
-        normL[0]=vL[0]-vT[0];
-        normL[1]=vL[1]-vT[1];
-        }
-      else
-        {
-        normL[0]= v[2*curr  ] - v[2*prev  ];
-        normL[1]= v[2*curr+1] - v[2*prev+1];
-        }
+      int outerL = belongsToOuter(vL[0],vL[1]);
+      int outerR = belongsToOuter(vR[0],vR[1]);
 
-      if( eupn<0 )
-        {
-        normR[0]=vR[0]-vT[0];
-        normR[1]=vR[1]-vT[1];
-        }
-      else
-        {
-        int nnxt= next==len-1 ? 0 : next+1;
-        normR[0]= v[2*next  ] - v[2*nnxt  ];
-        normR[1]= v[2*next+1] - v[2*nnxt+1];
-        }
+      float[] vl = mOuterVectors[outerL];
+      float[] vr = mOuterVectors[outerR];
+
+      normL[0] = -vl[0];
+      normL[1] = -vl[1];
+      normR[0] = -vr[0];
+      normR[1] = -vr[1];
 
       return MeshBandedTriangle.MODE_NORMAL;
       }
@@ -323,8 +337,10 @@ public class MeshMultigon extends MeshBase
         }
       else
         {
-        float dx=v[2*next  ]-v[2*curr  ];
-        float dy=v[2*next+1]-v[2*curr+1];
+        int outerT = belongsToOuter(vT[0],vT[1]);
+        float[] vt = mOuterVectors[outerT];
+        float dx = vt[0];
+        float dy = vt[1];
 
         normL[0]=dx;
         normL[1]=dy;
@@ -357,6 +373,9 @@ public class MeshMultigon extends MeshBase
     for(float[] vertex : vertices) numTriangles+=vertex.length/2;
     MeshBandedTriangle[] triangles = new MeshBandedTriangle[numTriangles];
 
+    computeOuterVertices(vertices);
+    computeOuterVectors();
+
     int[][] edgesUp = computeEdgesUp(vertices);
     boolean[][] vertsUp = computeVertsUp(vertices);
     float[][] centers = computeCenters(vertices);
