location-iterator.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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 { Iterator } from '../../mol-data';
  7. import { NullLocation, Location } from '../../mol-model/location';
  8. export interface LocationValue {
  9. location: Location
  10. index: number
  11. groupIndex: number
  12. instanceIndex: number
  13. isSecondary: boolean
  14. }
  15. export const NullLocationValue: LocationValue = {
  16. location: NullLocation,
  17. index: 0,
  18. groupIndex: 0,
  19. instanceIndex: 0,
  20. isSecondary: false
  21. }
  22. export interface LocationIterator extends Iterator<LocationValue> {
  23. readonly hasNext: boolean
  24. readonly isNextNewInstance: boolean
  25. readonly groupCount: number
  26. readonly instanceCount: number
  27. readonly count: number
  28. /** If true, may have multiple units per instance; if false one unit per instance */
  29. readonly isComplex: boolean
  30. move(): LocationValue
  31. reset(): void
  32. skipInstance(): void
  33. }
  34. type LocationGetter = (groupIndex: number, instanceIndex: number) => Location
  35. type IsSecondaryGetter = (groupIndex: number, instanceIndex: number) => boolean
  36. export function LocationIterator(groupCount: number, instanceCount: number, getLocation: LocationGetter, isComplex = false, isSecondary: IsSecondaryGetter = () => false): LocationIterator {
  37. const value: LocationValue = {
  38. location: NullLocation as Location,
  39. index: 0,
  40. groupIndex: 0,
  41. instanceIndex: 0,
  42. isSecondary: false
  43. }
  44. let hasNext = value.groupIndex < groupCount
  45. let isNextNewInstance = false
  46. let groupIndex = 0
  47. let instanceIndex = 0
  48. return {
  49. get hasNext () { return hasNext },
  50. get isNextNewInstance () { return isNextNewInstance },
  51. groupCount,
  52. instanceCount,
  53. count: groupCount * instanceCount,
  54. isComplex,
  55. move() {
  56. if (hasNext) {
  57. value.groupIndex = groupIndex
  58. value.instanceIndex = instanceIndex
  59. value.index = instanceIndex * groupCount + groupIndex
  60. value.location = getLocation(groupIndex, instanceIndex)
  61. value.isSecondary = isSecondary(groupIndex, instanceIndex)
  62. ++groupIndex
  63. if (groupIndex === groupCount) {
  64. ++instanceIndex
  65. isNextNewInstance = true
  66. if (instanceIndex < instanceCount) groupIndex = 0
  67. } else {
  68. isNextNewInstance = false
  69. }
  70. hasNext = groupIndex < groupCount
  71. }
  72. return value
  73. },
  74. reset() {
  75. value.location = NullLocation
  76. value.index = 0
  77. value.groupIndex = 0
  78. value.instanceIndex = 0
  79. value.isSecondary = false
  80. hasNext = value.groupIndex < groupCount
  81. isNextNewInstance = false
  82. groupIndex = 0
  83. instanceIndex = 0
  84. },
  85. skipInstance() {
  86. if (hasNext && value.instanceIndex === instanceIndex) {
  87. ++instanceIndex
  88. groupIndex = 0
  89. hasNext = instanceIndex < instanceCount
  90. }
  91. }
  92. }
  93. }