pyramid.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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, createPrimitive } 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 pyramid with a polygonal base
  14. */
  15. export function Pyramid(points: ArrayLike<number>): Primitive {
  16. const sideCount = points.length / 3
  17. const baseCount = sideCount === 3 ? 1 : sideCount === 4 ? 2 : sideCount
  18. const count = 2 * baseCount + 2 * 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. builder.add(a, b, op)
  26. }
  27. // create base
  28. if (sideCount === 3) {
  29. Vec3.set(a, points[0], points[1], -0.5)
  30. Vec3.set(b, points[3], points[4], -0.5)
  31. Vec3.set(c, points[6], points[7], -0.5)
  32. builder.add(c, b, a)
  33. } else if (sideCount === 4) {
  34. Vec3.set(a, points[0], points[1], -0.5)
  35. Vec3.set(b, points[3], points[4], -0.5)
  36. Vec3.set(c, points[6], points[7], -0.5)
  37. Vec3.set(d, points[9], points[10], -0.5)
  38. builder.add(c, b, a)
  39. builder.add(a, d, c)
  40. } else {
  41. for (let i = 0; i < sideCount; ++i) {
  42. const ni = (i + 1) % sideCount
  43. Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5)
  44. Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5)
  45. builder.add(on, b, a)
  46. }
  47. }
  48. return builder.getPrimitive()
  49. }
  50. let octagonalPyramid: Primitive
  51. export function OctagonalPyramid() {
  52. if (!octagonalPyramid) octagonalPyramid = Pyramid(polygon(8, true))
  53. return octagonalPyramid
  54. }
  55. let perforatedOctagonalPyramid: Primitive
  56. export function PerforatedOctagonalPyramid() {
  57. if (!perforatedOctagonalPyramid) {
  58. const points = polygon(8, true)
  59. const vertices = new Float32Array(8 * 3 + 6)
  60. for (let i = 0; i < 8; ++i) {
  61. vertices[i * 3] = points[i * 3]
  62. vertices[i * 3 + 1] = points[i * 3 + 1]
  63. vertices[i * 3 + 2] = -0.5
  64. }
  65. vertices[8 * 3] = 0
  66. vertices[8 * 3 + 1] = 0
  67. vertices[8 * 3 + 2] = -0.5
  68. vertices[8 * 3 + 3] = 0
  69. vertices[8 * 3 + 4] = 0
  70. vertices[8 * 3 + 5] = 0.5
  71. const indices: ReadonlyArray<number> = [
  72. 0, 1, 8, 1, 2, 8, 4, 5, 8, 5, 6, 8,
  73. 2, 3, 9, 3, 4, 9, 6, 7, 9, 7, 0, 9
  74. ];
  75. perforatedOctagonalPyramid = createPrimitive(vertices, indices)
  76. }
  77. return perforatedOctagonalPyramid
  78. }
  79. //
  80. /**
  81. * Create a prism cage
  82. */
  83. export function PyramidCage(points: ArrayLike<number>): Cage {
  84. const sideCount = points.length / 3
  85. // const count = 4 * sideCount
  86. const vertices: number[] = []
  87. const edges: number[] = []
  88. let offset = 1
  89. vertices.push(op[0], op[1], op[2])
  90. // vertices and side edges
  91. for (let i = 0; i < sideCount; ++i) {
  92. vertices.push(points[i * 3], points[i * 3 + 1], -0.5)
  93. edges.push(0, offset)
  94. offset += 1
  95. }
  96. // bases edges
  97. for (let i = 0; i < sideCount; ++i) {
  98. const ni = (i + 1) % sideCount
  99. edges.push(i + 1, ni + 1)
  100. }
  101. return { vertices, edges }
  102. }
  103. let octagonalPyramidCage: Cage
  104. export function OctagonalPyramidCage() {
  105. if (!octagonalPyramidCage) octagonalPyramidCage = PyramidCage(polygon(8, true))
  106. return octagonalPyramidCage
  107. }