1 Clazz.declarePackage ("javajs.util");
\r
2 Clazz.load (["javajs.util.V3"], "javajs.util.Measure", ["java.lang.Float", "javajs.api.Interface", "javajs.util.Lst", "$.P3", "$.P4", "$.Quat"], function () {
\r
3 c$ = Clazz.declareType (javajs.util, "Measure");
\r
4 c$.computeAngle = Clazz.defineMethod (c$, "computeAngle",
\r
5 function (pointA, pointB, pointC, vectorBA, vectorBC, asDegrees) {
\r
6 vectorBA.sub2 (pointA, pointB);
\r
7 vectorBC.sub2 (pointC, pointB);
\r
8 var angle = vectorBA.angle (vectorBC);
\r
9 return (asDegrees ? angle / 0.017453292 : angle);
\r
10 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.V3,javajs.util.V3,~B");
\r
11 c$.computeAngleABC = Clazz.defineMethod (c$, "computeAngleABC",
\r
12 function (pointA, pointB, pointC, asDegrees) {
\r
13 var vectorBA = new javajs.util.V3 ();
\r
14 var vectorBC = new javajs.util.V3 ();
\r
15 return javajs.util.Measure.computeAngle (pointA, pointB, pointC, vectorBA, vectorBC, asDegrees);
\r
16 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,~B");
\r
17 c$.computeTorsion = Clazz.defineMethod (c$, "computeTorsion",
\r
18 function (p1, p2, p3, p4, asDegrees) {
\r
19 var ijx = p1.x - p2.x;
\r
20 var ijy = p1.y - p2.y;
\r
21 var ijz = p1.z - p2.z;
\r
22 var kjx = p3.x - p2.x;
\r
23 var kjy = p3.y - p2.y;
\r
24 var kjz = p3.z - p2.z;
\r
25 var klx = p3.x - p4.x;
\r
26 var kly = p3.y - p4.y;
\r
27 var klz = p3.z - p4.z;
\r
28 var ax = ijy * kjz - ijz * kjy;
\r
29 var ay = ijz * kjx - ijx * kjz;
\r
30 var az = ijx * kjy - ijy * kjx;
\r
31 var cx = kjy * klz - kjz * kly;
\r
32 var cy = kjz * klx - kjx * klz;
\r
33 var cz = kjx * kly - kjy * klx;
\r
34 var ai2 = 1 / (ax * ax + ay * ay + az * az);
\r
35 var ci2 = 1 / (cx * cx + cy * cy + cz * cz);
\r
36 var ai = Math.sqrt (ai2);
\r
37 var ci = Math.sqrt (ci2);
\r
38 var denom = ai * ci;
\r
39 var cross = ax * cx + ay * cy + az * cz;
\r
40 var cosang = cross * denom;
\r
45 }var torsion = Math.acos (cosang);
\r
46 var dot = ijx * cx + ijy * cy + ijz * cz;
\r
47 var absDot = Math.abs (dot);
\r
48 torsion = (dot / absDot > 0) ? torsion : -torsion;
\r
49 return (asDegrees ? torsion / 0.017453292 : torsion);
\r
50 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.T3,~B");
\r
51 c$.computeHelicalAxis = Clazz.defineMethod (c$, "computeHelicalAxis",
\r
52 function (a, b, dq) {
\r
53 var vab = new javajs.util.V3 ();
\r
55 var theta = dq.getTheta ();
\r
56 var n = dq.getNormal ();
\r
57 var v_dot_n = vab.dot (n);
\r
58 if (Math.abs (v_dot_n) < 0.0001) v_dot_n = 0;
\r
59 var va_prime_d = new javajs.util.V3 ();
\r
60 va_prime_d.cross (vab, n);
\r
61 if (va_prime_d.dot (va_prime_d) != 0) va_prime_d.normalize ();
\r
62 var vda = new javajs.util.V3 ();
\r
63 var vcb = javajs.util.V3.newV (n);
\r
64 if (v_dot_n == 0) v_dot_n = 1.4E-45;
\r
65 vcb.scale (v_dot_n);
\r
66 vda.sub2 (vcb, vab);
\r
68 va_prime_d.scale (theta == 0 ? 0 : (vda.length () / Math.tan (theta / 2 / 180 * 3.141592653589793)));
\r
69 var r = javajs.util.V3.newV (va_prime_d);
\r
70 if (theta != 0) r.add (vda);
\r
71 var pt_a_prime = javajs.util.P3.newP (a);
\r
73 if (v_dot_n != 1.4E-45) n.scale (v_dot_n);
\r
74 var pt_b_prime = javajs.util.P3.newP (pt_a_prime);
\r
76 theta = javajs.util.Measure.computeTorsion (a, pt_a_prime, pt_b_prime, b, true);
\r
77 if (Float.isNaN (theta) || r.length () < 0.0001) theta = dq.getThetaDirectedV (n);
\r
78 var residuesPerTurn = Math.abs (theta == 0 ? 0 : 360 / theta);
\r
79 var pitch = Math.abs (v_dot_n == 1.4E-45 ? 0 : n.length () * (theta == 0 ? 1 : 360 / theta));
\r
80 return Clazz.newArray (-1, [pt_a_prime, n, r, javajs.util.P3.new3 (theta, pitch, residuesPerTurn), pt_b_prime]);
\r
81 }, "javajs.util.P3,javajs.util.P3,javajs.util.Quat");
\r
82 c$.getPlaneThroughPoints = Clazz.defineMethod (c$, "getPlaneThroughPoints",
\r
83 function (pointA, pointB, pointC, vNorm, vAB, plane) {
\r
84 var w = javajs.util.Measure.getNormalThroughPoints (pointA, pointB, pointC, vNorm, vAB);
\r
85 plane.set4 (vNorm.x, vNorm.y, vNorm.z, w);
\r
87 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.V3,javajs.util.V3,javajs.util.P4");
\r
88 c$.getPlaneThroughPoint = Clazz.defineMethod (c$, "getPlaneThroughPoint",
\r
89 function (pt, normal, plane) {
\r
90 plane.set4 (normal.x, normal.y, normal.z, -normal.dot (pt));
\r
91 }, "javajs.util.T3,javajs.util.V3,javajs.util.P4");
\r
92 c$.distanceToPlane = Clazz.defineMethod (c$, "distanceToPlane",
\r
93 function (plane, pt) {
\r
94 return (plane == null ? NaN : (plane.dot (pt) + plane.w) / Math.sqrt (plane.dot (plane)));
\r
95 }, "javajs.util.P4,javajs.util.T3");
\r
96 c$.directedDistanceToPlane = Clazz.defineMethod (c$, "directedDistanceToPlane",
\r
97 function (pt, plane, ptref) {
\r
98 var f = plane.dot (pt) + plane.w;
\r
99 var f1 = plane.dot (ptref) + plane.w;
\r
100 return Math.signum (f1) * f / Math.sqrt (plane.dot (plane));
\r
101 }, "javajs.util.P3,javajs.util.P4,javajs.util.P3");
\r
102 c$.distanceToPlaneD = Clazz.defineMethod (c$, "distanceToPlaneD",
\r
103 function (plane, d, pt) {
\r
104 return (plane == null ? NaN : (plane.dot (pt) + plane.w) / d);
\r
105 }, "javajs.util.P4,~N,javajs.util.P3");
\r
106 c$.distanceToPlaneV = Clazz.defineMethod (c$, "distanceToPlaneV",
\r
107 function (norm, w, pt) {
\r
108 return (norm == null ? NaN : (norm.dot (pt) + w) / Math.sqrt (norm.dot (norm)));
\r
109 }, "javajs.util.V3,~N,javajs.util.P3");
\r
110 c$.calcNormalizedNormal = Clazz.defineMethod (c$, "calcNormalizedNormal",
\r
111 function (pointA, pointB, pointC, vNormNorm, vAB) {
\r
112 vAB.sub2 (pointB, pointA);
\r
113 vNormNorm.sub2 (pointC, pointA);
\r
114 vNormNorm.cross (vAB, vNormNorm);
\r
115 vNormNorm.normalize ();
\r
116 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.V3,javajs.util.V3");
\r
117 c$.getDirectedNormalThroughPoints = Clazz.defineMethod (c$, "getDirectedNormalThroughPoints",
\r
118 function (pointA, pointB, pointC, ptRef, vNorm, vAB) {
\r
119 var nd = javajs.util.Measure.getNormalThroughPoints (pointA, pointB, pointC, vNorm, vAB);
\r
120 if (ptRef != null) {
\r
121 var pt0 = javajs.util.P3.newP (pointA);
\r
123 var d = pt0.distance (ptRef);
\r
124 pt0.sub2 (pointA, vNorm);
\r
125 if (d > pt0.distance (ptRef)) {
\r
129 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.V3,javajs.util.V3");
\r
130 c$.getNormalThroughPoints = Clazz.defineMethod (c$, "getNormalThroughPoints",
\r
131 function (pointA, pointB, pointC, vNorm, vTemp) {
\r
132 javajs.util.Measure.calcNormalizedNormal (pointA, pointB, pointC, vNorm, vTemp);
\r
133 vTemp.setT (pointA);
\r
134 return -vTemp.dot (vNorm);
\r
135 }, "javajs.util.T3,javajs.util.T3,javajs.util.T3,javajs.util.V3,javajs.util.V3");
\r
136 c$.getPlaneProjection = Clazz.defineMethod (c$, "getPlaneProjection",
\r
137 function (pt, plane, ptProj, vNorm) {
\r
138 var dist = javajs.util.Measure.distanceToPlane (plane, pt);
\r
139 vNorm.set (plane.x, plane.y, plane.z);
\r
140 vNorm.normalize ();
\r
141 vNorm.scale (-dist);
\r
142 ptProj.add2 (pt, vNorm);
\r
143 }, "javajs.util.P3,javajs.util.P4,javajs.util.P3,javajs.util.V3");
\r
144 c$.getNormalToLine = Clazz.defineMethod (c$, "getNormalToLine",
\r
145 function (pointA, pointB, vNormNorm) {
\r
146 vNormNorm.sub2 (pointA, pointB);
\r
147 vNormNorm.cross (vNormNorm, javajs.util.Measure.axisY);
\r
148 vNormNorm.normalize ();
\r
149 if (Float.isNaN (vNormNorm.x)) vNormNorm.set (1, 0, 0);
\r
150 }, "javajs.util.P3,javajs.util.P3,javajs.util.V3");
\r
151 c$.getBisectingPlane = Clazz.defineMethod (c$, "getBisectingPlane",
\r
152 function (pointA, vAB, ptTemp, vTemp, plane) {
\r
153 ptTemp.scaleAdd2 (0.5, vAB, pointA);
\r
155 vTemp.normalize ();
\r
156 javajs.util.Measure.getPlaneThroughPoint (ptTemp, vTemp, plane);
\r
157 }, "javajs.util.P3,javajs.util.V3,javajs.util.T3,javajs.util.V3,javajs.util.P4");
\r
158 c$.projectOntoAxis = Clazz.defineMethod (c$, "projectOntoAxis",
\r
159 function (point, axisA, axisUnitVector, vectorProjection) {
\r
160 vectorProjection.sub2 (point, axisA);
\r
161 var projectedLength = vectorProjection.dot (axisUnitVector);
\r
162 point.scaleAdd2 (projectedLength, axisUnitVector, axisA);
\r
163 vectorProjection.sub2 (point, axisA);
\r
164 }, "javajs.util.P3,javajs.util.P3,javajs.util.V3,javajs.util.V3");
\r
165 c$.calcBestAxisThroughPoints = Clazz.defineMethod (c$, "calcBestAxisThroughPoints",
\r
166 function (points, axisA, axisUnitVector, vectorProjection, nTriesMax) {
\r
167 var nPoints = points.length;
\r
168 axisA.setT (points[0]);
\r
169 axisUnitVector.sub2 (points[nPoints - 1], axisA);
\r
170 axisUnitVector.normalize ();
\r
171 javajs.util.Measure.calcAveragePointN (points, nPoints, axisA);
\r
173 while (nTries++ < nTriesMax && javajs.util.Measure.findAxis (points, nPoints, axisA, axisUnitVector, vectorProjection) > 0.001) {
\r
175 var tempA = javajs.util.P3.newP (points[0]);
\r
176 javajs.util.Measure.projectOntoAxis (tempA, axisA, axisUnitVector, vectorProjection);
\r
177 axisA.setT (tempA);
\r
178 }, "~A,javajs.util.P3,javajs.util.V3,javajs.util.V3,~N");
\r
179 c$.findAxis = Clazz.defineMethod (c$, "findAxis",
\r
180 function (points, nPoints, axisA, axisUnitVector, vectorProjection) {
\r
181 var sumXiYi = new javajs.util.V3 ();
\r
182 var vTemp = new javajs.util.V3 ();
\r
183 var pt = new javajs.util.P3 ();
\r
184 var ptProj = new javajs.util.P3 ();
\r
185 var a = javajs.util.V3.newV (axisUnitVector);
\r
187 for (var i = nPoints; --i >= 0; ) {
\r
188 pt.setT (points[i]);
\r
190 javajs.util.Measure.projectOntoAxis (ptProj, axisA, axisUnitVector, vectorProjection);
\r
191 vTemp.sub2 (pt, ptProj);
\r
192 vTemp.cross (vectorProjection, vTemp);
\r
193 sumXiYi.add (vTemp);
\r
194 sum_Xi2 += vectorProjection.lengthSquared ();
\r
196 var m = javajs.util.V3.newV (sumXiYi);
\r
197 m.scale (1 / sum_Xi2);
\r
198 vTemp.cross (m, axisUnitVector);
\r
199 axisUnitVector.add (vTemp);
\r
200 axisUnitVector.normalize ();
\r
201 vTemp.sub2 (axisUnitVector, a);
\r
202 return vTemp.length ();
\r
203 }, "~A,~N,javajs.util.P3,javajs.util.V3,javajs.util.V3");
\r
204 c$.calcAveragePoint = Clazz.defineMethod (c$, "calcAveragePoint",
\r
205 function (pointA, pointB, pointC) {
\r
206 pointC.set ((pointA.x + pointB.x) / 2, (pointA.y + pointB.y) / 2, (pointA.z + pointB.z) / 2);
\r
207 }, "javajs.util.P3,javajs.util.P3,javajs.util.P3");
\r
208 c$.calcAveragePointN = Clazz.defineMethod (c$, "calcAveragePointN",
\r
209 function (points, nPoints, averagePoint) {
\r
210 averagePoint.setT (points[0]);
\r
211 for (var i = 1; i < nPoints; i++) averagePoint.add (points[i]);
\r
213 averagePoint.scale (1 / nPoints);
\r
214 }, "~A,~N,javajs.util.P3");
\r
215 c$.transformPoints = Clazz.defineMethod (c$, "transformPoints",
\r
216 function (vPts, m4, center) {
\r
217 var v = new javajs.util.Lst ();
\r
218 for (var i = 0; i < vPts.size (); i++) {
\r
219 var pt = javajs.util.P3.newP (vPts.get (i));
\r
226 }, "javajs.util.Lst,javajs.util.M4,javajs.util.P3");
\r
227 c$.isInTetrahedron = Clazz.defineMethod (c$, "isInTetrahedron",
\r
228 function (pt, ptA, ptB, ptC, ptD, plane, vTemp, vTemp2, fullyEnclosed) {
\r
229 var b = (javajs.util.Measure.distanceToPlane (javajs.util.Measure.getPlaneThroughPoints (ptC, ptD, ptA, vTemp, vTemp2, plane), pt) >= 0);
\r
230 if (b != (javajs.util.Measure.distanceToPlane (javajs.util.Measure.getPlaneThroughPoints (ptA, ptD, ptB, vTemp, vTemp2, plane), pt) >= 0)) return false;
\r
231 if (b != (javajs.util.Measure.distanceToPlane (javajs.util.Measure.getPlaneThroughPoints (ptB, ptD, ptC, vTemp, vTemp2, plane), pt) >= 0)) return false;
\r
232 var d = javajs.util.Measure.distanceToPlane (javajs.util.Measure.getPlaneThroughPoints (ptA, ptB, ptC, vTemp, vTemp2, plane), pt);
\r
233 if (fullyEnclosed) return (b == (d >= 0));
\r
234 var d1 = javajs.util.Measure.distanceToPlane (plane, ptD);
\r
235 return d1 * d <= 0 || Math.abs (d1) > Math.abs (d);
\r
236 }, "javajs.util.P3,javajs.util.P3,javajs.util.P3,javajs.util.P3,javajs.util.P3,javajs.util.P4,javajs.util.V3,javajs.util.V3,~B");
\r
237 c$.getIntersectionPP = Clazz.defineMethod (c$, "getIntersectionPP",
\r
238 function (plane1, plane2) {
\r
247 var norm1 = javajs.util.V3.new3 (a1, b1, c1);
\r
248 var norm2 = javajs.util.V3.new3 (a2, b2, c2);
\r
249 var nxn = new javajs.util.V3 ();
\r
250 nxn.cross (norm1, norm2);
\r
251 var ax = Math.abs (nxn.x);
\r
252 var ay = Math.abs (nxn.y);
\r
253 var az = Math.abs (nxn.z);
\r
258 var type = (ax > ay ? (ax > az ? 1 : 3) : ay > az ? 2 : 3);
\r
262 diff = (b1 * c2 - b2 * c1);
\r
263 if (Math.abs (diff) < 0.01) return null;
\r
264 y = (c1 * d2 - c2 * d1) / diff;
\r
265 z = (b2 * d1 - d2 * b1) / diff;
\r
268 diff = (a1 * c2 - a2 * c1);
\r
269 if (Math.abs (diff) < 0.01) return null;
\r
270 x = (c1 * d2 - c2 * d1) / diff;
\r
272 z = (a2 * d1 - d2 * a1) / diff;
\r
276 diff = (a1 * b2 - a2 * b1);
\r
277 if (Math.abs (diff) < 0.01) return null;
\r
278 x = (b1 * d2 - b2 * d1) / diff;
\r
279 y = (a2 * d1 - d2 * a1) / diff;
\r
282 var list = new javajs.util.Lst ();
\r
283 list.addLast (javajs.util.P3.new3 (x, y, z));
\r
285 list.addLast (nxn);
\r
287 }, "javajs.util.P4,javajs.util.P4");
\r
288 c$.getIntersection = Clazz.defineMethod (c$, "getIntersection",
\r
289 function (pt1, v, plane, ptRet, tempNorm, vTemp) {
\r
290 javajs.util.Measure.getPlaneProjection (pt1, plane, ptRet, tempNorm);
\r
291 tempNorm.set (plane.x, plane.y, plane.z);
\r
292 tempNorm.normalize ();
\r
293 if (v == null) v = javajs.util.V3.newV (tempNorm);
\r
294 var l_dot_n = v.dot (tempNorm);
\r
295 if (Math.abs (l_dot_n) < 0.01) return null;
\r
296 vTemp.sub2 (ptRet, pt1);
\r
297 ptRet.scaleAdd2 (vTemp.dot (tempNorm) / l_dot_n, v, pt1);
\r
299 }, "javajs.util.P3,javajs.util.V3,javajs.util.P4,javajs.util.P3,javajs.util.V3,javajs.util.V3");
\r
300 c$.calculateQuaternionRotation = Clazz.defineMethod (c$, "calculateQuaternionRotation",
\r
301 function (centerAndPoints, retStddev) {
\r
302 retStddev[1] = NaN;
\r
303 var q = new javajs.util.Quat ();
\r
304 if (centerAndPoints[0].length == 1 || centerAndPoints[0].length != centerAndPoints[1].length) return q;
\r
305 var n = centerAndPoints[0].length - 1;
\r
306 if (n < 2) return q;
\r
316 var ptA = new javajs.util.P3 ();
\r
317 var ptB = new javajs.util.P3 ();
\r
318 for (var i = n + 1; --i >= 1; ) {
\r
319 var aij = centerAndPoints[0][i];
\r
320 var bij = centerAndPoints[1][i];
\r
321 ptA.sub2 (aij, centerAndPoints[0][0]);
\r
322 ptB.sub2 (bij, centerAndPoints[0][1]);
\r
323 Sxx += ptA.x * ptB.x;
\r
324 Sxy += ptA.x * ptB.y;
\r
325 Sxz += ptA.x * ptB.z;
\r
326 Syx += ptA.y * ptB.x;
\r
327 Syy += ptA.y * ptB.y;
\r
328 Syz += ptA.y * ptB.z;
\r
329 Szx += ptA.z * ptB.x;
\r
330 Szy += ptA.z * ptB.y;
\r
331 Szz += ptA.z * ptB.z;
\r
333 retStddev[0] = javajs.util.Measure.getRmsd (centerAndPoints, q);
\r
334 var N = Clazz.newDoubleArray (4, 4, 0);
\r
335 N[0][0] = Sxx + Syy + Szz;
\r
336 N[0][1] = N[1][0] = Syz - Szy;
\r
337 N[0][2] = N[2][0] = Szx - Sxz;
\r
338 N[0][3] = N[3][0] = Sxy - Syx;
\r
339 N[1][1] = Sxx - Syy - Szz;
\r
340 N[1][2] = N[2][1] = Sxy + Syx;
\r
341 N[1][3] = N[3][1] = Szx + Sxz;
\r
342 N[2][2] = -Sxx + Syy - Szz;
\r
343 N[2][3] = N[3][2] = Syz + Szy;
\r
344 N[3][3] = -Sxx - Syy + Szz;
\r
345 var v = (javajs.api.Interface.getInterface ("javajs.util.Eigen")).setM (N).getEigenvectorsFloatTransposed ()[3];
\r
346 q = javajs.util.Quat.newP4 (javajs.util.P4.new4 (v[1], v[2], v[3], v[0]));
\r
347 retStddev[1] = javajs.util.Measure.getRmsd (centerAndPoints, q);
\r
350 c$.getTransformMatrix4 = Clazz.defineMethod (c$, "getTransformMatrix4",
\r
351 function (ptsA, ptsB, m, centerA) {
\r
352 var cptsA = javajs.util.Measure.getCenterAndPoints (ptsA);
\r
353 var cptsB = javajs.util.Measure.getCenterAndPoints (ptsB);
\r
354 var retStddev = Clazz.newFloatArray (2, 0);
\r
355 var q = javajs.util.Measure.calculateQuaternionRotation ( Clazz.newArray (-1, [cptsA, cptsB]), retStddev);
\r
356 var r = q.getMatrix ();
\r
357 if (centerA == null) r.rotate (cptsA[0]);
\r
358 else centerA.setT (cptsA[0]);
\r
359 var t = javajs.util.V3.newVsub (cptsB[0], cptsA[0]);
\r
361 return retStddev[1];
\r
362 }, "javajs.util.Lst,javajs.util.Lst,javajs.util.M4,javajs.util.P3");
\r
363 c$.getCenterAndPoints = Clazz.defineMethod (c$, "getCenterAndPoints",
\r
365 var n = vPts.size ();
\r
366 var pts = new Array (n + 1);
\r
367 pts[0] = new javajs.util.P3 ();
\r
369 for (var i = 0; i < n; i++) {
\r
370 pts[0].add (pts[i + 1] = vPts.get (i));
\r
372 pts[0].scale (1 / n);
\r
374 }, "javajs.util.Lst");
\r
375 c$.getRmsd = Clazz.defineMethod (c$, "getRmsd",
\r
376 function (centerAndPoints, q) {
\r
378 var ptsA = centerAndPoints[0];
\r
379 var ptsB = centerAndPoints[1];
\r
382 var n = ptsA.length - 1;
\r
383 var ptAnew = new javajs.util.P3 ();
\r
384 for (var i = n + 1; --i >= 1; ) {
\r
385 ptAnew.sub2 (ptsA[i], cA);
\r
386 q.transform2 (ptAnew, ptAnew).add (cB);
\r
387 sum2 += ptAnew.distanceSquared (ptsB[i]);
\r
389 return Math.sqrt (sum2 / n);
\r
390 }, "~A,javajs.util.Quat");
\r
391 Clazz.defineStatics (c$,
\r
392 "radiansPerDegree", (0.017453292519943295));
\r
393 c$.axisY = c$.prototype.axisY = javajs.util.V3.new3 (0, 1, 0);
\r