checkpoint
authoradam <adam@megacz.com>
Wed, 5 Dec 2007 04:16:50 +0000 (20:16 -0800)
committeradam <adam@megacz.com>
Wed, 5 Dec 2007 04:16:50 +0000 (20:16 -0800)
darcs-hash:20071205041650-5007d-879a786f9cb499f3fd31bd74d9adfd4d44e2fa17.gz

src/edu/berkeley/qfat/Geom.java
src/edu/berkeley/qfat/Main.java
src/edu/berkeley/qfat/geom/Matrix.java [new file with mode: 0644]
src/edu/berkeley/qfat/geom/Point.java [new file with mode: 0644]
src/edu/berkeley/qfat/geom/Vec.java [new file with mode: 0644]

index 80d2dd6..18b17d1 100644 (file)
@@ -5,7 +5,9 @@ import java.awt.event.*;
 import javax.swing.*;
 import javax.media.opengl.*;
 import javax.media.opengl.glu.*;
+import edu.berkeley.qfat.geom.*;
 import edu.wlu.cs.levy.CG.KDTree;
+import edu.berkeley.qfat.geom.Point;
 
 public class Geom implements Iterable<Geom.T> {
 
@@ -65,7 +67,7 @@ public class Geom implements Iterable<Geom.T> {
         return (float)(dist/num);
     }
 
-    public void transform(M m) {
+    public void transform(Matrix m) {
         ArrayList<Vert> set = new ArrayList<Vert>();
         set.addAll(ps.values());
         for(Vert v : set) v.transform(m);
@@ -237,7 +239,7 @@ public class Geom implements Iterable<Geom.T> {
 
 
         /** does NOT update bound pairs! */
-        public boolean transform(M m) {
+        public boolean transform(Matrix m) {
             // FIXME: screws up kdtree 
             // FIXME: screws up hashmap
             unscore();
@@ -272,7 +274,7 @@ public class Geom implements Iterable<Geom.T> {
             return good;
         }
         public boolean move(Vec v) {
-            M m = new M(v);
+            Matrix m = new Matrix(v);
             Vert p = this;
             boolean good = true;
             do {
@@ -328,12 +330,12 @@ public class Geom implements Iterable<Geom.T> {
             return false;
         }
 
-        public void unbind() { bound_to = this; binding = new M(); }
-        public void bind(Vert p) { bind(p, new M()); }
-        public void bind(Vert p, M binding) {
+        public void unbind() { bound_to = this; binding = new Matrix(); }
+        public void bind(Vert p) { bind(p, new Matrix()); }
+        public void bind(Vert p, Matrix binding) {
             if (isBoundTo(p)) return;
             Vert temp_bound_to = p.bound_to;
-            M temp_binding = p.binding;
+            Matrix temp_binding = p.binding;
             p.bound_to = this.bound_to;
             p.binding = binding.times(this.binding); // FIXME: may have order wrong here
             this.bound_to = temp_bound_to;
@@ -356,7 +358,7 @@ public class Geom implements Iterable<Geom.T> {
         float watch_z;
         Vert watch;
         E e;                // some edge *leaving* this point
-        M binding = new M();
+        Matrix binding = new Matrix();
         float oldscore = 0;
         boolean inserted = false;
     }
@@ -447,8 +449,8 @@ public class Geom implements Iterable<Geom.T> {
 
         public BindingGroup bg = new BindingGroup(this);
 
-        public void bind(E e) { bind(e, new M()); }
-        public void bind(E e, M m) { e.bg.add(this); }
+        public void bind(E e) { bind(e, new Matrix()); }
+        public void bind(E e, Matrix m) { e.bg.add(this); }
 
         public void dobind() {
             if (bg==null) return;
@@ -681,104 +683,4 @@ public class Geom implements Iterable<Geom.T> {
     
     public Vert register(Point p) { Vert v = ps.get(p); return v==null ? new Vert(p) : v; }
 
-    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-    /** point in 3-space; immutable */
-    public static final class Point {
-        public final float x, y, z;
-        public Point(double x, double y, double z) { this((float)x, (float)y, (float)z); }
-        public Point(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
-        public float distance(Point p) { return distance(p.x, p.y, p.z); }
-        public float distance(float ox, float oy, float oz) { return (float)Math.sqrt((x-ox)*(x-ox)+(y-oy)*(y-oy)+(z-oz)*(z-oz)); }
-        public Point times(M 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 boolean equals(Object o) { return o!=null && (o instanceof Point) && ((Point)o).x==x && ((Point)o).y==y && ((Point)o).z==z; }
-        public void glVertex(GL gl) { _glVertex(gl); }
-        private void _glVertex(GL gl) { gl.glVertex3f(x, y, z); }
-        public String toString() { return "("+x+","+y+","+z+")"; }
-        public int hashCode() { return Float.floatToIntBits(x) ^ Float.floatToIntBits(y) ^ Float.floatToIntBits(z); }
-    }
-
-    /** vector in 3-space; immutable */
-    public static final class Vec {
-        public final float x, y, z;
-        public Vec(double x, double y, double z) { this((float)x, (float)y, (float)z); }
-        public Vec(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
-        public Vec(Point p1, Point p2) { this(p2.x-p1.x, p2.y-p1.y, p2.z-p1.z); }
-        public Vec cross(Vec v) { return new Vec(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); }
-        public Vec plus(Vec v) { return new Vec(x+v.x, y+v.y, z+v.z); }
-        public Vec norm() { return mag()==0 ? this : div(mag()); }
-        public Vec times(M m) { return m.apply(this); }
-        public float mag() { return (float)Math.sqrt(x*x+y*y+z*z); }
-        public float dot(Vec v) { return x*v.x + y*v.y + z*v.z; }
-        public Vec times(float mag) { return new Vec(x*mag, y*mag, z*mag); }
-        public Vec div(float mag) { return new Vec(x/mag, y/mag, z/mag); }
-        public String toString() { return "<"+x+","+y+","+z+">"; }
-    }
-
-    /** affine matrix; immutable */
-    public static class M {
-        //
-        //  [ a b c d ]   [ x ]
-        //  [ e f g h ]   [ y ]
-        //  [ i j k l ]   [ z ]
-        //  [ 0 0 0 1 ]   [ 1 ]
-        //
-        public final float a, b, c, d, e, f, g, h, i, j, k, l;
-        public M() { this(1); }
-        public M(float scale) {
-            a = f = k = scale;
-            l = h = d = e = b = i = c = j = g = 0;            
-        }
-        public M(float scalex, float scaley, float scalez) {
-            a = scalex;
-            f = scaley;
-            k = scalez;
-            l = h = d = e = b = i = c = j = g = 0;            
-        }
-        public M(Vec translate) {
-            d = translate.x; h = translate.y; l = translate.z;
-            a = f = k = 1;
-            b = c = e = g = i = j = 0;
-        }
-        public M(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) {
-            this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; this.g = g; this.h = h; this.i = i;
-            this.j = j; this.k = k; this.l = l;
-        }
-        public M times(float x) {
-            return new M(a*x, b*x, c*x, d*x, e*x, f*x, g*x, h*x, i*x, j*x, k*x, l*x);
-        }
-        public M(Vec axis, float angle) {
-            double q = Math.cos(angle);
-            double s = Math.sin(angle);
-            double t = 1.0 - q;
-            a = (float)(q + axis.x*axis.x*t);
-            f = (float)(q + axis.y*axis.y*t);
-            k = (float)(q + axis.z*axis.z*t);
-            double tmp1 = axis.x*axis.y*t;
-            double tmp2 = axis.z*s;
-            e = (float)(tmp1 + tmp2);
-            b = (float)(tmp1 - tmp2);
-            tmp1 = axis.x*axis.z*t;
-            tmp2 = axis.y*s;
-            i = (float)(tmp1 - tmp2);
-            c = (float)(tmp1 + tmp2);
-            tmp1 = axis.y*axis.z*t;
-            tmp2 = axis.x*s;
-            j = (float)(tmp1 + tmp2);
-            g = (float)(tmp1 - tmp2);
-            d = h = l = 0;
-        }
-        public Point times(Point p) {
-            return new Point(a*p.x + b*p.y + c*p.z + d,
-                        e*p.x + f*p.y + g*p.z + h,
-                        i*p.x + j*p.y + k*p.z + l);
-        }
-        public Point apply(Point p) { return p; }
-        public Vec apply(Vec v) { return v; }
-        public M invert() { return this; }
-        public M times(M m) { return this; }
-    }
-
 }
index 8607e0a..5195886 100644 (file)
@@ -5,7 +5,8 @@ import javax.swing.*;
 import javax.media.opengl.*;
 import javax.media.opengl.glu.*;
 import java.util.*;
-import static edu.berkeley.qfat.Geom.*;
+import edu.berkeley.qfat.geom.*;
+import edu.berkeley.qfat.geom.Point;
 
 // FIXME: recenter goal to have centroid coincident with tile
 // FIXME: re-orient goal (how?)
@@ -73,62 +74,62 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
     /** magnification factor */
     private static final float MAG = 1;
 
-    Geom.M[] translations;
+    Matrix[] translations;
     Geom.Vert[] points;
 
     public Main(StlFile stlf) {
 
         for(int i=0; i<stlf.coordArray.length; i+=3) {
-            Geom.Vert p0 = goal.register(new Geom.Point(stlf.coordArray[i+0].x * MAG, stlf.coordArray[i+0].y * MAG, stlf.coordArray[i+0].z * MAG));
-            Geom.Vert p1 = goal.register(new Geom.Point(stlf.coordArray[i+1].x * MAG, stlf.coordArray[i+1].y * MAG, stlf.coordArray[i+1].z * MAG));
-            Geom.Vert p2 = goal.register(new Geom.Point(stlf.coordArray[i+2].x * MAG, stlf.coordArray[i+2].y * MAG, stlf.coordArray[i+2].z * MAG));
-            Geom.Vec n  = new Geom.Vec(stlf.normArray[i/3].x * MAG, stlf.normArray[i/3].y  * MAG, stlf.normArray[i/3].z * MAG);
+            Geom.Vert p0 = goal.register(new Point(stlf.coordArray[i+0].x * MAG, stlf.coordArray[i+0].y * MAG, stlf.coordArray[i+0].z * MAG));
+            Geom.Vert p1 = goal.register(new Point(stlf.coordArray[i+1].x * MAG, stlf.coordArray[i+1].y * MAG, stlf.coordArray[i+1].z * MAG));
+            Geom.Vert p2 = goal.register(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);
             Geom.T t  = goal.newT(p0, p1, p2, n);
         }
 
         // rotate to align major axis -- this probably needs to be done by a human.
-        goal.transform(new Geom.M(new Geom.Vec(0, 0, 1), (float)(Math.PI/2)));
+        goal.transform(new Matrix(new Vec(0, 0, 1), (float)(Math.PI/2)));
 
 
-        float goal_width  = goal.diagonal().dot(new Geom.Vec(1, 0, 0));
-        float goal_height = goal.diagonal().dot(new Geom.Vec(0, 1, 0));
-        float goal_depth  = goal.diagonal().dot(new Geom.Vec(0, 0, 1));
+        float goal_width  = goal.diagonal().dot(new Vec(1, 0, 0));
+        float goal_height = goal.diagonal().dot(new Vec(0, 1, 0));
+        float goal_depth  = goal.diagonal().dot(new Vec(0, 0, 1));
 
         float width  = (float)0.6;
         float height = (float)0.08;
         float depth  = (float)0.3;
-        translations = new Geom.M[] {
-
-            new Geom.M(new Geom.Vec(-(width/2),  height,    0)),
-            new Geom.M(new Geom.Vec( (width/2),  height,    0)),
-            new Geom.M(new Geom.Vec(-(width/2), -height,    0)),
-            new Geom.M(new Geom.Vec( (width/2), -height,    0)),
-            new Geom.M(new Geom.Vec(-(width/2),       0,  depth)),
-            new Geom.M(new Geom.Vec( (width/2),       0,  depth)),
-            new Geom.M(new Geom.Vec(-(width/2),       0, -depth)),
-            new Geom.M(new Geom.Vec( (width/2),       0, -depth)),
-
-            new Geom.M(new Geom.Vec( width,           0,    0)),
-            new Geom.M(new Geom.Vec(-width,           0,    0)),
+        translations = new Matrix[] {
+
+            new Matrix(new Vec(-(width/2),  height,    0)),
+            new Matrix(new Vec( (width/2),  height,    0)),
+            new Matrix(new Vec(-(width/2), -height,    0)),
+            new Matrix(new Vec( (width/2), -height,    0)),
+            new Matrix(new Vec(-(width/2),       0,  depth)),
+            new Matrix(new Vec( (width/2),       0,  depth)),
+            new Matrix(new Vec(-(width/2),       0, -depth)),
+            new Matrix(new Vec( (width/2),       0, -depth)),
+
+            new Matrix(new Vec( width,           0,    0)),
+            new Matrix(new Vec(-width,           0,    0)),
             /*
-            new Geom.M(new Geom.Vec(     0,           0,    depth)),
-            new Geom.M(new Geom.Vec(     0,           0,   -depth)),
+            new Matrix(new Vec(     0,           0,    depth)),
+            new Matrix(new Vec(     0,           0,   -depth)),
             */
         };
 
 
-        Geom.Vert ltf = tile.register(new Geom.Point(-(width/2),  (height/2),  (depth/2)));
-        Geom.Vert mtf = tile.register(new Geom.Point( 0.0,        (height/2),  (depth/2)));
-        Geom.Vert rtf = tile.register(new Geom.Point( (width/2),  (height/2),  (depth/2)));
-        Geom.Vert ltn = tile.register(new Geom.Point(-(width/2),  (height/2), -(depth/2)));
-        Geom.Vert mtn = tile.register(new Geom.Point( 0.0,        (height/2), -(depth/2)));
-        Geom.Vert rtn = tile.register(new Geom.Point( (width/2),  (height/2), -(depth/2)));
-        Geom.Vert lbf = tile.register(new Geom.Point(-(width/2), -(height/2),  (depth/2)));
-        Geom.Vert mbf = tile.register(new Geom.Point( 0.0,       -(height/2),  (depth/2)));
-        Geom.Vert rbf = tile.register(new Geom.Point( (width/2), -(height/2),  (depth/2)));
-        Geom.Vert lbn = tile.register(new Geom.Point(-(width/2), -(height/2), -(depth/2)));
-        Geom.Vert mbn = tile.register(new Geom.Point( 0.0,       -(height/2), -(depth/2)));
-        Geom.Vert rbn = tile.register(new Geom.Point( (width/2), -(height/2), -(depth/2)));
+        Geom.Vert ltf = tile.register(new Point(-(width/2),  (height/2),  (depth/2)));
+        Geom.Vert mtf = tile.register(new Point( 0.0,        (height/2),  (depth/2)));
+        Geom.Vert rtf = tile.register(new Point( (width/2),  (height/2),  (depth/2)));
+        Geom.Vert ltn = tile.register(new Point(-(width/2),  (height/2), -(depth/2)));
+        Geom.Vert mtn = tile.register(new Point( 0.0,        (height/2), -(depth/2)));
+        Geom.Vert rtn = tile.register(new Point( (width/2),  (height/2), -(depth/2)));
+        Geom.Vert lbf = tile.register(new Point(-(width/2), -(height/2),  (depth/2)));
+        Geom.Vert mbf = tile.register(new Point( 0.0,       -(height/2),  (depth/2)));
+        Geom.Vert rbf = tile.register(new Point( (width/2), -(height/2),  (depth/2)));
+        Geom.Vert lbn = tile.register(new Point(-(width/2), -(height/2), -(depth/2)));
+        Geom.Vert mbn = tile.register(new Point( 0.0,       -(height/2), -(depth/2)));
+        Geom.Vert rbn = tile.register(new Point( (width/2), -(height/2), -(depth/2)));
         
         points = new Geom.Vert[] {
             ltf,
@@ -178,7 +179,7 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
         tile.newT(rtf, mtf, rbf);
         tile.newT(rbf, mtf, mbf);
 
-        for(Geom.M m : translations) {
+        for(Matrix m : translations) {
             for(Geom.T t1 : tile) {
                 for(Geom.T t2 : tile) {
                     if (t1==t2) continue;
@@ -212,10 +213,10 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
 
         // rescale to match volume
         float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
-        goal.transform(new Geom.M(factor));
+        goal.transform(new Matrix(factor));
 
         // translate to match centroid
-        goal.transform(new Geom.M(tile.centroid().minus(goal.centroid())));
+        goal.transform(new Matrix(tile.centroid().minus(goal.centroid())));
 
         //tx.e2.shatter();
         //tx.e3.shatter();
@@ -223,10 +224,10 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
 
         tile.bind();
 
-        //mid.move(new Geom.Vec((float)0,0,(float)-0.05));
-        //ltn.move(new Geom.Vec((float)0,0,(float)-0.05));
+        //mid.move(new Vec((float)0,0,(float)-0.05));
+        //ltn.move(new Vec((float)0,0,(float)-0.05));
 
-        //mtf.move(new Geom.Vec(0, (float)-0.05, (float)0.05));
+        //mtf.move(new Vec(0, (float)-0.05, (float)0.05));
 
 
         System.out.println("tile volume: " + tile.volume());
@@ -263,18 +264,18 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
         r1 = r1 - (float)Math.floor(r1);
         r1 = r1 * (float)0.01;
         r1 = r1 - (float)0.005;
-        Geom.Vec v = p.watchback().p.minus(p.p).norm().times(r1);
+        Vec v = p.watchback().p.minus(p.p).norm().times(r1);
 
         //v = p.norm().times(v.dot(p.norm()));
 
         boolean aspect = false;//(Math.abs(random.nextInt()) % 100) <= 2;
-        Geom.M old_tile_aspect = null;//goal.aspect;
+        Matrix old_tile_aspect = null;//goal.aspect;
         boolean good = true;
         if (aspect) {
             /*
             v = v.times(10);
-            tile.aspect = new Geom.M(tile.aspect.a / (v.x+1), tile.aspect.f / (v.y+1), tile.aspect.k / (v.z+1));
-            tile.invaspect = new Geom.M(1/tile.aspect.a, 1/tile.aspect.f, 1/tile.aspect.k);
+            tile.aspect = new Matrix(tile.aspect.a / (v.x+1), tile.aspect.f / (v.y+1), tile.aspect.k / (v.z+1));
+            tile.invaspect = new Matrix(1/tile.aspect.a, 1/tile.aspect.f, 1/tile.aspect.k);
             goal.rescore();
             tile.rescore();
             */
@@ -297,7 +298,7 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
         } else {
             if (aspect) {
                 //tile.aspect = old_tile_aspect;
-                //tile.invaspect = new Geom.M(1/tile.aspect.a, 1/tile.aspect.f, 1/tile.aspect.k);
+                //tile.invaspect = new Matrix(1/tile.aspect.a, 1/tile.aspect.f, 1/tile.aspect.k);
                 goal.rescore();
                 tile.rescore();
             } else {
@@ -349,12 +350,12 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
         int i = 0;
         //gl.glDisable(GL.GL_DEPTH_TEST);
         gl.glColor4f(1,1,1,1);
-        for(Geom.M m : translations) {
+        for(Matrix m : translations) {
             //if (v1.z==0 && v1.y==0) continue;
             i++;
             if (i != 1 /*&& i!=4*/) continue;
-            Geom.Point p = new Geom.Point(0, 0, 0).times(m);
-            Geom.Vec v = new Geom.Vec(p.x, p.y, p.z);
+            Point p = new Point(0, 0, 0).times(m);
+            Vec v = new Vec(p.x, p.y, p.z);
             v = v.times((float)1.04);
             gl.glTranslatef(v.x, v.y, v.z);
             draw(gl, false, tile);
@@ -398,7 +399,7 @@ public class Main implements GLEventListener, MouseListener, MouseMotionListener
                 gl.glEnd();
             }
 
-            Geom.Point centroid = t.centroid();
+            Point centroid = t.centroid();
             gl.glBegin(GL.GL_LINES);
             gl.glColor3f(1, 1, 1);
             /*
diff --git a/src/edu/berkeley/qfat/geom/Matrix.java b/src/edu/berkeley/qfat/geom/Matrix.java
new file mode 100644 (file)
index 0000000..751dfa1
--- /dev/null
@@ -0,0 +1,65 @@
+package edu.berkeley.qfat.geom;
+
+/** affine matrix; immutable */
+public class Matrix {
+    //
+    //  [ a b c d ]   [ x ]
+    //  [ e f g h ]   [ y ]
+    //  [ i j k l ]   [ z ]
+    //  [ 0 0 0 1 ]   [ 1 ]
+    //
+    public final float a, b, c, d, e, f, g, h, i, j, k, l;
+    public Matrix() { this(1); }
+    public Matrix(float scale) {
+        a = f = k = scale;
+        l = h = d = e = b = i = c = j = g = 0;            
+    }
+    public Matrix(float scalex, float scaley, float scalez) {
+        a = scalex;
+        f = scaley;
+        k = scalez;
+        l = h = d = e = b = i = c = j = g = 0;            
+    }
+    public Matrix(Vec translate) {
+        d = translate.x; h = translate.y; l = translate.z;
+        a = f = k = 1;
+        b = c = e = g = i = j = 0;
+    }
+    public Matrix(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) {
+        this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; this.g = g; this.h = h; this.i = i;
+        this.j = j; this.k = k; this.l = l;
+    }
+    public Matrix times(float x) {
+        return new Matrix(a*x, b*x, c*x, d*x, e*x, f*x, g*x, h*x, i*x, j*x, k*x, l*x);
+    }
+    public Matrix(Vec axis, float angle) {
+        double q = Math.cos(angle);
+        double s = Math.sin(angle);
+        double t = 1.0 - q;
+        a = (float)(q + axis.x*axis.x*t);
+        f = (float)(q + axis.y*axis.y*t);
+        k = (float)(q + axis.z*axis.z*t);
+        double tmp1 = axis.x*axis.y*t;
+        double tmp2 = axis.z*s;
+        e = (float)(tmp1 + tmp2);
+        b = (float)(tmp1 - tmp2);
+        tmp1 = axis.x*axis.z*t;
+        tmp2 = axis.y*s;
+        i = (float)(tmp1 - tmp2);
+        c = (float)(tmp1 + tmp2);
+        tmp1 = axis.y*axis.z*t;
+        tmp2 = axis.x*s;
+        j = (float)(tmp1 + tmp2);
+        g = (float)(tmp1 - tmp2);
+        d = h = l = 0;
+    }
+    public Point times(Point p) {
+        return new Point(a*p.x + b*p.y + c*p.z + d,
+                         e*p.x + f*p.y + g*p.z + h,
+                         i*p.x + j*p.y + k*p.z + l);
+    }
+    public Point apply(Point p) { return p; }
+    public Vec apply(Vec v) { return v; }
+    public Matrix invert() { return this; }
+    public Matrix times(Matrix m) { return this; }
+}
diff --git a/src/edu/berkeley/qfat/geom/Point.java b/src/edu/berkeley/qfat/geom/Point.java
new file mode 100644 (file)
index 0000000..d54e631
--- /dev/null
@@ -0,0 +1,19 @@
+package edu.berkeley.qfat.geom;
+import javax.media.opengl.*;
+
+/** point in 3-space; immutable */
+public final class Point {
+    public final float x, y, z;
+    public Point(double x, double y, double z) { this((float)x, (float)y, (float)z); }
+    public Point(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
+    public float distance(Point p) { return distance(p.x, p.y, p.z); }
+    public float distance(float ox, float oy, float oz) { return (float)Math.sqrt((x-ox)*(x-ox)+(y-oy)*(y-oy)+(z-oz)*(z-oz)); }
+    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 boolean equals(Object o) { return o!=null && (o instanceof Point) && ((Point)o).x==x && ((Point)o).y==y && ((Point)o).z==z; }
+    public void glVertex(GL gl) { _glVertex(gl); }
+    private void _glVertex(GL gl) { gl.glVertex3f(x, y, z); }
+    public String toString() { return "("+x+","+y+","+z+")"; }
+    public int hashCode() { return Float.floatToIntBits(x) ^ Float.floatToIntBits(y) ^ Float.floatToIntBits(z); }
+}
diff --git a/src/edu/berkeley/qfat/geom/Vec.java b/src/edu/berkeley/qfat/geom/Vec.java
new file mode 100644 (file)
index 0000000..c331d39
--- /dev/null
@@ -0,0 +1,18 @@
+package edu.berkeley.qfat.geom;
+
+/** vector in 3-space; immutable */
+public final class Vec {
+    public final float x, y, z;
+    public Vec(double x, double y, double z) { this((float)x, (float)y, (float)z); }
+    public Vec(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
+    public Vec(Point p1, Point p2) { this(p2.x-p1.x, p2.y-p1.y, p2.z-p1.z); }
+    public Vec cross(Vec v) { return new Vec(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); }
+    public Vec plus(Vec v) { return new Vec(x+v.x, y+v.y, z+v.z); }
+    public Vec norm() { return mag()==0 ? this : div(mag()); }
+    public Vec times(Matrix m) { return m.apply(this); }
+    public float mag() { return (float)Math.sqrt(x*x+y*y+z*z); }
+    public float dot(Vec v) { return x*v.x + y*v.y + z*v.z; }
+    public Vec times(float mag) { return new Vec(x*mag, y*mag, z*mag); }
+    public Vec div(float mag) { return new Vec(x/mag, y/mag, z/mag); }
+    public String toString() { return "<"+x+","+y+","+z+">"; }
+}