@kitware/vtk.js 34.6.0 → 34.8.0

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.
Files changed (42) hide show
  1. package/Common/Core/Math/index.js +12 -1
  2. package/Common/Core/Math.d.ts +24 -18
  3. package/Common/Core/Math.js +1 -1
  4. package/Common/DataModel/Polygon.d.ts +13 -0
  5. package/Common/DataModel/Polygon.js +29 -2
  6. package/Common/DataModel/Triangle.js +8 -13
  7. package/Filters/Core/Cutter.js +1 -0
  8. package/Filters/General/ShrinkPolyData.d.ts +85 -0
  9. package/Filters/General/ShrinkPolyData.js +317 -0
  10. package/Filters/General.js +2 -0
  11. package/Filters/Sources/ArcSource.d.ts +244 -0
  12. package/Filters/Sources/ArcSource.js +138 -0
  13. package/Filters/Sources/EllipseArcSource.d.ts +212 -0
  14. package/Filters/Sources/EllipseArcSource.js +159 -0
  15. package/Filters/Sources/PlatonicSolidSource/Constants.d.ts +12 -0
  16. package/Filters/Sources/PlatonicSolidSource/Constants.js +12 -0
  17. package/Filters/Sources/PlatonicSolidSource.d.ts +109 -0
  18. package/Filters/Sources/PlatonicSolidSource.js +149 -0
  19. package/Filters/Sources.js +6 -0
  20. package/IO/Misc/OBJWriter.d.ts +103 -0
  21. package/IO/Misc/OBJWriter.js +237 -0
  22. package/IO/Misc.js +2 -0
  23. package/Interaction/Style/InteractorStyleManipulator.js +75 -2
  24. package/Proxy/Representations/GlyphRepresentationProxy.js +3 -0
  25. package/Rendering/Core/Camera.d.ts +3 -3
  26. package/Rendering/Core/Camera.js +33 -3
  27. package/Rendering/Core/ColorTransferFunction/CssFilters.js +1 -1
  28. package/Rendering/Core/ColorTransferFunction.js +1 -1
  29. package/Rendering/Core/Coordinate.js +1 -1
  30. package/Rendering/Core/CubeAxesActor.js +1 -1
  31. package/Rendering/Core/ImageMapper.js +1 -1
  32. package/Rendering/Core/Renderer.js +1 -1
  33. package/Rendering/Core/ScalarBarActor.js +1 -1
  34. package/Rendering/Core/TextActor.js +1 -1
  35. package/Rendering/Core/VolumeProperty.js +1 -1
  36. package/Rendering/OpenGL/PolyDataMapper2D.js +1 -1
  37. package/Rendering/OpenGL/Texture.js +1 -1
  38. package/Widgets/Widgets3D/AngleWidget.js +1 -1
  39. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
  40. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
  41. package/index.d.ts +6 -0
  42. package/package.json +1 -1
@@ -0,0 +1,149 @@
1
+ import { m as macro } from '../../macros2.js';
2
+ import vtkPolyData from '../../Common/DataModel/PolyData.js';
3
+ import vtkPoints from '../../Common/Core/Points.js';
4
+ import vtkCellArray from '../../Common/Core/CellArray.js';
5
+ import { SolidType } from './PlatonicSolidSource/Constants.js';
6
+ import { DesiredOutputPrecision } from '../../Common/DataModel/DataSetAttributes/Constants.js';
7
+ import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js';
8
+
9
+ const a = 0.61803398875;
10
+ const b = 0.38196601125;
11
+ const c = 0.5;
12
+ const d = 0.30901699;
13
+ const e = Math.sqrt(2);
14
+ const f = Math.sqrt(3.0);
15
+ const geometries = {
16
+ tetrahedron: {
17
+ points: [1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1],
18
+ cells: [0, 2, 1, 1, 2, 3, 0, 3, 2, 0, 1, 3],
19
+ numPoints: 4,
20
+ cellSize: 3,
21
+ numCells: 4,
22
+ scale: 1.0 / f
23
+ },
24
+ cube: {
25
+ points: [-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1],
26
+ cells: [0, 1, 5, 4, 0, 4, 7, 3, 4, 5, 6, 7, 3, 7, 6, 2, 1, 2, 6, 5, 0, 3, 2, 1],
27
+ numPoints: 8,
28
+ cellSize: 4,
29
+ numCells: 6,
30
+ scale: 1.0 / f
31
+ },
32
+ octahedron: {
33
+ points: [-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, 0, 0, -e, 0, 0, e],
34
+ cells: [4, 1, 0, 4, 2, 1, 4, 3, 2, 4, 0, 3, 0, 1, 5, 1, 2, 5, 2, 3, 5, 3, 0, 5],
35
+ numPoints: 6,
36
+ cellSize: 3,
37
+ numCells: 8,
38
+ scale: 1.0 / e
39
+ },
40
+ icosahedron: {
41
+ points: [0, d, -c, 0, d, c, 0, -d, c, -d, c, 0, -d, -c, 0, d, c, 0, d, -c, 0, 0, -d, -c, c, 0, d, -c, 0, d, -c, 0, -d, c, 0, -d],
42
+ cells: [0, 3, 5, 1, 5, 3, 1, 9, 2, 1, 2, 8, 0, 11, 7, 0, 7, 10, 2, 4, 6, 7, 6, 4, 3, 10, 9, 4, 9, 10, 5, 8, 11, 6, 11, 8, 1, 3, 9, 1, 8, 5, 0, 10, 3, 0, 5, 11, 7, 4, 10, 7, 11, 6, 2, 9, 4, 2, 6, 8],
43
+ numPoints: 12,
44
+ cellSize: 3,
45
+ numCells: 20,
46
+ scale: 1.0 / 0.58778524999243
47
+ },
48
+ dodecahedron: {
49
+ points: [b, 0, 1, -b, 0, 1, b, 0, -1, -b, 0, -1, 0, 1, -b, 0, 1, b, 0, -1, -b, 0, -1, b, 1, b, 0, 1, -b, 0, -1, b, 0, -1, -b, 0, -a, a, a, a, -a, a, -a, -a, -a, a, a, -a, a, a, a, -a, a, -a, -a, -a, a, a, -a, -a],
50
+ cells: [0, 16, 5, 12, 1, 1, 18, 7, 13, 0, 2, 19, 6, 14, 3, 3, 17, 4, 15, 2, 4, 5, 16, 8, 15, 5, 4, 17, 10, 12, 6, 7, 18, 11, 14, 7, 6, 19, 9, 13, 8, 16, 0, 13, 9, 9, 19, 2, 15, 8, 10, 17, 3, 14, 11, 11, 18, 1, 12, 10],
51
+ numPoints: 20,
52
+ cellSize: 5,
53
+ numCells: 12,
54
+ scale: 1.0 / 1.070466269319
55
+ }
56
+ };
57
+
58
+ // ----------------------------------------------------------------------------
59
+ // vtkPlatonicSolidSource methods
60
+ // ----------------------------------------------------------------------------
61
+
62
+ function vtkPlatonicSolidSource(publicAPI, model) {
63
+ // Set our className
64
+ model.classHierarchy.push('vtkPlatonicSolidSource');
65
+ publicAPI.requestData = (inData, outData) => {
66
+ const output = outData[0] || vtkPolyData.newInstance();
67
+ let solidData;
68
+ switch (model.solidType) {
69
+ case SolidType.VTK_SOLID_TETRAHEDRON:
70
+ solidData = geometries.tetrahedron;
71
+ break;
72
+ case SolidType.VTK_SOLID_CUBE:
73
+ solidData = geometries.cube;
74
+ break;
75
+ case SolidType.VTK_SOLID_OCTAHEDRON:
76
+ solidData = geometries.octahedron;
77
+ break;
78
+ case SolidType.VTK_SOLID_ICOSAHEDRON:
79
+ solidData = geometries.icosahedron;
80
+ break;
81
+ case SolidType.VTK_SOLID_DODECAHEDRON:
82
+ solidData = geometries.dodecahedron;
83
+ break;
84
+ default:
85
+ solidData = geometries.tetrahedron;
86
+ break;
87
+ }
88
+ let pointType;
89
+ if (model.outputPointsPrecision === DesiredOutputPrecision.SINGLE) {
90
+ pointType = VtkDataTypes.FLOAT;
91
+ } else if (model.outputPointsPrecision === DesiredOutputPrecision.DOUBLE) {
92
+ pointType = VtkDataTypes.DOUBLE;
93
+ }
94
+ const points = vtkPoints.newInstance({
95
+ dataType: pointType,
96
+ numberOfPoints: solidData.numPoints
97
+ });
98
+ for (let i = 0; i < solidData.points.length; i += 3) {
99
+ points.insertNextPoint(solidData.scale * solidData.points[i] * model.scale, solidData.scale * solidData.points[i + 1] * model.scale, solidData.scale * solidData.points[i + 2] * model.scale);
100
+ }
101
+ const polys = vtkCellArray.newInstance();
102
+ for (let i = 0; i < solidData.cells.length; i += solidData.cellSize) {
103
+ const cell = solidData.cells.slice(i, i + solidData.cellSize);
104
+ polys.insertNextCell(cell);
105
+ }
106
+ output.setPoints(points);
107
+ output.setPolys(polys);
108
+ outData[0] = output;
109
+ };
110
+ }
111
+
112
+ // ----------------------------------------------------------------------------
113
+ // Object factory
114
+ // ----------------------------------------------------------------------------
115
+
116
+ const DEFAULT_VALUES = {
117
+ solidType: SolidType.VTK_SOLID_TETRAHEDRON,
118
+ outputPointsPrecision: DesiredOutputPrecision.DEFAULT,
119
+ scale: 1
120
+ };
121
+
122
+ // ----------------------------------------------------------------------------
123
+
124
+ function extend(publicAPI, model) {
125
+ let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
126
+ Object.assign(model, DEFAULT_VALUES, initialValues);
127
+
128
+ // Build VTK API
129
+ macro.obj(publicAPI, model);
130
+ macro.setGet(publicAPI, model, ['solidType', 'outputPointsPrecision', 'scale']);
131
+ macro.algo(publicAPI, model, 0, 1);
132
+
133
+ // Object methods
134
+ vtkPlatonicSolidSource(publicAPI, model);
135
+ }
136
+
137
+ // ----------------------------------------------------------------------------
138
+
139
+ const newInstance = macro.newInstance(extend, 'vtkPlatonicSolidSource');
140
+
141
+ // ----------------------------------------------------------------------------
142
+
143
+ var vtkPlatonicSolidSource$1 = {
144
+ newInstance,
145
+ extend,
146
+ SolidType
147
+ };
148
+
149
+ export { vtkPlatonicSolidSource$1 as default, extend, newInstance };
@@ -1,3 +1,4 @@
1
+ import vtkArcSource from './Sources/ArcSource.js';
1
2
  import vtkArrowSource from './Sources/ArrowSource.js';
2
3
  import vtkCircleSource from './Sources/CircleSource.js';
3
4
  import vtkConcentricCylinderSource from './Sources/ConcentricCylinderSource.js';
@@ -6,15 +7,18 @@ import vtkCubeSource from './Sources/CubeSource.js';
6
7
  import vtkCursor3D from './Sources/Cursor3D.js';
7
8
  import vtkCylinderSource from './Sources/CylinderSource.js';
8
9
  import vtkDiskSource from './Sources/DiskSource.js';
10
+ import vtkEllipseArcSource from './Sources/EllipseArcSource.js';
9
11
  import vtkImageGridSource from './Sources/ImageGridSource.js';
10
12
  import vtkLineSource from './Sources/LineSource.js';
11
13
  import vtkPlaneSource from './Sources/PlaneSource.js';
14
+ import vtkPlatonicSolidSource from './Sources/PlatonicSolidSource.js';
12
15
  import vtkPointSource from './Sources/PointSource.js';
13
16
  import vtkRTAnalyticSource from './Sources/RTAnalyticSource.js';
14
17
  import vtkSLICSource from './Sources/SLICSource.js';
15
18
  import vtkSphereSource from './Sources/SphereSource.js';
16
19
 
17
20
  var Sources = {
21
+ vtkArcSource,
18
22
  vtkArrowSource,
19
23
  vtkCircleSource,
20
24
  vtkConcentricCylinderSource,
@@ -23,9 +27,11 @@ var Sources = {
23
27
  vtkCursor3D,
24
28
  vtkCylinderSource,
25
29
  vtkDiskSource,
30
+ vtkEllipseArcSource,
26
31
  vtkImageGridSource,
27
32
  vtkLineSource,
28
33
  vtkPlaneSource,
34
+ vtkPlatonicSolidSource,
29
35
  vtkPointSource,
30
36
  vtkRTAnalyticSource,
31
37
  vtkSLICSource,
@@ -0,0 +1,103 @@
1
+ import vtkPolyData from './../../Common/DataModel/PolyData';
2
+ import vtkTexture from './../../Rendering/Core/Texture';
3
+ import { vtkAlgorithm, vtkObject } from './../../interfaces';
4
+
5
+ /**
6
+ *
7
+ */
8
+ export interface IOBJWriterInitialValues {
9
+ modelFilename?: string;
10
+ materialFilename?: string;
11
+ texture?: vtkTexture;
12
+ textureFileName?: string;
13
+ }
14
+
15
+ type vtkOBJWriterBase = vtkObject & vtkAlgorithm;
16
+
17
+ export interface vtkOBJWriter extends vtkOBJWriterBase {
18
+ /**
19
+ * Get the zip file containing the OBJ and MTL files.
20
+ */
21
+ exportAsZip(): Promise<Uint8Array>;
22
+
23
+ /**
24
+ * Get the MTL file as a string.
25
+ */
26
+ getMtl(): string;
27
+
28
+ /**
29
+ *
30
+ * @param inData
31
+ * @param outData
32
+ */
33
+ requestData(inData: any, outData: any): void;
34
+
35
+ /**
36
+ * Set the material filename.
37
+ * @param materialFilename
38
+ * @returns {boolean} true if the material file name was set successfully
39
+ */
40
+ setMaterialFilename(materialFilename: string): boolean;
41
+
42
+ /**
43
+ * Set the model filename.
44
+ * @param modelFilename
45
+ */
46
+ setModelFilename(modelFilename: string): boolean;
47
+
48
+ /**
49
+ * Set the texture instance.
50
+ * @param {vtkTexture} texture
51
+ * @returns {boolean} true if the texture was set successfully
52
+ */
53
+ setTexture(texture: vtkTexture): boolean;
54
+
55
+ /**
56
+ * Set the texture file name.
57
+ * @param {string} textureFileName
58
+ * @returns {boolean} true if the texture file name was set successfully
59
+ */
60
+ setTextureFileName(textureFileName: string): boolean;
61
+ }
62
+
63
+ /**
64
+ * Method used to decorate a given object (publicAPI+model) with vtkOBJWriter characteristics.
65
+ *
66
+ * @param publicAPI object on which methods will be bounds (public)
67
+ * @param model object on which data structure will be bounds (protected)
68
+ * @param {IOBJWriterInitialValues} [initialValues] (default: {})
69
+ */
70
+ export function extend(
71
+ publicAPI: object,
72
+ model: object,
73
+ initialValues?: IOBJWriterInitialValues
74
+ ): void;
75
+
76
+ /**
77
+ * Method used to create a new instance of vtkOBJWriter
78
+ * @param {IOBJWriterInitialValues} [initialValues] for pre-setting some of its content
79
+ */
80
+ export function newInstance(
81
+ initialValues?: IOBJWriterInitialValues
82
+ ): vtkOBJWriter;
83
+
84
+ /**
85
+ *
86
+ * @param {vktPolyData} polyData
87
+ */
88
+ export function writeOBJ(polyData: vtkPolyData): vtkPolyData;
89
+
90
+ /**
91
+ * vtkOBJWriter writes wavefront obj (.obj) files in ASCII form. OBJ files
92
+ * contain the geometry including lines, triangles and polygons. Normals and
93
+ * texture coordinates on points are also written if they exist.
94
+ *
95
+ * One can specify a texture passing a vtkTexture using `setTexture`. If a texture is
96
+ * set, additional .mtl and .png files are generated.
97
+ */
98
+ export declare const vtkOBJWriter: {
99
+ newInstance: typeof newInstance;
100
+ extend: typeof extend;
101
+ writeOBJ: typeof writeOBJ;
102
+ };
103
+ export default vtkOBJWriter;
@@ -0,0 +1,237 @@
1
+ import { strToU8, zipSync } from 'fflate';
2
+ import { m as macro } from '../../macros2.js';
3
+ import vtkCellArray from '../../Common/Core/CellArray.js';
4
+ import vtkTriangleStrip from '../../Common/DataModel/TriangleStrip.js';
5
+
6
+ const {
7
+ vtkErrorMacro
8
+ } = macro;
9
+
10
+ // ----------------------------------------------------------------------------
11
+ // Global methods
12
+ // ----------------------------------------------------------------------------
13
+
14
+ // ----------------------------------------------------------------------------
15
+ // vtkOBJWriter methods
16
+ // ----------------------------------------------------------------------------
17
+
18
+ const writeFaces = (faces, withNormals, withTCoords) => {
19
+ let outputData = '';
20
+ const fd = faces.getData();
21
+ let offset = 0;
22
+ while (offset < fd.length) {
23
+ const faceSize = fd[offset++];
24
+ outputData += 'f';
25
+ for (let i = 0; i < faceSize; i++) {
26
+ outputData += ` ${fd[offset + i] + 1}`;
27
+ if (withTCoords) {
28
+ outputData += `/${fd[offset + i] + 1}`;
29
+ if (withNormals) {
30
+ outputData += `//${fd[offset + i] + 1}`;
31
+ }
32
+ } else if (withNormals) {
33
+ outputData += `//${fd[offset + i] + 1}`;
34
+ }
35
+ }
36
+ offset += faceSize;
37
+ outputData += '\n';
38
+ }
39
+ return outputData;
40
+ };
41
+ const writeLines = lines => {
42
+ let outputData = '';
43
+ const ld = lines.getData();
44
+ let offset = 0;
45
+ while (offset < ld.length) {
46
+ const lineSize = ld[offset++];
47
+ outputData += 'l';
48
+ for (let i = 0; i < lineSize; i++) {
49
+ outputData += ` ${ld[offset + i] + 1}`;
50
+ }
51
+ offset += lineSize;
52
+ outputData += '\n';
53
+ }
54
+ return outputData;
55
+ };
56
+ const writePoints = (pts, normals, tcoords) => {
57
+ const outputData = [];
58
+ const nbPts = pts.getNumberOfPoints();
59
+ let p;
60
+
61
+ // Positions
62
+ for (let i = 0; i < nbPts; i++) {
63
+ p = pts.getPoint(i);
64
+ outputData.push(`v ${p[0]} ${p[1]} ${p[2]}`);
65
+ }
66
+
67
+ // Normals
68
+ if (normals) {
69
+ for (let i = 0; i < nbPts; i++) {
70
+ p = normals.getTuple(i);
71
+ outputData.push(`vn ${p[0]} ${p[1]} ${p[2]}`);
72
+ }
73
+ }
74
+
75
+ // Textures
76
+ if (tcoords) {
77
+ for (let i = 0; i < nbPts; i++) {
78
+ p = tcoords.getTuple(i);
79
+ if (p[0] !== -1.0) {
80
+ outputData.push(`vt ${p[0]} ${p[1]}`);
81
+ }
82
+ }
83
+ }
84
+ return `${outputData.join('\n')}\n`;
85
+ };
86
+ const writeMTL = (materialName, textureFileName) => {
87
+ const outputData = [];
88
+ outputData.push(`newmtl ${materialName}`);
89
+ outputData.push(`map_Kd ${textureFileName}`);
90
+ return outputData.join('\n');
91
+ };
92
+ const writeOBJ = (polyData, materialFilename, materialName) => {
93
+ let outputData = '# VTK.js generated OBJ File\n';
94
+ const pts = polyData.getPoints();
95
+ const polys = polyData.getPolys();
96
+ const strips = polyData.getStrips() ? polyData.getStrips().getData() : null;
97
+ const lines = polyData.getLines();
98
+ const normals = polyData.getPointData().getNormals();
99
+ const tcoords = polyData.getPointData().getTCoords();
100
+ const hasPtNormals = normals !== null;
101
+ const hasPtTCoords = tcoords !== null;
102
+ if (!pts) {
103
+ vtkErrorMacro('No data to write!');
104
+ return outputData;
105
+ }
106
+ if (materialFilename) {
107
+ // Write material library
108
+ outputData += `mtllib ${materialFilename}\n`;
109
+ }
110
+
111
+ // Write material if a texture is specified
112
+ if (materialName) {
113
+ // declare material in obj file
114
+ outputData += `usemtl ${materialName}\n`;
115
+ }
116
+
117
+ // Write points
118
+ outputData += writePoints(pts, normals, tcoords);
119
+
120
+ // Decompose any triangle strips into triangles
121
+ const polyStrips = vtkCellArray.newInstance();
122
+ if (strips && strips.length > 0) {
123
+ vtkTriangleStrip.decomposeStrip(pts, polyStrips);
124
+ }
125
+
126
+ // Write triangle strips
127
+ if (polyStrips.getNumberOfCells() > 0) {
128
+ outputData += writeFaces(polyStrips, hasPtNormals, hasPtTCoords);
129
+ }
130
+
131
+ // Write polygons.
132
+ if (polys) {
133
+ outputData += writeFaces(polys, hasPtNormals, hasPtTCoords);
134
+ }
135
+
136
+ // Write lines.
137
+ if (lines) {
138
+ outputData += writeLines(lines);
139
+ }
140
+ return outputData;
141
+ };
142
+
143
+ // ----------------------------------------------------------------------------
144
+ // Static API
145
+ // ----------------------------------------------------------------------------
146
+
147
+ const STATIC = {
148
+ writeOBJ
149
+ };
150
+
151
+ // ----------------------------------------------------------------------------
152
+ // vtkOBJWriter methods
153
+ // ----------------------------------------------------------------------------
154
+
155
+ function vtkOBJWriter(publicAPI, model) {
156
+ // Set our className
157
+ model.classHierarchy.push('vtkOBJWriter');
158
+ publicAPI.exportAsZip = () => {
159
+ publicAPI.update();
160
+ const modelFilename = model.modelFilename;
161
+ const materialFilename = model.materialFilename;
162
+ const textureFileName = model.textureFileName;
163
+ const imageData = model.texture.getInputAsJsImageData?.();
164
+ const zipContent = {};
165
+ zipContent[`${modelFilename}.obj`] = strToU8(model.output[0]);
166
+ zipContent[`${materialFilename}.mtl`] = strToU8(model.mtl);
167
+ const canvas = document.createElement('canvas');
168
+ canvas.width = imageData.width;
169
+ canvas.height = imageData.height;
170
+ const ctx = canvas.getContext('2d');
171
+ ctx.putImageData(imageData, 0, 0);
172
+ return new Promise(resolve => {
173
+ canvas.toBlob(async blob => {
174
+ const arrayBuffer = await blob.arrayBuffer();
175
+ zipContent[`${textureFileName}.png`] = new Uint8Array(arrayBuffer);
176
+ resolve(zipSync(zipContent));
177
+ }, 'image/png');
178
+ });
179
+ };
180
+ publicAPI.requestData = (inData, outData) => {
181
+ const input = inData[0];
182
+ if (!input || !input.isA('vtkPolyData')) {
183
+ vtkErrorMacro('Invalid or missing vtkPolyData input');
184
+ return;
185
+ }
186
+
187
+ // Update output
188
+ const materialFilename = `${model.materialFilename}.mtl`;
189
+ const textureFileName = `${model.textureFileName}.png`;
190
+ outData[0] = writeOBJ(input, materialFilename, model.materialName);
191
+ model.mtl = writeMTL(model.materialName, textureFileName);
192
+ };
193
+ }
194
+
195
+ // ----------------------------------------------------------------------------
196
+ // Object factory
197
+ // ----------------------------------------------------------------------------
198
+
199
+ const DEFAULT_VALUES = {
200
+ modelFilename: 'model',
201
+ materialName: 'mat_01',
202
+ materialFilename: 'material',
203
+ texture: null,
204
+ textureFileName: 'texture'
205
+ };
206
+
207
+ // ----------------------------------------------------------------------------
208
+
209
+ function extend(publicAPI, model) {
210
+ let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
211
+ Object.assign(model, DEFAULT_VALUES, initialValues);
212
+
213
+ // Make this a VTK object
214
+ macro.obj(publicAPI, model);
215
+
216
+ // Also make it an algorithm with one input and one output
217
+ macro.algo(publicAPI, model, 1, 1);
218
+ macro.get(publicAPI, model, ['mtl']);
219
+ macro.set(publicAPI, model, ['modelFilename', 'materialFilename', 'texture', 'textureFileName']);
220
+
221
+ // Object specific methods
222
+ vtkOBJWriter(publicAPI, model);
223
+ }
224
+
225
+ // ----------------------------------------------------------------------------
226
+
227
+ const newInstance = macro.newInstance(extend, 'vtkOBJWriter');
228
+
229
+ // ----------------------------------------------------------------------------
230
+
231
+ var vtkOBJWriter$1 = {
232
+ newInstance,
233
+ extend,
234
+ ...STATIC
235
+ };
236
+
237
+ export { STATIC, vtkOBJWriter$1 as default, extend, newInstance };
package/IO/Misc.js CHANGED
@@ -5,6 +5,7 @@ import vtkJSONNucleoReader from './Misc/JSONNucleoReader.js';
5
5
  import vtkJSONReader from './Misc/JSONReader.js';
6
6
  import vtkMTLReader from './Misc/MTLReader.js';
7
7
  import vtkOBJReader from './Misc/OBJReader.js';
8
+ import vtkOBJWriter from './Misc/OBJWriter.js';
8
9
  import vtkPDBReader from './Misc/PDBReader.js';
9
10
  import vtkSkyboxReader from './Misc/SkyboxReader.js';
10
11
  import vtkGCodeReader from './Misc/GCodeReader.js';
@@ -17,6 +18,7 @@ var Misc = {
17
18
  vtkJSONReader,
18
19
  vtkMTLReader,
19
20
  vtkOBJReader,
21
+ vtkOBJWriter,
20
22
  vtkPDBReader,
21
23
  vtkSkyboxReader,
22
24
  vtkGCodeReader
@@ -1,6 +1,7 @@
1
1
  import { m as macro } from '../../macros2.js';
2
2
  import { MouseButton } from '../../Rendering/Core/RenderWindowInteractor/Constants.js';
3
3
  import vtkInteractorStyle from '../../Rendering/Core/InteractorStyle.js';
4
+ import { mat4, vec3 } from 'gl-matrix';
4
5
 
5
6
  const {
6
7
  vtkDebugMacro
@@ -101,6 +102,62 @@ function dollyByFactor(interactor, renderer, factor) {
101
102
  renderer.updateLightsGeometryToFollowCamera();
102
103
  }
103
104
  }
105
+ function getCameraMatrix(renderer, tempMatrix) {
106
+ const cam = renderer.getActiveCamera();
107
+ if (cam) {
108
+ mat4.copy(tempMatrix, cam.getViewMatrix());
109
+ return tempMatrix;
110
+ }
111
+ return null;
112
+ }
113
+
114
+ /**
115
+ * Transforms a vector by the transformation delta between two matrices.
116
+ *
117
+ * @param {Object} tempObjects - Temporary matrices/vectors for computation
118
+ * @param {mat4} beforeMatrix - Matrix before transformation
119
+ * @param {mat4} afterMatrix - Matrix after transformation
120
+ * @param {Array} vector - Vector to transform [x, y, z]
121
+ * @returns {Array} Transformed vector [x, y, z]
122
+ */
123
+ function transformVectorByTransformation(tempObjects, beforeMatrix, afterMatrix, vector) {
124
+ const {
125
+ matrixA,
126
+ matrixB,
127
+ newCenter
128
+ } = tempObjects;
129
+
130
+ // The view matrix from vtk.js is row-major, but gl-matrix expects column-major.
131
+ // We need to transpose them before use.
132
+ mat4.transpose(matrixA, beforeMatrix);
133
+ mat4.transpose(matrixB, afterMatrix);
134
+ mat4.invert(matrixB, matrixB);
135
+
136
+ // Compute delta transformation matrix
137
+ mat4.multiply(matrixA, matrixB, matrixA);
138
+ vec3.transformMat4(newCenter, vector, matrixA);
139
+ return newCenter;
140
+ }
141
+
142
+ /**
143
+ * Computes the new center of rotation based on camera movement.
144
+ * When the camera moves (pan), the center of rotation should move
145
+ * by the same transformation to maintain consistent rotation behavior.
146
+ *
147
+ * @param {Object} tempObjects - Temporary matrices/vectors for computation
148
+ * @param {Object} renderer - VTK renderer
149
+ * @param {mat4} beforeCameraMatrix - Camera view matrix before movement
150
+ * @param {Array} oldCenterOfRotation - Previous center of rotation [x, y, z]
151
+ * @returns {Array} New center of rotation [x, y, z]
152
+ */
153
+ function computeNewCenterOfRotation(tempObjects, renderer, beforeCameraMatrix, oldCenterOfRotation) {
154
+ const cam = renderer.getActiveCamera();
155
+ if (!cam || !beforeCameraMatrix) {
156
+ return oldCenterOfRotation;
157
+ }
158
+ const afterMatrixRowMajor = cam.getViewMatrix();
159
+ return transformVectorByTransformation(tempObjects, beforeCameraMatrix, afterMatrixRowMajor, oldCenterOfRotation);
160
+ }
104
161
 
105
162
  // ----------------------------------------------------------------------------
106
163
  // Static API
@@ -119,6 +176,14 @@ const STATIC = {
119
176
  function vtkInteractorStyleManipulator(publicAPI, model) {
120
177
  // Set our className
121
178
  model.classHierarchy.push('vtkInteractorStyleManipulator');
179
+
180
+ // Initialize temporary objects to reduce garbage collection
181
+ const tempCameraMatrix = mat4.create();
182
+ const tempComputeObjects = {
183
+ matrixA: mat4.create(),
184
+ matrixB: mat4.create(),
185
+ newCenter: vec3.create()
186
+ };
122
187
  model.currentVRManipulators = new Map();
123
188
  model.mouseManipulators = [];
124
189
  model.keyboardManipulators = [];
@@ -415,7 +480,11 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
415
480
  publicAPI.handleMouseMove = callData => {
416
481
  model.cachedMousePosition = callData.position;
417
482
  if (model.currentManipulator && model.currentManipulator.onMouseMove) {
418
- model.currentManipulator.onMouseMove(model._interactor, model.getRenderer(callData), callData.position);
483
+ const renderer = model.getRenderer(callData);
484
+ const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
485
+ model.currentManipulator.onMouseMove(model._interactor, renderer, callData.position);
486
+ const newCenter = computeNewCenterOfRotation(tempComputeObjects, renderer, beforeCameraMatrix, model.centerOfRotation);
487
+ publicAPI.setCenterOfRotation(newCenter);
419
488
  publicAPI.invokeInteractionEvent(INTERACTION_EVENT);
420
489
  }
421
490
  };
@@ -557,16 +626,20 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
557
626
 
558
627
  //----------------------------------------------------------------------------
559
628
  publicAPI.handlePan = callData => {
629
+ const renderer = model.getRenderer(callData);
630
+ const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
560
631
  let count = model.gestureManipulators.length;
561
632
  let actionCount = 0;
562
633
  while (count--) {
563
634
  const manipulator = model.gestureManipulators[count];
564
635
  if (manipulator && manipulator.isPanEnabled()) {
565
- manipulator.onPan(model._interactor, model.getRenderer(callData), callData.translation);
636
+ manipulator.onPan(model._interactor, renderer, callData.translation);
566
637
  actionCount++;
567
638
  }
568
639
  }
569
640
  if (actionCount) {
641
+ const newCenter = computeNewCenterOfRotation(tempComputeObjects, renderer, beforeCameraMatrix, model.centerOfRotation);
642
+ publicAPI.setCenterOfRotation(newCenter);
570
643
  publicAPI.invokeInteractionEvent(INTERACTION_EVENT);
571
644
  }
572
645
  };
@@ -7,6 +7,7 @@ import vtkDataArray from '../../Common/Core/DataArray.js';
7
7
  import vtkPolyData from '../../Common/DataModel/PolyData.js';
8
8
  import vtkColorTransferFunction from '../../Rendering/Core/ColorTransferFunction.js';
9
9
  import vtkAbstractRepresentationProxy from '../Core/AbstractRepresentationProxy.js';
10
+ import '../../Filters/Sources/ArcSource.js';
10
11
  import '../../Filters/Sources/ArrowSource.js';
11
12
  import '../../Filters/Sources/CircleSource.js';
12
13
  import '../../Filters/Sources/ConcentricCylinderSource.js';
@@ -15,9 +16,11 @@ import '../../Filters/Sources/CubeSource.js';
15
16
  import '../../Filters/Sources/Cursor3D.js';
16
17
  import '../../Filters/Sources/CylinderSource.js';
17
18
  import '../../Filters/Sources/DiskSource.js';
19
+ import '../../Filters/Sources/EllipseArcSource.js';
18
20
  import '../../Filters/Sources/ImageGridSource.js';
19
21
  import '../../Filters/Sources/LineSource.js';
20
22
  import '../../Filters/Sources/PlaneSource.js';
23
+ import '../../Filters/Sources/PlatonicSolidSource.js';
21
24
  import '../../Filters/Sources/PointSource.js';
22
25
  import '../../Filters/Sources/RTAnalyticSource.js';
23
26
  import '../../Filters/Sources/SLICSource.js';
@@ -156,11 +156,11 @@ export interface vtkCamera extends vtkObject {
156
156
  getFreezeFocalPoint(): boolean;
157
157
 
158
158
  /**
159
- * Not implemented yet
160
159
  * Get the plane equations that bound the view frustum.
161
- * @param {Number} aspect Camera frustum aspect ratio.
160
+ * @param {Number} [aspect] Camera frustum aspect ratio (default: 1.0).
161
+ * @param {Float64Array} [planes] Optional array to fill with the plane equations.
162
162
  */
163
- getFrustumPlanes(aspect: number): void;
163
+ getFrustumPlanes(aspect?: number, planes?: Float64Array): Float64Array;
164
164
 
165
165
  /**
166
166
  * Not implemented yet