1 package edu.berkeley.qfat.bind;
2 import edu.berkeley.qfat.geom.*;
3 import javax.media.opengl.*;
7 * An equivalence class of geometric objects whose positions are
8 * related by affine transformation matrices and are constrained by
9 * an affine constraint.
11 class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
13 /** the arbitrarily-chosen master of the binding group */
14 private T master = null;
16 /** the affine constraint, in master coordinates, of this binding group */
17 private AffineConstraint constraint = AffineConstraint.ALL;
20 * For each member of the binding group, the matrix which must be
21 * multiplied by the master to get the member's position
23 private HashMap<T,Matrix> matrices = new HashMap<T,Matrix>();
25 public BindingGroup(T master) {
27 matrices.put(master, Matrix.ONE);
30 /** the size of this binding group */
31 int size() { return matrices.size(); }
33 /** merge another binding group into this one */
34 void merge(BindingGroup<T> bg, Matrix m, float epsilon) {
36 if (m.equalsModuloEpsilon(Matrix.ONE, epsilon)) return;
37 // FIXME: what if points do not fall on the merged constraint-line?
38 constraint = constraint.intersect(m.getAffineConstraint(epsilon), epsilon);
42 for(HasBindingGroup hbg : bg) {
43 matrices.put((T)hbg, bg.getMatrix((T)hbg).times(m));
44 hbg.bindingGroup = this;
47 // FIXME: what if points do not fall on the merged constraint-line?
48 AffineConstraint ac = bg.constraint.multiply(getMatrix(master, bg.master));
49 constraint = constraint.intersect(ac, epsilon);
52 for(HasBindingGroup hbg : bg) hbg.bindingGroupChanged();
57 public Matrix getMatrix(T t) { return matrices.get(t); }
59 public Iterator<T> iterator() { return matrices.keySet().iterator(); }
61 /** t1 = getMatrix(t1, t2) * t2 */
62 public Matrix getMatrix(T t1, T t2) {
63 // t1 = getMatrix(t1) * master
64 // getMatrix(t2)^-1 * t2 = master
65 // t1 = getMatrix(t1) * getMatrix(t2)^-1 * t2
66 return getMatrix(t1).times(getMatrix(t2).inverse());
69 public AffineConstraint getAffineConstraint(T t) {
70 return constraint.multiply(matrices.get(t));
75 matrices.remove(trem);
78 if (matrices.size()==1) {
80 matrices.remove(trem);
83 Iterator<T> it = iterator();
84 T newmaster = it.next();
85 if (newmaster==trem) newmaster = it.next();
86 if (newmaster==trem) throw new Error("impossible");
88 // FIXME: is this correct?
89 constraint = constraint.multiply(getMatrix(newmaster, master));
91 HashMap<T,Matrix> newmatrices = new HashMap<T,Matrix>();
92 for(T t : matrices.keySet()) {
93 if (t==trem) continue;
94 newmatrices.put(t, getMatrix(t, newmaster));
97 matrices = newmatrices;
100 public boolean contains(HasBindingGroup t) {
101 return matrices.get((T)t) != null;