molstar
Version:
A comprehensive macromolecular library.
257 lines • 16.9 kB
JavaScript
/**
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DihedralRepresentation = exports.DihedralParams = void 0;
var tslib_1 = require("tslib");
var loci_1 = require("../../../mol-model/loci");
var lines_1 = require("../../../mol-geo/geometry/lines/lines");
var text_1 = require("../../../mol-geo/geometry/text/text");
var param_definition_1 = require("../../../mol-util/param-definition");
var names_1 = require("../../../mol-util/color/names");
var representation_1 = require("../representation");
var representation_2 = require("../../representation");
var shape_1 = require("../../../mol-model/shape");
var lines_builder_1 = require("../../../mol-geo/geometry/lines/lines-builder");
var text_builder_1 = require("../../../mol-geo/geometry/text/text-builder");
var linear_algebra_1 = require("../../../mol-math/linear-algebra");
var mesh_1 = require("../../../mol-geo/geometry/mesh/mesh");
var mesh_builder_1 = require("../../../mol-geo/geometry/mesh/mesh-builder");
var misc_1 = require("../../../mol-math/misc");
var circle_1 = require("../../../mol-geo/primitive/circle");
var primitive_1 = require("../../../mol-geo/primitive/primitive");
var marker_action_1 = require("../../../mol-util/marker-action");
var label_1 = require("../../../mol-theme/label");
var common_1 = require("./common");
var geometry_1 = require("../../../mol-math/geometry");
var SharedParams = {
color: param_definition_1.ParamDefinition.Color(names_1.ColorNames.lightgreen),
arcScale: param_definition_1.ParamDefinition.Numeric(0.7, { min: 0.01, max: 1, step: 0.01 })
};
var LinesParams = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, lines_1.Lines.Params), SharedParams), { lineSizeAttenuation: param_definition_1.ParamDefinition.Boolean(true), linesSize: param_definition_1.ParamDefinition.Numeric(0.04, { min: 0.01, max: 5, step: 0.01 }), dashLength: param_definition_1.ParamDefinition.Numeric(0.04, { min: 0.01, max: 0.2, step: 0.01 }) });
var VectorsParams = (0, tslib_1.__assign)({}, LinesParams);
var ExtendersParams = (0, tslib_1.__assign)({}, LinesParams);
var ArmsParams = (0, tslib_1.__assign)({}, LinesParams);
var ArcParams = (0, tslib_1.__assign)({}, LinesParams);
var SectorParams = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, mesh_1.Mesh.Params), SharedParams), { ignoreLight: param_definition_1.ParamDefinition.Boolean(true), sectorOpacity: param_definition_1.ParamDefinition.Numeric(0.75, { min: 0, max: 1, step: 0.01 }) });
var DihedralVisuals = {
'vectors': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getVectorsShape, lines_1.Lines.Utils, { modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { pickable: false })); } }); },
'extenders': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getExtendersShape, lines_1.Lines.Utils, { modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { pickable: false })); } }); },
'connector': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getConnectorShape, lines_1.Lines.Utils, { modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { pickable: false })); } }); },
'arms': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getArmsShape, lines_1.Lines.Utils, { modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { pickable: false })); } }); },
'arc': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getArcShape, lines_1.Lines.Utils, { modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { pickable: false })); } }); },
'sector': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getSectorShape, mesh_1.Mesh.Utils, { modifyProps: function (p) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, p), { alpha: p.sectorOpacity })); }, modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { markerActions: marker_action_1.MarkerActions.Highlighting })); } }); },
'text': function (ctx, getParams) { return (0, representation_1.ShapeRepresentation)(getTextShape, text_1.Text.Utils, { modifyState: function (s) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, s), { markerActions: marker_action_1.MarkerAction.None })); } }); },
};
exports.DihedralParams = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, VectorsParams), ExtendersParams), ArmsParams), ArcParams), SectorParams), common_1.LociLabelTextParams), { visuals: param_definition_1.ParamDefinition.MultiSelect(['extenders', 'arms', 'sector', 'text'], param_definition_1.ParamDefinition.objectToOptions(DihedralVisuals)) });
//
function getDihedralState() {
return {
sphereA: (0, geometry_1.Sphere3D)(),
sphereB: (0, geometry_1.Sphere3D)(),
sphereC: (0, geometry_1.Sphere3D)(),
sphereD: (0, geometry_1.Sphere3D)(),
dirBA: (0, linear_algebra_1.Vec3)(),
dirCD: (0, linear_algebra_1.Vec3)(),
projA: (0, linear_algebra_1.Vec3)(),
projD: (0, linear_algebra_1.Vec3)(),
arcPointA: (0, linear_algebra_1.Vec3)(),
arcPointD: (0, linear_algebra_1.Vec3)(),
arcDirA: (0, linear_algebra_1.Vec3)(),
arcDirD: (0, linear_algebra_1.Vec3)(),
arcCenter: (0, linear_algebra_1.Vec3)(),
arcNormal: (0, linear_algebra_1.Vec3)(),
radius: 0,
angle: 0,
};
}
var tmpVec = (0, linear_algebra_1.Vec3)();
var tmpMat = (0, linear_algebra_1.Mat4)();
// TODO improper dihedrals are not handled correctly
function setDihedralState(quad, state, arcScale) {
var sphereA = state.sphereA, sphereB = state.sphereB, sphereC = state.sphereC, sphereD = state.sphereD, dirBA = state.dirBA, dirCD = state.dirCD, projA = state.projA, projD = state.projD;
var arcPointA = state.arcPointA, arcPointD = state.arcPointD, arcDirA = state.arcDirA, arcDirD = state.arcDirD, arcCenter = state.arcCenter, arcNormal = state.arcNormal;
var _a = quad.loci, lociA = _a[0], lociB = _a[1], lociC = _a[2], lociD = _a[3];
loci_1.Loci.getBoundingSphere(lociA, sphereA);
loci_1.Loci.getBoundingSphere(lociB, sphereB);
loci_1.Loci.getBoundingSphere(lociC, sphereC);
loci_1.Loci.getBoundingSphere(lociD, sphereD);
linear_algebra_1.Vec3.add(arcCenter, sphereB.center, sphereC.center);
linear_algebra_1.Vec3.scale(arcCenter, arcCenter, 0.5);
linear_algebra_1.Vec3.sub(dirBA, sphereA.center, sphereB.center);
linear_algebra_1.Vec3.sub(dirCD, sphereD.center, sphereC.center);
linear_algebra_1.Vec3.add(arcPointA, arcCenter, dirBA);
linear_algebra_1.Vec3.add(arcPointD, arcCenter, dirCD);
linear_algebra_1.Vec3.sub(arcNormal, sphereC.center, sphereB.center);
linear_algebra_1.Vec3.orthogonalize(arcDirA, arcNormal, dirBA);
linear_algebra_1.Vec3.orthogonalize(arcDirD, arcNormal, dirCD);
linear_algebra_1.Vec3.projectPointOnVector(projA, arcPointA, arcDirA, arcCenter);
linear_algebra_1.Vec3.projectPointOnVector(projD, arcPointD, arcDirD, arcCenter);
var len = Math.min(linear_algebra_1.Vec3.distance(projA, arcCenter), linear_algebra_1.Vec3.distance(projD, arcCenter));
var radius = len * arcScale;
linear_algebra_1.Vec3.setMagnitude(arcDirA, arcDirA, radius);
linear_algebra_1.Vec3.setMagnitude(arcDirD, arcDirD, radius);
linear_algebra_1.Vec3.add(arcPointA, arcCenter, arcDirA);
linear_algebra_1.Vec3.add(arcPointD, arcCenter, arcDirD);
state.radius = radius;
state.angle = linear_algebra_1.Vec3.dihedralAngle(sphereA.center, sphereB.center, sphereC.center, sphereD.center);
linear_algebra_1.Vec3.matchDirection(tmpVec, arcNormal, linear_algebra_1.Vec3.sub(tmpVec, arcPointA, sphereA.center));
var angleA = linear_algebra_1.Vec3.angle(dirBA, tmpVec);
var lenA = radius / Math.cos(angleA - misc_1.halfPI);
linear_algebra_1.Vec3.add(projA, sphereB.center, linear_algebra_1.Vec3.setMagnitude(tmpVec, dirBA, lenA));
linear_algebra_1.Vec3.matchDirection(tmpVec, arcNormal, linear_algebra_1.Vec3.sub(tmpVec, arcPointD, sphereD.center));
var angleD = linear_algebra_1.Vec3.angle(dirCD, tmpVec);
var lenD = radius / Math.cos(angleD - misc_1.halfPI);
linear_algebra_1.Vec3.add(projD, sphereC.center, linear_algebra_1.Vec3.setMagnitude(tmpVec, dirCD, lenD));
return state;
}
function getCircle(state, segmentLength) {
var radius = state.radius, angle = state.angle;
var segments = segmentLength ? (0, misc_1.arcLength)(angle, radius) / segmentLength : 32;
linear_algebra_1.Mat4.targetTo(tmpMat, state.arcCenter, angle < 0 ? state.arcPointD : state.arcPointA, state.arcNormal);
linear_algebra_1.Mat4.setTranslation(tmpMat, state.arcCenter);
linear_algebra_1.Mat4.mul(tmpMat, tmpMat, linear_algebra_1.Mat4.rotY180);
var circle = (0, circle_1.Circle)({ radius: radius, thetaLength: Math.abs(angle), segments: segments });
return (0, primitive_1.transformPrimitive)(circle, tmpMat);
}
var tmpState = getDihedralState();
function getDihedralName(data) {
return data.quads.length === 1 ? "Dihedral " + (0, label_1.dihedralLabel)(data.quads[0], { measureOnly: true }) : data.quads.length + " Dihedrals";
}
//
function buildVectorsLines(data, props, lines) {
var builder = lines_builder_1.LinesBuilder.create(128, 64, lines);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
builder.addFixedLengthDashes(tmpState.arcCenter, tmpState.arcPointA, props.dashLength, i);
builder.addFixedLengthDashes(tmpState.arcCenter, tmpState.arcPointD, props.dashLength, i);
}
return builder.getLines();
}
function getVectorsShape(ctx, data, props, shape) {
var lines = buildVectorsLines(data, props, shape && shape.geometry);
var name = getDihedralName(data);
return shape_1.Shape.create(name, data, lines, function () { return props.color; }, function () { return props.linesSize; }, function () { return ''; });
}
//
function buildConnectorLine(data, props, lines) {
var builder = lines_builder_1.LinesBuilder.create(128, 64, lines);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
builder.addFixedLengthDashes(tmpState.sphereB.center, tmpState.sphereC.center, props.dashLength, i);
}
return builder.getLines();
}
function getConnectorShape(ctx, data, props, shape) {
var lines = buildConnectorLine(data, props, shape && shape.geometry);
var name = getDihedralName(data);
return shape_1.Shape.create(name, data, lines, function () { return props.color; }, function () { return props.linesSize; }, function () { return ''; });
}
//
function buildArmsLines(data, props, lines) {
var builder = lines_builder_1.LinesBuilder.create(128, 64, lines);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
builder.addFixedLengthDashes(tmpState.sphereB.center, tmpState.sphereA.center, props.dashLength, i);
builder.addFixedLengthDashes(tmpState.sphereC.center, tmpState.sphereD.center, props.dashLength, i);
}
return builder.getLines();
}
function getArmsShape(ctx, data, props, shape) {
var lines = buildArmsLines(data, props, shape && shape.geometry);
var name = getDihedralName(data);
return shape_1.Shape.create(name, data, lines, function () { return props.color; }, function () { return props.linesSize; }, function () { return ''; });
}
//
function buildExtendersLines(data, props, lines) {
var builder = lines_builder_1.LinesBuilder.create(128, 64, lines);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
builder.addFixedLengthDashes(tmpState.arcPointA, tmpState.projA, props.dashLength, i);
builder.addFixedLengthDashes(tmpState.arcPointD, tmpState.projD, props.dashLength, i);
}
return builder.getLines();
}
function getExtendersShape(ctx, data, props, shape) {
var lines = buildExtendersLines(data, props, shape && shape.geometry);
var name = getDihedralName(data);
return shape_1.Shape.create(name, data, lines, function () { return props.color; }, function () { return props.linesSize; }, function () { return ''; });
}
//
function buildArcLines(data, props, lines) {
var builder = lines_builder_1.LinesBuilder.create(128, 64, lines);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
var circle = getCircle(tmpState, props.dashLength);
var indices = circle.indices, vertices = circle.vertices;
for (var j = 0, jl = indices.length; j < jl; j += 3) {
if (j % 2 === 1)
continue; // draw every other segment to get dashes
var start = indices[j] * 3;
var end = indices[j + 1] * 3;
var startX = vertices[start];
var startY = vertices[start + 1];
var startZ = vertices[start + 2];
var endX = vertices[end];
var endY = vertices[end + 1];
var endZ = vertices[end + 2];
builder.add(startX, startY, startZ, endX, endY, endZ, i);
}
}
return builder.getLines();
}
function getArcShape(ctx, data, props, shape) {
var lines = buildArcLines(data, props, shape && shape.geometry);
var name = getDihedralName(data);
return shape_1.Shape.create(name, data, lines, function () { return props.color; }, function () { return props.linesSize; }, function () { return ''; });
}
//
function buildSectorMesh(data, props, mesh) {
var state = mesh_builder_1.MeshBuilder.createState(128, 64, mesh);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
var circle = getCircle(tmpState);
state.currentGroup = i;
mesh_builder_1.MeshBuilder.addPrimitive(state, linear_algebra_1.Mat4.id, circle);
mesh_builder_1.MeshBuilder.addPrimitiveFlipped(state, linear_algebra_1.Mat4.id, circle);
}
return mesh_builder_1.MeshBuilder.getMesh(state);
}
function getSectorShape(ctx, data, props, shape) {
var mesh = buildSectorMesh(data, props, shape && shape.geometry);
var name = getDihedralName(data);
var getLabel = function (groupId) { return (0, label_1.dihedralLabel)(data.quads[groupId]); };
return shape_1.Shape.create(name, data, mesh, function () { return props.color; }, function () { return 1; }, getLabel);
}
//
function buildText(data, props, text) {
var builder = text_builder_1.TextBuilder.create(props, 128, 64, text);
for (var i = 0, il = data.quads.length; i < il; ++i) {
setDihedralState(data.quads[i], tmpState, props.arcScale);
linear_algebra_1.Vec3.add(tmpVec, tmpState.arcDirA, tmpState.arcDirD);
linear_algebra_1.Vec3.setMagnitude(tmpVec, tmpVec, tmpState.radius);
linear_algebra_1.Vec3.add(tmpVec, tmpState.arcCenter, tmpVec);
var angle = (0, misc_1.radToDeg)(tmpState.angle).toFixed(2);
if (angle === '-0.00')
angle = '0.00';
var label = props.customText || angle + "\u00B0";
var radius = Math.max(2, tmpState.sphereA.radius, tmpState.sphereB.radius, tmpState.sphereC.radius, tmpState.sphereD.radius);
var scale = radius / 2;
builder.add(label, tmpVec[0], tmpVec[1], tmpVec[2], 0.1, scale, i);
}
return builder.getText();
}
function getTextShape(ctx, data, props, shape) {
var text = buildText(data, props, shape && shape.geometry);
var name = getDihedralName(data);
var getLabel = function (groupId) { return (0, label_1.dihedralLabel)(data.quads[groupId]); };
return shape_1.Shape.create(name, data, text, function () { return props.textColor; }, function () { return props.textSize; }, getLabel);
}
function DihedralRepresentation(ctx, getParams) {
return representation_2.Representation.createMulti('Dihedral', ctx, getParams, representation_2.Representation.StateBuilder, DihedralVisuals);
}
exports.DihedralRepresentation = DihedralRepresentation;
//# sourceMappingURL=dihedral.js.map
;