molstar
Version:
A comprehensive macromolecular library.
257 lines (256 loc) • 12.5 kB
JavaScript
"use strict";
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElementIterator = exports.getSerialElementLoci = exports.eachSerialElement = exports.getElementLoci = exports.eachElement = exports.createElementSphereImpostor = exports.createElementSphereMesh = exports.makeElementIgnoreTest = void 0;
var linear_algebra_1 = require("../../../../mol-math/linear-algebra");
var structure_1 = require("../../../../mol-model/structure");
var loci_1 = require("../../../../mol-model/loci");
var int_1 = require("../../../../mol-data/int");
var mesh_1 = require("../../../../mol-geo/geometry/mesh/mesh");
var sphere_1 = require("../../../../mol-geo/primitive/sphere");
var mesh_builder_1 = require("../../../../mol-geo/geometry/mesh/mesh-builder");
var sphere_2 = require("../../../../mol-geo/geometry/mesh/builder/sphere");
var location_iterator_1 = require("../../../../mol-geo/util/location-iterator");
var spheres_1 = require("../../../../mol-geo/geometry/spheres/spheres");
var spheres_builder_1 = require("../../../../mol-geo/geometry/spheres/spheres-builder");
var common_1 = require("./common");
var geometry_1 = require("../../../../mol-math/geometry");
// avoiding namespace lookup improved performance in Chrome (Aug 2020)
var v3add = linear_algebra_1.Vec3.add;
function makeElementIgnoreTest(structure, unit, props) {
var ignoreHydrogens = props.ignoreHydrogens, traceOnly = props.traceOnly;
var atomicNumber = unit.model.atomicHierarchy.derived.atom.atomicNumber;
var isCoarse = structure_1.Unit.isCoarse(unit);
var child = structure.child;
var childUnit = child === null || child === void 0 ? void 0 : child.unitMap.get(unit.id);
if (child && !childUnit)
throw new Error('expected childUnit to exist if child exists');
if (!child && !ignoreHydrogens && !traceOnly)
return;
return function (element) {
return ((!!childUnit && !int_1.SortedArray.has(childUnit.elements, element)) ||
(!isCoarse && ignoreHydrogens && (0, common_1.isH)(atomicNumber, element)) ||
(traceOnly && !(0, common_1.isTrace)(unit, element)));
};
}
exports.makeElementIgnoreTest = makeElementIgnoreTest;
function createElementSphereMesh(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_1.Mesh.createEmpty(mesh);
var detail = props.detail, sizeFactor = props.sizeFactor;
var elements = unit.elements;
var elementCount = elements.length;
var vertexCount = elementCount * (0, sphere_1.sphereVertexCount)(detail);
var builderState = mesh_builder_1.MeshBuilder.createState(vertexCount, vertexCount / 2, mesh);
var v = (0, linear_algebra_1.Vec3)();
var pos = unit.conformation.invariantPosition;
var ignore = makeElementIgnoreTest(structure, unit, props);
var l = structure_1.StructureElement.Location.create(structure, unit);
var themeSize = theme.size.size;
var center = (0, linear_algebra_1.Vec3)();
var maxSize = 0;
var count = 0;
for (var i = 0; i < elementCount; i++) {
if (ignore && ignore(elements[i]))
continue;
l.element = elements[i];
pos(elements[i], v);
v3add(center, center, v);
count += 1;
builderState.currentGroup = i;
var size = themeSize(l);
if (size > maxSize)
maxSize = size;
(0, sphere_2.addSphere)(builderState, v, size * sizeFactor, detail);
}
var oldBoundingSphere = mesh ? geometry_1.Sphere3D.clone(mesh.boundingSphere) : undefined;
var m = mesh_builder_1.MeshBuilder.getMesh(builderState);
if (count === 0)
return m;
// re-use boundingSphere if it has not changed much
var boundingSphere;
linear_algebra_1.Vec3.scale(center, center, 1 / count);
if (oldBoundingSphere && linear_algebra_1.Vec3.distance(center, oldBoundingSphere.center) / oldBoundingSphere.radius < 1.0) {
boundingSphere = oldBoundingSphere;
}
else {
boundingSphere = geometry_1.Sphere3D.expand((0, geometry_1.Sphere3D)(), (childUnit !== null && childUnit !== void 0 ? childUnit : unit).boundary.sphere, maxSize * sizeFactor + 0.05);
}
m.setBoundingSphere(boundingSphere);
return m;
}
exports.createElementSphereMesh = createElementSphereMesh;
function createElementSphereImpostor(ctx, unit, structure, theme, props, spheres) {
var child = structure.child;
var childUnit = child === null || child === void 0 ? void 0 : child.unitMap.get(unit.id);
if (child && !childUnit)
return spheres_1.Spheres.createEmpty(spheres);
var elements = unit.elements;
var elementCount = elements.length;
var builder = spheres_builder_1.SpheresBuilder.create(elementCount, elementCount / 2, spheres);
var v = (0, linear_algebra_1.Vec3)();
var pos = unit.conformation.invariantPosition;
var ignore = makeElementIgnoreTest(structure, unit, props);
var l = structure_1.StructureElement.Location.create(structure, unit);
var themeSize = theme.size.size;
var center = (0, linear_algebra_1.Vec3)();
var maxSize = 0;
var count = 0;
for (var i = 0; i < elementCount; i++) {
if (ignore === null || ignore === void 0 ? void 0 : ignore(elements[i]))
continue;
pos(elements[i], v);
builder.add(v[0], v[1], v[2], i);
v3add(center, center, v);
count += 1;
l.element = elements[i];
var size = themeSize(l);
if (size > maxSize)
maxSize = size;
}
var oldBoundingSphere = spheres ? geometry_1.Sphere3D.clone(spheres.boundingSphere) : undefined;
var s = builder.getSpheres();
if (count === 0)
return s;
// re-use boundingSphere if it has not changed much
var boundingSphere;
linear_algebra_1.Vec3.scale(center, center, 1 / count);
if (oldBoundingSphere && linear_algebra_1.Vec3.distance(center, oldBoundingSphere.center) / oldBoundingSphere.radius < 1.0) {
boundingSphere = oldBoundingSphere;
}
else {
boundingSphere = geometry_1.Sphere3D.expand((0, geometry_1.Sphere3D)(), (childUnit !== null && childUnit !== void 0 ? childUnit : unit).boundary.sphere, maxSize * props.sizeFactor + 0.05);
}
s.setBoundingSphere(boundingSphere);
return s;
}
exports.createElementSphereImpostor = createElementSphereImpostor;
function eachElement(loci, structureGroup, apply) {
var changed = false;
if (!structure_1.StructureElement.Loci.is(loci))
return false;
var structure = structureGroup.structure, group = structureGroup.group;
if (!structure_1.Structure.areEquivalent(loci.structure, structure))
return false;
var elementCount = group.elements.length;
var unitIndexMap = group.unitIndexMap;
for (var _a = 0, _b = loci.elements; _a < _b.length; _a++) {
var e = _b[_a];
var unitIdx = unitIndexMap.get(e.unit.id);
if (unitIdx !== undefined) {
var offset = unitIdx * elementCount; // to target unit instance
if (int_1.Interval.is(e.indices)) {
var start = offset + int_1.Interval.start(e.indices);
var end = offset + int_1.Interval.end(e.indices);
if (apply(int_1.Interval.ofBounds(start, end)))
changed = true;
}
else {
for (var i = 0, _i = e.indices.length; i < _i; i++) {
var start = e.indices[i];
var endI = i + 1;
while (endI < _i && e.indices[endI] === start)
endI++;
i = endI - 1;
var end = e.indices[i];
changed = apply(int_1.Interval.ofRange(offset + start, offset + end)) || changed;
}
}
}
}
return changed;
}
exports.eachElement = eachElement;
function getElementLoci(pickingId, structureGroup, id) {
var objectId = pickingId.objectId, instanceId = pickingId.instanceId, groupId = pickingId.groupId;
if (id === objectId) {
var structure = structureGroup.structure, group = structureGroup.group;
var unit = group.units[instanceId];
var indices = int_1.OrderedSet.ofSingleton(groupId);
return structure_1.StructureElement.Loci(structure.target, [{ unit: unit, indices: indices }]);
}
return loci_1.EmptyLoci;
}
exports.getElementLoci = getElementLoci;
//
function eachSerialElement(loci, structure, apply) {
var changed = false;
if (!structure_1.StructureElement.Loci.is(loci))
return false;
if (!structure_1.Structure.areEquivalent(loci.structure, structure))
return false;
var cumulativeUnitElementCount = structure.serialMapping.cumulativeUnitElementCount;
for (var _a = 0, _b = loci.elements; _a < _b.length; _a++) {
var e = _b[_a];
var unitIdx = structure.unitIndexMap.get(e.unit.id);
if (unitIdx !== undefined) {
if (int_1.Interval.is(e.indices)) {
var start = cumulativeUnitElementCount[unitIdx] + int_1.Interval.start(e.indices);
var end = cumulativeUnitElementCount[unitIdx] + int_1.Interval.end(e.indices);
if (apply(int_1.Interval.ofBounds(start, end)))
changed = true;
}
else {
for (var i = 0, _i = e.indices.length; i < _i; i++) {
var idx = cumulativeUnitElementCount[unitIdx] + e.indices[i];
if (apply(int_1.Interval.ofSingleton(idx)))
changed = true;
}
}
}
}
return changed;
}
exports.eachSerialElement = eachSerialElement;
function getSerialElementLoci(pickingId, structure, id) {
var objectId = pickingId.objectId, groupId = pickingId.groupId;
if (id === objectId) {
var _a = structure.serialMapping, unitIndices = _a.unitIndices, cumulativeUnitElementCount = _a.cumulativeUnitElementCount;
var unitIdx = unitIndices[groupId];
var unit = structure.units[unitIdx];
var idx = groupId - cumulativeUnitElementCount[unitIdx];
var indices = int_1.OrderedSet.ofSingleton(idx);
return structure_1.StructureElement.Loci(structure, [{ unit: unit, indices: indices }]);
}
return loci_1.EmptyLoci;
}
exports.getSerialElementLoci = getSerialElementLoci;
//
var ElementIterator;
(function (ElementIterator) {
function fromGroup(structureGroup) {
var group = structureGroup.group, structure = structureGroup.structure;
var groupCount = group.elements.length;
var instanceCount = group.units.length;
var location = structure_1.StructureElement.Location.create(structure);
var getLocation = function (groupIndex, instanceIndex) {
var unit = group.units[instanceIndex];
location.unit = unit;
location.element = unit.elements[groupIndex];
return location;
};
return (0, location_iterator_1.LocationIterator)(groupCount, instanceCount, 1, getLocation);
}
ElementIterator.fromGroup = fromGroup;
function fromStructure(structure) {
var units = structure.units, elementCount = structure.elementCount;
var groupCount = elementCount;
var instanceCount = 1;
var _a = structure.serialMapping, unitIndices = _a.unitIndices, elementIndices = _a.elementIndices;
var location = structure_1.StructureElement.Location.create(structure);
var getLocation = function (groupIndex) {
location.unit = units[unitIndices[groupIndex]];
location.element = elementIndices[groupIndex];
return location;
};
return (0, location_iterator_1.LocationIterator)(groupCount, instanceCount, 1, getLocation, true);
}
ElementIterator.fromStructure = fromStructure;
})(ElementIterator = exports.ElementIterator || (exports.ElementIterator = {}));