checkpoint
[anneal.git] / src / edu / berkeley / qfat / geom / Triangle.java
1 package edu.berkeley.qfat.geom;
2 import javax.media.opengl.*;
3
4 /**
5  *  An oriented triangle, defined by three points in clockwise order;
6  *  note that the Point objects returned by p1/p2/p3 may vary over time.
7  */
8 public abstract class Triangle implements HasBoundingBox {
9     public abstract Point p1();
10     public abstract Point p2();
11     public abstract Point p3();
12
13     /** the face normal vector */
14     public Vec norm() {
15         return p2().minus(p1()).cross(p3().minus(p1())).norm();
16     }
17
18     /** the area of the triangle */
19     public float area() {
20         return
21             (float)Math.abs(0.5*p1().distance(p2())
22                             * new Vec(p1(), p2()).norm().dot(new Vec(p2(), p3())));
23     }
24
25     /** issue gl.glVertex() for each of the triangle's points */
26     public void glVertices(GL gl) {
27         norm().glNormal(gl);
28         p1().glVertex(gl);
29         p2().glVertex(gl);
30         p3().glVertex(gl);
31     }
32     public void glVertices(GL gl, Matrix m) {
33         m.times(norm()).glNormal(gl);
34         m.times(p1()).glVertex(gl);
35         m.times(p2()).glVertex(gl);
36         m.times(p3()).glVertex(gl);
37     }
38
39     /** the triangle's centroid */
40     public Point centroid() {
41         return new Point((p1().x+p2().x+p3().x)/3,
42                          (p1().y+p2().y+p3().y)/3, 
43                          (p1().z+p2().z+p3().z)/3);
44     }
45
46     /** ratio of the area of the triangle to that of the square formed from its longest edge */
47     public float aspect() {
48         float max = Math.max(Math.max(p1().distance(p2()),
49                                       p2().distance(p3())),
50                              p3().distance(p1())) / 2;
51         return 1/(1+area()/(max*max));
52     }
53
54     /** decide if the segment from p1-p2 intersects this triangle */
55     public boolean intersects(Point p1, Point p2) {
56         double A0=p1().x, A1=p1().y, A2=p1().z;
57         double B0=p2().x, B1=p2().y, B2=p2().z;
58         double C0=p3().x, C1=p3().y, C2=p3().z;
59         double j0=p1.x, j1=p1.y, j2=p1.z;
60         double k0=p2.x, k1=p2.y, k2=p2.z;
61         double J0, J1, J2;
62         double K0, K1, K2;
63         double i0, i1, i2;
64         double a0, a1, a2;
65         double b0, b1, b2;
66         double c0, c1, c2;
67         double in_det;
68         double R00, R01, R02, R03,
69             R10, R11, R12, R13,
70             R20, R21, R22, R23,
71             R30, R31, R32, R33;
72
73
74         /* a = B - A */
75         a0 = B0 - A0; 
76         a1 = B1 - A1; 
77         a2 = B2 - A2;
78         /* b = C - B */
79         b0 = C0 - A0;
80         b1 = C1 - A1;
81         b2 = C2 - A2;
82         /* c = a × b */
83         c0 = a1 * b2 - a2 * b1;
84         c1 = a2 * b0 - a0 * b2;
85         c2 = a0 * b1 - a1 * b0;
86  
87         /* M^(-1) = (1/det(M)) * adj(M) */
88         in_det = 1 / (c0 * c0 + c1 * c1 + c2 * c2);
89         R00 = (b1 * c2 - b2 * c1) * in_det;
90         R01 = (b2 * c0 - b0 * c2) * in_det;
91         R02 = (b0 * c1 - b1 * c0) * in_det;
92         R10 = (c1 * a2 - c2 * a1) * in_det;
93         R11 = (c2 * a0 - c0 * a2) * in_det;
94         R12 = (c0 * a1 - c1 * a0) * in_det;
95         R20 = (c0) * in_det;
96         R21 = (c1) * in_det;
97         R22 = (c2) * in_det;
98   
99         /* O = M^(-1) * A */
100         R03 = -(R00 * A0 + R01 * A1 + R02 * A2);
101         R13 = -(R10 * A0 + R11 * A1 + R12 * A2);
102         R23 = -(R20 * A0 + R21 * A1 + R22 * A2);
103  
104         /* fill in last row of 4x4 matrix */
105         R30 = R31 = R32 = 0;
106         R33 = 1;
107   
108         J2 = R20 * j0 + R21 * j1 + R22 * j2 + R23;
109         K2 = R20 * k0 + R21 * k1 + R22 * k2 + R23;
110         if (J2 * K2 >= 0) return false;
111
112         J0 = R00 * j0 + R01 * j1 + R02 * j2 + R03;
113         K0 = R00 * k0 + R01 * k1 + R02 * k2 + R03;
114         i0 = J0 + J2 * ((K0 - J0) / (J2 - K2));
115         if (i0 < 0 || i0 > 1) return false;
116   
117         J1 = R10 * j0 + R11 * j1 + R12 * j2 + R13;
118         K1 = R10 * k0 + R11 * k1 + R12 * k2 + R13;
119         i1 = J1 + J2 * ((K1 - J1) / (J2 - K2));
120         if (i1 < 0 || i1 > 1 || i0 + i1 > 1) return false;
121
122         return true;            
123     }
124
125     public float getMaxX() { return Math.max(p1().x, Math.max(p2().x, p3().x)); }
126     public float getMinX() { return Math.min(p1().x, Math.min(p2().x, p3().x)); }
127     public float getMaxY() { return Math.max(p1().y, Math.max(p2().y, p3().y)); }
128     public float getMinY() { return Math.min(p1().y, Math.min(p2().y, p3().y)); }
129     public float getMaxZ() { return Math.max(p1().z, Math.max(p2().z, p3().z)); }
130     public float getMinZ() { return Math.min(p1().z, Math.min(p2().z, p3().z)); }
131 }