- public void breakit() {
- int oldverts = verts;
- if (verts > 2000 && !force) return;
- force = false;
- System.out.println("doubling vertices.");
- PriorityQueue<Mesh.E> es = new PriorityQueue<Mesh.E>();
- for(Mesh.T t : tile) {
- es.add(t.e1());
- es.add(t.e2());
- es.add(t.e3());
- Thread.yield();
- repaint();
- }
- for(int i=0; i<Math.min(oldverts,50); i++) {
- Mesh.E e = es.poll();
- verts++;
- e.shatter();
- Thread.yield();
- repaint();
- }
- System.out.println("now have " + verts + " vertices; max is 2000");
- tile.rebindPoints();
- }
-
- public boolean rand(double temp, Mesh.Vertex p) {
-
- p.reComputeErrorAround();
- double tile_error = tile.error();
- double goal_error = goal.error();
-
- float max = p.averageEdgeLength()/5;
- Vec v = new Vec(random.nextFloat(), random.nextFloat(), random.nextFloat());
- v = v.norm().times((random.nextFloat() - 0.5f) * max);
- Matrix m = Matrix.translate(v);
- boolean good = p.move(v, false);
- if (!good) { return false; }
-
- 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);
-
- //boolean doSwap = good && (tile_delta <= 0 && goal_delta <= 0);
- //boolean doSwap = good && (tile_delta + goal_delta <= 0);
- //if (temp < 0.000001) doSwap = good && (tile_delta <= 0 && goal_delta <= 0);
- boolean doSwap = good && (Math.random() < swapProbability);
-
- // always move uphill if possible -- potential idea
- if (tile_delta <= 0 && goal_delta <= 0 && good) doSwap = true;
- if (hillclimb)
- doSwap = tile_delta <= 0 && goal_delta <= 0 && good;
-
- if (doSwap) {
- tile_error = new_tile_error;
- goal_error = new_goal_error;
- hits++;
- p.goodp = p.p;
- } else {
- p.move(v.times(-1), true);
- misses++;
- }
- p.reComputeErrorAround();
- return true;
- }
-
- float hits = 0;
- float misses = 0;
- public void anneal() throws Exception {
- double hightemp = 1;
- temp = hightemp;
- double last = 10;
- boolean seek_upward = false;
- double acceptance = 1;
- while(true) {
- synchronized(this) {
- if (!anneal) { repaint(); Thread.sleep(10); continue; }
-
- double ratio = (hits+misses==0) ? 1 : (hits / (hits+misses));
- hits = 0;
- misses = 0;
- double 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) {
- breaks--;
- breakit();
- }
- seek_upward = true;
- continue;
- } else if (acceptance > 0.96) gamma = 0.1f;
- else if (acceptance > 0.9) gamma = 0.2f;
- else if (acceptance > 0.8) gamma = 0.3f;
- else if (acceptance > 0.6) gamma = 0.4f;
- else if (acceptance > 0.3) gamma = 0.8f;
- else if (acceptance > 0.15) gamma = 0.94f;
- else if (acceptance > 0.10) gamma = 0.98f;
-
- else if (acceptance < 0.01) breaks++;
-
- if (seek_upward) {
- if (acceptance > 0.25) seek_upward = false;
- else gamma = 2-gamma;
- }
-
- if (anneal)
- temp = temp * gamma;
-
-
- HashSet<Mesh.Vertex> hs = new HashSet<Mesh.Vertex>();
- for(Mesh.Vertex p : tile.vertices()) hs.add(p);
- Mesh.Vertex[] pts = (Mesh.Vertex[])hs.toArray(new Mesh.Vertex[0]);
-
- int count = 0;
- long then = System.currentTimeMillis();
- for(int i=0; i<300; i++) {
- if (anneal) {
- Mesh.Vertex v = pts[Math.abs(random.nextInt()) % pts.length];
- if (breaks>0) break;
- if (!rand(temp,v)) { i--; continue; }
- v.recomputeFundamentalQuadricIfStale();
- v.recomputeFundamentalQuadricIfNeighborChanged();
- count++;
- }
- Thread.yield();
- repaint();
- }
-
- System.out.println("temp="+temp + " ratio="+(Math.ceil(acceptance*100)) + " " +
- "points_per_second=" +
- (count*1000)/((double)(System.currentTimeMillis()-then)));
- for(Mesh.Vertex p : goal.vertices()) {
- p.quadricStale = true;
- p.recomputeFundamentalQuadricIfNeighborChanged();
- }
- }
- }
- }
-
-
- public static void main(String[] s) throws Exception {
- JFrame f = new JFrame();
- f.setLayout(new BorderLayout());
- Main main = new Main(f);
- f.add(main, BorderLayout.CENTER);
- f.setJMenuBar(main.new MyMenuBar());
- f.pack();
- f.show();
- f.setSize(900, 900);
- f.doLayout();
- main.anneal();
- }