X-Git-Url: http://git.megacz.com/?p=anneal.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fqfat%2Fgeom%2FTriangle.java;h=9db806b45bb43f4c8660664df2e6e3fa447976a8;hp=df7c463aeed105a22609325fb08e300c20197d95;hb=20fe91a50615c12bdfdec4a72665ff92a700abd5;hpb=0f9ce20a060db6537a47b549cbf24fd268699ac6 diff --git a/src/edu/berkeley/qfat/geom/Triangle.java b/src/edu/berkeley/qfat/geom/Triangle.java index df7c463..9db806b 100644 --- a/src/edu/berkeley/qfat/geom/Triangle.java +++ b/src/edu/berkeley/qfat/geom/Triangle.java @@ -1,47 +1,153 @@ package edu.berkeley.qfat.geom; import javax.media.opengl.*; +/** + * An oriented triangle, defined by three points in order; + * note that the Point objects returned by p1/p2/p3 may vary over time. + */ public abstract class Triangle implements HasBoundingBox { public abstract Point p1(); public abstract Point p2(); public abstract Point p3(); + /** the face normal vector */ public Vec norm() { return p2().minus(p1()).cross(p3().minus(p1())).norm(); } + + /** the area of the triangle */ public float area() { return (float)Math.abs(0.5*p1().distance(p2()) * new Vec(p1(), p2()).norm().dot(new Vec(p2(), p3()))); } - public void glVertices(GL gl) { - p1().glVertex(gl); - p2().glVertex(gl); - p3().glVertex(gl); + + /** 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); + } } + + /** the triangle's centroid */ public Point centroid() { return new Point((p1().x+p2().x+p3().x)/3, (p1().y+p2().y+p3().y)/3, (p1().z+p2().z+p3().z)/3); } - public float diameter() { - // FIXME: what is this supposed to be? - return Math.max(Math.max(p1().distance(p2()), - p2().distance(p3())), - p3().distance(p1())) / 2; - } + /** ratio of the area of the triangle to that of the square formed from its longest edge */ + /* public float aspect() { float max = Math.max(Math.max(p1().distance(p2()), p2().distance(p3())), p3().distance(p1())) / 2; return 1/(1+area()/(max*max)); } - public float aspect0() { - float max = Math.max(Math.max(p1().distance(p2()), - p2().distance(p3())), - p3().distance(p1())) / 2; - return (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 (r==0) throw new Error(); + float ret = (float)((d*Math.cos(Math.PI/6))/(r*2)); + 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 */ + public boolean intersects(Point p1, Point p2) { + double A0=p1().x, A1=p1().y, A2=p1().z; + double B0=p2().x, B1=p2().y, B2=p2().z; + double C0=p3().x, C1=p3().y, C2=p3().z; + double j0=p1.x, j1=p1.y, j2=p1.z; + double k0=p2.x, k1=p2.y, k2=p2.z; + double J0, J1, J2; + double K0, K1, K2; + double i0, i1, i2; + double a0, a1, a2; + double b0, b1, b2; + double c0, c1, c2; + double in_det; + double R00, R01, R02, R03, + R10, R11, R12, R13, + R20, R21, R22, R23, + R30, R31, R32, R33; + + + /* a = B - A */ + a0 = B0 - A0; + a1 = B1 - A1; + a2 = B2 - A2; + /* b = C - B */ + b0 = C0 - A0; + b1 = C1 - A1; + b2 = C2 - A2; + /* c = a × b */ + c0 = a1 * b2 - a2 * b1; + c1 = a2 * b0 - a0 * b2; + c2 = a0 * b1 - a1 * b0; + + /* M^(-1) = (1/det(M)) * adj(M) */ + in_det = 1 / (c0 * c0 + c1 * c1 + c2 * c2); + R00 = (b1 * c2 - b2 * c1) * in_det; + R01 = (b2 * c0 - b0 * c2) * in_det; + R02 = (b0 * c1 - b1 * c0) * in_det; + R10 = (c1 * a2 - c2 * a1) * in_det; + R11 = (c2 * a0 - c0 * a2) * in_det; + R12 = (c0 * a1 - c1 * a0) * in_det; + R20 = (c0) * in_det; + R21 = (c1) * in_det; + R22 = (c2) * in_det; + + /* O = M^(-1) * A */ + R03 = -(R00 * A0 + R01 * A1 + R02 * A2); + R13 = -(R10 * A0 + R11 * A1 + R12 * A2); + R23 = -(R20 * A0 + R21 * A1 + R22 * A2); + + /* fill in last row of 4x4 matrix */ + R30 = R31 = R32 = 0; + R33 = 1; + + J2 = R20 * j0 + R21 * j1 + R22 * j2 + R23; + K2 = R20 * k0 + R21 * k1 + R22 * k2 + R23; + if (J2 * K2 >= 0) return false; + + J0 = R00 * j0 + R01 * j1 + R02 * j2 + R03; + K0 = R00 * k0 + R01 * k1 + R02 * k2 + R03; + i0 = J0 + J2 * ((K0 - J0) / (J2 - K2)); + if (i0 < 0 || i0 > 1) return false; + + J1 = R10 * j0 + R11 * j1 + R12 * j2 + R13; + K1 = R10 * k0 + R11 * k1 + R12 * k2 + R13; + i1 = J1 + J2 * ((K1 - J1) / (J2 - K2)); + if (i1 < 0 || i1 > 1 || i0 + i1 > 1) return false; + + return true; } public float getMaxX() { return Math.max(p1().x, Math.max(p2().x, p3().x)); }