checkpoint
[anneal.git] / src / edu / berkeley / qfat / geom / Matrix.java
index e52b895..c2419d6 100644 (file)
@@ -80,6 +80,7 @@ public class Matrix {
                           0, 0, 0, 1);
     }
 
+    /** a reflection matrix across the plane passing through the origin with the specified normal */
     public static Matrix reflect(Vec v) {
         Vec reflectionPlaneNormal = v.norm();
         float a = reflectionPlaneNormal.x;
@@ -92,9 +93,8 @@ public class Matrix {
                             0,       0,       0,       1);
     }
 
-    public Vec getTranslationalComponent() {
-        return new Vec(d, h, l);
-    }
+    /** returns the translational component of this matrix */
+    public Vec getTranslationalComponent() { return this.times(Point.ZERO).minus(Point.ZERO); }
 
     public Matrix plus(Matrix x) {
         return new Matrix(a+x.a, b+x.b, c+x.c, d+x.d, e+x.e, f+x.f, g+x.g, h+x.h, i+x.i, j+x.j, k+x.k, l+x.l, m+x.m, n+x.n, o+x.o, p+x.p);
@@ -116,9 +116,7 @@ public class Matrix {
         return ret;
     }
 
-    /** discards bottom row */
     public Point times(Point p) {
-        // discards bottom row
         double x = a*p.x + b*p.y + c*p.z + d;
         double y = e*p.x + f*p.y + g*p.z + h;
         double z = i*p.x + j*p.y + k*p.z + l;
@@ -126,19 +124,8 @@ public class Matrix {
         return new Point(x/q, y/q, z/q);
     }
 
-    /** discards bottom row */
     public Vec times(Vec p) {
-        return new Vec(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 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);
+        return this.times(Matrix.translate(p)).getTranslationalComponent();
     }
 
     /** multiply by another matrix */
@@ -273,25 +260,43 @@ public class Matrix {
         if (!(oo instanceof Matrix)) return false;
         Matrix z = (Matrix)oo;
         return
-            near(a,z.a) && 
-            near(b,z.b) && 
-            near(c,z.c) && 
-            near(d,z.d) && 
-            near(e,z.e) && 
-            near(f,z.f) && 
-            near(g,z.g) && 
-            near(h,z.h) && 
-            near(i,z.i) && 
-            near(j,z.j) && 
-            near(k,z.k) && 
-            near(l,z.l) && 
-            near(m,z.m) && 
-            near(n,z.n) && 
-            near(o,z.o) && 
-            near(p,z.p);
+            (a==z.a) && 
+            (b==z.b) && 
+            (c==z.c) && 
+            (d==z.d) && 
+            (e==z.e) && 
+            (f==z.f) && 
+            (g==z.g) && 
+            (h==z.h) && 
+            (i==z.i) && 
+            (j==z.j) && 
+            (k==z.k) && 
+            (l==z.l) && 
+            (m==z.m) && 
+            (n==z.n) && 
+            (o==z.o) && 
+            (p==z.p);
+    }
+
+    public boolean equalsModuloEpsilon(Matrix z, float epsilon) {
+        return
+            Math.abs(a-z.a)<epsilon && 
+            Math.abs(b-z.b)<epsilon && 
+            Math.abs(c-z.c)<epsilon && 
+            Math.abs(d-z.d)<epsilon && 
+            Math.abs(e-z.e)<epsilon && 
+            Math.abs(f-z.f)<epsilon && 
+            Math.abs(g-z.g)<epsilon && 
+            Math.abs(h-z.h)<epsilon && 
+            Math.abs(i-z.i)<epsilon && 
+            Math.abs(j-z.j)<epsilon && 
+            Math.abs(k-z.k)<epsilon && 
+            Math.abs(l-z.l)<epsilon && 
+            Math.abs(m-z.m)<epsilon && 
+            Math.abs(n-z.n)<epsilon && 
+            Math.abs(o-z.o)<epsilon && 
+            Math.abs(p-z.p)<epsilon;
     }
-    private static final float EPSILON = 0.001f;
-    private static boolean near(float a, float b) { return Math.abs(a-b)<EPSILON; }
 
     public int hashCode() {
         return
@@ -313,6 +318,7 @@ public class Matrix {
             Float.floatToIntBits(p);
     }
 
+    /** retrieves the current objectspace-to-windowspace projection matrix from the GL context */
     public static Matrix getProjectionMatrix(GL gl) {
         int view[] = new int[4];
         double mvmatrix[] = new double[16];
@@ -360,4 +366,23 @@ public class Matrix {
         return z.times(p).times(m);
     }
 
+    /** returns the constraint-conjunction "(forall v)Mv=v" */
+    public AffineConstraint getAffineConstraint(float epsilon) {
+        AffineConstraint c1 = getAffineConstraint(a-1, b,   c,   d  , epsilon);
+        AffineConstraint c2 = getAffineConstraint(e,   f-1, g,   h  , epsilon);
+        AffineConstraint c3 = getAffineConstraint(i,   j,   k-1, l  , epsilon);
+        // FIXME: bottom row constraint?
+        return c1.intersect(c2.intersect(c3, epsilon), epsilon);
+    }
+
+    /** the AffineConstraint representing ax+by+cz+d=0 */
+    private static AffineConstraint getAffineConstraint(float a, float b, float c, float d, float epsilon) {
+        a = Math.abs(a) <= epsilon ? 0 : a;
+        b = Math.abs(b) <= epsilon ? 0 : b;
+        c = Math.abs(c) <= epsilon ? 0 : c;
+        d = Math.abs(d) <= epsilon ? 0 : d;
+        if (a!=0 || b!=0 || c!=0) return new Plane(a, b, c, d);
+        if (d==0) return new AffineConstraint.All();
+        return new AffineConstraint.Nothing();
+    }
 }