prism.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 { Vec3 } from '../../mol-math/linear-algebra'
  7. import { Primitive, PrimitiveBuilder } from './primitive';
  8. import { polygon } from './polygon'
  9. import { Cage } from './cage';
  10. const on = Vec3.create(0, 0, -0.5), op = Vec3.create(0, 0, 0.5)
  11. const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero()
  12. /**
  13. * Create a prism with a base of 4 or more points
  14. */
  15. export function Prism(points: ArrayLike<number>): Primitive {
  16. const sideCount = points.length / 3
  17. if (sideCount < 4) throw new Error('need at least 4 points to build a prism')
  18. const count = 4 * sideCount
  19. const builder = PrimitiveBuilder(count)
  20. // create sides
  21. for (let i = 0; i < sideCount; ++i) {
  22. const ni = (i + 1) % sideCount
  23. Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5)
  24. Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5)
  25. Vec3.set(c, points[ni * 3], points[ni * 3 + 1], 0.5)
  26. Vec3.set(d, points[i * 3], points[i * 3 + 1], 0.5)
  27. builder.add(a, b, c)
  28. builder.add(c, d, a)
  29. }
  30. // create bases
  31. for (let i = 0; i < sideCount; ++i) {
  32. const ni = (i + 1) % sideCount
  33. Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5)
  34. Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5)
  35. builder.add(on, b, a)
  36. Vec3.set(a, points[i * 3], points[i * 3 + 1], 0.5)
  37. Vec3.set(b, points[ni * 3], points[ni * 3 + 1], 0.5)
  38. builder.add(a, b, op)
  39. }
  40. return builder.getPrimitive()
  41. }
  42. let diamond: Primitive
  43. export function DiamondPrism() {
  44. if (!diamond) diamond = Prism(polygon(4, false))
  45. return diamond
  46. }
  47. let pentagonalPrism: Primitive
  48. export function PentagonalPrism() {
  49. if (!pentagonalPrism) pentagonalPrism = Prism(polygon(5, false))
  50. return pentagonalPrism
  51. }
  52. let hexagonalPrism: Primitive
  53. export function HexagonalPrism() {
  54. if (!hexagonalPrism) hexagonalPrism = Prism(polygon(6, true))
  55. return hexagonalPrism
  56. }
  57. //
  58. /**
  59. * Create a prism cage
  60. */
  61. export function PrismCage(points: ArrayLike<number>): Cage {
  62. const sideCount = points.length / 3
  63. // const count = 4 * sideCount
  64. const vertices: number[] = []
  65. const edges: number[] = []
  66. let offset = 0
  67. // vertices and side edges
  68. for (let i = 0; i < sideCount; ++i) {
  69. vertices.push(
  70. points[i * 3], points[i * 3 + 1], -0.5,
  71. points[i * 3], points[i * 3 + 1], 0.5
  72. )
  73. edges.push(offset, offset + 1)
  74. offset += 2
  75. }
  76. // bases edges
  77. for (let i = 0; i < sideCount; ++i) {
  78. const ni = (i + 1) % sideCount
  79. edges.push(
  80. i * 2, ni * 2,
  81. i * 2 + 1, ni * 2 + 1
  82. )
  83. }
  84. return { vertices, edges }
  85. }
  86. let diamondCage: Cage
  87. export function DiamondPrismCage() {
  88. if (!diamondCage) diamondCage = PrismCage(polygon(4, false))
  89. return diamondCage
  90. }
  91. let pentagonalPrismCage: Cage
  92. export function PentagonalPrismCage() {
  93. if (!pentagonalPrismCage) pentagonalPrismCage = PrismCage(polygon(5, false))
  94. return pentagonalPrismCage
  95. }
  96. let hexagonalPrismCage: Cage
  97. export function HexagonalPrismCage() {
  98. if (!hexagonalPrismCage) hexagonalPrismCage = PrismCage(polygon(6, true))
  99. return hexagonalPrismCage
  100. }