shape.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Color } from 'mol-util/color';
  7. import { UUID } from 'mol-util';
  8. import { OrderedSet } from 'mol-data/int';
  9. import { Geometry } from 'mol-geo/geometry/geometry';
  10. import { Mat4 } from 'mol-math/linear-algebra';
  11. export interface Shape<G extends Geometry = Geometry> {
  12. /** A uuid to identify a shape object */
  13. readonly id: UUID
  14. /** A name to describe the shape */
  15. readonly name: string
  16. /** The data used to create the shape */
  17. readonly sourceData: unknown
  18. /** The geometry of the shape, e.g. `Mesh` or `Lines` */
  19. readonly geometry: G
  20. /** An array of transformation matrices to describe multiple instances of the geometry */
  21. readonly transforms: Mat4[]
  22. /** Number of groups in the geometry */
  23. readonly groupCount: number
  24. /** Get color for a given group */
  25. getColor(groupId: number, instanceId: number): Color
  26. /** Get size for a given group */
  27. getSize(groupId: number, instanceId: number): number
  28. /** Get label for a given group */
  29. getLabel(groupId: number, instanceId: number): string
  30. }
  31. export namespace Shape {
  32. export function create<G extends Geometry>(name: string, sourceData: unknown, geometry: G, getColor: Shape['getColor'], getSize: Shape['getSize'], getLabel: Shape['getLabel'], transforms?: Mat4[]): Shape<G> {
  33. return {
  34. id: UUID.create22(),
  35. name,
  36. sourceData,
  37. geometry,
  38. transforms: transforms || [Mat4.identity()],
  39. get groupCount() { return Geometry.getGroupCount(geometry) },
  40. getColor,
  41. getSize,
  42. getLabel
  43. }
  44. }
  45. export interface Loci { readonly kind: 'shape-loci', readonly shape: Shape }
  46. export function Loci(shape: Shape): Loci { return { kind: 'shape-loci', shape } }
  47. export function isLoci(x: any): x is Loci { return !!x && x.kind === 'shape-loci' }
  48. export function areLociEqual(a: Loci, b: Loci) { return a.shape === b.shape }
  49. }
  50. export namespace ShapeGroup {
  51. export interface Location {
  52. readonly kind: 'group-location'
  53. shape: Shape
  54. group: number
  55. instance: number
  56. }
  57. export function Location(shape?: Shape, group?: number, instance?: number): Location {
  58. return { kind: 'group-location', shape: shape!, group: group || 0, instance: instance || 0 };
  59. }
  60. export function isLocation(x: any): x is Location {
  61. return !!x && x.kind === 'group-location';
  62. }
  63. export interface Loci {
  64. readonly kind: 'group-loci',
  65. readonly shape: Shape,
  66. readonly groups: ReadonlyArray<{
  67. ids: OrderedSet<number>
  68. }>
  69. readonly instance: number
  70. }
  71. export function Loci(shape: Shape, groups: ArrayLike<{ ids: OrderedSet<number> }>, instance: number): Loci {
  72. return { kind: 'group-loci', shape, groups: groups as Loci['groups'], instance };
  73. }
  74. export function isLoci(x: any): x is Loci {
  75. return !!x && x.kind === 'group-loci';
  76. }
  77. export function areLociEqual(a: Loci, b: Loci) {
  78. if (a.shape !== b.shape) return false
  79. if (a.groups.length !== b.groups.length) return false
  80. if (a.instance !== b.instance) return false
  81. for (let i = 0, il = a.groups.length; i < il; ++i) {
  82. const groupA = a.groups[i]
  83. const groupB = b.groups[i]
  84. if (!OrderedSet.areEqual(groupA.ids, groupB.ids)) return false
  85. }
  86. return true
  87. }
  88. }