@math.gl/geometry 5.0.0-alpha.15 → 5.0.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,36 +1,89 @@
1
1
  // math.gl
2
2
  // SPDX-License-Identifier: MIT
3
3
  // SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
4
- import { assertPositive } from "../geometries/geometry-helpers.js";
4
+ import { Geometry } from "../lib/geometry.js";
5
+ import { assertPositive, assertSegments, makeIndices } from "../geometries/geometry-helpers.js";
5
6
  import { ParametricGeometry } from "./parametric-geometry.js";
6
7
  /** Ring torus around Y, with outward analytic normals and separate UV seam rows. */
7
8
  export class TorusGeometry extends ParametricGeometry {
8
9
  constructor(props = {}) {
9
- const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2 } = props;
10
+ const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2, startAngle = 0, cap = false } = props;
10
11
  assertPositive(majorRadius, 'majorRadius');
11
12
  assertPositive(minorRadius, 'minorRadius');
12
13
  if (minorRadius >= majorRadius)
13
14
  throw new RangeError('Ring torus requires minorRadius < majorRadius');
14
15
  if (!Number.isFinite(arc) || arc <= 0 || arc > Math.PI * 2)
15
16
  throw new RangeError('arc must be in (0, 2π]');
16
- if (majorSegments < 3 || minorSegments < 3)
17
- throw new RangeError('Torus requires at least three segments per axis');
17
+ assertSegments(majorSegments, 'majorSegments', 3);
18
+ assertSegments(minorSegments, 'minorSegments', 3);
19
+ if (!Number.isFinite(startAngle))
20
+ throw new RangeError('startAngle must be finite');
21
+ const hasCaps = cap && arc < Math.PI * 2;
18
22
  super({
19
23
  ...props,
24
+ attributes: hasCaps ? undefined : props.attributes,
20
25
  uSegments: majorSegments,
21
26
  vSegments: minorSegments,
22
27
  periodicU: arc === Math.PI * 2,
23
28
  periodicV: true,
24
29
  sample: (u, v) => {
25
- const theta = u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
30
+ const theta = startAngle + u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
26
31
  return [radius * Math.cos(theta), minorRadius * Math.sin(phi), -radius * Math.sin(theta)];
27
32
  },
28
33
  normal: (u, v) => [
29
- Math.cos(v * Math.PI * 2) * Math.cos(u * arc),
34
+ Math.cos(v * Math.PI * 2) * Math.cos(startAngle + u * arc),
30
35
  Math.sin(v * Math.PI * 2),
31
- -Math.cos(v * Math.PI * 2) * Math.sin(u * arc)
36
+ -Math.cos(v * Math.PI * 2) * Math.sin(startAngle + u * arc)
32
37
  ]
33
38
  });
39
+ if (hasCaps) {
40
+ const surfacePositions = this.attributes['POSITION'].value;
41
+ const positions = Array.from(surfacePositions);
42
+ const normals = Array.from(this.attributes['NORMAL'].value);
43
+ const textureCoordinates = Array.from(this.attributes['TEXCOORD_0'].value);
44
+ const indices = Array.from(this.indices.value);
45
+ for (const [angle, direction] of [
46
+ [startAngle, -1],
47
+ [startAngle + arc, 1]
48
+ ]) {
49
+ const normal = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
50
+ const centerIndex = positions.length / 3;
51
+ positions.push(majorRadius * Math.cos(angle), 0, -majorRadius * Math.sin(angle));
52
+ normals.push(...normal);
53
+ textureCoordinates.push(0.5, 0.5);
54
+ for (let minorSegment = 0; minorSegment <= minorSegments; minorSegment++) {
55
+ // The final disk vertex duplicates the first exactly, matching the tube UV seam.
56
+ const tubeAngle = ((minorSegment % minorSegments) * Math.PI * 2) / minorSegments;
57
+ // Copy boundary positions so disk and tube edges match bit for bit.
58
+ const boundaryOffset = (minorSegment * (majorSegments + 1) + (direction < 0 ? 0 : majorSegments)) * 3;
59
+ positions.push(...surfacePositions.slice(boundaryOffset, boundaryOffset + 3));
60
+ normals.push(...normal);
61
+ textureCoordinates.push((Math.cos(tubeAngle) + 1) / 2, (Math.sin(tubeAngle) + 1) / 2);
62
+ if (minorSegment < minorSegments) {
63
+ const firstIndex = centerIndex + minorSegment + 1;
64
+ const secondIndex = firstIndex + 1;
65
+ indices.push(centerIndex, ...(direction > 0 ? [secondIndex, firstIndex] : [firstIndex, secondIndex]));
66
+ }
67
+ }
68
+ }
69
+ const cappedGeometry = new Geometry({
70
+ id: this.id,
71
+ topology: this.topology,
72
+ indices: makeIndices(positions.length / 3, indices),
73
+ attributes: {
74
+ POSITION: { size: 3, value: new Float32Array(positions) },
75
+ NORMAL: { size: 3, value: new Float32Array(normals) },
76
+ TEXCOORD_0: { size: 2, value: new Float32Array(textureCoordinates) },
77
+ ...props.attributes
78
+ }
79
+ });
80
+ // Finish construction with validated cap data while retaining ParametricGeometry inheritance.
81
+ Object.assign(this, {
82
+ attributes: cappedGeometry.attributes,
83
+ indices: cappedGeometry.indices,
84
+ vertexCount: cappedGeometry.vertexCount
85
+ });
86
+ }
34
87
  }
35
88
  }
36
89
  //# sourceMappingURL=torus-geometry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"torus-geometry.js","sourceRoot":"","sources":["../../src/parametric/torus-geometry.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,4DAA4D;AAC5D,OAAO,EAAC,cAAc,EAA8B,0CAAuC;AAC3F,OAAO,EAAC,kBAAkB,EAAC,iCAA8B;AASzD,oFAAoF;AACpF,MAAM,OAAO,aAAc,SAAQ,kBAAkB;IACnD,YAAY,QAA4B,EAAE;QACxC,MAAM,EACJ,WAAW,GAAG,CAAC,EACf,WAAW,GAAG,GAAG,EACjB,aAAa,GAAG,EAAE,EAClB,aAAa,GAAG,EAAE,EAClB,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,EAClB,GAAG,KAAK,CAAC;QACV,cAAc,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC3C,cAAc,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC3C,IAAI,WAAW,IAAI,WAAW;YAC5B,MAAM,IAAI,UAAU,CAAC,+CAA+C,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC;YACxD,MAAM,IAAI,UAAU,CAAC,wBAAwB,CAAC,CAAC;QACjD,IAAI,aAAa,GAAG,CAAC,IAAI,aAAa,GAAG,CAAC;YACxC,MAAM,IAAI,UAAU,CAAC,iDAAiD,CAAC,CAAC;QAC1E,KAAK,CAAC;YACJ,GAAG,KAAK;YACR,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC,EAAE,GAAG,CAAC;YAC9B,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACf,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,EACnB,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,EACrB,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACrD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5F,CAAC;YACD,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;gBAC7C,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;gBACzB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;aAC/C;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"torus-geometry.js","sourceRoot":"","sources":["../../src/parametric/torus-geometry.ts"],"names":[],"mappings":"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"}
@@ -119,6 +119,9 @@ function assertSegments(value, name, minimum = 1) {
119
119
  if (!Number.isInteger(value) || value < minimum)
120
120
  throw new Error(`${name} must be an integer >= ${minimum}`);
121
121
  }
122
+ function makeIndices(vertexCount, values) {
123
+ return vertexCount > 65535 ? new Uint32Array(values) : new Uint16Array(values);
124
+ }
122
125
 
123
126
  // dist/parametric/parametric-geometry.js
124
127
  var ParametricGeometry = class extends Geometry {
@@ -204,31 +207,80 @@ function normalized(vector) {
204
207
  // dist/parametric/torus-geometry.js
205
208
  var TorusGeometry = class extends ParametricGeometry {
206
209
  constructor(props = {}) {
207
- const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2 } = props;
210
+ const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2, startAngle = 0, cap = false } = props;
208
211
  assertPositive(majorRadius, "majorRadius");
209
212
  assertPositive(minorRadius, "minorRadius");
210
213
  if (minorRadius >= majorRadius)
211
214
  throw new RangeError("Ring torus requires minorRadius < majorRadius");
212
215
  if (!Number.isFinite(arc) || arc <= 0 || arc > Math.PI * 2)
213
216
  throw new RangeError("arc must be in (0, 2\u03C0]");
214
- if (majorSegments < 3 || minorSegments < 3)
215
- throw new RangeError("Torus requires at least three segments per axis");
217
+ assertSegments(majorSegments, "majorSegments", 3);
218
+ assertSegments(minorSegments, "minorSegments", 3);
219
+ if (!Number.isFinite(startAngle))
220
+ throw new RangeError("startAngle must be finite");
221
+ const hasCaps = cap && arc < Math.PI * 2;
216
222
  super({
217
223
  ...props,
224
+ attributes: hasCaps ? void 0 : props.attributes,
218
225
  uSegments: majorSegments,
219
226
  vSegments: minorSegments,
220
227
  periodicU: arc === Math.PI * 2,
221
228
  periodicV: true,
222
229
  sample: (u, v) => {
223
- const theta = u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
230
+ const theta = startAngle + u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
224
231
  return [radius * Math.cos(theta), minorRadius * Math.sin(phi), -radius * Math.sin(theta)];
225
232
  },
226
233
  normal: (u, v) => [
227
- Math.cos(v * Math.PI * 2) * Math.cos(u * arc),
234
+ Math.cos(v * Math.PI * 2) * Math.cos(startAngle + u * arc),
228
235
  Math.sin(v * Math.PI * 2),
229
- -Math.cos(v * Math.PI * 2) * Math.sin(u * arc)
236
+ -Math.cos(v * Math.PI * 2) * Math.sin(startAngle + u * arc)
230
237
  ]
231
238
  });
239
+ if (hasCaps) {
240
+ const surfacePositions = this.attributes["POSITION"].value;
241
+ const positions = Array.from(surfacePositions);
242
+ const normals = Array.from(this.attributes["NORMAL"].value);
243
+ const textureCoordinates = Array.from(this.attributes["TEXCOORD_0"].value);
244
+ const indices = Array.from(this.indices.value);
245
+ for (const [angle, direction] of [
246
+ [startAngle, -1],
247
+ [startAngle + arc, 1]
248
+ ]) {
249
+ const normal = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
250
+ const centerIndex = positions.length / 3;
251
+ positions.push(majorRadius * Math.cos(angle), 0, -majorRadius * Math.sin(angle));
252
+ normals.push(...normal);
253
+ textureCoordinates.push(0.5, 0.5);
254
+ for (let minorSegment = 0; minorSegment <= minorSegments; minorSegment++) {
255
+ const tubeAngle = minorSegment % minorSegments * Math.PI * 2 / minorSegments;
256
+ const boundaryOffset = (minorSegment * (majorSegments + 1) + (direction < 0 ? 0 : majorSegments)) * 3;
257
+ positions.push(...surfacePositions.slice(boundaryOffset, boundaryOffset + 3));
258
+ normals.push(...normal);
259
+ textureCoordinates.push((Math.cos(tubeAngle) + 1) / 2, (Math.sin(tubeAngle) + 1) / 2);
260
+ if (minorSegment < minorSegments) {
261
+ const firstIndex = centerIndex + minorSegment + 1;
262
+ const secondIndex = firstIndex + 1;
263
+ indices.push(centerIndex, ...direction > 0 ? [secondIndex, firstIndex] : [firstIndex, secondIndex]);
264
+ }
265
+ }
266
+ }
267
+ const cappedGeometry = new Geometry({
268
+ id: this.id,
269
+ topology: this.topology,
270
+ indices: makeIndices(positions.length / 3, indices),
271
+ attributes: {
272
+ POSITION: { size: 3, value: new Float32Array(positions) },
273
+ NORMAL: { size: 3, value: new Float32Array(normals) },
274
+ TEXCOORD_0: { size: 2, value: new Float32Array(textureCoordinates) },
275
+ ...props.attributes
276
+ }
277
+ });
278
+ Object.assign(this, {
279
+ attributes: cappedGeometry.attributes,
280
+ indices: cappedGeometry.indices,
281
+ vertexCount: cappedGeometry.vertexCount
282
+ });
283
+ }
232
284
  }
233
285
  };
234
286
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/parametric.ts", "../src/lib/geometry.ts", "../src/geometries/geometry-helpers.ts", "../src/parametric/parametric-geometry.ts", "../src/parametric/torus-geometry.ts", "../src/parametric/lathe-geometry.ts"],
4
- "mappings": "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",
4
+ "mappings": "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",
5
5
  "names": []
6
6
  }
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
9
- "version": "5.0.0-alpha.15",
9
+ "version": "5.0.0-alpha.16",
10
10
  "keywords": [
11
11
  "geometry",
12
12
  "gltf",
@@ -39,7 +39,7 @@
39
39
  "src"
40
40
  ],
41
41
  "dependencies": {
42
- "@math.gl/types": "5.0.0-alpha.15"
42
+ "@math.gl/types": "5.0.0-alpha.16"
43
43
  },
44
- "gitHead": "cac4021fb41136cf5c7aca8f041806bc975edef9"
44
+ "gitHead": "95d9d242bd9a2060ab8a0aaeb32d6657c3f06b3b"
45
45
  }
@@ -0,0 +1,84 @@
1
+ // math.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
4
+
5
+ import type {GeometryProps} from '../lib/geometry';
6
+ import {assertSegments, makeIndices, type PrimitiveGeometryProps} from './geometry-helpers';
7
+ export const FULL_CIRCLE = Math.PI * 2;
8
+ export type Vector = [number, number, number];
9
+ export type Vertex = {position: Vector; normal: Vector; textureCoordinates: [number, number]};
10
+ export function radial(angle: number, direction = 1): Vector {
11
+ return [Math.cos(angle) * direction, 0, -Math.sin(angle) * direction];
12
+ }
13
+ export function vertex(
14
+ radius: number,
15
+ height: number,
16
+ angle: number,
17
+ normal: Vector,
18
+ textureCoordinates?: [number, number]
19
+ ): Vertex {
20
+ return {
21
+ position: [radius * Math.cos(angle), height, -radius * Math.sin(angle)],
22
+ normal,
23
+ textureCoordinates: textureCoordinates ?? [(Math.cos(angle) + 1) / 2, (Math.sin(angle) + 1) / 2]
24
+ };
25
+ }
26
+ export function validateArc(segments: number, startAngle: number, sweepAngle: number): void {
27
+ assertSegments(segments, 'segments', 3);
28
+ if (!Number.isFinite(startAngle)) throw new Error('startAngle must be finite');
29
+ if (!Number.isFinite(sweepAngle) || sweepAngle <= 0 || sweepAngle > FULL_CIRCLE)
30
+ throw new Error('sweepAngle must be positive and at most 2π');
31
+ }
32
+ export class PrimitiveMeshBuilder {
33
+ private positions: number[] = [];
34
+ private normals: number[] = [];
35
+ private textureCoordinates: number[] = [];
36
+ private indices: number[] = [];
37
+ private addVertex(current: Vertex): number {
38
+ const index = this.positions.length / 3;
39
+ this.positions.push(...current.position);
40
+ this.normals.push(...current.normal);
41
+ this.textureCoordinates.push(...current.textureCoordinates);
42
+ return index;
43
+ }
44
+ private addTriangle(first: Vertex, second: Vertex, third: Vertex, indices: number[]): void {
45
+ const firstEdge = second.position.map((value, index) => value - first.position[index]);
46
+ const secondEdge = third.position.map((value, index) => value - first.position[index]);
47
+ const cross = [
48
+ firstEdge[1] * secondEdge[2] - firstEdge[2] * secondEdge[1],
49
+ firstEdge[2] * secondEdge[0] - firstEdge[0] * secondEdge[2],
50
+ firstEdge[0] * secondEdge[1] - firstEdge[1] * secondEdge[0]
51
+ ];
52
+ const orientation = cross.reduce(
53
+ (sum, value, index) =>
54
+ sum + value * (first.normal[index] + second.normal[index] + third.normal[index]),
55
+ 0
56
+ );
57
+ this.indices.push(...(orientation < 0 ? [indices[0], indices[2], indices[1]] : indices));
58
+ }
59
+ triangle(first: Vertex, second: Vertex, third: Vertex): void {
60
+ this.addTriangle(first, second, third, [
61
+ this.addVertex(first),
62
+ this.addVertex(second),
63
+ this.addVertex(third)
64
+ ]);
65
+ }
66
+ quad(first: Vertex, second: Vertex, third: Vertex, fourth: Vertex): void {
67
+ const indices = [first, second, third, fourth].map(current => this.addVertex(current));
68
+ this.addTriangle(first, second, third, indices.slice(0, 3));
69
+ this.addTriangle(first, third, fourth, [indices[0], indices[2], indices[3]]);
70
+ }
71
+ getProps(props: PrimitiveGeometryProps): GeometryProps {
72
+ return {
73
+ id: props.id,
74
+ topology: 'triangle-list',
75
+ indices: makeIndices(this.positions.length / 3, this.indices),
76
+ attributes: {
77
+ POSITION: {size: 3, value: new Float32Array(this.positions)},
78
+ NORMAL: {size: 3, value: new Float32Array(this.normals)},
79
+ TEXCOORD_0: {size: 2, value: new Float32Array(this.textureCoordinates)},
80
+ ...props.attributes
81
+ }
82
+ };
83
+ }
84
+ }
@@ -0,0 +1,57 @@
1
+ // math.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
4
+
5
+ import {Geometry} from '../lib/geometry';
6
+ import {assertPositive, type PrimitiveGeometryProps} from './geometry-helpers';
7
+ import {
8
+ PrimitiveMeshBuilder,
9
+ FULL_CIRCLE,
10
+ radial,
11
+ validateArc,
12
+ vertex,
13
+ type Vector,
14
+ type Vertex
15
+ } from './primitive-mesh-builder';
16
+ export type PrismGeometryProps = PrimitiveGeometryProps & {
17
+ radius?: number;
18
+ height?: number;
19
+ sides?: number;
20
+ startAngle?: number;
21
+ };
22
+ /** Closed regular prism, centered at the origin with Y vertical and flat side normals. */
23
+ export class PrismGeometry extends Geometry {
24
+ constructor(props: PrismGeometryProps = {}) {
25
+ const {radius = 1, height = 1, sides = 6, startAngle = 0} = props;
26
+ assertPositive(radius, 'radius');
27
+ assertPositive(height, 'height');
28
+ validateArc(sides, startAngle, FULL_CIRCLE);
29
+ const mesh = new PrimitiveMeshBuilder();
30
+ for (let segment = 0; segment < sides; segment++) {
31
+ const firstAngle = startAngle + (segment * FULL_CIRCLE) / sides;
32
+ const secondAngle = startAngle + ((segment + 1) * FULL_CIRCLE) / sides;
33
+ const normal = radial((firstAngle + secondAngle) / 2);
34
+ const secondCornerAngle = segment === sides - 1 ? startAngle : secondAngle;
35
+ mesh.quad(
36
+ vertex(radius, -height / 2, firstAngle, normal, [segment / sides, 0]),
37
+ vertex(radius, height / 2, firstAngle, normal, [segment / sides, 1]),
38
+ vertex(radius, height / 2, secondCornerAngle, normal, [(segment + 1) / sides, 1]),
39
+ vertex(radius, -height / 2, secondCornerAngle, normal, [(segment + 1) / sides, 0])
40
+ );
41
+ for (const direction of [-1, 1]) {
42
+ const capNormal: Vector = [0, direction, 0];
43
+ const center: Vertex = {
44
+ position: [0, (direction * height) / 2, 0],
45
+ normal: capNormal,
46
+ textureCoordinates: [0.5, 0.5]
47
+ };
48
+ mesh.triangle(
49
+ center,
50
+ vertex(radius, (direction * height) / 2, firstAngle, capNormal),
51
+ vertex(radius, (direction * height) / 2, secondCornerAngle, capNormal)
52
+ );
53
+ }
54
+ }
55
+ super(mesh.getProps(props));
56
+ }
57
+ }
@@ -0,0 +1,102 @@
1
+ // math.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
4
+
5
+ import {Geometry} from '../lib/geometry';
6
+ import {assertPositive, type PrimitiveGeometryProps} from './geometry-helpers';
7
+ import {
8
+ PrimitiveMeshBuilder,
9
+ FULL_CIRCLE,
10
+ radial,
11
+ validateArc,
12
+ vertex,
13
+ type Vector
14
+ } from './primitive-mesh-builder';
15
+ export type RingGeometryProps = PrimitiveGeometryProps & {
16
+ innerRadius?: number;
17
+ outerRadius?: number;
18
+ height?: number;
19
+ segments?: number;
20
+ startAngle?: number;
21
+ sweepAngle?: number;
22
+ };
23
+ /** Closed annular sector in XZ, centered vertically with hard top, bottom and end caps. */
24
+ export class RingGeometry extends Geometry {
25
+ constructor(props: RingGeometryProps = {}) {
26
+ const {
27
+ innerRadius = 0.5,
28
+ outerRadius = 1,
29
+ height = 0.1,
30
+ segments = 48,
31
+ startAngle = 0,
32
+ sweepAngle = FULL_CIRCLE
33
+ } = props;
34
+ assertPositive(innerRadius, 'innerRadius');
35
+ assertPositive(outerRadius, 'outerRadius');
36
+ assertPositive(height, 'height');
37
+ if (innerRadius >= outerRadius) throw new Error('innerRadius must be smaller than outerRadius');
38
+ validateArc(segments, startAngle, sweepAngle);
39
+ const mesh = new PrimitiveMeshBuilder();
40
+ for (let segment = 0; segment < segments; segment++) {
41
+ const firstAngle = startAngle + (segment * sweepAngle) / segments;
42
+ const secondAngle =
43
+ segment === segments - 1
44
+ ? sweepAngle === FULL_CIRCLE
45
+ ? startAngle
46
+ : startAngle + sweepAngle
47
+ : startAngle + ((segment + 1) * sweepAngle) / segments;
48
+ const makeCapVertex = (radius: number, height: number, angle: number, normal: Vector) =>
49
+ vertex(radius, height, angle, normal, [
50
+ ((radius * Math.cos(angle)) / outerRadius + 1) / 2,
51
+ ((radius * Math.sin(angle)) / outerRadius + 1) / 2
52
+ ]);
53
+ for (const direction of [-1, 1]) {
54
+ const normal: Vector = [0, direction, 0];
55
+ mesh.quad(
56
+ makeCapVertex(innerRadius, (direction * height) / 2, firstAngle, normal),
57
+ makeCapVertex(outerRadius, (direction * height) / 2, firstAngle, normal),
58
+ makeCapVertex(outerRadius, (direction * height) / 2, secondAngle, normal),
59
+ makeCapVertex(innerRadius, (direction * height) / 2, secondAngle, normal)
60
+ );
61
+ }
62
+ for (const [radius, direction] of [
63
+ [innerRadius, -1],
64
+ [outerRadius, 1]
65
+ ]) {
66
+ mesh.quad(
67
+ vertex(radius, -height / 2, firstAngle, radial(firstAngle, direction), [
68
+ segment / segments,
69
+ 0
70
+ ]),
71
+ vertex(radius, height / 2, firstAngle, radial(firstAngle, direction), [
72
+ segment / segments,
73
+ 1
74
+ ]),
75
+ vertex(radius, height / 2, secondAngle, radial(secondAngle, direction), [
76
+ (segment + 1) / segments,
77
+ 1
78
+ ]),
79
+ vertex(radius, -height / 2, secondAngle, radial(secondAngle, direction), [
80
+ (segment + 1) / segments,
81
+ 0
82
+ ])
83
+ );
84
+ }
85
+ }
86
+ if (sweepAngle < FULL_CIRCLE) {
87
+ for (const [angle, direction] of [
88
+ [startAngle, -1],
89
+ [startAngle + sweepAngle, 1]
90
+ ]) {
91
+ const normal: Vector = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
92
+ mesh.quad(
93
+ vertex(innerRadius, -height / 2, angle, normal, [0, 0]),
94
+ vertex(outerRadius, -height / 2, angle, normal, [1, 0]),
95
+ vertex(outerRadius, height / 2, angle, normal, [1, 1]),
96
+ vertex(innerRadius, height / 2, angle, normal, [0, 1])
97
+ );
98
+ }
99
+ }
100
+ super(mesh.getProps(props));
101
+ }
102
+ }
package/src/index.ts CHANGED
@@ -26,3 +26,9 @@ export {TruncatedConeGeometry} from './geometries/truncated-cone-geometry';
26
26
  export type {TruncatedConeGeometryProps} from './geometries/truncated-cone-geometry';
27
27
  export {IcoSphereGeometry} from './geometries/ico-sphere-geometry';
28
28
  export type {IcoSphereGeometryProps} from './geometries/ico-sphere-geometry';
29
+
30
+ export {PrismGeometry} from './geometries/prism-geometry';
31
+ export type {PrismGeometryProps} from './geometries/prism-geometry';
32
+
33
+ export {RingGeometry} from './geometries/ring-geometry';
34
+ export type {RingGeometryProps} from './geometries/ring-geometry';
@@ -1,15 +1,25 @@
1
1
  // math.gl
2
2
  // SPDX-License-Identifier: MIT
3
3
  // SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
4
- import {assertPositive, type PrimitiveGeometryProps} from '../geometries/geometry-helpers';
4
+ import {Geometry} from '../lib/geometry';
5
+ import {
6
+ assertPositive,
7
+ assertSegments,
8
+ makeIndices,
9
+ type PrimitiveGeometryProps
10
+ } from '../geometries/geometry-helpers';
5
11
  import {ParametricGeometry} from './parametric-geometry';
6
12
  export type TorusGeometryProps = PrimitiveGeometryProps & {
7
13
  majorRadius?: number;
8
14
  minorRadius?: number;
9
15
  majorSegments?: number;
10
16
  minorSegments?: number;
11
- /** Sweep in radians, (0, 2π]. Partial sweeps have open ends. */
17
+ /** Sweep in radians, (0, 2π]. Partial sweeps have open ends unless cap is enabled. */
12
18
  arc?: number;
19
+ /** Rotation in radians about Y; positive angles turn toward negative Z. */
20
+ startAngle?: number;
21
+ /** Close partial sweeps with flat end disks. Ignored for a full revolution. */
22
+ cap?: boolean;
13
23
  };
14
24
  /** Ring torus around Y, with outward analytic normals and separate UV seam rows. */
15
25
  export class TorusGeometry extends ParametricGeometry {
@@ -19,7 +29,9 @@ export class TorusGeometry extends ParametricGeometry {
19
29
  minorRadius = 0.3,
20
30
  majorSegments = 48,
21
31
  minorSegments = 24,
22
- arc = Math.PI * 2
32
+ arc = Math.PI * 2,
33
+ startAngle = 0,
34
+ cap = false
23
35
  } = props;
24
36
  assertPositive(majorRadius, 'majorRadius');
25
37
  assertPositive(minorRadius, 'minorRadius');
@@ -27,25 +39,80 @@ export class TorusGeometry extends ParametricGeometry {
27
39
  throw new RangeError('Ring torus requires minorRadius < majorRadius');
28
40
  if (!Number.isFinite(arc) || arc <= 0 || arc > Math.PI * 2)
29
41
  throw new RangeError('arc must be in (0, 2π]');
30
- if (majorSegments < 3 || minorSegments < 3)
31
- throw new RangeError('Torus requires at least three segments per axis');
42
+ assertSegments(majorSegments, 'majorSegments', 3);
43
+ assertSegments(minorSegments, 'minorSegments', 3);
44
+ if (!Number.isFinite(startAngle)) throw new RangeError('startAngle must be finite');
45
+ const hasCaps = cap && arc < Math.PI * 2;
32
46
  super({
33
47
  ...props,
48
+ attributes: hasCaps ? undefined : props.attributes,
34
49
  uSegments: majorSegments,
35
50
  vSegments: minorSegments,
36
51
  periodicU: arc === Math.PI * 2,
37
52
  periodicV: true,
38
53
  sample: (u, v) => {
39
- const theta = u * arc,
54
+ const theta = startAngle + u * arc,
40
55
  phi = v * Math.PI * 2,
41
56
  radius = majorRadius + minorRadius * Math.cos(phi);
42
57
  return [radius * Math.cos(theta), minorRadius * Math.sin(phi), -radius * Math.sin(theta)];
43
58
  },
44
59
  normal: (u, v) => [
45
- Math.cos(v * Math.PI * 2) * Math.cos(u * arc),
60
+ Math.cos(v * Math.PI * 2) * Math.cos(startAngle + u * arc),
46
61
  Math.sin(v * Math.PI * 2),
47
- -Math.cos(v * Math.PI * 2) * Math.sin(u * arc)
62
+ -Math.cos(v * Math.PI * 2) * Math.sin(startAngle + u * arc)
48
63
  ]
49
64
  });
65
+ if (hasCaps) {
66
+ const surfacePositions = this.attributes['POSITION'].value;
67
+ const positions = Array.from(surfacePositions);
68
+ const normals = Array.from(this.attributes['NORMAL'].value);
69
+ const textureCoordinates = Array.from(this.attributes['TEXCOORD_0'].value);
70
+ const indices = Array.from(this.indices!.value);
71
+ for (const [angle, direction] of [
72
+ [startAngle, -1],
73
+ [startAngle + arc, 1]
74
+ ]) {
75
+ const normal = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
76
+ const centerIndex = positions.length / 3;
77
+ positions.push(majorRadius * Math.cos(angle), 0, -majorRadius * Math.sin(angle));
78
+ normals.push(...normal);
79
+ textureCoordinates.push(0.5, 0.5);
80
+ for (let minorSegment = 0; minorSegment <= minorSegments; minorSegment++) {
81
+ // The final disk vertex duplicates the first exactly, matching the tube UV seam.
82
+ const tubeAngle = ((minorSegment % minorSegments) * Math.PI * 2) / minorSegments;
83
+ // Copy boundary positions so disk and tube edges match bit for bit.
84
+ const boundaryOffset =
85
+ (minorSegment * (majorSegments + 1) + (direction < 0 ? 0 : majorSegments)) * 3;
86
+ positions.push(...surfacePositions.slice(boundaryOffset, boundaryOffset + 3));
87
+ normals.push(...normal);
88
+ textureCoordinates.push((Math.cos(tubeAngle) + 1) / 2, (Math.sin(tubeAngle) + 1) / 2);
89
+ if (minorSegment < minorSegments) {
90
+ const firstIndex = centerIndex + minorSegment + 1;
91
+ const secondIndex = firstIndex + 1;
92
+ indices.push(
93
+ centerIndex,
94
+ ...(direction > 0 ? [secondIndex, firstIndex] : [firstIndex, secondIndex])
95
+ );
96
+ }
97
+ }
98
+ }
99
+ const cappedGeometry = new Geometry({
100
+ id: this.id,
101
+ topology: this.topology,
102
+ indices: makeIndices(positions.length / 3, indices),
103
+ attributes: {
104
+ POSITION: {size: 3, value: new Float32Array(positions)},
105
+ NORMAL: {size: 3, value: new Float32Array(normals)},
106
+ TEXCOORD_0: {size: 2, value: new Float32Array(textureCoordinates)},
107
+ ...props.attributes
108
+ }
109
+ });
110
+ // Finish construction with validated cap data while retaining ParametricGeometry inheritance.
111
+ Object.assign(this, {
112
+ attributes: cappedGeometry.attributes,
113
+ indices: cappedGeometry.indices,
114
+ vertexCount: cappedGeometry.vertexCount
115
+ });
116
+ }
50
117
  }
51
118
  }