element.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. */
  6. import { Vec3 } from 'mol-math/linear-algebra';
  7. import { Unit, Element } from 'mol-model/structure';
  8. import { SizeTheme } from '../../../../theme';
  9. import { RuntimeContext } from 'mol-task';
  10. import { icosahedronVertexCount } from '../../../../primitive/icosahedron';
  11. import { Mesh } from '../../../../shape/mesh';
  12. import { MeshBuilder } from '../../../../shape/mesh-builder';
  13. import { ValueCell, defaults } from 'mol-util';
  14. import { TextureImage } from 'mol-gl/renderable/util';
  15. import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci';
  16. import { MarkerAction, applyMarkerAction } from '../../../../util/marker-data';
  17. import { Interval, OrderedSet } from 'mol-data/int';
  18. import { getPhysicalRadius } from '../../../../theme/structure/size/physical';
  19. import { PickingId } from '../../../../util/picking';
  20. export function getElementRadius(unit: Unit, props: SizeTheme): Element.Property<number> {
  21. switch (props.name) {
  22. case 'uniform':
  23. return () => props.value
  24. case 'physical':
  25. const radius = getPhysicalRadius(unit)
  26. const factor = defaults(props.factor, 1)
  27. return (l) => radius(l) * factor
  28. }
  29. }
  30. export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, radius: Element.Property<number>, detail: number, mesh?: Mesh) {
  31. const { elements } = unit;
  32. const elementCount = elements.length;
  33. const vertexCount = elementCount * icosahedronVertexCount(detail)
  34. const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
  35. const v = Vec3.zero()
  36. const pos = unit.conformation.invariantPosition
  37. const l = Element.Location()
  38. l.unit = unit
  39. for (let i = 0; i < elementCount; i++) {
  40. l.element = elements[i]
  41. pos(elements[i], v)
  42. meshBuilder.setId(i)
  43. meshBuilder.addIcosahedron(v, radius(l), detail)
  44. if (i % 10000 === 0 && ctx.shouldUpdate) {
  45. await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
  46. }
  47. }
  48. return meshBuilder.getMesh()
  49. }
  50. export function markElement(tMarker: ValueCell<TextureImage>, group: Unit.SymmetryGroup, loci: Loci, action: MarkerAction) {
  51. let changed = false
  52. const elementCount = group.elements.length
  53. const instanceCount = group.units.length
  54. const array = tMarker.ref.value.array
  55. if (isEveryLoci(loci)) {
  56. applyMarkerAction(array, 0, elementCount * instanceCount, action)
  57. changed = true
  58. } else if (Element.isLoci(loci)) {
  59. for (const e of loci.elements) {
  60. const unitIdx = Unit.findUnitById(e.unit.id, group.units)
  61. if (unitIdx !== -1) {
  62. if (Interval.is(e.indices)) {
  63. const idxStart = unitIdx * elementCount + Interval.start(e.indices);
  64. const idxEnd = unitIdx * elementCount + Interval.end(e.indices);
  65. if (applyMarkerAction(array, idxStart, idxEnd, action) && !changed) {
  66. changed = true
  67. }
  68. } else {
  69. for (let i = 0, _i = e.indices.length; i < _i; i++) {
  70. const idx = unitIdx * elementCount + e.indices[i];
  71. if (applyMarkerAction(array, idx, idx + 1, action) && !changed) {
  72. changed = true
  73. }
  74. }
  75. }
  76. }
  77. }
  78. } else {
  79. return
  80. }
  81. if (changed) {
  82. ValueCell.update(tMarker, tMarker.ref.value)
  83. }
  84. }
  85. export function getElementLoci(id: number, group: Unit.SymmetryGroup, pickingId: PickingId) {
  86. const { objectId, instanceId, elementId } = pickingId
  87. if (id === objectId) {
  88. const unit = group.units[instanceId]
  89. const indices = OrderedSet.ofSingleton(elementId as Element.Index);
  90. return Element.Loci([{ unit, indices }])
  91. }
  92. return EmptyLoci
  93. }