add items to TODO list
[anneal.git] / src / edu / berkeley / qfat / bind / BindingGroup.java
index 0882fa5..6b06b47 100644 (file)
@@ -1,64 +1,82 @@
 package edu.berkeley.qfat.bind;
 import 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> {
+/**
+ *  An equivalence class of geometric objects whose positions are
+ *  related by affine transformation matrices and are constrained by
+ *  an affine constraint.
+ */
+class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
 
+    /** the arbitrarily-chosen master of the binding group */
     private T                  master     = null;
-    private AffineConstraint   constraint = new AffineConstraint.All();
+
+    /** the affine constraint, in master coordinates, of this binding group */
+    private AffineConstraint   constraint = AffineConstraint.ALL;
+
+    /**
+     *  For each member of the binding group, the matrix which must be
+     *  multiplied by the master to get the member's position
+     */
     private HashMap<T,Matrix>  matrices   = new HashMap<T,Matrix>();
 
-    public BindingGroup(T master) {
+    BindingGroup(T master) {
         this.master = master;
         matrices.put(master, Matrix.ONE);
     }
 
-    public int size() { return matrices.size(); }
+    /** the size of this binding group */
+    int size() { return matrices.size(); }
 
-    public void merge(BindingGroup<T> bg, Matrix m) {
+    /** merge another binding group into this one */
+    void merge(BindingGroup<T> bg, Matrix m, float epsilon) {
         if (bg==this) {
-            if (m.equalsModuloEpsilon(Matrix.ONE, 0.001f)) return;
-            constraint = constraint.intersect(m.getAffineConstraint(0.001f), 0.001f);
+            if (m.equalsModuloEpsilon(Matrix.ONE, epsilon)) return;
+            /*
+            if (master instanceof edu.berkeley.qfat.Mesh.Vertex)
+                System.err.println(m.times(m));
+            */
+            // FIXME: what if points do not fall on the merged constraint-line?
+            constraint = constraint.intersect(m.getAffineConstraint(epsilon), epsilon);
             return;
         }
 
-        for(HasBindingGroup hbg : bg.matrices.keySet()) {
-            matrices.put((T)hbg, bg.matrices.get(hbg).times(m));
+        // bg.master = m * master
+        // hbg       = bg.getMatrix(hbg) * bg.master
+        // hbg       = bg.getMatrix(hbg) * m * master
+        for(HasBindingGroup hbg : bg) {
+            matrices.put((T)hbg, bg.getMatrix((T)hbg).times(m));
             hbg.bindingGroup = this;
         }
 
         // FIXME: what if points do not fall on the merged constraint-line?
         AffineConstraint ac = bg.constraint.multiply(getMatrix(master, bg.master));
-        constraint = constraint.intersect(ac, 0.001f);
+        constraint = constraint.intersect(ac, epsilon);
 
-        HashSet<HasBindingGroup> stuff = new HashSet<HasBindingGroup>();
-        for(HasBindingGroup hbg : bg.matrices.keySet())
-            stuff.add(hbg);
-        bg.matrices.clear();
         bg.master = null;
-        for(HasBindingGroup hbg : stuff)
-            hbg.bindingGroupChanged(this);
+        for(HasBindingGroup hbg : bg) hbg.bindingGroupChanged();
+        bg.matrices.clear();
+        bg.matrices = null;
     }
 
-    public Matrix getMatrix(T t) { return matrices.get(t); }
+    Matrix getMatrix(T t) { return matrices.get(t); }
 
     public Iterator<T> iterator() { return matrices.keySet().iterator(); }
 
     /** t1 = getMatrix(t1, t2) * t2 */
-    public Matrix getMatrix(T t1, T t2) {
+    Matrix getMatrix(T t1, T t2) {
         //                    t1 = getMatrix(t1) * master
         // getMatrix(t2)^-1 * t2 =                 master
         //                    t1 = getMatrix(t1) * getMatrix(t2)^-1 * t2
         return getMatrix(t1).times(getMatrix(t2).inverse());
     }
 
-    public AffineConstraint getConstraint(T t) {
+    AffineConstraint getAffineConstraint(T t) {
         return constraint.multiply(matrices.get(t));
     }
 
-    public void unbind(T trem) {
+    void unbind(T trem) {
         if (trem != master) {
             matrices.remove(trem);
             return;
@@ -71,7 +89,11 @@ public class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
         Iterator<T> it = iterator();
         T newmaster = it.next();
         if (newmaster==trem) newmaster = it.next();
-        if (newmaster==trem) throw new Error();
+        if (newmaster==trem) throw new Error("impossible");
+
+        // FIXME: is this correct?
+        constraint = constraint.multiply(getMatrix(newmaster, master));
+
         HashMap<T,Matrix> newmatrices = new HashMap<T,Matrix>();
         for(T t : matrices.keySet()) {
             if (t==trem) continue;
@@ -81,7 +103,7 @@ public class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
         matrices = newmatrices;
     }
 
-    public boolean contains(HasBindingGroup t) {
+    boolean contains(HasBindingGroup t) {
         return matrices.get((T)t) != null;
     }
 }