good checkpoint
[anneal.git] / src / edu / berkeley / qfat / Main.java
index 7841ad3..14e6bcd 100644 (file)
@@ -51,6 +51,7 @@ public class Main extends MeshViewer {
     
     /** magnification factor */
     private static final float MAG = 1;
+    public static final float MATCHING_EPSILON = 0.01f;
 
     public Main(StlFile stlf, Frame f) {
         super(f);
@@ -63,8 +64,6 @@ public class Main extends MeshViewer {
             Mesh.T t  = goal.newT(p0, p1, p2, n, 0);
         }
 
-        goal.ignorecollision = true;
-
         // rotate to align major axis -- this probably needs to be done by a human.
         goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(Math.PI/2)));
 
@@ -88,22 +87,30 @@ public class Main extends MeshViewer {
         float halfup = 0;
 
         translations = new Matrix[] {
-
+            /*
             Matrix.translate(new Vec(lshift,  depth,    halfup)),
             Matrix.translate(new Vec(rshift,  depth,    halfup)),
             Matrix.translate(new Vec(lshift, -depth,    halfup)),
             Matrix.translate(new Vec(rshift, -depth,    halfup)),
-
-            /*
-              Matrix.translate(new Vec(0,  depth,    halfup)),
-              Matrix.translate(new Vec(0, -depth,    halfup)),
             */
 
-            Matrix.translate(new Vec(lshift,       0,  height)),
-            Matrix.translate(new Vec(rshift,       0,  height)),
-            Matrix.translate(new Vec(lshift,       0, -height)),
-            Matrix.translate(new Vec(rshift,       0, -height)),
+            //Matrix.translate(new Vec(0,  depth,    0)).times(Matrix.rotate(new Vec(0, 0, 1), (float)Math.PI)),
+            //Matrix.translate(new Vec(0, -depth,    0)).times(Matrix.rotate(new Vec(0, 0, 1), (float)Math.PI)),
 
+            Matrix.translate(new Vec(0,   0,    height)).times(Matrix.rotate(new Vec(0, 0, 1), (float)Math.PI)),
+            Matrix.translate(new Vec(0,   0,   -height)).times(Matrix.rotate(new Vec(0, 0, 1), (float)Math.PI)),
+            /*
+            Matrix.translate(new Vec(0,  depth, 0)),
+            Matrix.translate(new Vec(0, -depth, 0)),
+            Matrix.translate(new Vec(0,      0,  height)),
+            Matrix.translate(new Vec(0,      0, -height)),
+            */
+            //Matrix.translate(new Vec(lshift,        depth,  height/2)),
+            //Matrix.translate(new Vec(lshift,        depth, -height/2)),
+            //Matrix.translate(new Vec(rshift,       -depth,  height/2)),
+            //Matrix.translate(new Vec(rshift,       -depth, -height/2)),
+            //Matrix.translate(new Vec(rshift,       0,  height)),
+            //Matrix.translate(new Vec(rshift,       0, -height)),
 
             Matrix.translate(new Vec( width,           0,    0)),
             Matrix.translate(new Vec(-width,           0,    0)),
@@ -208,31 +215,44 @@ public class Main extends MeshViewer {
         tile.newT(rtf, mtf, rbf, null, 6);
         tile.newT(rbf, mtf, mbf, null, 6);
 
+        HashSet<Mesh.E> es = new HashSet<Mesh.E>();
+        for(Mesh.T t : tile) {
+            es.add(t.e1());
+            es.add(t.e2());
+            es.add(t.e3());
+        }
+        for(Mesh.E e : es) {
+            if (e.p1.p.x == e.p2.p.x && e.p1.p.y == e.p2.p.y) continue;
+            if (e.p1.p.z == e.p2.p.z && e.p1.p.y == e.p2.p.y) continue;
+            if (e.p1.p.x == e.p2.p.x && e.p1.p.z == e.p2.p.z) continue;
+            e.shatter();
+        }
+
         for(Matrix m : translations) {
             for(Mesh.T t1 : tile) {
                 for(Mesh.T t2 : tile) {
                     if (t1==t2) continue;
 
-                    if ((t1.v1().p.times(m).minus(t2.v1().p).mag() < Mesh.EPSILON) &&
-                        (t1.v2().p.times(m).minus(t2.v3().p).mag() < Mesh.EPSILON) &&
-                        (t1.v3().p.times(m).minus(t2.v2().p).mag() < Mesh.EPSILON)) {
-                        t1.e1().bindEdge(t2.e3());
-                        t1.e2().bindEdge(t2.e2());
-                        t1.e3().bindEdge(t2.e1());
+                    if ((t1.v1().p.times(m).minus(t2.v1().p).mag() < MATCHING_EPSILON) &&
+                        (t1.v2().p.times(m).minus(t2.v3().p).mag() < MATCHING_EPSILON) &&
+                        (t1.v3().p.times(m).minus(t2.v2().p).mag() < MATCHING_EPSILON)) {
+                        t2.e3().bindEdge(t1.e1(), m);
+                        t2.e2().bindEdge(t1.e2(), m);
+                        t2.e1().bindEdge(t1.e3(), m);
                     }
-                    if ((t1.v2().p.times(m).minus(t2.v1().p).mag() < Mesh.EPSILON) &&
-                        (t1.v3().p.times(m).minus(t2.v3().p).mag() < Mesh.EPSILON) &&
-                        (t1.v1().p.times(m).minus(t2.v2().p).mag() < Mesh.EPSILON)) {
-                        t1.e2().bindEdge(t2.e3());
-                        t1.e3().bindEdge(t2.e2());
-                        t1.e1().bindEdge(t2.e1());
+                    if ((t1.v2().p.times(m).minus(t2.v1().p).mag() < MATCHING_EPSILON) &&
+                        (t1.v3().p.times(m).minus(t2.v3().p).mag() < MATCHING_EPSILON) &&
+                        (t1.v1().p.times(m).minus(t2.v2().p).mag() < MATCHING_EPSILON)) {
+                        t2.e3().bindEdge(t1.e2(), m);
+                        t2.e2().bindEdge(t1.e3(), m);
+                        t2.e1().bindEdge(t1.e1(), m);
                     }
-                    if ((t1.v3().p.times(m).minus(t2.v1().p).mag() < Mesh.EPSILON) &&
-                        (t1.v1().p.times(m).minus(t2.v3().p).mag() < Mesh.EPSILON) &&
-                        (t1.v2().p.times(m).minus(t2.v2().p).mag() < Mesh.EPSILON)) {
-                        t1.e3().bindEdge(t2.e3());
-                        t1.e1().bindEdge(t2.e2());
-                        t1.e2().bindEdge(t2.e1());
+                    if ((t1.v3().p.times(m).minus(t2.v1().p).mag() < MATCHING_EPSILON) &&
+                        (t1.v1().p.times(m).minus(t2.v3().p).mag() < MATCHING_EPSILON) &&
+                        (t1.v2().p.times(m).minus(t2.v2().p).mag() < MATCHING_EPSILON)) {
+                        t2.e3().bindEdge(t1.e3(), m);
+                        t2.e2().bindEdge(t1.e1(), m);
+                        t2.e1().bindEdge(t1.e2(), m);
                     }
 
                 }
@@ -268,7 +288,7 @@ public class Main extends MeshViewer {
         goal.error_against = tile;
     }
 
-    public synchronized void breakit() {
+    public void breakit() {
         int oldverts = verts;
         System.out.println("doubling vertices.");
         PriorityQueue<Mesh.E> es = new PriorityQueue<Mesh.E>();
@@ -276,50 +296,43 @@ public class Main extends MeshViewer {
             es.add(t.e1());
             es.add(t.e2());
             es.add(t.e3());
+            Thread.yield();
+            repaint();
         }
-        for(int i=0; i<oldverts; i++) {
+        for(int i=0; i<Math.min(oldverts,200); i++) {
             Mesh.E e = es.poll();
             verts++;
             //System.out.println("shatter " + e);
+            //e.shatter(e.midpoint(), null, null, true, true);
+            
             e.shatter();
+            Thread.yield();
+            repaint();
         }
         tile.rebindPoints();
     }
 
     public synchronized void rand(float temp, Mesh.Vertex p) {
 
-        //p.reComputeError();
         p.reComputeErrorAround();
         double tile_error = tile.error();
         double goal_error = goal.error();
 
-        Vec v;
-        /*
-          Matrix inv = p.errorQuadric();
-          v = new Vec(inv.d, inv.h, inv.l).norm().times(1/(float)300);
-          if (p.quadric_count == 0) {
-          v = goal.nearest(p.p).p.minus(p.p).norm().times(1/(float)300);
-          }
-        */
-        Vec v2 = new Vec((random.nextFloat() - (float)0.5) / 500,
-                         (random.nextFloat() - (float)0.5)  / 500,
-                         (random.nextFloat() - (float)0.5)  / 500);
-        //v = v.plus(v2.norm().times(1/(float)300));
-        v = v2.norm().times(1/(float)300);
-
+        float max = p.averageEdgeLength()/10;
+        Vec v = new Vec(random.nextFloat(), random.nextFloat(), random.nextFloat());
+        v = v.norm().times((random.nextFloat() - 0.5f) * max);
+        //System.out.println(max + " " + p.averageEdgeLength() + " " + v.mag());
         Matrix m = Matrix.translate(v);
 
         boolean good = p.move(m, false);
-        if (!good) { misses++; return; }
-
-        p.reComputeErrorAround();
+        if (!good) { /*misses++;*/ return; }
 
         double new_tile_error = tile.error();
         double new_goal_error = goal.error();
         double tile_delta = (new_tile_error - tile_error) / tile_error;
         double goal_delta = (new_goal_error - goal_error) / goal_error;
         double delta = tile_delta + goal_delta;
-        double swapProbability = Math.exp((-1 * delta) / temp);
+        double swapProbability = Math.exp((-1 * delta) / (((double)temp)/1000000));
         boolean doSwap = good && (Math.random() < swapProbability);
         //boolean doSwap = good && (tile_delta <= 0 && goal_delta <= 0);
         //boolean doSwap = good && (tile_delta + goal_delta <= 0);
@@ -328,6 +341,7 @@ public class Main extends MeshViewer {
             goal_error = new_goal_error;
             //System.out.println("error: " + tile_error + " / " + goal_error);
             hits++;
+            p.goodp = p.p;
         } else {
             p.move(Matrix.translate(v.times(-1)), true);
             misses++;
@@ -337,57 +351,42 @@ public class Main extends MeshViewer {
     float hits = 0;
     float misses = 0;
     public void anneal() throws Exception {
-        float hightemp = 10;
+        float hightemp = 1;
         float temp = hightemp;
         float last = 10;
-        float lastbreak = 10;
+        boolean seek_upward = false;
+        double acceptance = 1;
         while(true) {
             synchronized(this) {
                 double ratio = (hits+misses==0) ? 1 : (hits / (hits+misses));
                 hits = 0;
                 misses = 0;
-                float gamma = 0;
-                double acceptance = ratio;
+                float gamma = 1;
+                acceptance = (ratio+acceptance)/2;
                 accepts = (int)(Math.ceil(ratio*100));
                 temps = (int)(Math.ceil(temp*1000));
                 vertss = tile.size();
-                if (breaks > 0) { while (breaks>0) {
+                if (breaks > 0) {
+                    while (breaks>0) {
                         breaks--;
                         breakit();
-                        //gamma = 1;
-                        float t = temp;
-                        temp = lastbreak;
-                        gamma = 1;
-                        lastbreak = t;
-                        //temp = last * 0.8f;
-                        //last = temp;
-                        //temp = hightemp;
-                    } } else
-                    if (acceptance > 0.96) gamma = 0.4f;
-                    else if (acceptance > 0.9) gamma = 0.5f;
-                    else if (acceptance > 0.8) gamma = 0.65f;
-                    else if (acceptance > 0.6) gamma = 0.7f;
-                    else {
-                        if (acceptance > 0.3) {
-                            gamma = 0.9f;
-                        } else if (acceptance > 0.15) {
-                            gamma = 0.95f;
-                        } else if (acceptance > 0.10) {
-                            gamma = 0.98f;
-                        } else {
-                            breakit();
-                        float t = temp;
-                        temp = lastbreak;
-                        gamma = 1;
-                        lastbreak = t;
-                            //gamma = 1;
-                        //gamma = 0.99f;
-                            //gamma = 1;
-                            //temp = last * 0.8f;
-                            //last = temp;
-                            //temp = hightemp;
-                        }
                     }
+                    seek_upward = true;
+                } else if (acceptance > 0.96) gamma = 0.4f;
+                else if (acceptance > 0.9)    gamma = 0.5f;
+                else if (acceptance > 0.8)    gamma = 0.65f;
+                else if (acceptance > 0.6)    gamma = 0.7f;
+                else if (acceptance > 0.3)    gamma = 0.8f;
+                else if (acceptance > 0.15)   gamma = 0.9f;
+                else if (acceptance > 0.05)   gamma = 0.95f;
+                else if (acceptance > 0.01)   gamma = 0.98f;
+                else { /*breaks++;*/ }
+
+                if (seek_upward) {
+                    if (acceptance > 0.2) seek_upward = false;
+                    else gamma = 2-gamma;
+                }
+
                 temp = temp * gamma;
 
 
@@ -408,7 +407,25 @@ public class Main extends MeshViewer {
                     Thread.yield();
                     repaint();
                 }
-                System.out.println("temp="+temp + " ratio="+(Math.ceil(ratio*100)) + " " +
+                PriorityQueue<Mesh.E> es = new PriorityQueue<Mesh.E>();
+                for(Mesh.T t : tile) {
+                    float max = 5;
+                    for(Mesh.E e : new Mesh.E[] { t.e1(), t.e2(), t.e3() }) {
+                        if (e==null) continue;
+                        if (e.stretchRatio() > max) es.add(e);
+                        if (t.aspect() < 0.1 && e.length()>e.next.length() && e.length()>e.prev.length()) es.add(e);
+                    }
+                }
+                /*
+                for(int i=0; i<5; i++) {
+                    Mesh.E e = es.poll();
+                    if (e==null) break;
+                    e.shatter();
+                }
+                */
+                tile.rebindPoints();
+
+                System.out.println("temp="+temp + " ratio="+(Math.ceil(acceptance*100)) + " " +
                                    "points_per_second=" +
                                    (count*1000)/((double)(System.currentTimeMillis()-then)));
 
@@ -416,7 +433,9 @@ public class Main extends MeshViewer {
 
                 synchronized(safeTriangles) {
                     safeTriangles.clear();
-                    for(Mesh.T t : tile) if (t.shouldBeDrawn()) safeTriangles.add(t);
+                    for(Mesh.T t : tile) 
+                        if (t.shouldBeDrawn())
+                            safeTriangles.add(t);
                 }
             }
         }