JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / site / j2s / JU / Measure.js
1 Clazz.declarePackage ("JU");\r
2 Clazz.load (["JU.V3"], "JU.Measure", ["java.lang.Float", "javajs.api.Interface", "JU.Lst", "$.P3", "$.P4", "$.Quat"], function () {\r
3 c$ = Clazz.declareType (JU, "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 }, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,~B");\r
11 c$.computeAngleABC = Clazz.defineMethod (c$, "computeAngleABC", \r
12 function (pointA, pointB, pointC, asDegrees) {\r
13 var vectorBA =  new JU.V3 ();\r
14 var vectorBC =  new JU.V3 ();\r
15 return JU.Measure.computeAngle (pointA, pointB, pointC, vectorBA, vectorBC, asDegrees);\r
16 }, "JU.T3,JU.T3,JU.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
41 if (cosang > 1) {\r
42 cosang = 1;\r
43 }if (cosang < -1) {\r
44 cosang = -1;\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 }, "JU.T3,JU.T3,JU.T3,JU.T3,~B");\r
51 c$.computeHelicalAxis = Clazz.defineMethod (c$, "computeHelicalAxis", \r
52 function (a, b, dq) {\r
53 var vab =  new JU.V3 ();\r
54 vab.sub2 (b, a);\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 JU.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 JU.V3 ();\r
63 var vcb = JU.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
67 vda.scale (0.5);\r
68 va_prime_d.scale (theta == 0 ? 0 : (vda.length () / Math.tan (theta / 2 / 180 * 3.141592653589793)));\r
69 var r = JU.V3.newV (va_prime_d);\r
70 if (theta != 0) r.add (vda);\r
71 var pt_a_prime = JU.P3.newP (a);\r
72 pt_a_prime.sub (r);\r
73 if (v_dot_n != 1.4E-45) n.scale (v_dot_n);\r
74 var pt_b_prime = JU.P3.newP (pt_a_prime);\r
75 pt_b_prime.add (n);\r
76 theta = JU.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, JU.P3.new3 (theta, pitch, residuesPerTurn), pt_b_prime]);\r
81 }, "JU.P3,JU.P3,JU.Quat");\r
82 c$.getPlaneThroughPoints = Clazz.defineMethod (c$, "getPlaneThroughPoints", \r
83 function (pointA, pointB, pointC, vNorm, vAB, plane) {\r
84 var w = JU.Measure.getNormalThroughPoints (pointA, pointB, pointC, vNorm, vAB);\r
85 plane.set4 (vNorm.x, vNorm.y, vNorm.z, w);\r
86 return plane;\r
87 }, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,JU.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 }, "JU.T3,JU.V3,JU.P4");\r
92 c$.distanceToPlane = Clazz.defineMethod (c$, "distanceToPlane", \r
93 function (plane, pt) {\r
94 return (plane == null ? NaN : (plane.x * pt.x + plane.y * pt.y + plane.z * pt.z + plane.w) / Math.sqrt (plane.x * plane.x + plane.y * plane.y + plane.z * plane.z));\r
95 }, "JU.P4,JU.T3");\r
96 c$.distanceToPlaneD = Clazz.defineMethod (c$, "distanceToPlaneD", \r
97 function (plane, d, pt) {\r
98 return (plane == null ? NaN : (plane.x * pt.x + plane.y * pt.y + plane.z * pt.z + plane.w) / d);\r
99 }, "JU.P4,~N,JU.P3");\r
100 c$.distanceToPlaneV = Clazz.defineMethod (c$, "distanceToPlaneV", \r
101 function (norm, w, pt) {\r
102 return (norm == null ? NaN : (norm.x * pt.x + norm.y * pt.y + norm.z * pt.z + w) / Math.sqrt (norm.x * norm.x + norm.y * norm.y + norm.z * norm.z));\r
103 }, "JU.V3,~N,JU.P3");\r
104 c$.calcNormalizedNormal = Clazz.defineMethod (c$, "calcNormalizedNormal", \r
105 function (pointA, pointB, pointC, vNormNorm, vAB) {\r
106 vAB.sub2 (pointB, pointA);\r
107 vNormNorm.sub2 (pointC, pointA);\r
108 vNormNorm.cross (vAB, vNormNorm);\r
109 vNormNorm.normalize ();\r
110 }, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3");\r
111 c$.getDirectedNormalThroughPoints = Clazz.defineMethod (c$, "getDirectedNormalThroughPoints", \r
112 function (pointA, pointB, pointC, ptRef, vNorm, vAB) {\r
113 var nd = JU.Measure.getNormalThroughPoints (pointA, pointB, pointC, vNorm, vAB);\r
114 if (ptRef != null) {\r
115 var pt0 = JU.P3.newP (pointA);\r
116 pt0.add (vNorm);\r
117 var d = pt0.distance (ptRef);\r
118 pt0.sub2 (pointA, vNorm);\r
119 if (d > pt0.distance (ptRef)) {\r
120 vNorm.scale (-1);\r
121 nd = -nd;\r
122 }}return nd;\r
123 }, "JU.T3,JU.T3,JU.T3,JU.T3,JU.V3,JU.V3");\r
124 c$.getNormalThroughPoints = Clazz.defineMethod (c$, "getNormalThroughPoints", \r
125 function (pointA, pointB, pointC, vNorm, vTemp) {\r
126 JU.Measure.calcNormalizedNormal (pointA, pointB, pointC, vNorm, vTemp);\r
127 vTemp.setT (pointA);\r
128 return -vTemp.dot (vNorm);\r
129 }, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3");\r
130 c$.getPlaneProjection = Clazz.defineMethod (c$, "getPlaneProjection", \r
131 function (pt, plane, ptProj, vNorm) {\r
132 var dist = JU.Measure.distanceToPlane (plane, pt);\r
133 vNorm.set (plane.x, plane.y, plane.z);\r
134 vNorm.normalize ();\r
135 vNorm.scale (-dist);\r
136 ptProj.add2 (pt, vNorm);\r
137 }, "JU.P3,JU.P4,JU.P3,JU.V3");\r
138 c$.getNormalFromCenter = Clazz.defineMethod (c$, "getNormalFromCenter", \r
139 function (ptCenter, ptA, ptB, ptC, isOutward, normal) {\r
140 var vAB =  new JU.V3 ();\r
141 var d = JU.Measure.getNormalThroughPoints (ptA, ptB, ptC, normal, vAB);\r
142 var isReversed = (JU.Measure.distanceToPlaneV (normal, d, ptCenter) > 0);\r
143 if (isReversed == isOutward) normal.scale (-1.0);\r
144 return !isReversed;\r
145 }, "JU.P3,JU.P3,JU.P3,JU.P3,~B,JU.V3");\r
146 c$.getNormalToLine = Clazz.defineMethod (c$, "getNormalToLine", \r
147 function (pointA, pointB, vNormNorm) {\r
148 vNormNorm.sub2 (pointA, pointB);\r
149 vNormNorm.cross (vNormNorm, JU.Measure.axisY);\r
150 vNormNorm.normalize ();\r
151 if (Float.isNaN (vNormNorm.x)) vNormNorm.set (1, 0, 0);\r
152 }, "JU.P3,JU.P3,JU.V3");\r
153 c$.getBisectingPlane = Clazz.defineMethod (c$, "getBisectingPlane", \r
154 function (pointA, vAB, ptTemp, vTemp, plane) {\r
155 ptTemp.scaleAdd2 (0.5, vAB, pointA);\r
156 vTemp.setT (vAB);\r
157 vTemp.normalize ();\r
158 JU.Measure.getPlaneThroughPoint (ptTemp, vTemp, plane);\r
159 }, "JU.P3,JU.V3,JU.T3,JU.V3,JU.P4");\r
160 c$.projectOntoAxis = Clazz.defineMethod (c$, "projectOntoAxis", \r
161 function (point, axisA, axisUnitVector, vectorProjection) {\r
162 vectorProjection.sub2 (point, axisA);\r
163 var projectedLength = vectorProjection.dot (axisUnitVector);\r
164 point.scaleAdd2 (projectedLength, axisUnitVector, axisA);\r
165 vectorProjection.sub2 (point, axisA);\r
166 }, "JU.P3,JU.P3,JU.V3,JU.V3");\r
167 c$.calcBestAxisThroughPoints = Clazz.defineMethod (c$, "calcBestAxisThroughPoints", \r
168 function (points, axisA, axisUnitVector, vectorProjection, nTriesMax) {\r
169 var nPoints = points.length;\r
170 axisA.setT (points[0]);\r
171 axisUnitVector.sub2 (points[nPoints - 1], axisA);\r
172 axisUnitVector.normalize ();\r
173 JU.Measure.calcAveragePointN (points, nPoints, axisA);\r
174 var nTries = 0;\r
175 while (nTries++ < nTriesMax && JU.Measure.findAxis (points, nPoints, axisA, axisUnitVector, vectorProjection) > 0.001) {\r
176 }\r
177 var tempA = JU.P3.newP (points[0]);\r
178 JU.Measure.projectOntoAxis (tempA, axisA, axisUnitVector, vectorProjection);\r
179 axisA.setT (tempA);\r
180 }, "~A,JU.P3,JU.V3,JU.V3,~N");\r
181 c$.findAxis = Clazz.defineMethod (c$, "findAxis", \r
182 function (points, nPoints, axisA, axisUnitVector, vectorProjection) {\r
183 var sumXiYi =  new JU.V3 ();\r
184 var vTemp =  new JU.V3 ();\r
185 var pt =  new JU.P3 ();\r
186 var ptProj =  new JU.P3 ();\r
187 var a = JU.V3.newV (axisUnitVector);\r
188 var sum_Xi2 = 0;\r
189 for (var i = nPoints; --i >= 0; ) {\r
190 pt.setT (points[i]);\r
191 ptProj.setT (pt);\r
192 JU.Measure.projectOntoAxis (ptProj, axisA, axisUnitVector, vectorProjection);\r
193 vTemp.sub2 (pt, ptProj);\r
194 vTemp.cross (vectorProjection, vTemp);\r
195 sumXiYi.add (vTemp);\r
196 sum_Xi2 += vectorProjection.lengthSquared ();\r
197 }\r
198 var m = JU.V3.newV (sumXiYi);\r
199 m.scale (1 / sum_Xi2);\r
200 vTemp.cross (m, axisUnitVector);\r
201 axisUnitVector.add (vTemp);\r
202 axisUnitVector.normalize ();\r
203 vTemp.sub2 (axisUnitVector, a);\r
204 return vTemp.length ();\r
205 }, "~A,~N,JU.P3,JU.V3,JU.V3");\r
206 c$.calcAveragePoint = Clazz.defineMethod (c$, "calcAveragePoint", \r
207 function (pointA, pointB, pointC) {\r
208 pointC.set ((pointA.x + pointB.x) / 2, (pointA.y + pointB.y) / 2, (pointA.z + pointB.z) / 2);\r
209 }, "JU.P3,JU.P3,JU.P3");\r
210 c$.calcAveragePointN = Clazz.defineMethod (c$, "calcAveragePointN", \r
211 function (points, nPoints, averagePoint) {\r
212 averagePoint.setT (points[0]);\r
213 for (var i = 1; i < nPoints; i++) averagePoint.add (points[i]);\r
214 \r
215 averagePoint.scale (1 / nPoints);\r
216 }, "~A,~N,JU.P3");\r
217 c$.transformPoints = Clazz.defineMethod (c$, "transformPoints", \r
218 function (vPts, m4, center) {\r
219 var v =  new JU.Lst ();\r
220 for (var i = 0; i < vPts.size (); i++) {\r
221 var pt = JU.P3.newP (vPts.get (i));\r
222 pt.sub (center);\r
223 m4.rotTrans (pt);\r
224 pt.add (center);\r
225 v.addLast (pt);\r
226 }\r
227 return v;\r
228 }, "JU.Lst,JU.M4,JU.P3");\r
229 c$.isInTetrahedron = Clazz.defineMethod (c$, "isInTetrahedron", \r
230 function (pt, ptA, ptB, ptC, ptD, plane, vTemp, vTemp2, fullyEnclosed) {\r
231 var b = (JU.Measure.distanceToPlane (JU.Measure.getPlaneThroughPoints (ptC, ptD, ptA, vTemp, vTemp2, plane), pt) >= 0);\r
232 if (b != (JU.Measure.distanceToPlane (JU.Measure.getPlaneThroughPoints (ptA, ptD, ptB, vTemp, vTemp2, plane), pt) >= 0)) return false;\r
233 if (b != (JU.Measure.distanceToPlane (JU.Measure.getPlaneThroughPoints (ptB, ptD, ptC, vTemp, vTemp2, plane), pt) >= 0)) return false;\r
234 var d = JU.Measure.distanceToPlane (JU.Measure.getPlaneThroughPoints (ptA, ptB, ptC, vTemp, vTemp2, plane), pt);\r
235 if (fullyEnclosed) return (b == (d >= 0));\r
236 var d1 = JU.Measure.distanceToPlane (plane, ptD);\r
237 return d1 * d <= 0 || Math.abs (d1) > Math.abs (d);\r
238 }, "JU.P3,JU.P3,JU.P3,JU.P3,JU.P3,JU.P4,JU.V3,JU.V3,~B");\r
239 c$.getIntersectionPP = Clazz.defineMethod (c$, "getIntersectionPP", \r
240 function (plane1, plane2) {\r
241 var a1 = plane1.x;\r
242 var b1 = plane1.y;\r
243 var c1 = plane1.z;\r
244 var d1 = plane1.w;\r
245 var a2 = plane2.x;\r
246 var b2 = plane2.y;\r
247 var c2 = plane2.z;\r
248 var d2 = plane2.w;\r
249 var norm1 = JU.V3.new3 (a1, b1, c1);\r
250 var norm2 = JU.V3.new3 (a2, b2, c2);\r
251 var nxn =  new JU.V3 ();\r
252 nxn.cross (norm1, norm2);\r
253 var ax = Math.abs (nxn.x);\r
254 var ay = Math.abs (nxn.y);\r
255 var az = Math.abs (nxn.z);\r
256 var x;\r
257 var y;\r
258 var z;\r
259 var diff;\r
260 var type = (ax > ay ? (ax > az ? 1 : 3) : ay > az ? 2 : 3);\r
261 switch (type) {\r
262 case 1:\r
263 x = 0;\r
264 diff = (b1 * c2 - b2 * c1);\r
265 if (Math.abs (diff) < 0.01) return null;\r
266 y = (c1 * d2 - c2 * d1) / diff;\r
267 z = (b2 * d1 - d2 * b1) / diff;\r
268 break;\r
269 case 2:\r
270 diff = (a1 * c2 - a2 * c1);\r
271 if (Math.abs (diff) < 0.01) return null;\r
272 x = (c1 * d2 - c2 * d1) / diff;\r
273 y = 0;\r
274 z = (a2 * d1 - d2 * a1) / diff;\r
275 break;\r
276 case 3:\r
277 default:\r
278 diff = (a1 * b2 - a2 * b1);\r
279 if (Math.abs (diff) < 0.01) return null;\r
280 x = (b1 * d2 - b2 * d1) / diff;\r
281 y = (a2 * d1 - d2 * a1) / diff;\r
282 z = 0;\r
283 }\r
284 var list =  new JU.Lst ();\r
285 list.addLast (JU.P3.new3 (x, y, z));\r
286 nxn.normalize ();\r
287 list.addLast (nxn);\r
288 return list;\r
289 }, "JU.P4,JU.P4");\r
290 c$.getIntersection = Clazz.defineMethod (c$, "getIntersection", \r
291 function (pt1, v, plane, ptRet, tempNorm, vTemp) {\r
292 JU.Measure.getPlaneProjection (pt1, plane, ptRet, tempNorm);\r
293 tempNorm.set (plane.x, plane.y, plane.z);\r
294 tempNorm.normalize ();\r
295 if (v == null) v = JU.V3.newV (tempNorm);\r
296 var l_dot_n = v.dot (tempNorm);\r
297 if (Math.abs (l_dot_n) < 0.01) return null;\r
298 vTemp.sub2 (ptRet, pt1);\r
299 ptRet.scaleAdd2 (vTemp.dot (tempNorm) / l_dot_n, v, pt1);\r
300 return ptRet;\r
301 }, "JU.P3,JU.V3,JU.P4,JU.P3,JU.V3,JU.V3");\r
302 c$.calculateQuaternionRotation = Clazz.defineMethod (c$, "calculateQuaternionRotation", \r
303 function (centerAndPoints, retStddev) {\r
304 retStddev[1] = NaN;\r
305 var q =  new JU.Quat ();\r
306 if (centerAndPoints[0].length == 1 || centerAndPoints[0].length != centerAndPoints[1].length) return q;\r
307 var n = centerAndPoints[0].length - 1;\r
308 if (n < 2) return q;\r
309 var Sxx = 0;\r
310 var Sxy = 0;\r
311 var Sxz = 0;\r
312 var Syx = 0;\r
313 var Syy = 0;\r
314 var Syz = 0;\r
315 var Szx = 0;\r
316 var Szy = 0;\r
317 var Szz = 0;\r
318 var ptA =  new JU.P3 ();\r
319 var ptB =  new JU.P3 ();\r
320 for (var i = n + 1; --i >= 1; ) {\r
321 var aij = centerAndPoints[0][i];\r
322 var bij = centerAndPoints[1][i];\r
323 ptA.sub2 (aij, centerAndPoints[0][0]);\r
324 ptB.sub2 (bij, centerAndPoints[0][1]);\r
325 Sxx += ptA.x * ptB.x;\r
326 Sxy += ptA.x * ptB.y;\r
327 Sxz += ptA.x * ptB.z;\r
328 Syx += ptA.y * ptB.x;\r
329 Syy += ptA.y * ptB.y;\r
330 Syz += ptA.y * ptB.z;\r
331 Szx += ptA.z * ptB.x;\r
332 Szy += ptA.z * ptB.y;\r
333 Szz += ptA.z * ptB.z;\r
334 }\r
335 retStddev[0] = JU.Measure.getRmsd (centerAndPoints, q);\r
336 var N =  Clazz.newDoubleArray (4, 4, 0);\r
337 N[0][0] = Sxx + Syy + Szz;\r
338 N[0][1] = N[1][0] = Syz - Szy;\r
339 N[0][2] = N[2][0] = Szx - Sxz;\r
340 N[0][3] = N[3][0] = Sxy - Syx;\r
341 N[1][1] = Sxx - Syy - Szz;\r
342 N[1][2] = N[2][1] = Sxy + Syx;\r
343 N[1][3] = N[3][1] = Szx + Sxz;\r
344 N[2][2] = -Sxx + Syy - Szz;\r
345 N[2][3] = N[3][2] = Syz + Szy;\r
346 N[3][3] = -Sxx - Syy + Szz;\r
347 var v = (javajs.api.Interface.getInterface ("JU.Eigen")).setM (N).getEigenvectorsFloatTransposed ()[3];\r
348 q = JU.Quat.newP4 (JU.P4.new4 (v[1], v[2], v[3], v[0]));\r
349 retStddev[1] = JU.Measure.getRmsd (centerAndPoints, q);\r
350 return q;\r
351 }, "~A,~A");\r
352 c$.getTransformMatrix4 = Clazz.defineMethod (c$, "getTransformMatrix4", \r
353 function (ptsA, ptsB, m, centerA) {\r
354 var cptsA = JU.Measure.getCenterAndPoints (ptsA);\r
355 var cptsB = JU.Measure.getCenterAndPoints (ptsB);\r
356 var retStddev =  Clazz.newFloatArray (2, 0);\r
357 var q = JU.Measure.calculateQuaternionRotation ( Clazz.newArray (-1, [cptsA, cptsB]), retStddev);\r
358 var r = q.getMatrix ();\r
359 if (centerA == null) r.rotate (cptsA[0]);\r
360  else centerA.setT (cptsA[0]);\r
361 var t = JU.V3.newVsub (cptsB[0], cptsA[0]);\r
362 m.setMV (r, t);\r
363 return retStddev[1];\r
364 }, "JU.Lst,JU.Lst,JU.M4,JU.P3");\r
365 c$.getCenterAndPoints = Clazz.defineMethod (c$, "getCenterAndPoints", \r
366 function (vPts) {\r
367 var n = vPts.size ();\r
368 var pts =  new Array (n + 1);\r
369 pts[0] =  new JU.P3 ();\r
370 if (n > 0) {\r
371 for (var i = 0; i < n; i++) {\r
372 pts[0].add (pts[i + 1] = vPts.get (i));\r
373 }\r
374 pts[0].scale (1 / n);\r
375 }return pts;\r
376 }, "JU.Lst");\r
377 c$.getRmsd = Clazz.defineMethod (c$, "getRmsd", \r
378 function (centerAndPoints, q) {\r
379 var sum2 = 0;\r
380 var ptsA = centerAndPoints[0];\r
381 var ptsB = centerAndPoints[1];\r
382 var cA = ptsA[0];\r
383 var cB = ptsB[0];\r
384 var n = ptsA.length - 1;\r
385 var ptAnew =  new JU.P3 ();\r
386 for (var i = n + 1; --i >= 1; ) {\r
387 ptAnew.sub2 (ptsA[i], cA);\r
388 q.transform2 (ptAnew, ptAnew).add (cB);\r
389 sum2 += ptAnew.distanceSquared (ptsB[i]);\r
390 }\r
391 return Math.sqrt (sum2 / n);\r
392 }, "~A,JU.Quat");\r
393 Clazz.defineStatics (c$,\r
394 "radiansPerDegree", (0.017453292519943295));\r
395 c$.axisY = c$.prototype.axisY = JU.V3.new3 (0, 1, 0);\r
396 });\r