package edu.berkeley.qfat.bind;
import edu.berkeley.qfat.geom.*;
-import javax.media.opengl.*;
-import java.util.*;
-import edu.berkeley.qfat.Mesh;
+/**
+ * A member of an equivalence class of geometric objects whose
+ * positions are related by affine transformation matrices and are
+ * constrained by an affine constraint.
+ *
+ * Every HasBindingGroup (henceforth, HBG) begins life as a member of
+ * a singleton binding group consisting only of itself.
+ *
+ * Invoking bindTo() upon a pair of HBG's that are not part of the
+ * same BindingGroup will merge the two BG's. Invoking bindTo() upon
+ * a pair of HBG's that are already part of the same BG will result
+ * in the imposition of an AffineConstraint on the BG.
+ */
public abstract class HasBindingGroup {
- public BindingGroup bindingGroup;
+ BindingGroup bindingGroup;
- // know: self = bindingGroup[self] * master
- // know: other = other.bindingGroup[other] * other.bindingGroup.master
- // want: self = bindingMatrix * other
- // therefore: master = bindingGroup[self]^-1 * bindingMatrix * other
- // therefore: = bindingGroup[self]^-1 * bindingMatrix * other.bindingGroup[other] * other.bindingGroup.master
- public void bindTo(Matrix bindingMatrix, HasBindingGroup other) {
+ /**
+ * Merge the BGs of this and other, ensuring that
+ * this==bindingMatrix*other, and treating differences of less
+ * than epsilon as irrelevant for AffineConstraint purposes.
+ */
+ public void bindTo(Matrix bindingMatrix, HasBindingGroup other, float epsilon) {
+ // know: self = bindingGroup[self] * master
+ // know: other = other.bindingGroup[other] * other.bindingGroup.master
+ // want: self = bindingMatrix * other
+ // therefore: master = bindingGroup[self]^-1 * bindingMatrix * other
+ // therefore: = bindingGroup[self]^-1 * bindingMatrix * other.bindingGroup[other] * other.bindingGroup.master
if (bindingGroup == null) bindingGroup = new BindingGroup(this);
if (other.bindingGroup == null) other.bindingGroup = new BindingGroup(other);
+ Matrix bm = bindingGroup.getMatrix(this);
+ Matrix obm = other.bindingGroup.getMatrix(other);
bindingMatrix =
- getBindingMatrix().inverse()
+ bm.inverse()
.times(bindingMatrix)
- .times(other.getBindingMatrix());
- other.bindingGroup.merge(bindingGroup, bindingMatrix);
+ .times(obm);
+ other.bindingGroup.merge(bindingGroup, bindingMatrix, epsilon);
}
+ /** number of distinct HBG's in the binding group */
public int bindingGroupSize() {
if (bindingGroup == null) return 1;
return bindingGroup.size();
}
+ /** returns the AffineConstraint of this BG, translated into this HBG's space */
public AffineConstraint getBindingConstraint() {
if (bindingGroup==null) return new AffineConstraint.All();
- return bindingGroup.getConstraint(this);
- }
-
- public Matrix getBindingMatrix() {
- if (bindingGroup==null) return Matrix.ONE;
- return bindingGroup.getMatrix(this);
+ return bindingGroup.getAffineConstraint(this);
}
+ /** return the matrix M which relates the position p2 of other to the position p1 of this; p1=M*p2 */
public Matrix getBindingMatrix(HasBindingGroup other) {
if (other==this) return Matrix.ONE;
return bindingGroup.getMatrix(this, other);
}
+ /** remove this HBG from its BG and place it in its own individual BG */
public void unbind() {
if (bindingGroup==null) return;
bindingGroup.unbind(this);
bindingGroup = null;
- bindingGroupChanged(bindingGroup);
+ bindingGroupChanged();
}
+ /** true iff this HBG is in the same BG as the argument */
public boolean isBoundTo(HasBindingGroup t) {
return t==this || (bindingGroup!=null && bindingGroup.contains(t));
}
+ /** enumerates all members of this HBG's BG, including this */
public Iterable getBoundPeers() {
if (bindingGroup==null) bindingGroup = new BindingGroup(this);
return bindingGroup;
}
- public void bindingGroupChanged(BindingGroup newBindingGroup) { }
+
+ /** invoked after the binding group of this HBG has changed due to bindTo() or unbind() */
+ public void bindingGroupChanged() {
+ }
}