unitcell.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Model, Symmetry } from '../../../mol-model/structure';
  7. import { ShapeRepresentation } from '../representation';
  8. import { Shape } from '../../../mol-model/shape';
  9. import { ColorNames } from '../../../mol-util/color/names';
  10. import { RuntimeContext } from '../../../mol-task';
  11. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  12. import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
  13. import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder';
  14. import { BoxCage } from '../../../mol-geo/primitive/box';
  15. import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
  16. import { transformCage, cloneCage } from '../../../mol-geo/primitive/cage';
  17. import { Sphere3D } from '../../../mol-math/geometry';
  18. import { RepresentationParamsGetter, Representation, RepresentationContext } from '../../representation';
  19. const translate05 = Mat4.fromTranslation(Mat4(), Vec3.create(0.5, 0.5, 0.5));
  20. const unitCage = transformCage(cloneCage(BoxCage()), translate05);
  21. const tmpRef = Vec3();
  22. const tmpTranslate = Mat4();
  23. interface UnitcellData {
  24. symmetry: Symmetry
  25. ref: Vec3
  26. }
  27. const CellRef = {
  28. origin: 'Origin',
  29. model: 'Model'
  30. };
  31. const CellAttachment = {
  32. corner: 'Corner',
  33. center: 'Center'
  34. };
  35. const CellParams = {
  36. ...Mesh.Params,
  37. cellColor: PD.Color(ColorNames.orange),
  38. cellScale: PD.Numeric(2, { min: 0.1, max: 5, step: 0.1 }),
  39. ref: PD.Select('model', PD.objectToOptions(CellRef), { isEssential: true }),
  40. attachment: PD.Select('corner', PD.objectToOptions(CellAttachment), { isEssential: true }),
  41. };
  42. type CellParams = typeof CellParams
  43. const UnitcellVisuals = {
  44. 'mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<UnitcellData, CellParams>) => ShapeRepresentation(getUnitcellShape, Mesh.Utils),
  45. };
  46. export const UnitcellParams = {
  47. ...CellParams
  48. };
  49. export type UnitcellParams = typeof UnitcellParams
  50. export type UnitcellProps = PD.Values<UnitcellParams>
  51. function getUnitcellMesh(data: UnitcellData, props: UnitcellProps, mesh?: Mesh) {
  52. const state = MeshBuilder.createState(256, 128, mesh);
  53. const { fromFractional } = data.symmetry.spacegroup.cell;
  54. Vec3.copy(tmpRef, data.ref);
  55. if (props.attachment === 'center') {
  56. Vec3.trunc(tmpRef, tmpRef);
  57. Vec3.subScalar(tmpRef, tmpRef, 0.5);
  58. } else {
  59. Vec3.floor(tmpRef, tmpRef);
  60. }
  61. Mat4.fromTranslation(tmpTranslate, tmpRef);
  62. const cellCage = transformCage(cloneCage(unitCage), tmpTranslate);
  63. const radius = (Math.cbrt(data.symmetry.spacegroup.cell.volume) / 300) * props.cellScale;
  64. state.currentGroup = 1;
  65. MeshBuilder.addCage(state, fromFractional, cellCage, radius, 2, 20);
  66. const sphere = Sphere3D.fromDimensionsAndTransform(Sphere3D(), Vec3.unit, fromFractional);
  67. Vec3.transformMat4(tmpRef, tmpRef, fromFractional);
  68. Sphere3D.translate(sphere, sphere, tmpRef);
  69. Sphere3D.expand(sphere, sphere, radius);
  70. const m = MeshBuilder.getMesh(state);
  71. m.setBoundingSphere(sphere);
  72. return m;
  73. }
  74. function getUnitcellShape(ctx: RuntimeContext, data: UnitcellData, props: UnitcellProps, shape?: Shape<Mesh>) {
  75. const geo = getUnitcellMesh(data, props, shape && shape.geometry);
  76. const label = Symmetry.getUnitcellLabel(data.symmetry);
  77. return Shape.create(label, data, geo, () => props.cellColor, () => 1, () => label);
  78. }
  79. //
  80. export function getUnitcellData(model: Model, symmetry: Symmetry, props: UnitcellProps) {
  81. const ref = Vec3();
  82. if (props.ref === 'model') {
  83. Vec3.transformMat4(ref, Model.getCenter(model), symmetry.spacegroup.cell.toFractional);
  84. }
  85. return { symmetry, ref };
  86. }
  87. export type UnitcellRepresentation = Representation<UnitcellData, UnitcellParams>
  88. export function UnitcellRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<UnitcellData, UnitcellParams>): UnitcellRepresentation {
  89. return Representation.createMulti('Unit Cell', ctx, getParams, Representation.StateBuilder, UnitcellVisuals as unknown as Representation.Def<UnitcellData, UnitcellParams>);
  90. }