if (v.mag() < 0.0001) continue;
v = v.times(-1);
v = v.times(0.5f);
- Point p = Point.ORIGIN.plus(v);
+ Point p = Point.ZERO.plus(v);
v = v.times(-1);
//System.out.println(v);
//Matrix m = Matrix.scale(1f, 2.1f, 1f);
tile.transform(m);
for(int i=0; i<transforms.length; i++)
- transforms[i] = transforms[i].preMultiplyTranslationalComponentBy(m);
+ transforms[i] = preMultiplyTranslationalComponentBy(transforms[i], m);
fixupTile();
} });
}
+ private static Matrix preMultiplyTranslationalComponentBy(Matrix mthis, Matrix mm) {
+ Vec v = mm.times(mthis.getTranslationalComponent());
+ return new Matrix(mthis.a, mthis.b, mthis.c, v.x,
+ mthis.e, mthis.f, mthis.g, v.y,
+ mthis.i, mthis.j, mthis.k, v.z,
+ mthis.m, mthis.n, mthis.o, 1);
+ }
+
}
\ No newline at end of file
float minangle = (float)(Math.PI * 0.8);
//nerror += ((ang / Math.PI)*(ang/Math.PI)) * e.length() * 0.05;
- nerror += (1-e.t.quality())*0.0001;
+ //nerror += (1-e.t.quality())*0.0001;
if (ang > minangle) nerror += (ang - minangle);
//System.out.println(((ang / Math.PI)*(ang/Math.PI)) * 0.000001);
// t1 = t1.getMatrix(t2) * t2
// M * t1 = M * t1.getMatrix(t2) * t2
+ /*
if (bindingGroup!=null && this != bindingGroup.getMaster()) {
Matrix m2 = getBindingMatrix(bindingGroup.getMaster());
Vec v2 = m2.times(vv.plus(getPoint())).minus(m2.times(getPoint()));
return ((Vertex)bindingGroup.getMaster()).move(v2, ignoreProblems);
}
+ */
Point op = this.p;
Point pp = vv.plus(getPoint());
edu.berkeley.qfat.geom.BindingGroup<E> newBindingGroup =
(edu.berkeley.qfat.geom.BindingGroup<E>)newBindingGroup_;
if (newBindingGroup==null) return;
- if (this==newBindingGroup.getMaster()) return;
+ //if (this==newBindingGroup.getMaster()) return;
HashSet<E> nbg = new HashSet<E>();
for(E eother : (Iterable<E>)newBindingGroup) nbg.add(eother);
for(E eother : nbg) {
if (e==this) continue;
v1.bindTo(getBindingMatrix(e), e.v1);
v2.bindTo(getBindingMatrix(e), e.v2);
+ /*
e.v1.setConstraint(getConstraint());
e.v2.setConstraint(getConstraint());
+ */
}
}
import javax.media.opengl.*;
import java.util.*;
+/** tracks an equivalence class of geometric objects which are related to each other by transformation matrices */
public class BindingGroup<T extends HasBindingGroup> implements Iterable<T> {
public Matrix krank = Matrix.ONE;
hbg.bindingGroupChanged(this);
}
- public T getMaster() { return master; }
public Matrix getMatrix(T t) { return matrices.get(t); }
public Iterator<T> iterator() { return matrices.keySet().iterator(); }
public HalfSpace(Point p, Vec norm) { super(p, norm); }
- /*
- public Segment clip(Segment s) {
- // FIXME: return null if segment is entirely excluded
- throw new Error();
+ public boolean contains(Point p, float epsilon) {
+ return p.x*norm.x+p.y*norm.y+p.z*norm.z + dvalue <= epsilon;
}
-
- public Point intersect(Segment s) {
- }
-
- public HalfPlane intersect(Plane p) {
- if (norm.minus(hs.norm).mag() < 0.001)
- throw new Error("half-spaces are nearly parallel");
-
- }
- */
-
- public boolean contains(Point p) {
- float checker = p.x*norm.x+p.y*norm.y+p.z*norm.z + dvalue;
- //System.out.println(norm+" "+dvalue+" contains " + p + " => " + checker);
- return checker <= 0.00001;
- }
-
- public boolean contains(HalfSpace hs) {
- // FIXME
- return false;
- }
-
}
if (other.bindingGroup == null) other.bindingGroup = new BindingGroup(other);
if (other.bindingGroup == this.bindingGroup) {
- if (getBindingMatrix(other).equals(bindingMatrix))
+ if (getBindingMatrix(other).equalsModuloEpsilon(bindingMatrix, 0.001f))
return;
- /*
- if (this instanceof Mesh.E)
- throw new Error("rebind attempt: "+this+" and "+other+" with "
- + bindingMatrix
- + "; expected "
- + getBindingMatrix(other));
- */
- setConstraint(bindingMatrix);
- /*
- System.err.println("WARNING: discarding rebind attempt: "+this+" and "+other+m);
- */
- //" with "
- //+ bindingMatrix
- //+ "; expected "
- //+ getBindingMatrix(other));
return;
}
-
bindingMatrix =
getBindingMatrix().inverse()
.times(bindingMatrix)
return bindingGroup.getMatrix(this, other);
}
- public HasBindingGroup getMaster() {
- if (bindingGroup==null) return this;
- return bindingGroup.getMaster();
- }
-
- public Matrix getConstraint() {
- if (bindingGroup==null) return Matrix.ONE;
- Matrix v = getBindingMatrix(getMaster());
- return v.inverse().times(bindingGroup.krank).times(v);
- }
- public void setConstraint(Matrix m) {
- if (bindingGroup==null) bindingGroup = new BindingGroup(this);
- Matrix v = getBindingMatrix(getMaster());
- bindingGroup.krank = bindingGroup.krank.times(v.inverse().times(m).times(v));
- }
-
public void unbind() {
if (bindingGroup==null) return;
bindingGroup.unbind(this);
--- /dev/null
+package edu.berkeley.qfat.geom;
+import javax.media.opengl.*;
+
+/** an infinitely long line in 3-space */
+public class Line {
+
+ // y=mx+c
+ // z=nx+d
+ public final float m, n, c, d;
+
+ /** the line passing through two points */
+ public Line(Point p1, Point p2) {
+ this.m = (p2.y-p1.y)/(p2.x-p1.x);
+ this.n = (p2.z-p1.z)/(p2.x-p1.x);
+ this.c = p1.y - m * p1.x;
+ this.d = p1.z - n * p1.x;
+ }
+
+ public int hashCode() {
+ return
+ Float.floatToIntBits(m) ^
+ Float.floatToIntBits(n) ^
+ Float.floatToIntBits(c) ^
+ Float.floatToIntBits(d);
+ }
+ public boolean equals(Object o) {
+ if (o==null || !(o instanceof Line)) return false;
+ Line line = (Line)o;
+ return line.m==m && line.n==n && line.c==c && line.d==d;
+ }
+
+ public String toString() {
+ return "[line: y="+m+"x+"+c+" z="+n+"x+"+d+"]";
+ }
+
+ public double distance(Point p) { return projection(p).distance(p); }
+
+ /** returns the point on this line which is closest to p */
+ public Point projection(Point p) {
+ /*
+ Point p1 = new Point(0, c, d);
+ Point p2 = new Point(1, m+c, n+d);
+ Vec w = p.minus(p1);
+ return getUnit().times(w.dot(getUnit()));
+ */
+ throw new RuntimeException("test this before using; may not be correct");
+ }
+
+ public Vec getUnit() {
+ Point p1 = new Point(0, c, d);
+ Point p2 = new Point(1, m+c, n+d);
+ return p2.minus(p1).norm();
+ }
+
+}
0, 0, 0, 1);
}
+ /** a reflection matrix across the plane passing through the origin with the specified normal */
public static Matrix reflect(Vec v) {
Vec reflectionPlaneNormal = v.norm();
float a = reflectionPlaneNormal.x;
0, 0, 0, 1);
}
- public Vec getTranslationalComponent() {
- return new Vec(d, h, l);
- }
+ /** returns the translational component of this matrix */
+ public Vec getTranslationalComponent() { return this.times(Point.ZERO).minus(Point.ZERO); }
public Matrix plus(Matrix x) {
return new Matrix(a+x.a, b+x.b, c+x.c, d+x.d, e+x.e, f+x.f, g+x.g, h+x.h, i+x.i, j+x.j, k+x.k, l+x.l, m+x.m, n+x.n, o+x.o, p+x.p);
return ret;
}
- /** discards bottom row */
public Point times(Point p) {
- // discards bottom row
double x = a*p.x + b*p.y + c*p.z + d;
double y = e*p.x + f*p.y + g*p.z + h;
double z = i*p.x + j*p.y + k*p.z + l;
return new Point(x/q, y/q, z/q);
}
- /** discards bottom row */
public Vec times(Vec p) {
- return new Vec(a*p.x + b*p.y + c*p.z + d,
- e*p.x + f*p.y + g*p.z + h,
- i*p.x + j*p.y + k*p.z + l);
- }
-
- public Matrix preMultiplyTranslationalComponentBy(Matrix mm) {
- Vec v = mm.times(getTranslationalComponent());
- return new Matrix(a, b, c, v.x,
- e, f, g, v.y,
- i, j, k, v.z,
- m, n, o, 1);
+ return this.times(Matrix.translate(p)).getTranslationalComponent();
}
/** multiply by another matrix */
if (!(oo instanceof Matrix)) return false;
Matrix z = (Matrix)oo;
return
- near(a,z.a) &&
- near(b,z.b) &&
- near(c,z.c) &&
- near(d,z.d) &&
- near(e,z.e) &&
- near(f,z.f) &&
- near(g,z.g) &&
- near(h,z.h) &&
- near(i,z.i) &&
- near(j,z.j) &&
- near(k,z.k) &&
- near(l,z.l) &&
- near(m,z.m) &&
- near(n,z.n) &&
- near(o,z.o) &&
- near(p,z.p);
+ (a==z.a) &&
+ (b==z.b) &&
+ (c==z.c) &&
+ (d==z.d) &&
+ (e==z.e) &&
+ (f==z.f) &&
+ (g==z.g) &&
+ (h==z.h) &&
+ (i==z.i) &&
+ (j==z.j) &&
+ (k==z.k) &&
+ (l==z.l) &&
+ (m==z.m) &&
+ (n==z.n) &&
+ (o==z.o) &&
+ (p==z.p);
+ }
+
+ public boolean equalsModuloEpsilon(Matrix z, float epsilon) {
+ return
+ Math.abs(a-z.a)<epsilon &&
+ Math.abs(b-z.b)<epsilon &&
+ Math.abs(c-z.c)<epsilon &&
+ Math.abs(d-z.d)<epsilon &&
+ Math.abs(e-z.e)<epsilon &&
+ Math.abs(f-z.f)<epsilon &&
+ Math.abs(g-z.g)<epsilon &&
+ Math.abs(h-z.h)<epsilon &&
+ Math.abs(i-z.i)<epsilon &&
+ Math.abs(j-z.j)<epsilon &&
+ Math.abs(k-z.k)<epsilon &&
+ Math.abs(l-z.l)<epsilon &&
+ Math.abs(m-z.m)<epsilon &&
+ Math.abs(n-z.n)<epsilon &&
+ Math.abs(o-z.o)<epsilon &&
+ Math.abs(p-z.p)<epsilon;
}
- private static final float EPSILON = 0.001f;
- private static boolean near(float a, float b) { return Math.abs(a-b)<EPSILON; }
public int hashCode() {
return
Float.floatToIntBits(p);
}
+ /** retrieves the current objectspace-to-windowspace projection matrix from the GL context */
public static Matrix getProjectionMatrix(GL gl) {
int view[] = new int[4];
double mvmatrix[] = new double[16];
public class Plane {
+ // FIXME: could be given by
+ // ax+by+cz=d
+
public final Vec norm;
public final float dvalue;
Vec v1 = p2.norm.cross(p3.norm).times(-1 * p1.dvalue);
Vec v2 = p3.norm.cross(p1.norm).times(-1 * p2.dvalue);
Vec v3 = p1.norm.cross(p2.norm).times(-1 * p3.dvalue);
- return Point.ORIGIN.plus(v1.plus(v2).plus(v3).times(1/z));
+ return Point.ZERO.plus(v1.plus(v2).plus(v3).times(1/z));
}
}
public Point(double x, double y, double z) { this((float)x, (float)y, (float)z); }
public Point(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
- public static final Point ORIGIN = new Point(0,0,0);
-
public float distance(Point p) { return (float)Math.sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)+(z-p.z)*(z-p.z)); }
public Vec minus(Point p) { return new Vec(x-p.x, y-p.y, z-p.z); }
return rtree.nearest(p, vis);
}
- // FEATURE: compute incrementally?
public Vec diagonal() {
float min_x = Float.MAX_VALUE;
float min_y = Float.MAX_VALUE;
for(int k=0; k<halfSpaces.length; k++) {
if (i==k || j==k) continue;
- if (!halfSpaces[k].contains(p)) { p = null; break; }
+ if (!halfSpaces[k].contains(p, 0.0001f)) { p = null; break; }
}
if (p!=null) {
if (p1==null) p1 = p;
}
Vec cen = new Vec(0,0,0);
for(Segment s : segments)
- cen = cen.plus(s.p1.minus(Point.ORIGIN)).plus(s.p2.minus(Point.ORIGIN));
- Point centroid = Point.ORIGIN.plus(cen.times(1f/(2*segments.size())));
+ cen = cen.plus(s.p1.minus(Point.ZERO)).plus(s.p2.minus(Point.ZERO));
+ Point centroid = Point.ZERO.plus(cen.times(1f/(2*segments.size())));
//centroid = new Point(round(centroid.x), round(centroid.y), round(centroid.z));
if (segments.size() >= 3)
for(Segment s : segments) {
public float getMaxZ() { return Math.max(p1.z, p2.z); }
public float getMinZ() { return Math.min(p1.z, p2.z); }
+ /** the line passing through both endpoints of this segment */
+ public Line getLine() { return new Line(p1, p2); }
+
+ public float length() { return p1.distance(p2); }
+
public double distance(Point p) {
- throw new RuntimeException("not yet implemented");
+ Line line = getLine();
+ Point proj = line.projection(p);
+ if (proj.distance(p1)+proj.distance(p2) > length())
+ return Math.min(p1.distance(p),
+ p2.distance(p));
+ return proj.distance(p);
}
}
/** issue gl.glVertex() for each of the triangle's points */
public void glVertices(GL gl, Matrix m) {
- if (m==null) {
- norm().glNormal(gl);
- p1().glVertex(gl);
- p2().glVertex(gl);
- p3().glVertex(gl);
- } else {
- m.times(norm()).glNormal(gl);
- m.times(p1()).glVertex(gl);
- m.times(p2()).glVertex(gl);
- m.times(p3()).glVertex(gl);
- }
+ (m==null ? norm() : m.times(norm())).glNormal(gl);
+ (m==null ? p1() : m.times(p1())).glVertex(gl);
+ (m==null ? p2() : m.times(p2())).glVertex(gl);
+ (m==null ? p3() : m.times(p3())).glVertex(gl);
}
/** the triangle's centroid */
return 1/(1+area()/(max*max));
}
*/
-
+ /*
public float circumcircleRadius() {
double a = p1().distance(p2());
double b = p2().distance(p3());
double c = p3().distance(p1());
return (float)((a*b*c)/Math.sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)));
}
-
+ */
+ /*
public float shortestEdgeLength() {
float a = p1().distance(p2());
float b = p2().distance(p3());
float c = p3().distance(p1());
return Math.min(a, Math.min(b,c));
}
-
+ */
/** a number ranging from 0..1 with 0 being lower quality */
+ /*
public float quality() {
float d = shortestEdgeLength();
float r = circumcircleRadius();
if (ret < 0 || ret > 1) throw new Error("ret="+ret);
return ret;
}
+ */
// FIXME: I stole this off the net, and I need to credit whoever wrote it
/** decide if the segment from p1-p2 intersects this triangle */