Revision: 18376 http://sourceforge.net/p/jmol/code/18376 Author: hansonr Date: 2013-06-27 21:26:13 +0000 (Thu, 27 Jun 2013) Log Message: -----------
Modified Paths: -------------- trunk/Jmol/src/org/jmol/adapter/readers/xtal/MagResReader.java trunk/Jmol/src/org/jmol/adapter/smarter/AtomSetCollection.java trunk/Jmol/src/org/jmol/g3d/SphereRenderer.java trunk/Jmol/src/org/jmol/modelset/Atom.java trunk/Jmol/src/org/jmol/renderspecial/EllipsoidsRenderer.java trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java trunk/Jmol/src/org/jmol/symmetry/UnitCell.java trunk/Jmol/src/org/jmol/util/Eigen.java trunk/Jmol/src/org/jmol/util/Tensor.java Modified: trunk/Jmol/src/org/jmol/adapter/readers/xtal/MagResReader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/xtal/MagResReader.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/adapter/readers/xtal/MagResReader.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -88,7 +88,7 @@ String[] tokens = getTokens(); String atomName = (tokens[1] + tokens[2]); fillFloatArray(line.substring(30), 0, data); - float f = (iType == 0 ? 0.04f : 1f); + float f = (iType == 0 ? 0.01f : 1f); // if (isJ) { // discardLinesUntilContains("Isotropic"); // float iso = parseFloatStr(getTokens()[3]); @@ -102,7 +102,7 @@ a[i][j] = data[pt++]; atom = atomSetCollection.getAtoms()[atomSetCollection.getAtomIndexFromName(atomName)]; atom.tensors[iType] = Eigen.getEllipsoidDD(a); - atom.tensors[iType].setScale(f); + atom.tensors[iType].setTypeFactor(f); if (tensorTypes.indexOf("" + iType) < 0) { tensorTypes += "" + iType; appendLoadNote("Ellipsoids set " + (iType + 1) + ": " @@ -202,6 +202,6 @@ for (int j = 0; j < 3; j++) a[i][j] = data[pt++]; atom.setEllipsoid(Eigen.getEllipsoidDD(a)); - atom.tensors[0].setScale(f); + atom.tensors[0].setTypeFactor(f); } } Modified: trunk/Jmol/src/org/jmol/adapter/smarter/AtomSetCollection.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/smarter/AtomSetCollection.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/adapter/smarter/AtomSetCollection.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -1348,9 +1348,8 @@ Tensor t = atoms[i].tensors[j]; if (t == null) continue; - V3[] axes = t.eigenVectors; - float[] lengths = t.eigenValues; - if (axes != null) { + V3[] eigenVectors = t.eigenVectors; + if (eigenVectors != null) { // note -- PDB reader specifically turns off cartesians if (addCartesian) { ptTemp.setT(cartesians[i - iAtomFirst]); @@ -1358,10 +1357,10 @@ ptTemp.setT(atoms[i]); symmetry.toCartesian(ptTemp, false); } - axes = symmetry.rotateEllipsoid(iSym, ptTemp, axes, ptTemp1, + eigenVectors = symmetry.rotateEllipsoid(iSym, ptTemp, eigenVectors, ptTemp1, ptTemp2); } - atom1.tensors[j] = new Tensor().fromVectors(axes, lengths, t.eigenSignMask, t.isThermalEllipsoid); + atom1.tensors[j] = new Tensor().setVectors(eigenVectors, t.eigenValues, t.forThermalEllipsoid, t.typeFactor); } } } Modified: trunk/Jmol/src/org/jmol/g3d/SphereRenderer.java =================================================================== --- trunk/Jmol/src/org/jmol/g3d/SphereRenderer.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/g3d/SphereRenderer.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -503,7 +503,7 @@ continue; int zPixel; if (isEllipsoid) { - if (!Tensor.getQuardricZ(xCurrent, yCurrent, coef, zroot)) { + if (!getQuardricZ(xCurrent, yCurrent, coef, zroot)) { if (iRoot >= 0) { // done for this line break; @@ -577,7 +577,36 @@ // Bob Hanson, 4/2008 // ////////////////////////////////////// - + + private static boolean getQuardricZ(double x, double y, double[] coef, + double[] zroot) { + + /* simple quadratic formula for: + * + * c0 x^2 + c1 y^2 + c2 z^2 + c3 xy + c4 xz + c5 yz + c6 x + c7 y + c8 z - 1 = 0 + * + * or: + * + * c2 z^2 + (c4 x + c5 y + c8)z + (c0 x^2 + c1 y^2 + c3 xy + c6 x + c7 y - 1) = 0 + * + * so: + * + * z = -(b/2a) +/- sqrt( (b/2a)^2 - c/a ) + */ + + double b_2a = (coef[4] * x + coef[5] * y + coef[8]) / coef[2] / 2; + double c_a = (coef[0] * x * x + coef[1] * y * y + coef[3] * x * y + coef[6] + * x + coef[7] * y - 1) + / coef[2]; + double f = b_2a * b_2a - c_a; + if (f < 0) + return false; + f = Math.sqrt(f); + zroot[0] = (-b_2a - f); + zroot[1] = (-b_2a + f); + return true; + } + private void setPlaneDerivatives() { planeShade = -1; for (int i = 0; i < 3; i ++) { Modified: trunk/Jmol/src/org/jmol/modelset/Atom.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/Atom.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/modelset/Atom.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -292,9 +292,7 @@ public float getADPMinMax(boolean isMax) { Tensor[] tensors = getTensors(); - return (tensors == null ? 0 : tensors[0] == null ? - Math.abs(tensors[1].eigenValues[isMax ? 2 : 0]) * tensors[1].scale - : Math.abs(tensors[0].eigenValues[isMax ? 2 : 0]) * tensors[0].scale); + return (tensors == null ? 0 : tensors[tensors[0] == null ? 1 : 0].getLength(isMax ? 2 : 0)); } public int getRasMolRadius() { @@ -651,13 +649,6 @@ return group.chain.model.modelSet.getEllipsoid(index); } - public void scaleEllipsoid(int size, int iSelect) { - Tensor[] ellipsoid = getTensors(); - if (ellipsoid == null || iSelect >= ellipsoid.length || ellipsoid[iSelect] == null) - return; - ellipsoid[iSelect].setSize(size); - } - /** * Given a symmetry operation number, the set of cells in the model, and the * number of operations, this method returns either 0 or the cell number (555, 666) Modified: trunk/Jmol/src/org/jmol/renderspecial/EllipsoidsRenderer.java =================================================================== --- trunk/Jmol/src/org/jmol/renderspecial/EllipsoidsRenderer.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/renderspecial/EllipsoidsRenderer.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -231,7 +231,7 @@ s0.set(atom.screenX, atom.screenY, atom.screenZ); boolean isOK = true; for (int i = 3; --i >= 0;) { - factoredLengths[i] = tensor.eigenValues[i] * tensor.scale; + factoredLengths[i] = tensor.getLength(i); if (Float.isNaN(factoredLengths[i])) isOK = false; else if (factoredLengths[i] < 0.02f) @@ -279,7 +279,17 @@ } private void setMatrices() { - Tensor.setEllipsoidMatrix(axes, factoredLengths, v1, mat); + + // Create a matrix that transforms cartesian coordinates + // into ellipsoidal coordinates, where in that system we + // are drawing a sphere. + + for (int i = 0; i < 3; i++) { + v1.setT(axes[i]); + v1.scale(factoredLengths[i]); + mat.setColumnV(i, v1); + } + mat.invertM(mat); // make this screen coordinates to ellisoidal coordinates matScreenToEllipsoid.mul2(mat, matScreenToCartesian); matEllipsoidToScreen.invertM(matScreenToEllipsoid); @@ -316,7 +326,7 @@ private void renderBall() { setSelectedOctant(); // get equation and differential - Tensor.getEquationForQuadricWithCenter(s0.x, s0.y, s0.z, + Ellipsoids.getEquationForQuadricWithCenter(s0.x, s0.y, s0.z, matScreenToEllipsoid, v1, mTemp, coef, mDeriv); g3d.fillEllipsoid(center, points, s0.x, s0.y, s0.z, dx + dx, matScreenToEllipsoid, coef, mDeriv, selectedOctant, selectedOctant >= 0 ? selectedPoints : null); Modified: trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -11709,7 +11709,7 @@ continue; case T.delete: value = Boolean.TRUE; - checkLength(3); + checkLength(i + 1); break; case T.modelindex: value = Integer.valueOf(intParameter(++i)); Modified: trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java =================================================================== --- trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/shapespecial/Ellipsoids.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -36,9 +36,10 @@ import org.jmol.util.BS; import org.jmol.util.BSUtil; import org.jmol.util.C; -import org.jmol.util.Eigen; +//import org.jmol.util.Eigen; import org.jmol.util.Escape; import org.jmol.util.Matrix3f; +import org.jmol.util.Matrix4f; import org.jmol.util.P3; import org.jmol.util.Tensor; import org.jmol.util.SB; @@ -69,7 +70,7 @@ for (int i = bsSelected.nextSetBit(0); i >= 0; i = bsSelected .nextSetBit(i + 1)) { if (size != 0) - atoms[i].scaleEllipsoid(size, iSelect); + scaleEllipsoid(atoms[i], size, iSelect); boolean isVisible = (madset[0] != null && madset[0].length > i && madset[0][i] > 0 || madset[1] != null && madset[1].length > i && madset[1][i] > 0 || madset[2] != null && madset[2].length > i @@ -79,6 +80,35 @@ } } + void scaleEllipsoid(Atom atom, int size, int iSelect) { + Tensor[] tensors = atom.getTensors(); + Tensor t = (tensors != null && iSelect < tensors.length ? tensors[iSelect] : null); + if (t != null) + tensors[iSelect].setScale(t.forThermalEllipsoid ? getThermalRadius(size) : size < 1 ? 0 : size / 100.0f); + } + + // from ORTEP manual ftp://ftp.ornl.gov/pub/ortep/man/pdf/chap6.pdf + + private static float[] crtval = new float[] { + 0.3389f, 0.4299f, 0.4951f, 0.5479f, 0.5932f, 0.6334f, 0.6699f, 0.7035f, + 0.7349f, 0.7644f, 0.7924f, 0.8192f, 0.8447f, 0.8694f, 0.8932f, 0.9162f, + 0.9386f, 0.9605f, 0.9818f, 1.0026f, 1.0230f, 1.0430f, 1.0627f, 1.0821f, + 1.1012f, 1.1200f, 1.1386f, 1.1570f, 1.1751f, 1.1932f, 1.2110f, 1.2288f, + 1.2464f, 1.2638f, 1.2812f, 1.2985f, 1.3158f, 1.3330f, 1.3501f, 1.3672f, + 1.3842f, 1.4013f, 1.4183f, 1.4354f, 1.4524f, 1.4695f, 1.4866f, 1.5037f, + 1.5209f, 1.5382f, 1.5555f, 1.5729f, 1.5904f, 1.6080f, 1.6257f, 1.6436f, + 1.6616f, 1.6797f, 1.6980f, 1.7164f, 1.7351f, 1.7540f, 1.7730f, 1.7924f, + 1.8119f, 1.8318f, 1.8519f, 1.8724f, 1.8932f, 1.9144f, 1.9360f, 1.9580f, + 1.9804f, 2.0034f, 2.0269f, 2.0510f, 2.0757f, 2.1012f, 2.1274f, 2.1544f, + 2.1824f, 2.2114f, 2.2416f, 2.2730f, 2.3059f, 2.3404f, 2.3767f, 2.4153f, + 2.4563f, 2.5003f, 2.5478f, 2.5997f, 2.6571f, 2.7216f, 2.7955f, 2.8829f, + 2.9912f, 3.1365f, 3.3682f + }; + + final public static float getThermalRadius(int prob) { + return crtval[prob < 1 ? 0 : prob > 99 ? 98 : prob - 1]; + } + @Override public void setProperty(String propertyName, Object value, BS bs) { if (propertyName == "thisID") { @@ -122,63 +152,28 @@ return; } if ("atoms" == propertyName) { - setAtoms((BS) value); + //setPoints(viewer.modelSet.atoms, (BS) value); return; } if ("points" == propertyName) { - setPoints((Object[])value); + //Object[] o = (Object[]) value; + //setPoints((P3[]) o[1], (BS) o[2]); return; } if ("axes" == propertyName) { - ellipsoid.isValid = false; - ellipsoid.axes = (V3[]) value; - ellipsoid.lengths = new float[3]; - ellipsoid.scale = 1; - for (int i = 0; i < 2; i++) { - if (ellipsoid.axes[i].length() > ellipsoid.axes[i + 1].length()) { - V3 v = ellipsoid.axes[i]; - ellipsoid.axes[i] = ellipsoid.axes[i + 1]; - ellipsoid.axes[i + 1] = v; - if (i == 1) - i = -1; - } - } - for (int i = 0; i < 3; i++) { - ellipsoid.lengths[i] = ellipsoid.axes[i].length(); - if (ellipsoid.lengths[i] == 0) - return; - ellipsoid.axes[i].normalize(); - } - if (Math.abs(ellipsoid.axes[0].dot(ellipsoid.axes[1])) > 0.0001f - || Math.abs(ellipsoid.axes[0].dot(ellipsoid.axes[1])) > 0.0001f - || Math.abs(ellipsoid.axes[0].dot(ellipsoid.axes[1])) > 0.0001f) - return; - updateEquation(ellipsoid); + ellipsoid.setAxes((V3[]) value); return; } if ("equation" == propertyName) { - ellipsoid.coef = (double[]) value; - ellipsoid.axes = new V3[3]; - ellipsoid.lengths = new float[3]; - Tensor.getAxesForEllipsoid(ellipsoid.coef, ellipsoid.axes, - ellipsoid.lengths); + ellipsoid.setEquation((double[]) value); return; } if ("center" == propertyName) { - ellipsoid.center = (P3) value; - updateEquation(ellipsoid); + ellipsoid.setCenter((P3) value); return; } if ("scale" == propertyName) { - float scale = ((Float) value).floatValue(); - if (scale <= 0 || ellipsoid.lengths == null) { - ellipsoid.isValid = false; - } else { - for (int i = 0; i < 3; i++) - ellipsoid.lengths[i] *= scale / ellipsoid.scale; - ellipsoid.scale = scale; - updateEquation(ellipsoid); - } + ellipsoid.setScale(((Float) value).floatValue()); return; } if ("color" == propertyName) { @@ -225,91 +220,38 @@ } } - private void setPoints(Object[] data) { - P3[] value = (P3[]) data[1]; - if (value == null) - return; - BS bs = (BS) data[2]; - int n = bs.cardinality(); - if (n < 3) - return; - P3 ptCenter = new P3(); - for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) - ptCenter.add(value[i]); - ptCenter.scale(1.0f/n); - ellipsoid.center = ptCenter; - double Sxx = 0, Syy = 0, Szz = 0, Sxy = 0, Sxz = 0, Syz = 0; - P3 pt = new P3(); - for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { - pt.setT(value[i]); - pt.sub(ptCenter); - Sxx += (double) pt.x * (double) pt.x; - Syy += (double) pt.y * (double) pt.y; - Szz += (double) pt.z * (double) pt.z; - Sxy += (double) pt.x * (double) pt.y; - Sxz += (double) pt.x * (double) pt.z; - Syz += (double) pt.y * (double) pt.z; - } - double[][] N = new double[3][3]; - N[0][0] = Syy + Szz; - N[0][1] = N[1][0] = -Sxy; - N[0][2] = N[2][0] = -Sxz; - N[1][1] = Sxx + Szz; - N[1][2] = N[2][1] = -Syz; - N[2][2] = Sxx + Syy; +// private void setPoints(P3[] points, BS bs) { +// return; + // doesn't really work. Just something I was playing with. +// if (points == null) +// return; +// int n = bs.cardinality(); +// if (n < 3) +// return; +// P3 ptCenter = new P3(); +// for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) +// ptCenter.add(points[i]); +// ptCenter.scale(1.0f/n); +// double Sxx = 0, Syy = 0, Szz = 0, Sxy = 0, Sxz = 0, Syz = 0; +// P3 pt = new P3(); +// for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { +// pt.setT(points[i]); +// pt.sub(ptCenter); +// Sxx += (double) pt.x * (double) pt.x; +// Sxy += (double) pt.x * (double) pt.y; +// Sxz += (double) pt.x * (double) pt.z; +// Syy += (double) pt.y * (double) pt.y; +// Szz += (double) pt.z * (double) pt.z; +// Syz += (double) pt.y * (double) pt.z; +// } +// double[][] N = new double[3][3]; +// N[0][0] = Syy + Szz; +// N[1][1] = Sxx + Szz; +// N[2][2] = Sxx + Syy; +// Eigen eigen = Eigen.newM(N); +// ellipsoid.setEigen(ptCenter, eigen, 1f / n / 3); +// } - Eigen eigen = Eigen.newM(N); - - ellipsoid.axes = eigen.getEigenVectors3(); - double[] v = eigen.getEigenvalues(); - ellipsoid.lengths = new float[3]; - for (int i = 0; i < 3; i++) - ellipsoid.lengths[i] = (float) v[i] / n / 3; - ellipsoid.scale = 1; - updateEquation(ellipsoid); - } - - private void setAtoms(BS bs) { - int n = bs.cardinality(); - if (n == 0) - return; - Atom[] atoms = viewer.modelSet.atoms; - P3 ptCenter = new P3(); - for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) - ptCenter.add(atoms[i]); - ptCenter.scale(1.0f/n); - ellipsoid.center = ptCenter; - double Sxx = 0, Syy = 0, Szz = 0, Sxy = 0, Sxz = 0, Syz = 0; - P3 pt = new P3(); - for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { - pt.setT(atoms[i]); - pt.sub(ptCenter); - Sxx += (double) pt.x * (double) pt.x; - Syy += (double) pt.y * (double) pt.y; - Szz += (double) pt.z * (double) pt.z; - Sxy += (double) pt.x * (double) pt.y; - Sxz += (double) pt.x * (double) pt.z; - Syz += (double) pt.y * (double) pt.z; - } - double[][] N = new double[3][3]; - N[0][0] = Syy + Szz; - N[0][1] = N[1][0] = -Sxy; - N[0][2] = N[2][0] = -Sxz; - N[1][1] = Sxx + Szz; - N[1][2] = N[2][1] = -Syz; - N[2][2] = Sxx + Syy; - - Eigen eigen = Eigen.newM(N); - - ellipsoid.axes = eigen.getEigenVectors3(); - double[] v = eigen.getEigenvalues(); - ellipsoid.lengths = new float[3]; - for (int i = 0; i < 3; i++) - ellipsoid.lengths[i] = (float) v[i] / n / 3; - ellipsoid.scale = 1; - updateEquation(ellipsoid); - } - private void checkSets() { if (colixset == null) { colixset = ArrayUtil.newShort2(3); @@ -318,17 +260,60 @@ } } - private static void updateEquation(Ellipsoid ellipsoid) { - if (ellipsoid.axes == null || ellipsoid.lengths == null) + public static void getEquationForQuadricWithCenter(float x, float y, float z, + Matrix3f mToElliptical, + V3 vTemp, Matrix3f mTemp, + double[] coef, + Matrix4f mDeriv) { + /* Starting with a center point and a matrix that converts cartesian + * or screen coordinates to ellipsoidal coordinates, + * this method fills a float[10] with the terms for the + * equation for the ellipsoid: + * + * c0 x^2 + c1 y^2 + c2 z^2 + c3 xy + c4 xz + c5 yz + c6 x + c7 y + c8 z - 1 = 0 + * + * I made this up; I haven't seen it in print. -- Bob Hanson, 4/2008 + * + */ + + vTemp.set(x, y, z); + mToElliptical.transform(vTemp); + double f = 1 - vTemp.dot(vTemp); // J + mTemp.transposeM(mToElliptical); + mTemp.transform(vTemp); + mTemp.mul(mToElliptical); + coef[0] = mTemp.m00 / f; // A = aXX + coef[1] = mTemp.m11 / f; // B = aYY + coef[2] = mTemp.m22 / f; // C = aZZ + coef[3] = mTemp.m01 * 2 / f; // D = aXY + coef[4] = mTemp.m02 * 2 / f; // E = aXZ + coef[5] = mTemp.m12 * 2 / f; // F = aYZ + coef[6] = -2 * vTemp.x / f; // G = aX + coef[7] = -2 * vTemp.y / f; // H = aY + coef[8] = -2 * vTemp.z / f; // I = aZ + coef[9] = -1; // J = -1 + + /* + * f = Ax^2 + By^2 + Cz^2 + Dxy + Exz + Fyz + Gx + Hy + Iz + J + * df/dx = 2Ax + Dy + Ez + G + * df/dy = Dx + 2By + Fz + H + * df/dz = Ex + Fy + 2Cz + I + */ + + if (mDeriv == null) return; - Matrix3f mat = new Matrix3f(); - Matrix3f mTemp = new Matrix3f(); - V3 v1 = new V3(); - ellipsoid.coef = new double[10]; - Tensor.getEquationForQuadricWithCenter(ellipsoid.center.x, - ellipsoid.center.y, ellipsoid.center.z, mat, v1, mTemp, ellipsoid.coef, - null); - ellipsoid.isValid = true; + mDeriv.setIdentity(); + mDeriv.m00 = (float) (2 * coef[0]); + mDeriv.m11 = (float) (2 * coef[1]); + mDeriv.m22 = (float) (2 * coef[2]); + + mDeriv.m01 = mDeriv.m10 = (float) coef[3]; + mDeriv.m02 = mDeriv.m20 = (float) coef[4]; + mDeriv.m12 = mDeriv.m21 = (float) coef[5]; + + mDeriv.m03 = (float) coef[6]; + mDeriv.m13 = (float) coef[7]; + mDeriv.m23 = (float) coef[8]; } @Override @@ -422,11 +407,83 @@ public boolean isValid; boolean isOn = true; - Ellipsoid(String id, int modelIndex) { + protected Ellipsoid(String id, int modelIndex) { this.id = id; this.modelIndex = modelIndex; } + public void setCenter(P3 center) { + this.center = center; + updateEquation(); + } + + public void setScale(float scale) { + if (scale <= 0 || lengths == null) { + isValid = false; + } else { + for (int i = 0; i < 3; i++) + lengths[i] *= scale / scale; + this.scale = scale; + updateEquation(); + } + } + +// public void setEigen(P3 ptCenter, Eigen eigen, float factor) { +// center = ptCenter; +// axes = eigen.getEigenVectors3(); +// double[] v = eigen.getEigenvalues(); +// lengths = new float[3]; +// for (int i = 0; i < 3; i++) +// lengths[i] = (float) (v[i] * factor); +// scale = 1; +// updateEquation(); +// } + + protected void setEquation(double[] coef) { + Tensor t = new Tensor().setThermal(this.coef = coef); + axes = t.eigenVectors; + lengths = new float[] { t.getLength(0), t.getLength(1), t.getLength(2) }; + } + + protected void setAxes(V3[] axes) { + isValid = false; + this.axes = axes; + lengths = new float[3]; + scale = 1; + for (int i = 0; i < 2; i++) { + if (axes[i].length() > axes[i + 1].length()) { + V3 v = axes[i]; + axes[i] = axes[i + 1]; + axes[i + 1] = v; + if (i == 1) + i = -1; + } + } + for (int i = 0; i < 3; i++) { + lengths[i] = axes[i].length(); + if (lengths[i] == 0) + return; + axes[i].normalize(); + } + if (Math.abs(axes[0].dot(axes[1])) > 0.0001f + || Math.abs(axes[0].dot(axes[1])) > 0.0001f + || Math.abs(axes[0].dot(axes[1])) > 0.0001f) + return; + updateEquation(); + } + + private void updateEquation() { + if (axes == null || lengths == null) + return; + Matrix3f mat = new Matrix3f(); + Matrix3f mTemp = new Matrix3f(); + V3 v1 = new V3(); + coef = new double[10]; + getEquationForQuadricWithCenter(center.x, center.y, center.z, mat, v1, + mTemp, coef, null); + isValid = true; + } + } } Modified: trunk/Jmol/src/org/jmol/symmetry/UnitCell.java =================================================================== --- trunk/Jmol/src/org/jmol/symmetry/UnitCell.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/symmetry/UnitCell.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -294,9 +294,11 @@ */ if (parBorU[0] == 0) { // this is iso - float[] lengths = new float[3]; - lengths[0] = lengths[1] = lengths[2] = (float) Math.sqrt(parBorU[7]); - return new Tensor().fromVectors(null, lengths, 7, true); + float[] eigenValues = new float[3]; + eigenValues[0] = eigenValues[1] = eigenValues[2] = parBorU[7]; + // sqrt will be taken when converted to lengths later + // no factor of 0.5 pi^2 + return new Tensor().setVectors(null, eigenValues, true, 1); } double[] Bcart = new double[6]; @@ -356,7 +358,7 @@ //System.out.println("UnitCell Bcart=" + Bcart[0] + " " + Bcart[1] + " " // + Bcart[2] + " " + Bcart[3] + " " + Bcart[4] + " " + Bcart[5]); - return new Tensor().fromBCart(Bcart); + return new Tensor().setThermal(Bcart); } P3[] getCanonicalCopy(float scale) { Modified: trunk/Jmol/src/org/jmol/util/Eigen.java =================================================================== --- trunk/Jmol/src/org/jmol/util/Eigen.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/util/Eigen.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.Comparator; - //import org.jmol.util.Escape; /** @@ -68,27 +67,31 @@ e = new double[n]; } - + /** + * + * @param m may be 3 or 4 here + * @return Eigen e + */ public static Eigen newM(double[][] m) { Eigen e = new Eigen(m.length); e.calc(m); return e; } - public static void getUnitVectors(double[][] m, V3[] unitVectors, float[] lengths) { - newM(m).set(unitVectors, lengths); - sort(unitVectors, lengths, null); + public static void getUnitVectors(double[][] m, V3[] eigenVectors, + float[] eigenValues) { + newM(m).fillArrays(eigenVectors, eigenValues); + sort(eigenVectors, eigenValues); } - private void set(V3[] unitVectors, float[] lengths) { - float[][] eigenVectors = getEigenvectorsFloatTransposed(); - double[] eigenValues = getRealEigenvalues(); - + private void fillArrays(V3[] eigenVectors, float[] eigenValues) { + float[][] vectors = getEigenvectorsFloatTransposed(); + double[] lambdas = getRealEigenvalues(); for (int i = 0; i < n; i++) { - if (unitVectors[i] == null) - unitVectors[i] = new V3(); - unitVectors[i].setA(eigenVectors[i]); - lengths[i] = (float) Math.sqrt(Math.abs(eigenValues[i])); + if (eigenVectors[i] == null) + eigenVectors[i] = new V3(); + eigenVectors[i].setA(vectors[i]); + eigenValues[i] = (float) lambdas[i]; } } @@ -100,7 +103,7 @@ */ public void calc(double[][] A) { - + /* Jmol only has need of symmetric solutions * issymmetric = true; @@ -113,35 +116,35 @@ if (issymmetric) { */ - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - V[i][j] = A[i][j]; - } + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + V[i][j] = A[i][j]; } + } - // Tridiagonalize. - tred2(); + // Tridiagonalize. + tred2(); - // Diagonalize. - tql2(); - /* - } else { - H = new double[n][n]; - ort = new double[n]; + // Diagonalize. + tql2(); + /* + } else { + H = new double[n][n]; + ort = new double[n]; - for (int j = 0; j < n; j++) { - for (int i = 0; i < n; i++) { - H[i][j] = A[i][j]; + for (int j = 0; j < n; j++) { + for (int i = 0; i < n; i++) { + H[i][j] = A[i][j]; + } } - } - // Reduce to Hessenberg form. - orthes(); + // Reduce to Hessenberg form. + orthes(); - // Reduce Hessenberg to real Schur form. - hqr2(); - } - */ + // Reduce Hessenberg to real Schur form. + hqr2(); + } + */ } @@ -181,11 +184,11 @@ f[j][i] = (float) V[i][j]; return f; } - + public V3[] getEigenVectors3() { V3[] v = new V3[3]; for (int i = 0; i < 3; i++) { - v[i] = V3.new3((float)V[0][i], (float)V[1][i], (float)V[2][i]); + v[i] = V3.new3((float) V[0][i], (float) V[1][i], (float) V[2][i]); } return v; } @@ -199,7 +202,7 @@ * * @serial matrix dimension. */ - private int n; + private int n = 3; /** * Symmetry flag. @@ -1057,15 +1060,15 @@ } public static Tensor getEllipsoidDD(double[][] a) { - Eigen eigen = new Eigen(3); + Eigen eigen = new Eigen(3); eigen.calc(a); Matrix3f m = new Matrix3f(); float[] mm = new float[9]; - for (int i = 0, p=0; i < 3; i++) + for (int i = 0, p = 0; i < 3; i++) for (int j = 0; j < 3; j++) mm[p++] = (float) a[i][j]; m.setA(mm); - + V3[] evec = eigen.getEigenVectors3(); V3 n = new V3(); V3 cross = new V3(); @@ -1076,65 +1079,58 @@ //Logger.info("v[i], n, n x v[i]"+ evec[i] + " " + n + " " + cross); n.setT(evec[i]); n.normalize(); - cross.cross(evec[i], evec[(i + 1)%3]); + cross.cross(evec[i], evec[(i + 1) % 3]); //Logger.info("draw id eigv" + i + " " + Escape.eP(evec[i]) + " color " + (i == 0 ? "red": i == 1 ? "green" : "blue") + " # " + n + " " + cross); } - Logger.info("eigVal+vec (" + eigen.d[0] + " + " + eigen.e[0] - + ")\n (" + eigen.d[1] + " + " + eigen.e[1] + Logger.info("eigVal+vec (" + eigen.d[0] + " + " + eigen.e[0] + + ")\n (" + eigen.d[1] + " + " + eigen.e[1] + ")\n (" + eigen.d[2] + " + " + eigen.e[2] + ")"); - + V3[] unitVectors = new V3[3]; - float[] lengths = new float[3]; - eigen.set(unitVectors, lengths); - int mask = sort(unitVectors, lengths, eigen.d); - return new Tensor().fromVectors(unitVectors, lengths, mask, false); + float[] eigenValues = new float[3]; + eigen.fillArrays(unitVectors, eigenValues); + return new Tensor().setVectors(unitVectors, eigenValues, false, 1); } - public static Tensor getEllipsoid(V3[] vectors, float[] lengths, boolean isThermal) { + public static Tensor getEllipsoid(V3[] eigenVectors, float[] eigenValues, + boolean isThermal) { //[0] is shortest; [2] is longest - V3[] unitVectors = new V3[vectors.length]; - for (int i = vectors.length; --i >= 0;) - unitVectors[i] = V3.newV(vectors[i]); - sort(unitVectors, lengths, null); - return new Tensor().fromVectors(unitVectors, lengths, 7, isThermal); + V3[] unitVectors = new V3[3]; + for (int i = eigenVectors.length; --i >= 0;) + unitVectors[i] = V3.newV(eigenVectors[i]); + sort(unitVectors, eigenValues); + return new Tensor().setVectors(unitVectors, eigenValues, isThermal, 1); } /** * sorts vectors by absolute value and normalizes them - * @param vectors - * @param lengths - * @param values - * @return mask 0 - 7 -- 1 for positive, 0 for negative eigenvalue + * + * @param eigenVectors + * @param eigenValues */ - private static int sort(V3[] vectors, float[] lengths, double[] values) { - // for atoms, lengths need to have length 3 to allow for scaling + private static void sort(V3[] eigenVectors, float[] eigenValues) { Object[][] o = new Object[][] { - new Object[] { vectors[0], Float.valueOf(Math.abs(lengths[0])), values == null || values[0] >= 0 ? Boolean.TRUE : null }, - new Object[] { vectors[1], Float.valueOf(Math.abs(lengths[1])), values == null || values[1] >= 0 ? Boolean.TRUE : null }, - new Object[] { vectors[2], Float.valueOf(Math.abs(lengths[2])), values == null || values[2] >= 0 ? Boolean.TRUE : null } }; + new Object[] { eigenVectors[0], Float.valueOf(eigenValues[0]) }, + new Object[] { eigenVectors[1], Float.valueOf(eigenValues[1]) }, + new Object[] { eigenVectors[2], Float.valueOf(eigenValues[2]) } }; Arrays.sort(o, new EigenSort()); - - int mask = 0; for (int i = 0; i < 3; i++) { - vectors[i] = V3.newV((V3) o[i][0]); - vectors[i].normalize(); - lengths[i] = ((Float) o[i][1]).floatValue(); - if (o[i][2] != null) - mask += 1 << i; + eigenVectors[i] = V3.newV((V3) o[i][0]); + eigenVectors[i].normalize(); + eigenValues[i] = ((Float) o[i][1]).floatValue(); } - return mask; } - + /** - * sort from smallest to largest + * sort from smallest to largest absolute * */ - protected static class EigenSort implements Comparator<Object[]> { + protected static class EigenSort implements Comparator<Object[]> { public int compare(Object[] o1, Object[] o2) { - float a = ((Float)o1[1]).floatValue(); - float b = ((Float)o2[1]).floatValue(); + float a = Math.abs(((Float) o1[1]).floatValue()); + float b = Math.abs(((Float) o2[1]).floatValue()); return (a < b ? -1 : a > b ? 1 : 0); - } + } } } Modified: trunk/Jmol/src/org/jmol/util/Tensor.java =================================================================== --- trunk/Jmol/src/org/jmol/util/Tensor.java 2013-06-27 16:03:02 UTC (rev 18375) +++ trunk/Jmol/src/org/jmol/util/Tensor.java 2013-06-27 21:26:13 UTC (rev 18376) @@ -28,15 +28,77 @@ public float[] eigenValues; public V3[] eigenVectors; - public boolean isThermalEllipsoid = true; + public boolean forThermalEllipsoid = true; public float scale = 1; + public float typeFactor = 1; public int eigenSignMask = 7; + private float[] lengths; - public void setScale(float f) { - for (int i = 0; i < 3; i++) - eigenValues[i] *= f; + private static float ONE_OVER_ROOT2_PI = (float) (Math.sqrt(0.5) / Math.PI); + + public Tensor setThermal(double[] coef) { + forThermalEllipsoid = true; + eigenValues = new float[3]; + eigenVectors = new V3[3]; + // assumes an ellipsoid centered on 0,0,0 + // called by UnitCell for the initial creation of Object[] ellipsoid + double[][] mat = new double[3][3]; + mat[0][0] = coef[0]; //XX + mat[1][1] = coef[1]; //YY + mat[2][2] = coef[2]; //ZZ + mat[0][1] = mat[1][0] = coef[3] / 2; //XY + mat[0][2] = mat[2][0] = coef[4] / 2; //XZ + mat[1][2] = mat[2][1] = coef[5] / 2; //YZ + Eigen.getUnitVectors(mat, eigenVectors, eigenValues); + typeFactor = ONE_OVER_ROOT2_PI; + eigenSignMask = 7; + return this; } + + /** + * + * @param eigenVectors may be null, in which case typeFactor = 1 + * @param eigenValues + * @param forThermalEllipsoid + * @param typeFactor + * @return this tensor + */ + public Tensor setVectors(V3[] eigenVectors, float[] eigenValues, boolean forThermalEllipsoid, float typeFactor) { + this.eigenVectors = eigenVectors; + this.eigenValues = eigenValues; + this.forThermalEllipsoid = forThermalEllipsoid; + this.typeFactor = typeFactor; + eigenSignMask = (eigenValues[0] >= 0 ? 1 : 0) + (eigenValues[1] >= 0 ? 2 : 0) + (eigenValues[2] >= 0 ? 4 : 0); + return this; + } + + public void setTypeFactor(float f) { + typeFactor = f; + lengths = null; + } + public void setScale(float scale) { + this.scale = scale; + lengths = null; + } + + public float getLength(int i) { + if (lengths == null) + setLengths(); + return lengths[i]; + } + + public void setLengths() { + if (lengths == null) + lengths = new float[3]; + if (forThermalEllipsoid) + for (int i = 0; i < lengths.length; i++) + lengths[i] = (float) (Math.sqrt(Math.abs(eigenValues[i])) * typeFactor * scale); + else + for (int i = 0; i < lengths.length; i++) + lengths[i] = (Math.abs(eigenValues[i]) * typeFactor * scale); + } + @Override public String toString() { return (eigenVectors == null ? "" + eigenValues[0] : @@ -45,15 +107,6 @@ + eigenVectors[2] + "\t" + eigenValues[2] + "\n"); } - public Tensor fromVectors(V3[] eigenVectors, float[] eigenValues, - int eigenSignMask, boolean isThermal) { - this.eigenVectors = eigenVectors; - this.eigenValues = eigenValues; - this.eigenSignMask = eigenSignMask; - isThermalEllipsoid = isThermal; - return this; - } - ////////// Ellipsoid Code /////////// // // Bob Hanson, 4/2008 @@ -64,141 +117,12 @@ // ////////////////////////////////////// - private static float ONE_OVER_ROOT2_PI = (float) (Math.sqrt(0.5) / Math.PI); - public Tensor fromBCart(double[] bcart) { - isThermalEllipsoid = true; - eigenValues = new float[3]; - eigenVectors = new V3[3]; - getAxesForEllipsoid(bcart, eigenVectors, eigenValues); - - for (int i = 0; i < 3; i++) - eigenValues[i] *= ONE_OVER_ROOT2_PI; - return this; - } - public void rotate(Matrix4f mat) { if (eigenVectors != null) for (int i = 0; i < 3; i++) mat.transformV(eigenVectors[i]); } - public void setSize(int size) { - scale = (isThermalEllipsoid ? Tensor.getThermalRadius(size) : size < 1 ? 0 : size / 100.0f); - } - - public static void getAxesForEllipsoid(double[] coef, V3[] unitVectors, float[] lengths) { - - // assumes an ellipsoid centered on 0,0,0 - // called by UnitCell for the initial creation of Object[] ellipsoid - - double[][] mat = new double[3][3]; - mat[0][0] = coef[0]; //XX - mat[1][1] = coef[1]; //YY - mat[2][2] = coef[2]; //ZZ - mat[0][1] = mat[1][0] = coef[3] / 2; //XY - mat[0][2] = mat[2][0] = coef[4] / 2; //XZ - mat[1][2] = mat[2][1] = coef[5] / 2; //YZ - Eigen.getUnitVectors(mat, unitVectors, lengths); - } - - public static Matrix3f setEllipsoidMatrix(V3[] unitAxes, float[] lengths, V3 vTemp, Matrix3f mat) { - /* - * Create a matrix that transforms cartesian coordinates - * into ellipsoidal coordinates, where in that system we - * are drawing a sphere. - * - */ - - for (int i = 0; i < 3; i++) { - vTemp.setT(unitAxes[i]); - vTemp.scale(lengths[i]); - mat.setColumnV(i, vTemp); - } - mat.invertM(mat); - return mat; - } - - public static void getEquationForQuadricWithCenter(float x, float y, float z, Matrix3f mToElliptical, - V3 vTemp, Matrix3f mTemp, double[] coef, Matrix4f mDeriv) { - /* Starting with a center point and a matrix that converts cartesian - * or screen coordinates to ellipsoidal coordinates, - * this method fills a float[10] with the terms for the - * equation for the ellipsoid: - * - * c0 x^2 + c1 y^2 + c2 z^2 + c3 xy + c4 xz + c5 yz + c6 x + c7 y + c8 z - 1 = 0 - * - * I made this up; I haven't seen it in print. -- Bob Hanson, 4/2008 - * - */ - - vTemp.set(x, y, z); - mToElliptical.transform(vTemp); - double f = 1 - vTemp.dot(vTemp); // J - mTemp.transposeM(mToElliptical); - mTemp.transform(vTemp); - mTemp.mul(mToElliptical); - coef[0] = mTemp.m00 / f; // A = aXX - coef[1] = mTemp.m11 / f; // B = aYY - coef[2] = mTemp.m22 / f; // C = aZZ - coef[3] = mTemp.m01 * 2 / f; // D = aXY - coef[4] = mTemp.m02 * 2 / f; // E = aXZ - coef[5] = mTemp.m12 * 2 / f; // F = aYZ - coef[6] = -2 * vTemp.x / f; // G = aX - coef[7] = -2 * vTemp.y / f; // H = aY - coef[8] = -2 * vTemp.z / f; // I = aZ - coef[9] = -1; // J = -1 - - /* - * f = Ax^2 + By^2 + Cz^2 + Dxy + Exz + Fyz + Gx + Hy + Iz + J - * df/dx = 2Ax + Dy + Ez + G - * df/dy = Dx + 2By + Fz + H - * df/dz = Ex + Fy + 2Cz + I - */ - - if (mDeriv == null) - return; - mDeriv.setIdentity(); - mDeriv.m00 = (float) (2 * coef[0]); - mDeriv.m11 = (float) (2 * coef[1]); - mDeriv.m22 = (float) (2 * coef[2]); - - mDeriv.m01 = mDeriv.m10 = (float) coef[3]; - mDeriv.m02 = mDeriv.m20 = (float) coef[4]; - mDeriv.m12 = mDeriv.m21 = (float) coef[5]; - - mDeriv.m03 = (float) coef[6]; - mDeriv.m13 = (float) coef[7]; - mDeriv.m23 = (float) coef[8]; - } - - public static boolean getQuardricZ(double x, double y, - double[] coef, double[] zroot) { - - /* simple quadratic formula for: - * - * c0 x^2 + c1 y^2 + c2 z^2 + c3 xy + c4 xz + c5 yz + c6 x + c7 y + c8 z - 1 = 0 - * - * or: - * - * c2 z^2 + (c4 x + c5 y + c8)z + (c0 x^2 + c1 y^2 + c3 xy + c6 x + c7 y - 1) = 0 - * - * so: - * - * z = -(b/2a) +/- sqrt( (b/2a)^2 - c/a ) - */ - - double b_2a = (coef[4] * x + coef[5] * y + coef[8]) / coef[2] / 2; - double c_a = (coef[0] * x * x + coef[1] * y * y + coef[3] * x * y - + coef[6] * x + coef[7] * y - 1) / coef[2]; - double f = b_2a * b_2a - c_a; - if (f < 0) - return false; - f = Math.sqrt(f); - zroot[0] = (-b_2a - f); - zroot[1] = (-b_2a + f); - return true; - } - public static int getOctant(P3 pt) { int i = 0; if (pt.x < 0) @@ -210,27 +134,4 @@ return i; } - // from ORTEP manual ftp://ftp.ornl.gov/pub/ortep/man/pdf/chap6.pdf - - private static float[] crtval = new float[] { - 0.3389f, 0.4299f, 0.4951f, 0.5479f, 0.5932f, 0.6334f, 0.6699f, 0.7035f, - 0.7349f, 0.7644f, 0.7924f, 0.8192f, 0.8447f, 0.8694f, 0.8932f, 0.9162f, - 0.9386f, 0.9605f, 0.9818f, 1.0026f, 1.0230f, 1.0430f, 1.0627f, 1.0821f, - 1.1012f, 1.1200f, 1.1386f, 1.1570f, 1.1751f, 1.1932f, 1.2110f, 1.2288f, - 1.2464f, 1.2638f, 1.2812f, 1.2985f, 1.3158f, 1.3330f, 1.3501f, 1.3672f, - 1.3842f, 1.4013f, 1.4183f, 1.4354f, 1.4524f, 1.4695f, 1.4866f, 1.5037f, - 1.5209f, 1.5382f, 1.5555f, 1.5729f, 1.5904f, 1.6080f, 1.6257f, 1.6436f, - 1.6616f, 1.6797f, 1.6980f, 1.7164f, 1.7351f, 1.7540f, 1.7730f, 1.7924f, - 1.8119f, 1.8318f, 1.8519f, 1.8724f, 1.8932f, 1.9144f, 1.9360f, 1.9580f, - 1.9804f, 2.0034f, 2.0269f, 2.0510f, 2.0757f, 2.1012f, 2.1274f, 2.1544f, - 2.1824f, 2.2114f, 2.2416f, 2.2730f, 2.3059f, 2.3404f, 2.3767f, 2.4153f, - 2.4563f, 2.5003f, 2.5478f, 2.5997f, 2.6571f, 2.7216f, 2.7955f, 2.8829f, - 2.9912f, 3.1365f, 3.3682f - }; - - final public static float getThermalRadius(int prob) { - return crtval[prob < 1 ? 0 : prob > 99 ? 98 : prob - 1]; - } - - } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits