2a443140630b1129e8746d1914d1b4cf7b6e02ea
[anneal.git] / src / edu / berkeley / qfat / geom / HasBindingGroup.java
1 package edu.berkeley.qfat.geom;
2 import javax.media.opengl.*;
3 import java.util.*;
4 import edu.berkeley.qfat.Mesh;
5
6 public abstract class HasBindingGroup {
7
8     public BindingGroup bindingGroup;
9
10     // know:      self   = bindingGroup[self] * master
11     // know:      other  = other.bindingGroup[other] * other.bindingGroup.master
12     // want:      self   = bindingMatrix * other
13     // therefore: master = bindingGroup[self]^-1 * bindingMatrix * other
14     // therefore:        = bindingGroup[self]^-1 * bindingMatrix * other.bindingGroup[other] * other.bindingGroup.master
15     public void bindTo(Matrix bindingMatrix, HasBindingGroup other) {
16         if (bindingGroup == null) bindingGroup = new BindingGroup(this);
17         if (other.bindingGroup == null) other.bindingGroup = new BindingGroup(other);
18
19         if (other.bindingGroup == this.bindingGroup) {
20             if (getBindingMatrix(other).equals(bindingMatrix))
21                 return;
22             /*
23             if (this instanceof Mesh.E)
24                 throw new Error("rebind attempt: "+this+" and "+other+" with "
25                                 + bindingMatrix
26                                 + "; expected "
27                                 + getBindingMatrix(other));
28             */
29             Matrix vom = other.getBindingMatrix(bindingGroup.getMaster());
30             Matrix v2 = bindingMatrix;
31             Matrix v3 = getBindingMatrix(other);
32             Matrix m = vom.inverse().times(v2.inverse()).times(v3).times(vom);
33             bindingGroup.krank = bindingGroup.krank.times(m);
34             /*
35               System.err.println("WARNING: discarding rebind attempt: "+this+" and "+other+m);
36             */
37             //" with "
38             //+ bindingMatrix
39             //+ "; expected "
40             //+ getBindingMatrix(other));
41             return;
42         }
43
44
45         bindingMatrix =
46             getBindingMatrix().inverse()
47             .times(bindingMatrix)
48             .times(other.getBindingMatrix());
49         other.bindingGroup.merge(bindingGroup, bindingMatrix);
50     }
51
52     public int bindingGroupSize() {
53         if (bindingGroup == null) return 1;
54         return bindingGroup.size();
55     }
56
57
58     public Matrix getBindingMatrix() {
59         if (bindingGroup==null) return Matrix.ONE;
60         return bindingGroup.getMatrix(this);
61     }
62
63     public Matrix getBindingMatrix(HasBindingGroup other) {
64         if (other==this) return Matrix.ONE;
65         return bindingGroup.getMatrix(this, other);
66     }
67
68     public HasBindingGroup getMaster() {
69         if (bindingGroup==null) return this;
70         return bindingGroup.getMaster();
71     }
72
73     public Matrix getConstraint() {
74         if (bindingGroup==null) return Matrix.ONE;
75         Matrix v = getBindingMatrix(getMaster());
76         return v.inverse().times(bindingGroup.krank).times(v);
77     }
78     public void setConstraint(Matrix m) {
79         /*
80         if (bindingGroup==null) bindingGroup = new BindingGroup(this);
81         Matrix v = getBindingMatrix(getMaster());
82         bindingGroup.krank = bindingGroup.krank.times(v.inverse().times(m).times(v));
83         */
84     }
85
86     public void unbind() {
87         if (bindingGroup==null) return;
88         bindingGroup.unbind(this);
89         bindingGroup = null;
90         bindingGroupChanged(bindingGroup);
91     }
92
93     public boolean isBoundTo(HasBindingGroup t) {
94         return t==this || (bindingGroup!=null && bindingGroup.contains(t));
95     }
96
97     public Iterable getBoundPeers() {
98         if (bindingGroup==null) bindingGroup = new BindingGroup(this);
99         return bindingGroup;
100     }
101     public void bindingGroupChanged(BindingGroup newBindingGroup) { }
102 }