molstar
Version:
A comprehensive macromolecular library.
216 lines • 9.14 kB
JavaScript
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { lerp as scalar_lerp } from '../../mol-math/interpolate';
import { defaults } from '../../mol-util';
import { Mat3 } from '../linear-algebra/3d/mat3';
import { Mat4 } from '../linear-algebra/3d/mat4';
import { Quat } from '../linear-algebra/3d/quat';
import { Vec3 } from '../linear-algebra/3d/vec3';
var SymmetryOperator;
(function (SymmetryOperator) {
SymmetryOperator.DefaultName = '1_555';
SymmetryOperator.Default = create(SymmetryOperator.DefaultName, Mat4.identity());
SymmetryOperator.RotationTranslationEpsilon = 0.005;
function create(name, matrix, info) {
var _a = info || {}, assembly = _a.assembly, ncsId = _a.ncsId, hkl = _a.hkl, spgrOp = _a.spgrOp;
var _hkl = hkl ? Vec3.clone(hkl) : Vec3();
spgrOp = defaults(spgrOp, -1);
ncsId = ncsId || -1;
var suffix = getSuffix(info);
if (Mat4.isIdentity(matrix))
return { name: name, assembly: assembly, matrix: matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp: spgrOp, ncsId: ncsId, suffix: suffix };
if (!Mat4.isRotationAndTranslation(matrix, SymmetryOperator.RotationTranslationEpsilon))
throw new Error("Symmetry operator (" + name + ") must be a composition of rotation and translation.");
return { name: name, assembly: assembly, matrix: matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp: spgrOp, ncsId: ncsId, suffix: suffix };
}
SymmetryOperator.create = create;
function getSuffix(info) {
if (!info)
return '';
if (info.assembly) {
return "_" + info.assembly.operId;
}
if (typeof info.spgrOp !== 'undefined' && typeof info.hkl !== 'undefined' && info.spgrOp !== -1) {
var _a = info.hkl, i = _a[0], j = _a[1], k = _a[2];
return "-" + (info.spgrOp + 1) + "_" + (5 + i) + (5 + j) + (5 + k);
}
if (info.ncsId !== -1) {
return "_" + info.ncsId;
}
return '';
}
function checkIfRotationAndTranslation(rot, offset) {
var matrix = Mat4.identity();
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
Mat4.setValue(matrix, i, j, Mat3.getValue(rot, i, j));
}
}
Mat4.setTranslation(matrix, offset);
return Mat4.isRotationAndTranslation(matrix, SymmetryOperator.RotationTranslationEpsilon);
}
SymmetryOperator.checkIfRotationAndTranslation = checkIfRotationAndTranslation;
function ofRotationAndOffset(name, rot, offset, ncsId) {
var t = Mat4.identity();
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
Mat4.setValue(t, i, j, Mat3.getValue(rot, i, j));
}
}
Mat4.setTranslation(t, offset);
return create(name, t, { ncsId: ncsId });
}
SymmetryOperator.ofRotationAndOffset = ofRotationAndOffset;
var _q1 = Quat.identity(), _q2 = Quat(), _q3 = Quat(), _axis = Vec3();
function lerpFromIdentity(out, op, t) {
var m = op.inverse;
if (op.isIdentity)
return Mat4.copy(out, m);
var _t = 1 - t;
// interpolate rotation
Mat4.getRotation(_q2, m);
Quat.slerp(_q2, _q1, _q2, _t);
var angle = Quat.getAxisAngle(_axis, _q2);
Mat4.fromRotation(out, angle, _axis);
// interpolate translation
Mat4.setValue(out, 0, 3, _t * Mat4.getValue(m, 0, 3));
Mat4.setValue(out, 1, 3, _t * Mat4.getValue(m, 1, 3));
Mat4.setValue(out, 2, 3, _t * Mat4.getValue(m, 2, 3));
return out;
}
SymmetryOperator.lerpFromIdentity = lerpFromIdentity;
function slerp(out, src, tar, t) {
if (Math.abs(t) <= 0.00001)
return Mat4.copy(out, src);
if (Math.abs(t - 1) <= 0.00001)
return Mat4.copy(out, tar);
// interpolate rotation
Mat4.getRotation(_q2, src);
Mat4.getRotation(_q3, tar);
Quat.slerp(_q3, _q2, _q3, t);
var angle = Quat.getAxisAngle(_axis, _q3);
Mat4.fromRotation(out, angle, _axis);
// interpolate translation
Mat4.setValue(out, 0, 3, scalar_lerp(Mat4.getValue(src, 0, 3), Mat4.getValue(tar, 0, 3), t));
Mat4.setValue(out, 1, 3, scalar_lerp(Mat4.getValue(src, 1, 3), Mat4.getValue(tar, 1, 3), t));
Mat4.setValue(out, 2, 3, scalar_lerp(Mat4.getValue(src, 2, 3), Mat4.getValue(tar, 2, 3), t));
return out;
}
SymmetryOperator.slerp = slerp;
/**
* Apply the 1st and then 2nd operator. ( = second.matrix * first.matrix).
* Keep `name`, `assembly`, `ncsId`, `hkl` and `spgrOpId` properties from second.
*/
function compose(first, second) {
var matrix = Mat4.mul(Mat4(), second.matrix, first.matrix);
return create(second.name, matrix, second);
}
SymmetryOperator.compose = compose;
function createMapping(operator, coords, radius) {
var invariantPosition = SymmetryOperator.createCoordinateMapper(SymmetryOperator.Default, coords);
var position = operator.isIdentity ? invariantPosition : SymmetryOperator.createCoordinateMapper(operator, coords);
var _a = createProjections(operator, coords), x = _a.x, y = _a.y, z = _a.z;
return { operator: operator, coordinates: coords, invariantPosition: invariantPosition, position: position, x: x, y: y, z: z, r: radius ? radius : _zeroRadius };
}
SymmetryOperator.createMapping = createMapping;
function createCoordinateMapper(t, coords) {
if (t.isIdentity)
return identityPosition(coords);
return generalPosition(t, coords);
}
SymmetryOperator.createCoordinateMapper = createCoordinateMapper;
})(SymmetryOperator || (SymmetryOperator = {}));
export { SymmetryOperator };
function _zeroRadius(i) { return 0; }
function createProjections(t, coords) {
if (t.isIdentity)
return { x: projectCoord(coords.x), y: projectCoord(coords.y), z: projectCoord(coords.z) };
return { x: projectX(t, coords), y: projectY(t, coords), z: projectZ(t, coords) };
}
function projectCoord(xs) {
return function projectCoord(i) {
return xs[i];
};
}
function isW1(m) {
return m[3] === 0 && m[7] === 0 && m[11] === 0 && m[15] === 1;
}
function projectX(_a, _b) {
var m = _a.matrix;
var xs = _b.x, ys = _b.y, zs = _b.z;
var xx = m[0], yy = m[4], zz = m[8], tx = m[12];
if (isW1(m)) {
// this should always be the case.
return function projectX_W1(i) {
return xx * xs[i] + yy * ys[i] + zz * zs[i] + tx;
};
}
return function projectX(i) {
var x = xs[i], y = ys[i], z = zs[i], w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0;
return (xx * x + yy * y + zz * z + tx) / w;
};
}
function projectY(_a, _b) {
var m = _a.matrix;
var xs = _b.x, ys = _b.y, zs = _b.z;
var xx = m[1], yy = m[5], zz = m[9], ty = m[13];
if (isW1(m)) {
// this should always be the case.
return function projectY_W1(i) {
return xx * xs[i] + yy * ys[i] + zz * zs[i] + ty;
};
}
return function projectY(i) {
var x = xs[i], y = ys[i], z = zs[i], w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0;
return (xx * x + yy * y + zz * z + ty) / w;
};
}
function projectZ(_a, _b) {
var m = _a.matrix;
var xs = _b.x, ys = _b.y, zs = _b.z;
var xx = m[2], yy = m[6], zz = m[10], tz = m[14];
if (isW1(m)) {
// this should always be the case.
return function projectZ_W1(i) {
return xx * xs[i] + yy * ys[i] + zz * zs[i] + tz;
};
}
return function projectZ(i) {
var x = xs[i], y = ys[i], z = zs[i], w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0;
return (xx * x + yy * y + zz * z + tz) / w;
};
}
function identityPosition(_a) {
var x = _a.x, y = _a.y, z = _a.z;
return function identityPosition(i, s) {
s[0] = x[i];
s[1] = y[i];
s[2] = z[i];
return s;
};
}
function generalPosition(_a, _b) {
var m = _a.matrix;
var xs = _b.x, ys = _b.y, zs = _b.z;
if (isW1(m)) {
// this should always be the case.
return function generalPosition_W1(i, r) {
var x = xs[i], y = ys[i], z = zs[i];
r[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
r[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
r[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
return r;
};
}
return function generalPosition(i, r) {
r[0] = xs[i];
r[1] = ys[i];
r[2] = zs[i];
Vec3.transformMat4(r, r, m);
return r;
};
}
//# sourceMappingURL=symmetry-operator.js.map