int tok;
Quaternion q = null;
boolean helicalPath = false;
List ptsB = null;
BitSet bsCompare = null;
Point3f invPoint = null;
Point4f invPlane = null;
boolean axesOrientationRasmol = viewer.getAxesOrientationRasmol();
for (int i = 1; i < statementLength; ++i) {
switch (tok = getToken(i).tok) {
case Token.bitset:
case Token.expressionBegin:
case Token.leftbrace:
case Token.point3f:
case Token.dollarsign:
if (tok == Token.bitset || tok == Token.expressionBegin) {
if (translation != null || q != null || nPoints == 2) {
bsAtoms = atomExpression(i);
ptsB = null;
isSelected = true;
break;
}
}
haveRotation = true;
if (nPoints == 2)
nPoints = 0;
// {X, Y, Z}
// $drawObject[n]
Point3f pt1 = centerParameter(i, viewer.getCurrentModelIndex());
if (!isSyntaxCheck && tok == Token.dollarsign
&& tokAt(i + 2) != Token.leftsquare) {
// rotation about an axis such as $line1
isMolecular = true;
rotAxis = getDrawObjectAxis(objectNameParameter(++i), viewer
.getCurrentModelIndex());
}
points[nPoints++] = pt1;
break;
case Token.spin:
isSpin = true;
continue;
case Token.internal:
case Token.molecular:
isMolecular = true;
continue;
case Token.selected:
isSelected = true;
break;
case Token.comma:
continue;
case Token.integer:
case Token.decimal:
if (endDegrees == Float.MAX_VALUE) {
endDegrees = floatParameter(i);
} else {
degreesPerSecond = floatParameter(i);
isSpin = (degreesPerSecond != 0);
}
continue;
case Token.minus:
direction = -1;
continue;
case Token.x:
haveRotation = true;
rotAxis.set(direction, 0, 0);
continue;
case Token.y:
haveRotation = true;
rotAxis.set(0, (axesOrientationRasmol && !isMolecular ? -direction
: direction), 0);
continue;
case Token.z:
haveRotation = true;
rotAxis.set(0, 0, direction);
continue;
// 11.6 options
case Token.point4f:
case Token.quaternion:
if (tok == Token.quaternion)
i++;
haveRotation = true;
q = getQuaternionParameter(i);
rotAxis.set(q.getNormal());
endDegrees = q.getTheta();
break;
case Token.axisangle:
haveRotation = true;
if (isPoint3f(++i)) {
rotAxis.set(centerParameter(i));
break;
}
Point4f p4 = getPoint4f(i);
rotAxis.set(p4.x, p4.y, p4.z);
endDegrees = p4.w;
q = new Quaternion(rotAxis, endDegrees);
break;
case Token.branch:
haveRotation = true;
int iAtom1 = atomExpression(++i).nextSetBit(0);
int iAtom2 = atomExpression(++iToken).nextSetBit(0);
if (iAtom1 < 0 || iAtom2 < 0)
return;
bsAtoms = viewer.getBranchBitSet(iAtom2, iAtom1);
isSelected = true;
isMolecular = true;
points[0] = viewer.getAtomPoint3f(iAtom1);
points[1] = viewer.getAtomPoint3f(iAtom2);
nPoints = 2;
break;
// 12.0 options
case Token.translate:
translation = new Vector3f(centerParameter(++i));
isMolecular = isSelected = true;
break;
case Token.helix:
// screw motion, for quaternion-based operations
helicalPath = true;
continue;
case Token.symop:
int symop = intParameter(++i);
if (isSyntaxCheck)
continue;
Hashtable info = viewer.getSpaceGroupInfo(null);
Object[] op = (info == null ? null : (Object[]) info.get("operations"));
if (symop == 0 || op == null || op.length < Math.abs(symop))
error(ERROR_invalidArgument);
op = (Object[]) op[Math.abs(symop) - 1];
translation = (Vector3f) op[5];
invPoint = (Point3f) op[6];
points[0] = (Point3f) op[7];
if (op[8] != null)
rotAxis = (Vector3f) op[8];
endDegrees = ((Integer) op[9]).intValue();
if (symop < 0) {
endDegrees = -endDegrees;
if (translation != null)
translation.scale(-1);
}
if (endDegrees == 0 && points[0] != null) {
// glide plane
invPlane = Measure.getPlaneThroughPoint(points[0], rotAxis);
}
q = new Quaternion(rotAxis, endDegrees);
nPoints = (points[0] == null ? 0 : 1);
isMolecular = true;
haveRotation = true;
isSelected = true;
continue;
case Token.compare:
case Token.matrix4f:
case Token.matrix3f:
haveRotation = true;
if (tok == Token.compare) {
bsCompare = atomExpression(++i);
ptsA = viewer.getAtomPointVector(bsCompare);
if (ptsA == null)
error(ERROR_invalidArgument, i);
i = iToken;
ptsB = getPointVector(getToken(++i), i);
if (ptsB == null || ptsA.size() != ptsB.size())
error(ERROR_invalidArgument, i);
m4 = new Matrix4f();
points[0] = new Point3f();
nPoints = 1;
float stddev = (isSyntaxCheck ? 0 : Measure.getTransformMatrix4(ptsA,
ptsB, m4, points[0]));
// if the standard deviation is very small, we leave ptsB
// because it will be used to set the absolute final positions
if (stddev > 0.001)
ptsB = null;
} else if (tok == Token.matrix4f) {
m4 = (Matrix4f) theToken.value;
}
m3 = new Matrix3f();
if (m4 != null) {
translation = new Vector3f();
m4.get(translation);
m4.get(m3);
} else {
m3 = (Matrix3f) theToken.value;
}
q = (isSyntaxCheck ? new Quaternion() : new Quaternion(m3));
rotAxis.set(q.getNormal());
endDegrees = q.getTheta();
isMolecular = true;
break;
default:
error(ERROR_invalidArgument);
}
i = iToken;
}
if (isSyntaxCheck)
return;
if (isSelected && bsAtoms == null)
bsAtoms = viewer.getSelectionSet(false);
if (bsCompare != null) {
isSelected = true;
if (bsAtoms == null)
bsAtoms = bsCompare;
}
float rate = (degreesPerSecond == Float.MIN_VALUE ? 10
: degreesPerSecond < 0 ?
// -n means number of seconds, not degreesPerSecond
-endDegrees / degreesPerSecond
: degreesPerSecond);
if (q != null) {
// only when there is a translation (4x4 matrix or TRANSLATE)
// do we set the rotation to be the center of the selected atoms or model
if (nPoints == 0 && translation != null)
points[0] = viewer.getAtomSetCenter(bsAtoms != null ? bsAtoms
: isSelected ? viewer.getSelectionSet(false) : viewer
.getModelUndeletedAtomsBitSet(-1));
if (helicalPath && translation != null) {
points[1] = new Point3f(points[0]);
points[1].add(translation);
Object[] ret = (Object[]) Measure.computeHelicalAxis(null, Token.array,
points[0], points[1], q);
points[0] = (Point3f) ret[0];
float theta = ((Point3f) ret[3]).x;
if (theta != 0) {
translation = (Vector3f) ret[1];
rotAxis = new Vector3f(translation);
if (theta < 0)
rotAxis.scale(-1);
}
m4 = null;
}
if (isSpin && m4 == null)
m4 = ScriptMathProcessor.getMatrix4f(q.getMatrix(), translation);
if (points[0] != null)
nPoints = 1;
}
if (invPoint != null) {
viewer.invertAtomCoord(invPoint, bsAtoms);
if (rotAxis == null)
return;
}
if (invPlane != null) {
viewer.invertAtomCoord(invPlane, bsAtoms);
if (rotAxis == null)
return;
}
if (nPoints < 2) {
if (!isMolecular) {
// fixed-frame rotation
// rotate x 10 # Chime-like
// rotate axisangle {0 1 0} 10
// rotate x 10 (atoms) # point-centered
// rotate x 10 $object # point-centered
viewer.rotateAxisAngleAtCenter(points[0], rotAxis, rate, endDegrees,
isSpin, bsAtoms);
return;
}
if (nPoints == 0)
points[0] = new Point3f();
// rotate MOLECULAR
// rotate MOLECULAR (atom1)
// rotate MOLECULAR x 10 (atom1)
// rotate axisangle MOLECULAR (atom1)
points[1] = new Point3f(points[0]);
points[1].add(rotAxis);
nPoints = 2;
}
if (nPoints == 0)
points[0] = new Point3f();
if (nPoints < 2 || points[0].distance(points[1]) == 0) {
points[1] = new Point3f(points[0]);
points[1].y += 1.0;
}
if (endDegrees == Float.MAX_VALUE)
endDegrees = 0;
if (endDegrees != 0 && translation != null && !haveRotation)