UNPKG

molstar

Version:

A comprehensive macromolecular library.

97 lines (96 loc) 5.07 kB
/** * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { __assign } from "tslib"; import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { UnitsMeshParams, UnitsMeshVisual } from '../../../mol-repr/structure/units-visual'; import { ElementIterator, getElementLoci, eachElement } from '../../../mol-repr/structure/visual/util/element'; import { StructureElement } from '../../../mol-model/structure'; import { Mesh } from '../../../mol-geo/geometry/mesh/mesh'; import { sphereVertexCount } from '../../../mol-geo/primitive/sphere'; import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder'; import { Vec3, Mat3, Tensor, EPSILON } from '../../../mol-math/linear-algebra'; import { isH } from '../../../mol-repr/structure/visual/util/common'; import { addEllipsoid } from '../../../mol-geo/geometry/mesh/builder/ellipsoid'; import { AtomSiteAnisotrop } from '../../../mol-model-formats/structure/property/anisotropic'; import { equalEps } from '../../../mol-math/linear-algebra/3d/common'; import { addSphere } from '../../../mol-geo/geometry/mesh/builder/sphere'; import { Sphere3D } from '../../../mol-math/geometry'; import { BaseGeometry } from '../../../mol-geo/geometry/base'; import { SortedArray } from '../../../mol-data/int/sorted-array'; export var EllipsoidMeshParams = __assign(__assign({}, UnitsMeshParams), { sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }), detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }, BaseGeometry.CustomQualityParamInfo), ignoreHydrogens: PD.Boolean(false) }); export function EllipsoidMeshVisual(materialId) { return UnitsMeshVisual({ defaultProps: PD.getDefaultValues(EllipsoidMeshParams), createGeometry: createEllipsoidMesh, createLocationIterator: ElementIterator.fromGroup, getLoci: getElementLoci, eachLocation: eachElement, setUpdateState: function (state, newProps, currentProps) { state.createGeometry = (newProps.sizeFactor !== currentProps.sizeFactor || newProps.detail !== currentProps.detail || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens); } }, materialId); } export function createEllipsoidMesh(ctx, unit, structure, theme, props, mesh) { var child = structure.child; var childUnit = child === null || child === void 0 ? void 0 : child.unitMap.get(unit.id); if (child && !childUnit) return Mesh.createEmpty(mesh); var detail = props.detail, sizeFactor = props.sizeFactor, ignoreHydrogens = props.ignoreHydrogens; var elements = unit.elements, model = unit.model; var atomicNumber = unit.model.atomicHierarchy.derived.atom.atomicNumber; var elementCount = elements.length; var vertexCount = elementCount * sphereVertexCount(detail); var builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh); var atomSiteAnisotrop = AtomSiteAnisotrop.Provider.get(model); if (!atomSiteAnisotrop) return Mesh.createEmpty(mesh); var v = Vec3(); var mat = Mat3(); var eigvals = Vec3(); var eigvec1 = Vec3(); var eigvec2 = Vec3(); var elementToAnsiotrop = atomSiteAnisotrop.elementToAnsiotrop, data = atomSiteAnisotrop.data; var U = data.U; var space = data._schema.U.space; var pos = unit.conformation.invariantPosition; var l = StructureElement.Location.create(structure); l.unit = unit; for (var i = 0; i < elementCount; i++) { var ei = elements[i]; var ai = elementToAnsiotrop[ei]; if (ai === -1) continue; if (((!!childUnit && !SortedArray.has(childUnit.elements, ei))) || (ignoreHydrogens && isH(atomicNumber, ei))) continue; l.element = ei; pos(ei, v); builderState.currentGroup = i; Tensor.toMat3(mat, space, U.value(ai)); Mat3.symmtricFromLower(mat, mat); Mat3.symmetricEigenvalues(eigvals, mat); Mat3.eigenvector(eigvec1, mat, eigvals[1]); Mat3.eigenvector(eigvec2, mat, eigvals[2]); for (var j = 0; j < 3; ++j) { // show 50% probability surface, needs sqrt as U matrix is in angstrom-squared // take abs of eigenvalue to avoid reflection // multiply by given size-factor eigvals[j] = sizeFactor * 1.5958 * Math.sqrt(Math.abs(eigvals[j])); } if (equalEps(eigvals[0], eigvals[1], EPSILON) && equalEps(eigvals[1], eigvals[2], EPSILON)) { addSphere(builderState, v, eigvals[0], detail); } else { addEllipsoid(builderState, v, eigvec2, eigvec1, eigvals, detail); } } var m = MeshBuilder.getMesh(builderState); var sphere = Sphere3D.expand(Sphere3D(), (childUnit || unit).boundary.sphere, 1 * sizeFactor); m.setBoundingSphere(sphere); return m; }