checkpoint
authoradam <adam@megacz.com>
Sun, 29 Jun 2008 04:47:27 +0000 (21:47 -0700)
committeradam <adam@megacz.com>
Sun, 29 Jun 2008 04:47:27 +0000 (21:47 -0700)
darcs-hash:20080629044727-5007d-82e649c22f31951011423bd8123d5cafcfb6a538.gz

Makefile
src/edu/berkeley/qfat/Main.java
src/edu/berkeley/qfat/Mesh.java
src/edu/berkeley/qfat/MeshViewer.java
src/edu/berkeley/qfat/StlFile.java
src/edu/berkeley/qfat/geom/Matrix.java
src/edu/berkeley/qfat/geom/Point.java
src/edu/berkeley/qfat/geom/Triangle.java

index d42a2b7..c9c0295 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,13 @@
-jars = lib/kd.jar:lib/trove-0.1.8.jar:lib/sil-0.43b-am1.jar
+jars = lib/kd.jar:lib/trove-0.1.8.jar:lib/sil-0.43b-am1.jar:lib/jogl/jogl.jar:lib/jogl/gluegen-rt.jar
 all:
        mkdir -p build
 all:
        mkdir -p build
+       cp *.stl build
        javac -cp $(jars) -d build `find src -name \*.java`
        javac -cp $(jars) -d build `find src -name \*.java`
-       java -server -cp $(jars):build edu.berkeley.qfat.Main
+       nice -n 19 java -Xmx1200m -server -Djava.library.path=lib/jogl -cp $(jars):build edu.berkeley.qfat.Main
+
+dist:
+       rm -f space-sculptor.jar
+       cd build; for A in ../lib/*.jar; do jar xvf $$A; done
+       echo 'Main-Class: edu.berkeley.qfat.Main' > build/manifest
+       cp *.stl build
+       cd build; jar cvmf manifest ../space-sculptor.jar .
index 50f44c0..95cd989 100644 (file)
@@ -1,5 +1,6 @@
 package edu.berkeley.qfat;
 import java.awt.*;
 package edu.berkeley.qfat;
 import java.awt.*;
+import java.io.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.media.opengl.*;
 import java.awt.event.*;
 import javax.swing.*;
 import javax.media.opengl.*;
@@ -65,17 +66,17 @@ public class Main extends MeshViewer {
         HashSet<HalfSpace> halfSpaces = new HashSet<HalfSpace>();
         HashSet<Polygon> polygons = new HashSet<Polygon>();
         for(Matrix m : matrices) {
         HashSet<HalfSpace> halfSpaces = new HashSet<HalfSpace>();
         HashSet<Polygon> polygons = new HashSet<Polygon>();
         for(Matrix m : matrices) {
-            Vec v = m.getTranslationalComponent();
-            if (v.mag() < 0.0001) continue;
-            v = v.times(0.5f);
-            Point p = Point.ORIGIN.plus(v);
-            Vec v0 = v;
-            if (v.dot(Point.ORIGIN.minus(p)) < 0) v = v.times(-1);
-
-            System.out.println(v);
-            HalfSpace hs = new HalfSpace(p, v.norm());
-            halfSpaces.add(hs);
-            polygons.add(new Polygon(hs));
+                Vec v = m.getTranslationalComponent();
+                if (v.mag() < 0.0001) continue;
+                v = v.times(-1);
+                v = v.times(0.5f);
+                Point p = Point.ORIGIN.plus(v);
+                v = v.times(-1);
+                
+                //System.out.println(v);
+                HalfSpace hs = new HalfSpace(p, v.norm());
+                halfSpaces.add(hs);
+                polygons.add(new Polygon(hs));
         }
         for(Polygon p : polygons) {
             System.out.println(p.plane.norm + " " + p.plane.dvalue);
         }
         for(Polygon p : polygons) {
             System.out.println(p.plane.norm + " " + p.plane.dvalue);
@@ -104,13 +105,14 @@ public class Main extends MeshViewer {
     public void loadGoal(String file) {
         try {
             StlFile stlf = new StlFile();
     public void loadGoal(String file) {
         try {
             StlFile stlf = new StlFile();
-            stlf.load(file);
+            InputStream res = this.getClass().getClassLoader().getResourceAsStream(file);
+            stlf.readBinaryFile(file, res);
             goal = new Mesh(false);
             for(int i=0; i<stlf.coordArray.length; i+=3) {
                 Point p0 = new Point(stlf.coordArray[i+0].x * MAG, stlf.coordArray[i+0].y * MAG, stlf.coordArray[i+0].z * MAG);
                 Point p1 = new Point(stlf.coordArray[i+1].x * MAG, stlf.coordArray[i+1].y * MAG, stlf.coordArray[i+1].z * MAG);
                 Point p2 = new Point(stlf.coordArray[i+2].x * MAG, stlf.coordArray[i+2].y * MAG, stlf.coordArray[i+2].z * MAG);
             goal = new Mesh(false);
             for(int i=0; i<stlf.coordArray.length; i+=3) {
                 Point p0 = new Point(stlf.coordArray[i+0].x * MAG, stlf.coordArray[i+0].y * MAG, stlf.coordArray[i+0].z * MAG);
                 Point p1 = new Point(stlf.coordArray[i+1].x * MAG, stlf.coordArray[i+1].y * MAG, stlf.coordArray[i+1].z * MAG);
                 Point p2 = new Point(stlf.coordArray[i+2].x * MAG, stlf.coordArray[i+2].y * MAG, stlf.coordArray[i+2].z * MAG);
-                Vec n  = new Vec(stlf.normArray[i/3].x * MAG, stlf.normArray[i/3].y  * MAG, stlf.normArray[i/3].z * MAG);
+                Vec n    = new Vec(stlf.normArray[i/3].x * MAG, stlf.normArray[i/3].y  * MAG, stlf.normArray[i/3].z * MAG);
                 Mesh.T t  = goal.newT(p0, p1, p2, n, 0);
             }
             float goal_width  = goal.diagonal().dot(new Vec(1, 0, 0));
                 Mesh.T t  = goal.newT(p0, p1, p2, n, 0);
             }
             float goal_width  = goal.diagonal().dot(new Vec(1, 0, 0));
@@ -119,12 +121,16 @@ public class Main extends MeshViewer {
             
         } catch (Exception e) { throw new RuntimeException(e);}
     }
             
         } catch (Exception e) { throw new RuntimeException(e);}
     }
-    public void fixupGoal() {
+    public void fixupGoal() { fixupGoal(true, true); }
+    public void fixupGoal(boolean recenter, boolean lock) {
         // translate to match centroid
         // translate to match centroid
-        goal.transform(Matrix.translate(tile.centroid().minus(goal.centroid())));
-        goal.makeVerticesImmutable();
-        tile.error_against = goal;
-        goal.error_against = tile;
+        if (recenter)
+            goal.transform(Matrix.translate(tile.centroid().minus(goal.centroid())));
+        if (lock) {
+            goal.makeVerticesImmutable();
+            tile.error_against = goal;
+            goal.error_against = tile;
+        }
     }
 
     public Main(JFrame f) { super(f); }
     }
 
     public Main(JFrame f) { super(f); }
@@ -138,50 +144,51 @@ public class Main extends MeshViewer {
                     for(Mesh.T t2 : tile) {
 
                         Matrix m = m1.inverse().times(m2);
                     for(Mesh.T t2 : tile) {
 
                         Matrix m = m1.inverse().times(m2);
-                        if ((t1.v1().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
-                            (t1.v2().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON) &&
-                            (t1.v3().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON)) {
+                        Point t1v1 = m.times(t1.v1().p);
+                        Point t1v2 = m.times(t1.v2().p);
+                        Point t1v3 = m.times(t1.v3().p);
+                        if (t1v1.distance(t2.v1().p) < MATCHING_EPSILON &&
+                            t1v2.distance(t2.v3().p) < MATCHING_EPSILON &&
+                            t1v3.distance(t2.v2().p) < MATCHING_EPSILON) {
                             t2.e3().bindEdge(t1.e1(), m);
                             t2.e2().bindEdge(t1.e2(), m);
                             t2.e1().bindEdge(t1.e3(), m);
                         }
                             t2.e3().bindEdge(t1.e1(), m);
                             t2.e2().bindEdge(t1.e2(), m);
                             t2.e1().bindEdge(t1.e3(), m);
                         }
-                        if ((t1.v2().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
-                            (t1.v3().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON) &&
-                            (t1.v1().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON)) {
+                        if (t1v2.distance(t2.v1().p) < MATCHING_EPSILON &&
+                            t1v3.distance(t2.v3().p) < MATCHING_EPSILON &&
+                            t1v1.distance(t2.v2().p) < MATCHING_EPSILON) {
                             t2.e3().bindEdge(t1.e2(), m);
                             t2.e2().bindEdge(t1.e3(), m);
                             t2.e1().bindEdge(t1.e1(), m);
                         }
                             t2.e3().bindEdge(t1.e2(), m);
                             t2.e2().bindEdge(t1.e3(), m);
                             t2.e1().bindEdge(t1.e1(), m);
                         }
-                        if ((t1.v3().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
-                            (t1.v1().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON) &&
-                            (t1.v2().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON)) {
+                        if (t1v3.distance(t2.v1().p) < MATCHING_EPSILON &&
+                            t1v1.distance(t2.v3().p) < MATCHING_EPSILON &&
+                            t1v2.distance(t2.v2().p) < MATCHING_EPSILON) {
                             t2.e3().bindEdge(t1.e3(), m);
                             t2.e2().bindEdge(t1.e1(), m);
                             t2.e1().bindEdge(t1.e2(), m);
                         }
                             t2.e3().bindEdge(t1.e3(), m);
                             t2.e2().bindEdge(t1.e1(), m);
                             t2.e1().bindEdge(t1.e2(), m);
                         }
-
-                        if ((t1.v1().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
-                            (t1.v2().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON) &&
-                            (t1.v3().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON)) {
+                        if (t1v1.distance(t2.v1().p) < MATCHING_EPSILON &&
+                            t1v2.distance(t2.v2().p) < MATCHING_EPSILON &&
+                            t1v3.distance(t2.v3().p) < MATCHING_EPSILON) {
                             t2.e1().bindEdge(t1.e1().pair, m);
                             t2.e2().bindEdge(t1.e2().pair, m);
                             t2.e3().bindEdge(t1.e3().pair, m);
                         }
                             t2.e1().bindEdge(t1.e1().pair, m);
                             t2.e2().bindEdge(t1.e2().pair, m);
                             t2.e3().bindEdge(t1.e3().pair, m);
                         }
-                        if ((t1.v2().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
-                            (t1.v3().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON) &&
-                            (t1.v1().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON)) {
+                        if (t1v2.distance(t2.v1().p) < MATCHING_EPSILON &&
+                            t1v3.distance(t2.v2().p) < MATCHING_EPSILON &&
+                            t1v1.distance(t2.v3().p) < MATCHING_EPSILON) {
                             t2.e2().bindEdge(t1.e1().pair, m);
                             t2.e3().bindEdge(t1.e2().pair, m);
                             t2.e1().bindEdge(t1.e3().pair, m);
                         }
                             t2.e2().bindEdge(t1.e1().pair, m);
                             t2.e3().bindEdge(t1.e2().pair, m);
                             t2.e1().bindEdge(t1.e3().pair, m);
                         }
-                        if ((t1.v3().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
-                            (t1.v1().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON) &&
-                            (t1.v2().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON)) {
+                        if (t1v3.distance(t2.v1().p) < MATCHING_EPSILON &&
+                            t1v1.distance(t2.v2().p) < MATCHING_EPSILON &&
+                            t1v2.distance(t2.v3().p) < MATCHING_EPSILON) {
                             t2.e3().bindEdge(t1.e1().pair, m);
                             t2.e1().bindEdge(t1.e2().pair, m);
                             t2.e2().bindEdge(t1.e3().pair, m);
                         }
                             t2.e3().bindEdge(t1.e1().pair, m);
                             t2.e1().bindEdge(t1.e2().pair, m);
                             t2.e2().bindEdge(t1.e3().pair, m);
                         }
-
                     }
                 }
             }
                     }
                 }
             }
@@ -197,6 +204,8 @@ public class Main extends MeshViewer {
 
     public void breakit() {
         int oldverts = verts;
 
     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) {
         System.out.println("doubling vertices.");
         PriorityQueue<Mesh.E> es = new PriorityQueue<Mesh.E>();
         for(Mesh.T t : tile) {
@@ -213,6 +222,7 @@ public class Main extends MeshViewer {
             Thread.yield();
             repaint();
         }
             Thread.yield();
             repaint();
         }
+        System.out.println("now have " + verts + " vertices; max is 2000");
         tile.rebindPoints();
     }
 
         tile.rebindPoints();
     }
 
@@ -241,6 +251,12 @@ public class Main extends MeshViewer {
         //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);
         //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;
         if (doSwap) {
             tile_error = new_tile_error;
             goal_error = new_goal_error;
@@ -263,6 +279,7 @@ public class Main extends MeshViewer {
         boolean seek_upward = false;
         double acceptance = 1;
         while(true) {
         boolean seek_upward = false;
         double acceptance = 1;
         while(true) {
+            synchronized(this) {
             synchronized(safeTriangles) {
                 safeTriangles.clear();
                 for(Mesh.T t : tile) 
             synchronized(safeTriangles) {
                 safeTriangles.clear();
                 for(Mesh.T t : tile) 
@@ -293,7 +310,8 @@ public class Main extends MeshViewer {
             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.3)    gamma = 0.8f;
             else if (acceptance > 0.15)   gamma = 0.94f;
             else if (acceptance > 0.10)   gamma = 0.98f;
-            else { breaks++; }
+
+            else if (acceptance < 0.01)   breaks++;
 
             if (seek_upward) {
                 if (acceptance > 0.25) seek_upward = false;
 
             if (seek_upward) {
                 if (acceptance > 0.25) seek_upward = false;
@@ -330,6 +348,7 @@ public class Main extends MeshViewer {
                 p.quadricStale = true;
                 p.recomputeFundamentalQuadricIfNeighborChanged();
             }
                 p.quadricStale = true;
                 p.recomputeFundamentalQuadricIfNeighborChanged();
             }
+            }
         }
     }
 
         }
     }
 
@@ -534,11 +553,38 @@ public class Main extends MeshViewer {
             hideMenu.add(new MyMenuItem("Show All Neighbors Wireframe") { public void hit() { neighborsWire = true; neighborsWireOne = false;}});
             hideMenu.add(new MyMenuItem("Hide Neighbors") { public void hit() { neighborsWire = false; neighborsWireOne = false; neighbors = false; }});
 
             hideMenu.add(new MyMenuItem("Show All Neighbors Wireframe") { public void hit() { neighborsWire = true; neighborsWireOne = false;}});
             hideMenu.add(new MyMenuItem("Hide Neighbors") { public void hit() { neighborsWire = false; neighborsWireOne = false; neighbors = false; }});
 
+            goalMenu.add(new MyMenuItem("Fish with face") { public void hit() {
+                loadGoal("face.stl");
+                //goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
+                goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(Math.PI/2)));
+                //goal.transform(Matrix.scale(1, 2.2f, 1));
+                float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
+                //factor = factor * 0.8f;
+                goal.transform(Matrix.scale(0.3f));
+                //goal.transform(Matrix.rotate(new Vec(0,1,0), (float)(Math.PI*1/3)));
+                goal.transform(Matrix.rotate(new Vec(1,0,0), (float)(Math.PI*1/3)));
+                fixupGoal(true, false);
+                //goal.transform(Matrix.translate(new Vec(0.145f, 0, 0)));
+                fixupGoal(false, true);
+            }});
             goalMenu.add(new MyMenuItem("Fish") { public void hit() {
                 loadGoal("fish.stl");
                 //goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
                 goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(Math.PI/2)));
             goalMenu.add(new MyMenuItem("Fish") { public void hit() {
                 loadGoal("fish.stl");
                 //goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
                 goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(Math.PI/2)));
+                goal.transform(Matrix.scale(1, 2.2f, 1));
+                float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
+                factor = factor * 0.8f;
+                goal.transform(Matrix.scale(factor));
+                fixupGoal(true, false);
+                //goal.transform(Matrix.translate(new Vec(0.145f, 0, 0)));
+                fixupGoal(false, true);
+            }});
+            goalMenu.add(new MyMenuItem("Hammerhead Fish") { public void hit() {
+                loadGoal("fish.stl");
+                goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
+                goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(3*Math.PI/2)));
                 float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
                 float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
+                factor *= 0.75f;
                 goal.transform(Matrix.scale(factor));
                 fixupGoal();
             }});
                 goal.transform(Matrix.scale(factor));
                 fixupGoal();
             }});
@@ -553,7 +599,7 @@ public class Main extends MeshViewer {
             goalMenu.add(new MyMenuItem("Torus") { public void hit() {
                 loadGoal("torus.stl");
                 float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
             goalMenu.add(new MyMenuItem("Torus") { public void hit() {
                 loadGoal("torus.stl");
                 float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
-                goal.transform(Matrix.scale(factor/3.3f));
+                goal.transform(Matrix.scale(factor/2.5f));
                 goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
                 fixupGoal();
             }});
                 goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
                 fixupGoal();
             }});
@@ -627,7 +673,7 @@ public class Main extends MeshViewer {
                 };
                 fixupTile();
             } });
                 };
                 fixupTile();
             } });
-            tileMenu.add(new MyMenuItem("Dense Packing (Hex)") { public void hit() {
+            tileMenu.add(new MyMenuItem("Dense Packing (hex)") { public void hit() {
                 tile = new Mesh(false);
                 float width  = (float)3.2;
                 float depth  = (float)0.32;
                 tile = new Mesh(false);
                 float width  = (float)3.2;
                 float depth  = (float)0.32;
@@ -669,30 +715,16 @@ public class Main extends MeshViewer {
                 generateTile(transforms, tile);
                 fixupTile();
             } });
                 generateTile(transforms, tile);
                 fixupTile();
             } });
-            tileMenu.add(new MyMenuItem("Slim Dense Packing (Hex)") { public void hit() {
+            tileMenu.add(new MyMenuItem("Slim Dense Packing (Cubic)") { public void hit() {
                 tile = new Mesh(false);
                 tile = new Mesh(false);
-                float width  = (float)3.2;
-                float depth  = (float)0.32;
-                float height = (float)1.6;
                 float unit = 0.4f;
                 float r = unit/2;
                 float sin = (float)(unit * Math.sin(Math.PI/3));
                 float cos = (float)(unit * Math.cos(Math.PI/3));
                 float x = (float)(r*Math.tan(Math.PI/6));
                 float z = (float)(r/Math.cos(Math.PI/6));
                 float unit = 0.4f;
                 float r = unit/2;
                 float sin = (float)(unit * Math.sin(Math.PI/3));
                 float cos = (float)(unit * Math.cos(Math.PI/3));
                 float x = (float)(r*Math.tan(Math.PI/6));
                 float z = (float)(r/Math.cos(Math.PI/6));
-                height = 2*r*(float)Math.sqrt(2f/3f);
-
+                float height = 2*r*(float)Math.sqrt(2f/3f);
 
 
-                r *= 0.3f;
-                cos *= 0.3f;
-                unit *= 0.3f;
-                height *= 1.5f;
-
-                /*
-                  sin *= 0.3f;
-                  x *= 0.3f;
-                  z *= 0.3f;
-                */
                 transforms = new Matrix[] {
                     Matrix.translate(new Vec(-unit, 0, 0)),
                     Matrix.translate(new Vec( unit, 0, 0)),
                 transforms = new Matrix[] {
                     Matrix.translate(new Vec(-unit, 0, 0)),
                     Matrix.translate(new Vec( unit, 0, 0)),
@@ -700,24 +732,51 @@ public class Main extends MeshViewer {
                     Matrix.translate(new Vec( cos,  0,  sin)),
                     Matrix.translate(new Vec(-cos,  0, -sin)),
                     Matrix.translate(new Vec( cos,  0, -sin)),
                     Matrix.translate(new Vec( cos,  0,  sin)),
                     Matrix.translate(new Vec(-cos,  0, -sin)),
                     Matrix.translate(new Vec( cos,  0, -sin)),
-                    Matrix.translate(new Vec( 0,  height, z)),
-                    Matrix.translate(new Vec(-r,  height, -x)),
-                    Matrix.translate(new Vec( r,  height, -x)),
-                    Matrix.translate(new Vec( 0, -height, -z)),
-                    Matrix.translate(new Vec(-r, -height, x)),
-                    Matrix.translate(new Vec( r, -height, x)),
-                    Matrix.ONE,
+
+                    /*
+                    Matrix.translate(new Vec( 0,  height, -z)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+                    Matrix.translate(new Vec(-r,  height,  x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+                    Matrix.translate(new Vec( r,  height,  x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+                    Matrix.translate(new Vec( 0, -height, -z)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+                    Matrix.translate(new Vec(-r, -height,  x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+                    Matrix.translate(new Vec( r, -height,  x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+                    */
+
+                    Matrix.translate(new Vec( 0,  height, -z)),
+                    Matrix.translate(new Vec(-r,  height,  x)),
+                    Matrix.translate(new Vec( r,  height,  x)),
+                    Matrix.translate(new Vec( 0, -height,  z)),
+                    Matrix.translate(new Vec(-r, -height, -x)),
+                    Matrix.translate(new Vec( r, -height, -x)),
+                    //Matrix.rotate(new Vec(0,0,1), (float)Math.PI),
+
+                    /*
+                    Matrix.translate(new Vec( 0,  height, -z)).times(Matrix.scale(-1,1,-1)),
+                    Matrix.translate(new Vec(-r,  height,  x)).times(Matrix.scale(-1,1,-1)),
+                    Matrix.translate(new Vec( r,  height,  x)).times(Matrix.scale(-1,1,-1)),
+                    Matrix.translate(new Vec( 0, -height, -z)).times(Matrix.scale(-1,1,-1)),
+                    Matrix.translate(new Vec(-r, -height,  x)).times(Matrix.scale(-1,1,-1)),
+                    Matrix.translate(new Vec( r, -height,  x)).times(Matrix.scale(-1,1,-1)),
+                    */
+                    Matrix.ONE
                 };
                 generateTile(transforms, tile);
                 };
                 generateTile(transforms, tile);
+                //for(int i=0; i<transforms.length; i++) transforms[i] = Matrix.translate(m.times(vecs[i]));
+                Matrix m = Matrix.scale(1.9f, 1f ,1);
+                //Matrix m = Matrix.scale(1f, 2.1f, 1f);
+                tile.transform(m);
+                for(int i=0; i<transforms.length; i++)
+                    transforms[i] = transforms[i].preMultiplyTranslationalComponentBy(m);
                 fixupTile();
                 fixupTile();
+
             } });
             tileMenu.add(new MyMenuItem("Genus-1") { public void hit() {
                 synchronized(this) {
                     tile = new Mesh(false);
             } });
             tileMenu.add(new MyMenuItem("Genus-1") { public void hit() {
                 synchronized(this) {
                     tile = new Mesh(false);
+                    Matrix mm = Matrix.scale(0.1f);
                     float height = 4;
                     float width  = 4;
                     float depth  = 1;
                     float height = 4;
                     float width  = 4;
                     float depth  = 1;
-                    Matrix mm = Matrix.scale(0.1f);
                     // top
                     quad(tile, mm, 
                          new Point( 2,  2,  0),
                     // top
                     quad(tile, mm, 
                          new Point( 2,  2,  0),
@@ -842,6 +901,80 @@ public class Main extends MeshViewer {
                     };
                     fixupTile();
                 }}});
                     };
                     fixupTile();
                 }}});
+            tileMenu.add(new MyMenuItem("Hammerhead") { public void hit() {
+                synchronized(this) {
+                    tile = new Mesh(false);
+                    Matrix mm = Matrix.ONE;
+                    float height1 = .1f;
+                    float height2 = .1f;
+                    float width  = .4f;
+                    float depth  = .1f;
+                    // top
+                    Point a1 = new Point( -width/2,         height2/2, -depth/2);
+                    Point b1 = new Point(        0,         height2/2, -depth/2);
+                    Point c1 = new Point(        0, height1+height2/2, -depth/2);
+                    Point d1 = new Point(  width/2, height1+height2/2, -depth/2);
+                    Point e1 = new Point(  width/2,         height2/2, -depth/2);
+                    Point f1 = new Point(  width/2,        -height2/2, -depth/2);
+                    Point g1 = new Point(  width/2,-height1-height2/2, -depth/2);
+                    Point h1 = new Point(        0,-height1-height2/2, -depth/2);
+                    Point i1 = new Point(        0,        -height2/2, -depth/2);
+                    Point j1 = new Point( -width/2,        -height2/2, -depth/2);
+                    Point a2 = new Point( -width/2,         height2/2,  depth/2);
+                    Point b2 = new Point(        0,         height2/2,  depth/2);
+                    Point c2 = new Point(        0, height1+height2/2,  depth/2);
+                    Point d2 = new Point(  width/2, height1+height2/2,  depth/2);
+                    Point e2 = new Point(  width/2,         height2/2,  depth/2);
+                    Point f2 = new Point(  width/2,        -height2/2,  depth/2);
+                    Point g2 = new Point(  width/2,-height1-height2/2,  depth/2);
+                    Point h2 = new Point(        0,-height1-height2/2,  depth/2);
+                    Point i2 = new Point(        0,        -height2/2,  depth/2);
+                    Point j2 = new Point( -width/2,        -height2/2,  depth/2);
+
+                    quad(tile, mm, a1, b1, i1, j1);
+                    quad(tile, mm, c1, d1, e1, b1);
+                    quad(tile, mm, b1, e1, f1, i1);
+                    quad(tile, mm, i1, f1, g1, h1);
+
+                    quad(tile, mm, j2, i2, b2, a2);
+                    quad(tile, mm, b2, e2, d2, c2);
+                    quad(tile, mm, i2, f2, e2, b2);
+                    quad(tile, mm, h2, g2, f2, i2);
+
+                    quad(tile, mm, d1, d2, e2, e1);
+                    quad(tile, mm, e1, e2, f2, f1);
+                    quad(tile, mm, f1, f2, g2, g1);
+                    quad(tile, mm, h1, g1, g2, h2);
+                    quad(tile, mm, i2, i1, h1, h2);
+                    quad(tile, mm, j1, i1, i2, j2);
+                    quad(tile, mm, a2, a1, j1, j2);
+                    quad(tile, mm, a1, a2, b2, b1);
+                    quad(tile, mm, c2, c1, b1, b2);
+                    quad(tile, mm, c1, c2, d2, d1);
+
+                    transforms = new Matrix[] {
+
+                        mm.times(Matrix.translate(new Vec(   width,     0, 0))),
+                        mm.times(Matrix.translate(new Vec(  -width,     0, 0))),
+                        mm.times(Matrix.translate(new Vec(-width/2, height1+height2, 0))),
+                        mm.times(Matrix.translate(new Vec( width/2, height1+height2, 0))),
+                        mm.times(Matrix.translate(new Vec(-width/2,-height1-height2, 0))),
+                        mm.times(Matrix.translate(new Vec( width/2,-height1-height2, 0))),
+
+                        mm.times(Matrix.translate(new Vec(   width/2,     0,  depth))),
+                        mm.times(Matrix.translate(new Vec(  -width/2,     0,  depth))),
+                        mm.times(Matrix.translate(new Vec(         0, height1+height2,  depth))),
+                        mm.times(Matrix.translate(new Vec(         0,-height1-height2,  depth))),
+
+                        mm.times(Matrix.translate(new Vec(   width/2,     0, -depth))),
+                        mm.times(Matrix.translate(new Vec(  -width/2,     0, -depth))),
+                        mm.times(Matrix.translate(new Vec(         0, height1+height2, -depth))),
+                        mm.times(Matrix.translate(new Vec(         0,-height1-height2, -depth))),
+
+                        Matrix.ONE
+                    };
+                    fixupTile();
+                }}});
 
             // Finally, add all the menus to the menu bar.
             add(tileMenu);
 
             // Finally, add all the menus to the menu bar.
             add(tileMenu);
index 57eda26..c041792 100644 (file)
@@ -134,6 +134,10 @@ public class Mesh implements Iterable<Mesh.T> {
                 m = m.plus(e.t.norm().fundamentalQuadric(e.t.centroid()));
                 count++;
             }
                 m = m.plus(e.t.norm().fundamentalQuadric(e.t.centroid()));
                 count++;
             }
+            if (count > 0) {
+                m = m.plus(norm().fundamentalQuadric(this.p).times(count));
+                count *= 2;
+            }
             return m.times(1/(float)count);
         }
 
             return m.times(1/(float)count);
         }
 
@@ -147,28 +151,45 @@ public class Mesh implements Iterable<Mesh.T> {
             if (quadric_count != 0)
                 nerror = (nerror + quadric.preAndPostMultiply(p))/(quadric_count+1);
 
             if (quadric_count != 0)
                 nerror = (nerror + quadric.preAndPostMultiply(p))/(quadric_count+1);
 
-            if (!immutableVertices && quadric_count == 0)
-                nerror *= 2;
+            if (!immutableVertices && quadric_count == 0) {
+                //nerror = Math.max(nerror, 0.4f);
+                //nerror *= 2;
+            }
             //System.out.println(nerror);
             for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
                 double ang = e.dihedralAngle();
                 if (ang > Math.PI) throw new Error();
                 if (ang < -Math.PI) throw new Error();
             //System.out.println(nerror);
             for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
                 double ang = e.dihedralAngle();
                 if (ang > Math.PI) throw new Error();
                 if (ang < -Math.PI) throw new Error();
-                //float minangle = (float)(Math.PI * 0.8);
-                nerror += ((ang / Math.PI)*(ang/Math.PI)) * e.length() * 0.05;
+                float minangle = (float)(Math.PI * 0.8);
+                //nerror += ((ang / Math.PI)*(ang/Math.PI)) * e.length() * 0.05;
+
+                nerror += (1-e.t.quality())*0.0001;
+                if (ang > minangle) nerror += (ang - minangle);
+
                 //System.out.println(((ang / Math.PI)*(ang/Math.PI)) * 0.000001);
                 //System.out.println(((ang / Math.PI)*(ang/Math.PI)) * 0.000001);
-                //if (ang > minangle) nerror += (ang - minangle);
                 /*
                 if (e.t.aspect() < 0.2) {
                     nerror += (0.2-e.t.aspect()) * 10;
                 }
                 */
             }
                 /*
                 if (e.t.aspect() < 0.2) {
                     nerror += (0.2-e.t.aspect()) * 10;
                 }
                 */
             }
+            if (!immutableVertices) {
+                Vertex n = (Vertex)nearest();
+                float d = norm().dot(n.norm());
+                if (d > 1 || d < -1) throw new Error();
+                if (d >= 0) {
+                    nerror *= (2.0f - d);
+                } else {
+                    nerror += 0.0003 * (2.0f + d);
+                    nerror *= (2.0f + d);
+                }
+            }
 
             setError(nerror);
         }
 
         public boolean move(Matrix m, boolean ignoreProblems) {
 
             setError(nerror);
         }
 
         public boolean move(Matrix m, boolean ignoreProblems) {
+
             boolean good = true;
 
             //     t1' = M * t1
             boolean good = true;
 
             //     t1' = M * t1
@@ -190,7 +211,7 @@ public class Mesh implements Iterable<Mesh.T> {
                 }
                 if (!m.equals(m2)) return true;
             }
                 }
                 if (!m.equals(m2)) return true;
             }
-
+            ok = false;
             Point op = this.p;
             Point pt = m.times(this.p);
             for(Vertex v : (Iterable<Vertex>)getBoundPeers()) {
             Point op = this.p;
             Point pt = m.times(this.p);
             for(Vertex v : (Iterable<Vertex>)getBoundPeers()) {
@@ -212,8 +233,10 @@ public class Mesh implements Iterable<Mesh.T> {
                 v.recomputeFundamentalQuadricIfNeighborChanged();
             for(Vertex v : (Iterable<Vertex>)getBoundPeers())
                 v.reComputeErrorAround();
                 v.recomputeFundamentalQuadricIfNeighborChanged();
             for(Vertex v : (Iterable<Vertex>)getBoundPeers())
                 v.reComputeErrorAround();
+            ok = true;
             return good;
         }
             return good;
         }
+        public boolean ok = true;
 
         /** does NOT update bound pairs! */
         private boolean transform(Point newp, boolean ignoreProblems, Matrix yes) {
 
         /** does NOT update bound pairs! */
         private boolean transform(Point newp, boolean ignoreProblems, Matrix yes) {
@@ -354,6 +377,12 @@ public class Mesh implements Iterable<Mesh.T> {
                 if (!next.isBoundTo(eother.pair.prev.pair) && prev.isBoundTo(eother.pair.next.pair))
                     next.bindTo(prev.getBindingMatrix(eother.pair.next.pair), eother.pair.prev.pair);
 
                 if (!next.isBoundTo(eother.pair.prev.pair) && prev.isBoundTo(eother.pair.next.pair))
                     next.bindTo(prev.getBindingMatrix(eother.pair.next.pair), eother.pair.prev.pair);
 
+                /*
+                if (next.isBoundTo(eother.prev) && !prev.isBoundTo(eother.next))
+                    prev.bindTo(next.getBindingMatrix(eother.prev), eother.next);
+                if (!next.isBoundTo(eother.prev) && prev.isBoundTo(eother.next))
+                    next.bindTo(prev.getBindingMatrix(eother.next), eother.prev);
+                */
                 if (next.isBoundTo(eother.next) && !prev.isBoundTo(eother.prev))
                     prev.bindTo(next.getBindingMatrix(eother.next), eother.prev);
                 if (!next.isBoundTo(eother.next) && prev.isBoundTo(eother.prev))
                 if (next.isBoundTo(eother.next) && !prev.isBoundTo(eother.prev))
                     prev.bindTo(next.getBindingMatrix(eother.next), eother.prev);
                 if (!next.isBoundTo(eother.next) && prev.isBoundTo(eother.prev))
@@ -372,7 +401,6 @@ public class Mesh implements Iterable<Mesh.T> {
         }
         public float comparator() {
             return length();
         }
         public float comparator() {
             return length();
-            //return t==null?0:(1/t.aspect());
         }
         public int compareTo(E e) {
             return e.comparator() > comparator() ? 1 : -1;
         }
         public int compareTo(E e) {
             return e.comparator() > comparator() ? 1 : -1;
@@ -401,8 +429,10 @@ public class Mesh implements Iterable<Mesh.T> {
             System.out.println("  " + p1.p + " " + m.times(e.p1.p));
             System.out.println("  " + p2.p + " " + m.times(e.p2.p));
             */
             System.out.println("  " + p1.p + " " + m.times(e.p1.p));
             System.out.println("  " + p2.p + " " + m.times(e.p2.p));
             */
+            /*
             if (m.times(e.p1.p).minus(p1.p).mag() > EPSILON) throw new Error();
             if (m.times(e.p2.p).minus(p2.p).mag() > EPSILON) throw new Error();
             if (m.times(e.p1.p).minus(p1.p).mag() > EPSILON) throw new Error();
             if (m.times(e.p2.p).minus(p2.p).mag() > EPSILON) throw new Error();
+            */
             this.bindTo(m, e);
         }
         
             this.bindTo(m, e);
         }
         
index c5c6a3b..cc05e86 100644 (file)
@@ -12,19 +12,24 @@ import edu.berkeley.qfat.geom.Point;
 
 public class MeshViewer implements GLEventListener, MouseListener, MouseMotionListener, KeyListener, MouseWheelListener  {
 
 
 public class MeshViewer implements GLEventListener, MouseListener, MouseMotionListener, KeyListener, MouseWheelListener  {
 
+    public boolean force = false;
     public Mesh tile = new Mesh(false);
     public Mesh goal = new Mesh(false);
     public Matrix[] transforms;
     public Mesh.Vertex[] points;
 
     public Mesh tile = new Mesh(false);
     public Mesh goal = new Mesh(false);
     public Matrix[] transforms;
     public Mesh.Vertex[] points;
 
+    public int whichNeighbor = 1;
+
     public double temp;
     public boolean tileon = true;
     public boolean tilemeshon = false;
     public boolean goalon = true;
     public boolean anneal = false;
     public double temp;
     public boolean tileon = true;
     public boolean tilemeshon = false;
     public boolean goalon = true;
     public boolean anneal = false;
+    public boolean hillclimb = false;
     public boolean neighbors = false;
     public boolean neighborsWire = false;
     public boolean neighborsWireOne = false;
     public boolean neighbors = false;
     public boolean neighborsWire = false;
     public boolean neighborsWireOne = false;
+    public boolean errorNormals = false;
 
     public int breaks = 0;
     boolean alt = false;
 
     public int breaks = 0;
     boolean alt = false;
@@ -41,11 +46,15 @@ public class MeshViewer implements GLEventListener, MouseListener, MouseMotionLi
             case KeyEvent.VK_CONTROL: control = true; break;
             case KeyEvent.VK_ALT: alt = true; break;
             case KeyEvent.VK_SHIFT: shift = true; break;
             case KeyEvent.VK_CONTROL: control = true; break;
             case KeyEvent.VK_ALT: alt = true; break;
             case KeyEvent.VK_SHIFT: shift = true; break;
-            case KeyEvent.VK_SPACE: breaks++; break;
+            case KeyEvent.VK_SPACE: breaks++; force = true; break;
             case KeyEvent.VK_UP: temp = temp * 2; break;
             case KeyEvent.VK_ENTER: temp = 10; break;
             case KeyEvent.VK_UP: temp = temp * 2; break;
             case KeyEvent.VK_ENTER: temp = 10; break;
+            case KeyEvent.VK_LEFT: whichNeighbor--; break;
+            case KeyEvent.VK_RIGHT: whichNeighbor++; break;
             case KeyEvent.VK_D: dump(); break;
             case KeyEvent.VK_D: dump(); break;
-            case KeyEvent.VK_A: anneal = !anneal; break;
+            case KeyEvent.VK_E: errorNormals = !errorNormals; break;
+            case KeyEvent.VK_A: hillclimb = false; anneal = !anneal; break;
+            case KeyEvent.VK_H: anneal = true; hillclimb = !hillclimb; break;
             case KeyEvent.VK_N: neighbors = !neighbors; break;
             case KeyEvent.VK_T: tileon = !tileon; break;
             case KeyEvent.VK_G: goalon = !goalon; break;
             case KeyEvent.VK_N: neighbors = !neighbors; break;
             case KeyEvent.VK_T: tileon = !tileon; break;
             case KeyEvent.VK_G: goalon = !goalon; break;
@@ -156,7 +165,7 @@ public class MeshViewer implements GLEventListener, MouseListener, MouseMotionLi
     public    int vertss;
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
     public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { }
     public    int vertss;
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
     public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { }
-    public synchronized void display(GLAutoDrawable drawable) {
+    public void display(GLAutoDrawable drawable) {
 
         if (transforms==null) return;
 
 
         if (transforms==null) return;
 
@@ -180,9 +189,29 @@ public class MeshViewer implements GLEventListener, MouseListener, MouseMotionLi
         gl.glPointSize(5.0f);
         gl.glLoadIdentity();
         glu.gluPerspective(50, ((float)drawable.getWidth())/drawable.getHeight(), 0.5, 10);
         gl.glPointSize(5.0f);
         gl.glLoadIdentity();
         glu.gluPerspective(50, ((float)drawable.getWidth())/drawable.getHeight(), 0.5, 10);
-        glu.gluLookAt(0, 0, (tz/10)-1, 0, 0, 0, 0, 1, 0);
+        glu.gluLookAt(0, 0, -((tz/10)-1), 0, 0, 0, 0, 1, 0);
         gl.glRotatef(anglex/3, 0, 1, 0);
         gl.glRotatef(anglex/3, 0, 1, 0);
-        gl.glRotatef(angley/3, 1, 0, 0);
+        gl.glRotatef(-(angley/3), 1, 0, 0);
+
+
+        gl.glDisable(GL.GL_LIGHTING);
+        gl.glColor4f(1, 0, 0, 1);
+        gl.glBegin(GL.GL_LINES);
+        gl.glVertex3f(0,0,0);
+        gl.glVertex3f(.3f,0,0);
+        gl.glEnd();
+        gl.glColor4f(0, 1, 0, 1);
+        gl.glBegin(GL.GL_LINES);
+        gl.glVertex3f(0,0,0);
+        gl.glVertex3f(0,.3f,0);
+        gl.glEnd();
+        gl.glColor4f(0, 0, 1, 1);
+        gl.glBegin(GL.GL_LINES);
+        gl.glVertex3f(0,0,0);
+        gl.glVertex3f(0,0,.3f);
+        gl.glEnd();
+        gl.glEnable(GL.GL_LIGHTING);
+
 
         gl.glBegin(GL.GL_TRIANGLES);
         if (tileon)
 
         gl.glBegin(GL.GL_TRIANGLES);
         if (tileon)
@@ -204,9 +233,17 @@ public class MeshViewer implements GLEventListener, MouseListener, MouseMotionLi
         //gl.glDisable(GL.GL_DEPTH_TEST);
         gl.glColor4f(1,1,1,1);
         for(Matrix m : transforms) {
         //gl.glDisable(GL.GL_DEPTH_TEST);
         gl.glColor4f(1,1,1,1);
         for(Matrix m : transforms) {
+            /*
+              gl.glColor4f(0, 1, 1, 1);
+              gl.glBegin(GL.GL_LINES);
+              new Point(0,0,0).glVertex(gl);
+              new Point(0,0,0).plus(m.getTranslationalComponent()).glVertex(gl);
+              gl.glEnd();
+              gl.glEnable(GL.GL_LIGHTING);
+            */
             //if (v1.z==0 && v1.y==0) continue;
             i++;
             //if (v1.z==0 && v1.y==0) continue;
             i++;
-            if (neighborsWireOne && i>1) continue;
+            if (neighborsWireOne && i!=whichNeighbor) continue;
             //if (i>4) continue;
             /*
             Point p = new Point(0, 0, 0).times(m);
             //if (i>4) continue;
             /*
             Point p = new Point(0, 0, 0).times(m);
@@ -285,25 +322,23 @@ public class MeshViewer implements GLEventListener, MouseListener, MouseMotionLi
             Point centroid = t.centroid();
             gl.glBegin(GL.GL_LINES);
             gl.glColor3f(1, 1, 1);
             Point centroid = t.centroid();
             gl.glBegin(GL.GL_LINES);
             gl.glColor3f(1, 1, 1);
-            /*
-            centroid.glVertex(gl);
-            centroid.plus(t.norm().times(t.diameter())).glVertex(gl);
-            */
-            /*
-            if (mesh==goal)
+
+            if (triangles && errorNormals)
                 for(Mesh.Vertex p : new Mesh.Vertex[] { t.v1(), t.v2(), t.v3() }) {
                 for(Mesh.Vertex p : new Mesh.Vertex[] { t.v1(), t.v2(), t.v3() }) {
-                gl.glDisable(GL.GL_LIGHTING);
-                gl.glBegin(GL.GL_LINES);
-                gl.glColor3f(1, 1, 1);
-                p.p.glVertex(gl);
-                //p.p.plus(p.norm().times(p.score())).glVertex(gl);
-                if (p.nearest_in_other_mesh != null) p.nearest_in_other_mesh.p.glVertex(gl);
-                    //tile.nearest(p).centroid().glVertex(gl);
-                gl.glEnd();
-                gl.glEnable(GL.GL_LIGHTING);
+                    if (p.ok) {
+                        //gl.glDisable(GL.GL_LIGHTING);
+                        gl.glBegin(GL.GL_LINES);
+                        gl.glColor3f(1, 1, 1);
+                        p.p.glVertex(gl);
+                        p.p.plus(p.norm().times((float)p.error()*10)).glVertex(gl);
+                        //if (p.nearest_in_other_mesh != null) p.nearest_in_other_mesh.p.glVertex(gl);
+                        //tile.nearest(p).centroid().glVertex(gl);
+                        gl.glEnd();
+                        //gl.glEnable(GL.GL_LIGHTING);
+                    }
                 }
                 }
-            */
             gl.glEnd();
             gl.glEnd();
+            
         }
         }
     }
         }
         }
     }
@@ -314,7 +349,8 @@ public class MeshViewer implements GLEventListener, MouseListener, MouseMotionLi
     private GLCanvas glcanvas;
     public MeshViewer(JFrame f) {
         this.f = f;
     private GLCanvas glcanvas;
     public MeshViewer(JFrame f) {
         this.f = f;
-       GLCapabilities glcaps = new GLCapabilities();
+
+        GLCapabilities glcaps = new GLCapabilities();
         glcanvas = new GLCanvas();
         glcanvas.addGLEventListener(this);
         f.add(glcanvas, BorderLayout.CENTER);
         glcanvas = new GLCanvas();
         glcanvas.addGLEventListener(this);
         f.add(glcanvas, BorderLayout.CENTER);
index b1eaca6..5a283c9 100644 (file)
@@ -14,6 +14,7 @@ import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.InputStreamReader;
 import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.InputStreamReader;
 import java.io.FileInputStream;
+import java.io.InputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
 
@@ -426,9 +427,8 @@ public class StlFile implements Loader
    *
    * @throws IOException
    */
    *
    * @throws IOException
    */
-  private void readBinaryFile(String file) throws IOException
+    public void readBinaryFile(String file, InputStream data) throws IOException
   {
   {
-    FileInputStream data;                 // For reading the file
     ByteBuffer dataBuffer;                // For reading in the correct endian
     byte[] Info=new byte[80];             // Header data
     byte[] Array_number= new byte[4];     // Holds the number of faces
     ByteBuffer dataBuffer;                // For reading in the correct endian
     byte[] Info=new byte[80];             // Header data
     byte[] Array_number= new byte[4];     // Holds the number of faces
@@ -447,7 +447,6 @@ public class StlFile implements Loader
     }
     else
     { // It's a local file
     }
     else
     { // It's a local file
-      data = new FileInputStream(file);
 
       // First 80 bytes aren't important
       if(80 != data.read(Info))
 
       // First 80 bytes aren't important
       if(80 != data.read(Info))
@@ -571,7 +570,7 @@ public class StlFile implements Loader
     else
     { // Binary file
       try{
     else
     { // Binary file
       try{
-        readBinaryFile(getFileName());
+          readBinaryFile(getFileName(), new FileInputStream(getFileName()));
       }
       catch(IOException e)
       {
       }
       catch(IOException e)
       {
index eeeb68f..31fe6e0 100644 (file)
@@ -122,6 +122,14 @@ public class Matrix {
                        i*p.x + j*p.y + k*p.z + l);
     }
 
                        i*p.x + j*p.y + k*p.z + l);
     }
 
+    public Matrix preMultiplyTranslationalComponentBy(Matrix mm) {
+        Vec v = mm.times(getTranslationalComponent());
+        return new Matrix(a, b, c, v.x,
+                          e, f, g, v.y,
+                          i, j, k, v.z,
+                          m, n, o, 1);
+    }
+
     /** multiply by another matrix */
     public Matrix times(Matrix z) {
         float t00 = a;
     /** multiply by another matrix */
     public Matrix times(Matrix z) {
         float t00 = a;
index fdef5e6..61fa603 100644 (file)
@@ -11,9 +11,6 @@ public final class Point implements HasBoundingBox {
 
     public float distance(Point p) { return (float)Math.sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)+(z-p.z)*(z-p.z)); }
 
 
     public float distance(Point p) { return (float)Math.sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)+(z-p.z)*(z-p.z)); }
 
-    // FIXME: this should be eliminated; wrong order
-    public Point times(Matrix m) { return m.times(this); }
-
     public Vec minus(Point p) { return new Vec(x-p.x, y-p.y, z-p.z); }
     public Point plus(Vec v) { return new Point(x+v.x, y+v.y, z+v.z); }
 
     public Vec minus(Point p) { return new Vec(x-p.x, y-p.y, z-p.z); }
     public Point plus(Vec v) { return new Point(x+v.x, y+v.y, z+v.z); }
 
index 9d16661..fece872 100644 (file)
@@ -44,13 +44,40 @@ public abstract class Triangle implements HasBoundingBox {
     }
 
     /** ratio of the area of the triangle to that of the square formed from its longest edge */
     }
 
     /** ratio of the area of the triangle to that of the square formed from its longest edge */
+    /*
     public float aspect() {
         float max = Math.max(Math.max(p1().distance(p2()),
                                       p2().distance(p3())),
                              p3().distance(p1())) / 2;
         return 1/(1+area()/(max*max));
     }
     public float aspect() {
         float max = Math.max(Math.max(p1().distance(p2()),
                                       p2().distance(p3())),
                              p3().distance(p1())) / 2;
         return 1/(1+area()/(max*max));
     }
+    */
 
 
+    public float circumcircleRadius() {
+        double a = p1().distance(p2());
+        double b = p2().distance(p3());
+        double c = p3().distance(p1());
+        return (float)((a*b*c)/Math.sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)));
+    }
+
+    public float shortestEdgeLength() {
+        float a = p1().distance(p2());
+        float b = p2().distance(p3());
+        float c = p3().distance(p1());
+        return Math.min(a, Math.min(b,c));
+    }
+
+    /** a number ranging from 0..1 with 0 being lower quality */
+    public float quality() {
+        float d = shortestEdgeLength();
+        float r = circumcircleRadius();
+        if (r==0) throw new Error();
+        float ret = (float)((d*Math.cos(Math.PI/6))/(r*2));
+        if (ret < 0 || ret > 1) throw new Error("ret="+ret);
+        return ret;
+    }
+
+    // FIXME: I stole this off the net, and I need to credit whoever wrote it
     /** decide if the segment from p1-p2 intersects this triangle */
     public boolean intersects(Point p1, Point p2) {
         double A0=p1().x, A1=p1().y, A2=p1().z;
     /** decide if the segment from p1-p2 intersects this triangle */
     public boolean intersects(Point p1, Point p2) {
         double A0=p1().x, A1=p1().y, A2=p1().z;