diff --git a/src/mol-math/geometry/symmetry-operator.ts b/src/mol-math/geometry/symmetry-operator.ts index 053113865b69a758645180e5d0fe3d11372a5939..d0065a740df3b01a91989834aa12e017e0a9fe7c 100644 --- a/src/mol-math/geometry/symmetry-operator.ts +++ b/src/mol-math/geometry/symmetry-operator.ts @@ -23,13 +23,19 @@ namespace SymmetryOperator { const RotationEpsilon = 0.0001; - export function create(name: string, matrix: Mat4, hkl?: number[]): SymmetryOperator { - const _hkl = hkl ? Vec3.create(hkl[0], hkl[1], hkl[2]) : Vec3.zero(); + export function create(name: string, matrix: Mat4, hkl?: Vec3): SymmetryOperator { + const _hkl = hkl ? Vec3.copy(Vec3.zero(), hkl) : Vec3.zero(); if (Mat4.isIdentity(matrix)) return { name, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl }; if (!Mat4.isRotationAndTranslation(matrix, RotationEpsilon)) throw new Error(`Symmetry operator (${name}) must be a composition of rotation and translation.`); return { name, matrix, inverse: Mat4.invert(Mat4.zero(), matrix), isIdentity: false, hkl: _hkl }; } + // Apply the 1st and then 2nd operator. ( = second.matrix * first.matrix) + export function compose(first: SymmetryOperator, second: SymmetryOperator) { + const matrix = Mat4.mul(Mat4.zero(), second.matrix, first.matrix); + return create(second.name, matrix, second.hkl); + } + export interface CoordinateMapper { (index: number, slot: Vec3): Vec3 } export interface ArrayMapping { readonly invariantPosition: CoordinateMapper, diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index 9d25590e4cd1cf317f31cace6c0dc0e29905ee57..da8546c2cf24c4d8d6ec76ac2cdc9d0bd60cd88e 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/src/mol-model/structure/structure/structure.ts @@ -37,7 +37,7 @@ namespace Structure { for (let c = 0; c < chains.count; c++) { const group = AtomGroup.createNew(OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1])); - const unit = Unit.create(c, model, SymmetryOperator.Default, group); + const unit = Unit.create(model, SymmetryOperator.Default, group); builder.add(unit, OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1])); } @@ -53,12 +53,13 @@ namespace Structure { } class BuilderImpl implements Builder { + private _unitId = 0; private units = IntMap.Mutable<Unit>(); private atoms = AtomSet.Generator(); atomCount = 0; - add(unit: Unit, atoms: OrderedSet) { this.addUnit(unit); this.setAtoms(unit.id, atoms); } - addUnit(unit: Unit) { this.units.set(unit.id, unit); } + add(unit: Unit, atoms: OrderedSet) { const id = this.addUnit(unit); this.setAtoms(id, atoms); } + addUnit(unit: Unit) { const id = this._unitId++; this.units.set(id, unit); return id; } setAtoms(unitId: number, atoms: OrderedSet) { this.atoms.add(unitId, atoms); this.atomCount += OrderedSet.size(atoms); } getStructure(): Structure { return this.atomCount > 0 ? Structure.create(this.units, this.atoms.getSet()) : Empty; } } diff --git a/src/mol-model/structure/structure/symmetry.ts b/src/mol-model/structure/structure/symmetry.ts index daa45f3fb6bf01fd034d057ac489af7d7962f4f0..a0348b6745dc02f4ba01c20542fdaa30d6cabf86 100644 --- a/src/mol-model/structure/structure/symmetry.ts +++ b/src/mol-model/structure/structure/symmetry.ts @@ -25,7 +25,6 @@ function buildAssemblyImpl(structure: Structure, name: string) { const assembler = Structure.Builder(); - let unitId = 0; for (const g of assembly.operatorGroups) { const selection = g.selector(structure); if (Selection.structureCount(selection) === 0) continue; @@ -36,7 +35,7 @@ function buildAssemblyImpl(structure: Structure, name: string) { for (const oper of g.operators) { for (let uI = 0, _uI = unitIds.length; uI < _uI; uI++) { const unit = units.get(unitIds[uI]); - assembler.add(Unit.create(unitId++, unit.model, oper, unit.naturalGroup), AtomSet.unitGetByIndex(atoms, uI)); + assembler.add(Unit.withOperator(unit, oper), AtomSet.unitGetByIndex(atoms, uI)); } } } diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts index e8edaa4c4f0e2a4964daa9c1bb6529a0a19e05dc..05bc6315c26f0448be4c9cf568e5cdf478a4b243 100644 --- a/src/mol-model/structure/structure/unit.ts +++ b/src/mol-model/structure/structure/unit.ts @@ -9,9 +9,6 @@ import AtomGroup from './atom/group' import { Model } from '../model' interface Unit extends SymmetryOperator.ArrayMapping { - // Structure-level unique identifier of the unit. - readonly id: number, - // Provides access to the underlying data. readonly model: Model, @@ -32,12 +29,11 @@ interface Unit extends SymmetryOperator.ArrayMapping { } namespace Unit { - export function create(id: number, model: Model, operator: SymmetryOperator, naturalGroup: AtomGroup): Unit { + export function create(model: Model, operator: SymmetryOperator, naturalGroup: AtomGroup): Unit { const h = model.hierarchy; const { invariantPosition, position, x, y, z } = SymmetryOperator.createMapping(operator, model.conformation); return { - id, model, operator, naturalGroup, @@ -50,6 +46,10 @@ namespace Unit { x, y, z }; } + + export function withOperator(unit: Unit, operator: SymmetryOperator) { + return create(unit.model, SymmetryOperator.compose(unit.operator, operator), unit.naturalGroup); + } } export default Unit; \ No newline at end of file