element.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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, StructureElement } from 'mol-model/structure';
  8. import { RuntimeContext } from 'mol-task';
  9. import { sphereVertexCount } from '../../../../primitive/sphere';
  10. import { Mesh } from '../../../../mesh/mesh';
  11. import { MeshBuilder } from '../../../../mesh/mesh-builder';
  12. import { Loci, EmptyLoci } from 'mol-model/loci';
  13. import { Interval, OrderedSet } from 'mol-data/int';
  14. import { PickingId } from '../../../../util/picking';
  15. import { SizeTheme, SizeThemeProps } from 'mol-view/theme/size';
  16. import { LocationIterator } from '../../../../util/location-iterator';
  17. import { addSphere } from '../../../../mesh/builder/sphere';
  18. export interface ElementSphereMeshProps {
  19. sizeTheme: SizeThemeProps,
  20. detail: number,
  21. }
  22. export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, props: ElementSphereMeshProps, mesh?: Mesh) {
  23. const { detail } = props
  24. const { elements } = unit;
  25. const sizeTheme = SizeTheme(props.sizeTheme)
  26. const elementCount = elements.length;
  27. const vertexCount = elementCount * sphereVertexCount(detail)
  28. const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
  29. const v = Vec3.zero()
  30. const pos = unit.conformation.invariantPosition
  31. const l = StructureElement.create()
  32. l.unit = unit
  33. for (let i = 0; i < elementCount; i++) {
  34. l.element = elements[i]
  35. pos(elements[i], v)
  36. meshBuilder.setGroup(i)
  37. addSphere(meshBuilder, v, sizeTheme.size(l), detail)
  38. if (i % 10000 === 0 && ctx.shouldUpdate) {
  39. await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
  40. }
  41. }
  42. return meshBuilder.getMesh()
  43. }
  44. export function markElement(loci: Loci, group: Unit.SymmetryGroup, apply: (interval: Interval) => boolean) {
  45. const elementCount = group.elements.length
  46. let changed = false
  47. if (StructureElement.isLoci(loci)) {
  48. for (const e of loci.elements) {
  49. const unitIdx = group.unitIndexMap.get(e.unit.id)
  50. if (unitIdx !== undefined) {
  51. if (Interval.is(e.indices)) {
  52. const start = unitIdx * elementCount + Interval.start(e.indices);
  53. const end = unitIdx * elementCount + Interval.end(e.indices);
  54. if (apply(Interval.ofBounds(start, end))) changed = true
  55. } else {
  56. for (let i = 0, _i = e.indices.length; i < _i; i++) {
  57. const idx = unitIdx * elementCount + e.indices[i];
  58. if (apply(Interval.ofSingleton(idx))) changed = true
  59. }
  60. }
  61. }
  62. }
  63. }
  64. return changed
  65. }
  66. export function getElementLoci(pickingId: PickingId, group: Unit.SymmetryGroup, id: number) {
  67. const { objectId, instanceId, groupId } = pickingId
  68. if (id === objectId) {
  69. const unit = group.units[instanceId]
  70. const indices = OrderedSet.ofSingleton(groupId as StructureElement.UnitIndex);
  71. return StructureElement.Loci([{ unit, indices }])
  72. }
  73. return EmptyLoci
  74. }
  75. export namespace StructureElementIterator {
  76. export function fromGroup(group: Unit.SymmetryGroup): LocationIterator {
  77. const groupCount = group.elements.length
  78. const instanceCount = group.units.length
  79. const location = StructureElement.create()
  80. const getLocation = (groupIndex: number, instanceIndex: number) => {
  81. const unit = group.units[instanceIndex]
  82. location.unit = unit
  83. location.element = unit.elements[groupIndex]
  84. return location
  85. }
  86. return LocationIterator(groupCount, instanceCount, getLocation)
  87. }
  88. }