utils.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import { Unit, Element } from 'mol-model/structure';
  8. import { Mat4, Vec3 } from 'mol-math/linear-algebra'
  9. import { createUniformColor, ColorData } from '../../util/color-data';
  10. import { createUniformSize } from '../../util/size-data';
  11. import { elementSizeData } from '../../theme/structure/size/element';
  12. import VertexMap from '../../shape/vertex-map';
  13. import { ColorTheme, SizeTheme } from '../../theme';
  14. import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color';
  15. import { ValueCell } from 'mol-util';
  16. import { Mesh } from '../../shape/mesh';
  17. import { Task } from 'mol-task';
  18. import { icosahedronVertexCount } from '../../primitive/icosahedron';
  19. import { MeshBuilder } from '../../shape/mesh-builder';
  20. import { TextureImage } from 'mol-gl/renderable/util';
  21. import { applyFlagAction, FlagAction } from '../../util/flag-data';
  22. import { Loci, isEveryLoci } from 'mol-model/loci';
  23. export function createTransforms({ units }: Unit.SymmetryGroup, transforms?: ValueCell<Float32Array>) {
  24. const unitCount = units.length
  25. const n = unitCount * 16
  26. const array = transforms && transforms.ref.value.length >= n ? transforms.ref.value : new Float32Array(n)
  27. for (let i = 0; i < unitCount; i++) {
  28. Mat4.toArray(units[i].conformation.operator.matrix, array, i * 16)
  29. }
  30. return transforms ? ValueCell.update(transforms, array) : ValueCell.create(array)
  31. }
  32. export function createColors(group: Unit.SymmetryGroup, vertexMap: VertexMap, props: ColorTheme, colorData?: ColorData) {
  33. switch (props.name) {
  34. case 'atom-index':
  35. return elementIndexColorData({ group, vertexMap }, colorData)
  36. case 'chain-id':
  37. return chainIdColorData({ group, vertexMap }, colorData)
  38. case 'element-symbol':
  39. return elementSymbolColorData({ group, vertexMap }, colorData)
  40. case 'instance-index':
  41. return instanceIndexColorData({ group, vertexMap }, colorData)
  42. case 'uniform':
  43. return createUniformColor(props, colorData)
  44. }
  45. }
  46. export function createSizes(group: Unit.SymmetryGroup, vertexMap: VertexMap, props: SizeTheme) {
  47. switch (props.name) {
  48. case 'uniform':
  49. return createUniformSize(props)
  50. case 'vdw':
  51. return elementSizeData({ group, vertexMap })
  52. }
  53. }
  54. export function createSphereMesh(unit: Unit, radius: Element.Property<number>, detail: number, mesh?: Mesh) {
  55. return Task.create('Sphere mesh', async ctx => {
  56. const { elements } = unit;
  57. const elementCount = elements.length;
  58. const vertexCount = elementCount * icosahedronVertexCount(detail)
  59. const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
  60. const v = Vec3.zero()
  61. const m = Mat4.identity()
  62. const { x, y, z } = unit.conformation
  63. const l = Element.Location()
  64. l.unit = unit
  65. for (let i = 0; i < elementCount; i++) {
  66. l.element = elements[i]
  67. v[0] = x(l.element); v[1] = y(l.element); v[2] = z(l.element)
  68. Mat4.setTranslation(m, v)
  69. meshBuilder.setId(i)
  70. meshBuilder.addIcosahedron(m, { radius: radius(l), detail })
  71. if (i % 10000 === 0 && ctx.shouldUpdate) {
  72. await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
  73. }
  74. }
  75. return meshBuilder.getMesh()
  76. })
  77. }
  78. export function applyElementFlags(tFlag: ValueCell<TextureImage>, group: Unit.SymmetryGroup, loci: Loci, action: FlagAction) {
  79. let changed = false
  80. const elementCount = group.elements.length
  81. const instanceCount = group.units.length
  82. const array = tFlag.ref.value.array
  83. if (isEveryLoci(loci)) {
  84. applyFlagAction(array, 0, elementCount * instanceCount, action)
  85. changed = true
  86. } else if (Element.isLoci(loci)) {
  87. for (const e of loci.elements) {
  88. const unitIdx = Unit.findUnitById(e.unit.id, group.units)
  89. if (unitIdx !== -1) {
  90. for (let i = 0, il = e.indices.length; i < il; ++i) {
  91. const idx = unitIdx * elementCount + e.indices[i]
  92. if (applyFlagAction(array, idx, idx + 1, action) && !changed) {
  93. changed = true
  94. }
  95. }
  96. }
  97. }
  98. } else {
  99. return
  100. }
  101. if (changed) {
  102. ValueCell.update(tFlag, tFlag.ref.value)
  103. }
  104. }