1 package edu.berkeley.qfat.bind;
2 import edu.berkeley.qfat.geom.*;
5 * A member of an equivalence class of geometric objects whose
6 * positions are related by affine transformation matrices and are
7 * constrained by an affine constraint.
9 * Every HasBindingGroup (henceforth, HBG) begins life as a member of
10 * a singleton binding group consisting only of itself.
12 * Invoking bindTo() upon a pair of HBG's that are not part of the
13 * same BindingGroup will merge the two BG's. Invoking bindTo() upon
14 * a pair of HBG's that are already part of the same BG will result
15 * in the imposition of an AffineConstraint on the BG.
17 public abstract class HasBindingGroup {
19 BindingGroup bindingGroup;
22 * Merge the BGs of this and other, ensuring that
23 * this==bindingMatrix*other, and treating differences of less
24 * than epsilon as irrelevant for AffineConstraint purposes.
26 public void bindTo(Matrix bindingMatrix, HasBindingGroup other, float epsilon) {
27 // know: self = bindingGroup[self] * master
28 // know: other = other.bindingGroup[other] * other.bindingGroup.master
29 // want: self = bindingMatrix * other
30 // therefore: master = bindingGroup[self]^-1 * bindingMatrix * other
31 // therefore: = bindingGroup[self]^-1 * bindingMatrix * other.bindingGroup[other] * other.bindingGroup.master
32 if (bindingGroup == null) bindingGroup = new BindingGroup(this);
33 if (other.bindingGroup == null) other.bindingGroup = new BindingGroup(other);
35 // this = bg.getMatrix(this) * bg.master
36 // other = obg.getMatrix(other) * obg.master
37 // this = bindingMatrix * other
38 // this = bindingMatrix * obg.getMatrix(other) * obg.master
39 // bg.getMatrix(this) * bg.master = bindingMatrix * obg.getMatrix(other) * obg.master
40 // bg.master = bg.getMatrix(this)^-1 * bindingMatrix * obg.getMatrix(other) * obg.master
41 // bg.master = XXX * obg.master
42 Matrix bm = bindingGroup.getMatrix(this);
43 Matrix obm = other.bindingGroup.getMatrix(other);
48 other.bindingGroup.merge(bindingGroup, bindingMatrix, epsilon);
51 /** number of distinct HBG's in the binding group */
52 public int bindingGroupSize() {
53 if (bindingGroup == null) return 1;
54 return bindingGroup.size();
57 /** returns the AffineConstraint of this BG, translated into this HBG's space */
58 public AffineConstraint getBindingConstraint() {
59 if (bindingGroup==null) return AffineConstraint.ALL;
60 return bindingGroup.getAffineConstraint(this);
63 /** return the matrix M which relates the position p2 of other to the position p1 of this; p1=M*p2 */
64 public Matrix getBindingMatrix(HasBindingGroup other) {
65 if (other==this) return Matrix.ONE;
66 return bindingGroup.getMatrix(this, other);
69 /** remove this HBG from its BG and place it in its own individual BG */
70 public void unbind() {
71 if (bindingGroup==null) return;
72 bindingGroup.unbind(this);
74 bindingGroupChanged();
77 /** true iff this HBG is in the same BG as the argument */
78 public boolean isBoundTo(HasBindingGroup t) {
79 return t==this || (bindingGroup!=null && bindingGroup.contains(t));
82 /** enumerates all members of this HBG's BG, including this */
83 public Iterable getBoundPeers() {
84 if (bindingGroup==null) bindingGroup = new BindingGroup(this);
88 /** invoked after the binding group of this HBG has changed due to bindTo() or unbind() */
89 public void bindingGroupChanged() {
92 public boolean bindingGroupUnconstrained() {
93 if (bindingGroupSize() > 1) return false;
94 if (getBindingConstraint()!=AffineConstraint.ALL) return false;