add code to read MRI data
[anneal.git] / src / edu / berkeley / qfat / Main.java
index b7df3d4..f404144 100644 (file)
@@ -9,9 +9,60 @@ import java.util.*;
 import edu.berkeley.qfat.bind.*;
 import edu.berkeley.qfat.geom.*;
 import edu.berkeley.qfat.stl.*;
+import edu.berkeley.qfat.voxel.*;
 import edu.berkeley.qfat.geom.Point;
 import edu.berkeley.qfat.geom.Polygon;
 
+/*
+
+
+Todo
+- review catmull-clark; move vertex points?
+- re-anneal fish
+
+- show constraints (?)
+- show in red if user tries to move a point to an illegal location
+
+- eliminate use of bindinggroupschanged()
+
+- post qfat on my software page
+
+
+With Sequin
+- constraints admit intersections (lattice)
+- constraints may be transformed linearly
+
+
+
+
+Log console
+  - blend-shaded overlay?  slick.
+
+face/vertex count
+rendering FPS
+ability to not draw edges between faces
+
+
+three circumcircles showing crystal ball -- these don't get scaled
+axes?
+
+drawing modes:
+  - bounding box
+  - vertices
+  - edges
+  - visible-edges
+  - flat with or without edges
+  - shaded with or without edges
+  * contrasting-faces
+
+
+quadric decimation?
+
+show normals
+show bounding box
+show axes (big+fat)
+ */
+
 // TO DO:
 //
 // - Ability to snap three views to orthgonal
@@ -170,48 +221,51 @@ public class Main extends InteractiveMeshViewer {
                         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().pair, m);
+                            t2.e2().bindEdge(t1.e2().pair, m);
+                            t2.e1().bindEdge(t1.e3().pair, m);
                         }
                         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().pair, m);
+                            t2.e2().bindEdge(t1.e3().pair, m);
+                            t2.e1().bindEdge(t1.e1().pair, m);
                         }
                         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().pair, m);
+                            t2.e2().bindEdge(t1.e1().pair, m);
+                            t2.e1().bindEdge(t1.e2().pair, m);
                         }
+
                         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(), m);
+                            t2.e2().bindEdge(t1.e2(), m);
+                            t2.e3().bindEdge(t1.e3(), m);
                         }
                         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(), m);
+                            t2.e3().bindEdge(t1.e2(), m);
+                            t2.e1().bindEdge(t1.e3(), m);
                         }
                         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(), m);
+                            t2.e1().bindEdge(t1.e2(), m);
+                            t2.e2().bindEdge(t1.e3(), m);
                         }
+
                     }
                 }
             }
@@ -238,6 +292,114 @@ public class Main extends InteractiveMeshViewer {
         public void hit() {}
     }
 
+    public void marchingCubes() {
+        Mesh mesh = new Mesh(false);
+        mesh.coalesce = true;
+        MarchingCubes.march(new VoxelData() {
+                float radius = 1.0f;
+                public float getMaxX()        { return  1.0f; }
+                public float getMinX()        { return -1.0f; }
+                public int   getNumSamplesX() { return   10; }
+                public float getMaxY()        { return  1.0f; }
+                public float getMinY()        { return -1.0f; }
+                public int   getNumSamplesY() { return   10; }
+                public float getMaxZ()        { return  1.0f; }
+                public float getMinZ()        { return -1.0f; }
+                public int   getNumSamplesZ() { return   10; }
+                public float getSample(Point p) {
+                    double x = p.x;
+                    double y = p.y;
+                    double z = p.z;
+                    return (float)(radius-Math.sqrt(x*x+y*y+z*z));
+                }
+            },
+            mesh);
+        setTile(mesh);
+        //fixupTile();
+    }
+
+    public void marchingCubes2() {
+        try {
+
+            final float[][][] samples = new float[256][256][124];
+            double total = 0;
+            int count = 0;
+            for(int i=1; i<=124; i++) {
+                String ix = ""+i;
+                while(ix.length() < 3) ix = "0"+ix;
+                FileInputStream fis = new FileInputStream("/Users/megacz/Desktop/projects/mri brain images/spgr/I."+ix);
+                DataInputStream dis = new DataInputStream(new BufferedInputStream(fis));
+                dis.skip(7904);
+                for(int x=0; x<256; x++)
+                    for(int y=0; y<256; y++) {
+                        short s = dis.readShort();
+                        samples[x][y][i-1] = (float)s;
+                        total += samples[x][y][i-1];
+                        count++;
+                    }
+            }
+            System.out.println("done reading samples; average sample is " + (total/count));
+
+            /*
+            PrintWriter pw = new PrintWriter(new FileOutputStream("/tmp/out"));
+            pw.println("new short[][][] {");
+            for(int x=0; x<256; x++) {
+                if (x>0) pw.println("  ,");
+                pw.println("  {");
+                for(int y=0; y<256; y++) {
+                    if (y>0) pw.println("    ,");
+                    pw.print("    {");
+                    for(int z=0; z<124; z++) {
+                        if (z>0) pw.print(", ");
+                        if ((z % 20) == 0) {
+                            pw.println();
+                            pw.print("      ");
+                        }
+                        pw.print(shorts[x][y][z]);
+                    }
+                    pw.println();
+                    pw.println("    }");
+                }
+                pw.println("  }");
+            }
+            pw.println("};");
+            pw.flush();
+            pw.close();
+            */
+
+            Mesh mesh = new Mesh(false);
+            mesh.coalesce = true;
+            MarchingCubes.march(new VoxelData() {
+                    float radius = 1.0f;
+                    public float getMaxX()        { return  2.4f; }
+                    public float getMinX()        { return    0f; }
+                    public int   getNumSamplesX() { return   256/10; }
+                    public float getMaxY()        { return  2.4f; }
+                    public float getMinY()        { return    0f; }
+                    public int   getNumSamplesY() { return   256/10; }
+                    public float getMaxZ()        { return 1.86f; }
+                    public float getMinZ()        { return    0f; }
+                    public int   getNumSamplesZ() { return   124/10; }
+                    public float getSample(Point p) {
+                        int x = (int)Math.floor(p.x / ((double)getMaxX() / (double)256));
+                        int y = (int)Math.floor(p.y / ((double)getMaxY() / (double)256));
+                        int z = (int)Math.floor(p.z / ((double)getMaxZ() / (double)124));
+                        if ( (x<0) || (x>=samples.length) ) return 0;
+                        if ( (y<0) || (y>=samples[x].length) ) return 0;
+                        if ( (z<0) || (z>=samples[x][y].length) ) return 0;
+                        return samples[x][y][z];
+                    }
+                },
+                200,
+                mesh);
+            setTile(mesh);
+            //fixupTile();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
     public void hexBrick(boolean offset, boolean rotated) {
         setTile(new Mesh(false));
                 float width  = (float)0.8;
@@ -574,6 +736,7 @@ public class Main extends InteractiveMeshViewer {
                 generateTile(transforms, tile);
                 fixupTile();
             } });
+
             tileMenu.add(new MyMenuItem("Slim Dense Packing (Cubic)") { public void hit() {
                 setTile(new Mesh(false));
                 float unit = 0.4f;
@@ -585,6 +748,9 @@ public class Main extends InteractiveMeshViewer {
                 float height = 2*r*(float)Math.sqrt(2f/3f);
 
                 transforms = new Matrix[] {
+
+                    //Matrix.reflect(new Vec( 0,  height, -z).norm()),
+
                     Matrix.translate(new Vec(-unit, 0, 0)),
                     Matrix.translate(new Vec( unit, 0, 0)),
                     Matrix.translate(new Vec(-cos,  0,  sin)),
@@ -592,6 +758,13 @@ public class Main extends InteractiveMeshViewer {
                     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.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)),
@@ -601,14 +774,6 @@ public class Main extends InteractiveMeshViewer {
                     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)),
@@ -620,12 +785,39 @@ public class Main extends InteractiveMeshViewer {
                     Matrix.ONE
                 };
                 generateTile(transforms, tile);
+
+
+                transforms = new Matrix[] {
+                    Matrix.reflect(new Vec( 0,  height, -z).norm()),
+                    //Matrix.reflect(new Vec( 0, -height,  z)),
+                    Matrix.ONE,
+                    Matrix.translate(new Vec(-unit, 0, 0)),
+                    Matrix.translate(new Vec( unit, 0, 0)),
+                    /*
+                    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)),
+                    */
+                };
+
+
                 //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] = preMultiplyTranslationalComponentBy(transforms[i], m);
+
+
                 fixupTile();
 
             } });
@@ -835,11 +1027,17 @@ public class Main extends InteractiveMeshViewer {
                     };
                     fixupTile();
                 }}});
+            tileMenu.add(new MyMenuItem("Marching Cubes") { public void hit() {
+                marchingCubes();
+            }});
+            tileMenu.add(new MyMenuItem("Brain") { public void hit() {
+                marchingCubes2();
+            }});
 
             // Finally, add all the menus to the menu bar.
             add(tileMenu);
-            add(goalMenu);
-            add(hideMenu);
+            //add(goalMenu);
+            //add(hideMenu);
         }
 
     }
@@ -1002,11 +1200,27 @@ public class Main extends InteractiveMeshViewer {
         f.setLayout(new BorderLayout());
         Main main = new Main(f);
         f.add(main, BorderLayout.CENTER);
-        f.setJMenuBar(main.new MyMenuBar());
+
+        f.addWindowListener(new WindowListener() {
+                public void windowActivated(WindowEvent e) { }
+                public void windowClosed(WindowEvent e) { System.exit(0); }
+                public void windowClosing(WindowEvent e) { System.exit(0); }
+                public void windowDeactivated(WindowEvent e)  { }
+                public void windowDeiconified(WindowEvent e)  { }
+                public void windowIconified(WindowEvent e)  { }
+                public void windowOpened(WindowEvent e) { }
+            });
+
         f.pack();
         f.show();
         f.setSize(900, 900);
         f.doLayout();
+
+        JFrame f2 = new JFrame();
+        f2.setJMenuBar(main.new MyMenuBar());
+        f2.setSize(100,100);
+        f2.show();
+
         main.anneal();
     }