@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.
- package/Common/Core/Math/index.js +12 -1
- package/Common/Core/Math.d.ts +24 -18
- package/Common/Core/Math.js +1 -1
- package/Common/DataModel/Polygon.d.ts +13 -0
- package/Common/DataModel/Polygon.js +29 -2
- package/Common/DataModel/Triangle.js +8 -13
- package/Filters/Core/Cutter.js +1 -0
- package/Filters/General/ShrinkPolyData.d.ts +85 -0
- package/Filters/General/ShrinkPolyData.js +317 -0
- package/Filters/General.js +2 -0
- package/Filters/Sources/ArcSource.d.ts +244 -0
- package/Filters/Sources/ArcSource.js +138 -0
- package/Filters/Sources/EllipseArcSource.d.ts +212 -0
- package/Filters/Sources/EllipseArcSource.js +159 -0
- package/Filters/Sources/PlatonicSolidSource/Constants.d.ts +12 -0
- package/Filters/Sources/PlatonicSolidSource/Constants.js +12 -0
- package/Filters/Sources/PlatonicSolidSource.d.ts +109 -0
- package/Filters/Sources/PlatonicSolidSource.js +149 -0
- package/Filters/Sources.js +6 -0
- package/IO/Misc/OBJWriter.d.ts +103 -0
- package/IO/Misc/OBJWriter.js +237 -0
- package/IO/Misc.js +2 -0
- package/Interaction/Style/InteractorStyleManipulator.js +75 -2
- package/Proxy/Representations/GlyphRepresentationProxy.js +3 -0
- package/Rendering/Core/Camera.d.ts +3 -3
- package/Rendering/Core/Camera.js +33 -3
- package/Rendering/Core/ColorTransferFunction/CssFilters.js +1 -1
- package/Rendering/Core/ColorTransferFunction.js +1 -1
- package/Rendering/Core/Coordinate.js +1 -1
- package/Rendering/Core/CubeAxesActor.js +1 -1
- package/Rendering/Core/ImageMapper.js +1 -1
- package/Rendering/Core/Renderer.js +1 -1
- package/Rendering/Core/ScalarBarActor.js +1 -1
- package/Rendering/Core/TextActor.js +1 -1
- package/Rendering/Core/VolumeProperty.js +1 -1
- package/Rendering/OpenGL/PolyDataMapper2D.js +1 -1
- package/Rendering/OpenGL/Texture.js +1 -1
- package/Widgets/Widgets3D/AngleWidget.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
- package/index.d.ts +6 -0
- 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 };
|
package/Filters/Sources.js
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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
|
|
163
|
+
getFrustumPlanes(aspect?: number, planes?: Float64Array): Float64Array;
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* Not implemented yet
|