molstar
Version:
A comprehensive macromolecular library.
126 lines (125 loc) • 5.96 kB
JavaScript
"use strict";
/**
* Copyright (c) 2026 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.CoordinationPolyhedronMeshParams = void 0;
exports.CoordinationPolyhedronMeshVisual = CoordinationPolyhedronMeshVisual;
const linear_algebra_1 = require("../../../mol-math/linear-algebra.js");
const structure_1 = require("../../../mol-model/structure.js");
const mesh_builder_1 = require("../../../mol-geo/geometry/mesh/mesh-builder.js");
const complex_visual_1 = require("../complex-visual.js");
const param_definition_1 = require("../../../mol-util/param-definition.js");
const location_iterator_1 = require("../../../mol-geo/util/location-iterator.js");
const picking_1 = require("../../../mol-geo/geometry/picking.js");
const int_1 = require("../../../mol-data/int.js");
const loci_1 = require("../../../mol-model/loci.js");
const convex_hull_1 = require("../../../mol-math/geometry/convex-hull.js");
const sorted_array_1 = require("../../../mol-data/int/sorted-array.js");
exports.CoordinationPolyhedronMeshParams = {
...complex_visual_1.ComplexMeshParams,
includeParent: param_definition_1.ParamDefinition.Boolean(false),
minCoordination: param_definition_1.ParamDefinition.Numeric(4, { min: 4, max: 12, step: 1 }, { description: 'Minimum number of coordinating atoms to draw a polyhedron' }),
maxCoordination: param_definition_1.ParamDefinition.Numeric(12, { min: 4, max: 24, step: 1 }, { description: 'Maximum coordination number' }),
};
function createCoordinationPolyhedronMesh(ctx, structure, theme, props, mesh) {
const { minCoordination, maxCoordination } = props;
const { child, coordination: { sites, eachLigand } } = structure;
const count = sites.count * 4;
const builderState = mesh_builder_1.MeshBuilder.createState(count, count / 2, mesh);
for (let i = 0; i < sites.count; i++) {
const number = sites.numbers[i];
if (number < minCoordination || number > maxCoordination)
continue;
if (child) {
const unit = structure.unitMap.get(sites.unitIds[i]);
const childUnit = child.unitMap.get(unit.id);
const element = unit.elements[sites.indices[i]];
if (!childUnit || !sorted_array_1.SortedArray.has(childUnit.elements, element))
continue;
}
const positions = [];
eachLigand(i, l => {
const p = l.unit.conformation.position(l.element, (0, linear_algebra_1.Vec3)());
positions.push(p);
});
const hull = (0, convex_hull_1.convexHull)(positions);
if (hull) {
builderState.currentGroup = i;
for (let i = 0; i < hull.indices.length; i += 3) {
const a = positions[hull.indices[i]];
const b = positions[hull.indices[i + 1]];
const c = positions[hull.indices[i + 2]];
mesh_builder_1.MeshBuilder.addTriangle(builderState, a, b, c);
}
}
}
return mesh_builder_1.MeshBuilder.getMesh(builderState);
}
function CoordinationPolyhedronIterator(structure, props) {
const { sites } = structure.coordination;
const groupCount = sites.count;
const instanceCount = 1;
const location = structure_1.StructureElement.Location.create(structure);
function getLocation(groupIndex) {
if (groupIndex < sites.count) {
const u = structure.unitMap.get(sites.unitIds[groupIndex]);
location.unit = u;
location.element = u.elements[sites.indices[groupIndex]];
}
return location;
}
return (0, location_iterator_1.LocationIterator)(groupCount, instanceCount, 1, getLocation, true);
}
function getCoordinationPolyhedronLoci(pickingId, structure, id) {
const { objectId, groupId } = pickingId;
if (id === objectId) {
if (groupId === picking_1.PickingId.Null) {
return structure_1.Structure.Loci(structure);
}
const { sites } = structure.coordination;
if (groupId < sites.count) {
return structure_1.StructureElement.Loci(structure, [{
unit: structure.unitMap.get(sites.unitIds[groupId]),
indices: int_1.OrderedSet.ofSingleton(sites.indices[groupId])
}]);
}
return structure_1.Structure.Loci(structure);
}
return loci_1.EmptyLoci;
}
function eachCoordinationPolyhedron(loci, structure, apply) {
let changed = false;
if (!structure_1.StructureElement.Loci.is(loci))
return false;
if (!structure_1.Structure.areEquivalent(loci.structure, structure))
return false;
const { getSiteIndex } = structure.coordination;
for (const { unit, indices } of loci.elements) {
if (!structure_1.Unit.isAtomic(unit))
continue;
int_1.OrderedSet.forEach(indices, v => {
const groupIndex = getSiteIndex(unit, unit.elements[v]);
if (groupIndex >= 0) {
if (apply(int_1.Interval.ofSingleton(groupIndex)))
changed = true;
}
});
}
return changed;
}
function CoordinationPolyhedronMeshVisual(materialId) {
return (0, complex_visual_1.ComplexMeshVisual)({
defaultProps: param_definition_1.ParamDefinition.getDefaultValues(exports.CoordinationPolyhedronMeshParams),
createGeometry: createCoordinationPolyhedronMesh,
createLocationIterator: CoordinationPolyhedronIterator,
getLoci: getCoordinationPolyhedronLoci,
eachLocation: eachCoordinationPolyhedron,
setUpdateState: (state, newProps, currentProps) => {
state.createGeometry = (newProps.minCoordination !== currentProps.minCoordination ||
newProps.maxCoordination !== currentProps.maxCoordination);
}
}, materialId);
}