checkpoint
authoradam <adam@megacz.com>
Sun, 6 Jul 2008 23:11:17 +0000 (16:11 -0700)
committeradam <adam@megacz.com>
Sun, 6 Jul 2008 23:11:17 +0000 (16:11 -0700)
darcs-hash:20080706231117-5007d-de586d390c28106ebfa766feead15a7914f83723.gz

13 files changed:
src/edu/berkeley/qfat/Main.java
src/edu/berkeley/qfat/Mesh.java
src/edu/berkeley/qfat/geom/BindingGroup.java
src/edu/berkeley/qfat/geom/HalfSpace.java
src/edu/berkeley/qfat/geom/HasBindingGroup.java
src/edu/berkeley/qfat/geom/Line.java [new file with mode: 0644]
src/edu/berkeley/qfat/geom/Matrix.java
src/edu/berkeley/qfat/geom/Plane.java
src/edu/berkeley/qfat/geom/Point.java
src/edu/berkeley/qfat/geom/PointSet.java
src/edu/berkeley/qfat/geom/Polygon.java
src/edu/berkeley/qfat/geom/Segment.java
src/edu/berkeley/qfat/geom/Triangle.java

index 8683a75..ac40acc 100644 (file)
@@ -97,7 +97,7 @@ public class Main extends InteractiveMeshViewer {
                 if (v.mag() < 0.0001) continue;
                 v = v.times(-1);
                 v = v.times(0.5f);
-                Point p = Point.ORIGIN.plus(v);
+                Point p = Point.ZERO.plus(v);
                 v = v.times(-1);
                 
                 //System.out.println(v);
@@ -784,7 +784,7 @@ public class Main extends InteractiveMeshViewer {
                 //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);
+                    transforms[i] = preMultiplyTranslationalComponentBy(transforms[i], m);
                 fixupTile();
 
             } });
@@ -1003,4 +1003,12 @@ public class Main extends InteractiveMeshViewer {
 
     }
 
+    private static Matrix preMultiplyTranslationalComponentBy(Matrix mthis, Matrix mm) {
+        Vec v = mm.times(mthis.getTranslationalComponent());
+        return new Matrix(mthis.a, mthis.b, mthis.c, v.x,
+                          mthis.e, mthis.f, mthis.g, v.y,
+                          mthis.i, mthis.j, mthis.k, v.z,
+                          mthis.m, mthis.n, mthis.o, 1);
+    }
+
 }
\ No newline at end of file
index f5ce535..43927d4 100644 (file)
@@ -364,7 +364,7 @@ public class Mesh implements Iterable<Mesh.T> {
                 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;
+                //nerror += (1-e.t.quality())*0.0001;
                 if (ang > minangle) nerror += (ang - minangle);
 
                 //System.out.println(((ang / Math.PI)*(ang/Math.PI)) * 0.000001);
@@ -399,11 +399,13 @@ public class Mesh implements Iterable<Mesh.T> {
             //     t1 =     t1.getMatrix(t2) * t2
             // M * t1 = M * t1.getMatrix(t2) * t2
 
+            /*
             if (bindingGroup!=null && this != bindingGroup.getMaster()) {
                 Matrix m2 = getBindingMatrix(bindingGroup.getMaster());
                 Vec v2 = m2.times(vv.plus(getPoint())).minus(m2.times(getPoint()));
                 return ((Vertex)bindingGroup.getMaster()).move(v2, ignoreProblems);
             }
+            */
 
             Point op = this.p;
             Point pp = vv.plus(getPoint());
@@ -621,7 +623,7 @@ public class Mesh implements Iterable<Mesh.T> {
             edu.berkeley.qfat.geom.BindingGroup<E> newBindingGroup =
                 (edu.berkeley.qfat.geom.BindingGroup<E>)newBindingGroup_;
             if (newBindingGroup==null) return;
-            if (this==newBindingGroup.getMaster()) return;
+            //if (this==newBindingGroup.getMaster()) return;
             HashSet<E> nbg = new HashSet<E>();
             for(E eother : (Iterable<E>)newBindingGroup) nbg.add(eother);
             for(E eother : nbg) {
@@ -697,8 +699,10 @@ public class Mesh implements Iterable<Mesh.T> {
                 if (e==this) continue;
                 v1.bindTo(getBindingMatrix(e), e.v1);
                 v2.bindTo(getBindingMatrix(e), e.v2);
+                /*
                 e.v1.setConstraint(getConstraint());
                 e.v2.setConstraint(getConstraint());
+                */
             }
         }
 
index 0c3049f..4c2d114 100644 (file)
@@ -2,6 +2,7 @@ package edu.berkeley.qfat.geom;
 import javax.media.opengl.*;
 import java.util.*;
 
+/** tracks an equivalence class of geometric objects which are related to each other by transformation matrices */
 public class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
 
     public Matrix krank = Matrix.ONE;
@@ -36,7 +37,6 @@ public class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
             hbg.bindingGroupChanged(this);
     }
 
-    public T getMaster() { return master; }
     public Matrix getMatrix(T t) { return matrices.get(t); }
 
     public Iterator<T> iterator() { return matrices.keySet().iterator(); }
index ebbd796..a48a22c 100644 (file)
@@ -5,32 +5,8 @@ public final class HalfSpace extends Plane {
 
     public HalfSpace(Point p, Vec norm) { super(p, norm); }
 
-    /*
-    public Segment clip(Segment s) {
-        // FIXME: return null if segment is entirely excluded
-        throw new Error();
+    public boolean contains(Point p, float epsilon) {
+        return p.x*norm.x+p.y*norm.y+p.z*norm.z + dvalue <= epsilon;
     }
 
-
-    public Point intersect(Segment s) {
-    }
-
-    public HalfPlane intersect(Plane p) {
-        if (norm.minus(hs.norm).mag() < 0.001)
-            throw new Error("half-spaces are nearly parallel");
-        
-    }
-    */
-
-    public boolean contains(Point p) {
-        float checker = p.x*norm.x+p.y*norm.y+p.z*norm.z + dvalue;
-        //System.out.println(norm+" "+dvalue+" contains " + p + " => " + checker);
-        return checker <= 0.00001;
-    }
-
-    public boolean contains(HalfSpace hs) {
-        // FIXME
-        return false;
-    }
-    
 }
index 65d581f..ecc4f1c 100644 (file)
@@ -17,27 +17,11 @@ public abstract class HasBindingGroup {
         if (other.bindingGroup == null) other.bindingGroup = new BindingGroup(other);
 
         if (other.bindingGroup == this.bindingGroup) {
-            if (getBindingMatrix(other).equals(bindingMatrix))
+            if (getBindingMatrix(other).equalsModuloEpsilon(bindingMatrix, 0.001f))
                 return;
-            /*
-            if (this instanceof Mesh.E)
-                throw new Error("rebind attempt: "+this+" and "+other+" with "
-                                + bindingMatrix
-                                + "; expected "
-                                + getBindingMatrix(other));
-            */
-            setConstraint(bindingMatrix);
-            /*
-              System.err.println("WARNING: discarding rebind attempt: "+this+" and "+other+m);
-            */
-            //" with "
-            //+ bindingMatrix
-            //+ "; expected "
-            //+ getBindingMatrix(other));
             return;
         }
 
-
         bindingMatrix =
             getBindingMatrix().inverse()
             .times(bindingMatrix)
@@ -61,22 +45,6 @@ public abstract class HasBindingGroup {
         return bindingGroup.getMatrix(this, other);
     }
 
-    public HasBindingGroup getMaster() {
-        if (bindingGroup==null) return this;
-        return bindingGroup.getMaster();
-    }
-
-    public Matrix getConstraint() {
-        if (bindingGroup==null) return Matrix.ONE;
-        Matrix v = getBindingMatrix(getMaster());
-        return v.inverse().times(bindingGroup.krank).times(v);
-    }
-    public void setConstraint(Matrix m) {
-        if (bindingGroup==null) bindingGroup = new BindingGroup(this);
-        Matrix v = getBindingMatrix(getMaster());
-        bindingGroup.krank = bindingGroup.krank.times(v.inverse().times(m).times(v));
-    }
-
     public void unbind() {
         if (bindingGroup==null) return;
         bindingGroup.unbind(this);
diff --git a/src/edu/berkeley/qfat/geom/Line.java b/src/edu/berkeley/qfat/geom/Line.java
new file mode 100644 (file)
index 0000000..7fb9b86
--- /dev/null
@@ -0,0 +1,55 @@
+package edu.berkeley.qfat.geom;
+import javax.media.opengl.*;
+
+/** an infinitely long line in 3-space */
+public class Line {
+
+    // y=mx+c
+    // z=nx+d
+    public final float m, n, c, d;
+
+    /** the line passing through two points */
+    public Line(Point p1, Point p2) {
+        this.m = (p2.y-p1.y)/(p2.x-p1.x);
+        this.n = (p2.z-p1.z)/(p2.x-p1.x);
+        this.c = p1.y - m * p1.x;
+        this.d = p1.z - n * p1.x;
+    }
+
+    public int hashCode() {
+        return
+            Float.floatToIntBits(m) ^
+            Float.floatToIntBits(n) ^
+            Float.floatToIntBits(c) ^
+            Float.floatToIntBits(d);
+    }
+    public boolean equals(Object o) {
+        if (o==null || !(o instanceof Line)) return false;
+        Line line = (Line)o;
+        return line.m==m && line.n==n && line.c==c && line.d==d;
+    }
+
+    public String toString() {
+        return "[line: y="+m+"x+"+c+" z="+n+"x+"+d+"]";
+    }
+
+    public double distance(Point p) { return projection(p).distance(p); }
+
+    /** returns the point on this line which is closest to p */
+    public Point projection(Point p) {
+        /*
+        Point p1 = new Point(0, c,   d);
+        Point p2 = new Point(1, m+c, n+d);
+        Vec w = p.minus(p1);
+        return getUnit().times(w.dot(getUnit()));
+        */
+        throw new RuntimeException("test this before using; may not be correct");
+    }
+
+    public Vec getUnit() {
+        Point p1 = new Point(0, c,   d);
+        Point p2 = new Point(1, m+c, n+d);
+        return p2.minus(p1).norm();
+    }
+
+}
index e52b895..dda8285 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];
index 419bb93..1789e55 100644 (file)
@@ -3,6 +3,9 @@ import javax.media.opengl.*;
 
 public class Plane {
 
+    // FIXME: could be given by
+    // ax+by+cz=d
+
     public final Vec norm;
     public final float dvalue;
 
@@ -18,7 +21,7 @@ public class Plane {
         Vec v1 = p2.norm.cross(p3.norm).times(-1 * p1.dvalue);
         Vec v2 = p3.norm.cross(p1.norm).times(-1 * p2.dvalue);
         Vec v3 = p1.norm.cross(p2.norm).times(-1 * p3.dvalue);
-        return Point.ORIGIN.plus(v1.plus(v2).plus(v3).times(1/z));
+        return Point.ZERO.plus(v1.plus(v2).plus(v3).times(1/z));
     }
 
 }
index 20048e4..cf44573 100644 (file)
@@ -12,8 +12,6 @@ public final class Point extends HasPoint implements HasBoundingBox {
     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 static final Point ORIGIN = new Point(0,0,0);
-
     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 Vec minus(Point p) { return new Vec(x-p.x, y-p.y, z-p.z); }
index b75038c..11e48a2 100644 (file)
@@ -42,7 +42,6 @@ public class PointSet<V extends HasPoint> implements Iterable<V> {
         return rtree.nearest(p, vis);
     }
 
-    // FEATURE: compute incrementally?
     public Vec diagonal() {
         float min_x = Float.MAX_VALUE;
         float min_y = Float.MAX_VALUE;
index ff75939..2afa144 100644 (file)
@@ -45,7 +45,7 @@ public final class Polygon {
 
                 for(int k=0; k<halfSpaces.length; k++) {
                     if (i==k || j==k) continue;
-                    if (!halfSpaces[k].contains(p)) { p = null; break; }
+                    if (!halfSpaces[k].contains(p, 0.0001f)) { p = null; break; }
                 }
                 if (p!=null) {
                     if (p1==null) p1 = p;
@@ -60,8 +60,8 @@ public final class Polygon {
         }
         Vec cen = new Vec(0,0,0);
         for(Segment s : segments)
-            cen = cen.plus(s.p1.minus(Point.ORIGIN)).plus(s.p2.minus(Point.ORIGIN));
-        Point centroid = Point.ORIGIN.plus(cen.times(1f/(2*segments.size())));
+            cen = cen.plus(s.p1.minus(Point.ZERO)).plus(s.p2.minus(Point.ZERO));
+        Point centroid = Point.ZERO.plus(cen.times(1f/(2*segments.size())));
         //centroid = new Point(round(centroid.x), round(centroid.y), round(centroid.z));
         if (segments.size() >= 3)
         for(Segment s : segments) {
index 5f46051..fa303d1 100644 (file)
@@ -25,8 +25,18 @@ public class Segment implements HasBoundingBox {
     public float getMaxZ() { return Math.max(p1.z, p2.z); }
     public float getMinZ() { return Math.min(p1.z, p2.z); }
 
+    /** the line passing through both endpoints of this segment */
+    public Line getLine() { return new Line(p1, p2); }
+
+    public float length() { return p1.distance(p2); }
+
     public double distance(Point p) {
-        throw new RuntimeException("not yet implemented");
+        Line line = getLine();
+        Point proj = line.projection(p);
+        if (proj.distance(p1)+proj.distance(p2) > length())
+            return Math.min(p1.distance(p),
+                            p2.distance(p));
+        return proj.distance(p);
     }
 
 }
index 9db806b..ddeae34 100644 (file)
@@ -24,17 +24,10 @@ public abstract class Triangle implements HasBoundingBox {
 
     /** issue gl.glVertex() for each of the triangle's points */
     public void glVertices(GL gl, Matrix m) {
-        if (m==null) {
-            norm().glNormal(gl);
-            p1().glVertex(gl);
-            p2().glVertex(gl);
-            p3().glVertex(gl);
-        } else {
-            m.times(norm()).glNormal(gl);
-            m.times(p1()).glVertex(gl);
-            m.times(p2()).glVertex(gl);
-            m.times(p3()).glVertex(gl);
-        }
+        (m==null ? norm() : m.times(norm())).glNormal(gl);
+        (m==null ? p1()   : m.times(p1())).glVertex(gl);
+        (m==null ? p2()   : m.times(p2())).glVertex(gl);
+        (m==null ? p3()   : m.times(p3())).glVertex(gl);
     }
 
     /** the triangle's centroid */
@@ -53,22 +46,24 @@ public abstract class Triangle implements HasBoundingBox {
         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();
@@ -77,6 +72,7 @@ public abstract class Triangle implements HasBoundingBox {
         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 */