UNPKG

molstar

Version:

A comprehensive macromolecular library.

184 lines 9.18 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 { Structure, StructureElement } from '../../../mol-model/structure'; import { Mesh } from '../../../mol-geo/geometry/mesh/mesh'; import { Vec3 } from '../../../mol-math/linear-algebra'; import { createLinkCylinderMesh, LinkCylinderParams } from '../../../mol-repr/structure/visual/util/link'; import { ComplexMeshParams, ComplexMeshVisual } from '../../../mol-repr/structure/complex-visual'; import { EmptyLoci } from '../../../mol-model/loci'; import { Interval, OrderedSet, SortedArray } from '../../../mol-data/int'; import { Interactions } from '../interactions/interactions'; import { InteractionsProvider } from '../interactions'; import { LocationIterator } from '../../../mol-geo/util/location-iterator'; import { Unit } from '../../../mol-model/structure/structure'; import { Sphere3D } from '../../../mol-math/geometry'; function createInterUnitInteractionCylinderMesh(ctx, structure, theme, props, mesh) { if (!structure.hasAtomic) return Mesh.createEmpty(mesh); var l = StructureElement.Location.create(structure); var interactions = InteractionsProvider.get(structure).value; var contacts = interactions.contacts, unitsFeatures = interactions.unitsFeatures; var edgeCount = contacts.edgeCount, edges = contacts.edges; var sizeFactor = props.sizeFactor; if (!edgeCount) return Mesh.createEmpty(mesh); var child = structure.child; var builderProps = { linkCount: edgeCount, position: function (posA, posB, edgeIndex) { var _a = edges[edgeIndex], unitA = _a.unitA, indexA = _a.indexA, unitB = _a.unitB, indexB = _a.indexB; var fA = unitsFeatures.get(unitA); var fB = unitsFeatures.get(unitB); var uA = structure.unitMap.get(unitA); var uB = structure.unitMap.get(unitB); Vec3.set(posA, fA.x[indexA], fA.y[indexA], fA.z[indexA]); Vec3.transformMat4(posA, posA, uA.conformation.operator.matrix); Vec3.set(posB, fB.x[indexB], fB.y[indexB], fB.z[indexB]); Vec3.transformMat4(posB, posB, uB.conformation.operator.matrix); }, style: function (edgeIndex) { return 1 /* Dashed */; }, radius: function (edgeIndex) { var b = edges[edgeIndex]; var fA = unitsFeatures.get(b.unitA); l.unit = structure.unitMap.get(b.unitA); l.element = l.unit.elements[fA.members[fA.offsets[b.indexA]]]; var sizeA = theme.size.size(l); var fB = unitsFeatures.get(b.unitB); l.unit = structure.unitMap.get(b.unitB); l.element = l.unit.elements[fB.members[fB.offsets[b.indexB]]]; var sizeB = theme.size.size(l); return Math.min(sizeA, sizeB) * sizeFactor; }, ignore: function (edgeIndex) { if (edges[edgeIndex].props.flag === 1 /* Filtered */) return true; if (child) { var b = edges[edgeIndex]; var childUnitA = child.unitMap.get(b.unitA); if (!childUnitA) return true; var unitA = structure.unitMap.get(b.unitA); var fA = unitsFeatures.get(b.unitA); // TODO: check all members var eA = unitA.elements[fA.members[fA.offsets[b.indexA]]]; if (!SortedArray.has(childUnitA.elements, eA)) return true; } return false; } }; var m = createLinkCylinderMesh(ctx, builderProps, props, mesh); var sphere = Sphere3D.expand(Sphere3D(), (child !== null && child !== void 0 ? child : structure).boundary.sphere, 1 * sizeFactor); m.setBoundingSphere(sphere); return m; } export var InteractionsInterUnitParams = __assign(__assign(__assign({}, ComplexMeshParams), LinkCylinderParams), { sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }), dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }), dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }), includeParent: PD.Boolean(false) }); export function InteractionsInterUnitVisual(materialId) { return ComplexMeshVisual({ defaultProps: PD.getDefaultValues(InteractionsInterUnitParams), createGeometry: createInterUnitInteractionCylinderMesh, createLocationIterator: createInteractionsIterator, getLoci: getInteractionLoci, eachLocation: eachInteraction, setUpdateState: function (state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure) { state.createGeometry = (newProps.sizeFactor !== currentProps.sizeFactor || newProps.dashCount !== currentProps.dashCount || newProps.dashScale !== currentProps.dashScale || newProps.dashCap !== currentProps.dashCap || newProps.radialSegments !== currentProps.radialSegments); var interactionsHash = InteractionsProvider.get(newStructure).version; if (state.info.interactionsHash !== interactionsHash) { state.createGeometry = true; state.updateTransform = true; state.updateColor = true; state.info.interactionsHash = interactionsHash; } } }, materialId); } function getInteractionLoci(pickingId, structure, id) { var objectId = pickingId.objectId, groupId = pickingId.groupId; if (id === objectId) { var interactions = InteractionsProvider.get(structure).value; var c = interactions.contacts.edges[groupId]; var unitA = structure.unitMap.get(c.unitA); var unitB = structure.unitMap.get(c.unitB); return Interactions.Loci(structure, interactions, [ { unitA: unitA, indexA: c.indexA, unitB: unitB, indexB: c.indexB }, { unitA: unitB, indexA: c.indexB, unitB: unitA, indexB: c.indexA }, ]); } return EmptyLoci; } function eachInteraction(loci, structure, apply, isMarking) { var _a; var changed = false; if (Interactions.isLoci(loci)) { if (!Structure.areEquivalent(loci.data.structure, structure)) return false; var interactions = InteractionsProvider.get(structure).value; if (loci.data.interactions !== interactions) return false; var contacts = interactions.contacts; for (var _i = 0, _b = loci.elements; _i < _b.length; _i++) { var c = _b[_i]; var idx = contacts.getEdgeIndex(c.indexA, c.unitA.id, c.indexB, c.unitB.id); if (idx !== -1) { if (apply(Interval.ofSingleton(idx))) changed = true; } } } else if (StructureElement.Loci.is(loci)) { if (!Structure.areEquivalent(loci.structure, structure)) return false; if (isMarking && loci.elements.length === 1) return false; // only a single unit var contacts_1 = (_a = InteractionsProvider.get(structure).value) === null || _a === void 0 ? void 0 : _a.contacts; if (!contacts_1) return false; var _loop_1 = function (e) { var unit = e.unit; if (!Unit.isAtomic(unit)) return "continue"; if (isMarking && OrderedSet.size(e.indices) === 1) return "continue"; OrderedSet.forEach(e.indices, function (v) { for (var _i = 0, _a = contacts_1.getContactIndicesForElement(v, unit); _i < _a.length; _i++) { var idx = _a[_i]; if (apply(Interval.ofSingleton(idx))) changed = true; } }); }; // TODO when isMarking, all elements of contact features need to be in the loci for (var _c = 0, _d = loci.elements; _c < _d.length; _c++) { var e = _d[_c]; _loop_1(e); } } return changed; } function createInteractionsIterator(structure) { var interactions = InteractionsProvider.get(structure).value; var contacts = interactions.contacts; var groupCount = contacts.edgeCount; var instanceCount = 1; var location = Interactions.Location(interactions, structure); var element = location.element; var getLocation = function (groupIndex) { var c = contacts.edges[groupIndex]; element.unitA = structure.unitMap.get(c.unitA); element.indexA = c.indexA; element.unitB = structure.unitMap.get(c.unitB); element.indexB = c.indexB; return location; }; return LocationIterator(groupCount, instanceCount, 1, getLocation, true); } //# sourceMappingURL=interactions-inter-unit-cylinder.js.map