checkpoint
[anneal.git] / src / edu / berkeley / qfat / geom / BindingGroup.java
1 package edu.berkeley.qfat.geom;
2 import javax.media.opengl.*;
3 import java.util.*;
4
5 /** tracks an equivalence class of geometric objects which are related to each other by transformation matrices */
6 public class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
7
8     private T                  master     = null;
9     private AffineConstraint   constraint = new AffineConstraint.All();
10     private HashMap<T,Matrix>  matrices   = new HashMap<T,Matrix>();
11
12     public BindingGroup(T master) {
13         this.master = master;
14         matrices.put(master, Matrix.ONE);
15     }
16
17     public int size() { return matrices.size(); }
18
19     public void merge(BindingGroup<T> bg, Matrix m) {
20         if (bg==this) {
21             if (m.equalsModuloEpsilon(Matrix.ONE, 0.001f)) return;
22             constraint = constraint.intersect(m.getAffineConstraint(0.001f), 0.001f);
23             return;
24         }
25
26         for(HasBindingGroup hbg : bg.matrices.keySet()) {
27             matrices.put((T)hbg, bg.matrices.get(hbg).times(m));
28             hbg.bindingGroup = this;
29         }
30
31         // FIXME: what if points do not fall on the merged constraint-line?
32         AffineConstraint ac = bg.constraint.multiply(getMatrix(master, bg.master));
33         constraint = constraint.intersect(ac, 0.001f);
34
35         HashSet<HasBindingGroup> stuff = new HashSet<HasBindingGroup>();
36         for(HasBindingGroup hbg : bg.matrices.keySet())
37             stuff.add(hbg);
38         bg.matrices.clear();
39         bg.master = null;
40         for(HasBindingGroup hbg : stuff)
41             hbg.bindingGroupChanged(this);
42     }
43
44     public Matrix getMatrix(T t) { return matrices.get(t); }
45
46     public Iterator<T> iterator() { return matrices.keySet().iterator(); }
47
48     /** t1 = getMatrix(t1, t2) * t2 */
49     public Matrix getMatrix(T t1, T t2) {
50         //                    t1 = getMatrix(t1) * master
51         // getMatrix(t2)^-1 * t2 =                 master
52         //                    t1 = getMatrix(t1) * getMatrix(t2)^-1 * t2
53         return getMatrix(t1).times(getMatrix(t2).inverse());
54     }
55
56     public AffineConstraint getConstraint(T t) {
57         return constraint.multiply(matrices.get(t));
58     }
59
60     public void unbind(T trem) {
61         if (trem != master) {
62             matrices.remove(trem);
63             return;
64         }
65         if (matrices.size()==1) {
66             master = null;
67             matrices.remove(trem);
68             return;
69         }
70         Iterator<T> it = iterator();
71         T newmaster = it.next();
72         if (newmaster==trem) newmaster = it.next();
73         if (newmaster==trem) throw new Error();
74         HashMap<T,Matrix> newmatrices = new HashMap<T,Matrix>();
75         for(T t : matrices.keySet()) {
76             if (t==trem) continue;
77             newmatrices.put(t, getMatrix(t, newmaster));
78         }
79         master = newmaster;
80         matrices = newmatrices;
81     }
82
83     public boolean contains(HasBindingGroup t) {
84         return matrices.get((T)t) != null;
85     }
86 }