Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Sources/IO/Geometry/STLReader/example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
import vtkSTLReader from '@kitware/vtk.js/IO/Geometry/STLReader';

import vtkPolyDataNormals from '@kitware/vtk.js/Filters/Core/PolyDataNormals';
// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------

const reader = vtkSTLReader.newInstance();
reader.setRemoveDuplicateVertices(5);
const mapper = vtkMapper.newInstance({ scalarVisibility: false });
const actor = vtkActor.newInstance();

actor.setMapper(mapper);
mapper.setInputConnection(reader.getOutputPort());
const normals = vtkPolyDataNormals.newInstance();
normals.setInputConnection(reader.getOutputPort());
mapper.setInputConnection(normals.getOutputPort());

// ----------------------------------------------------------------------------

Expand Down
14 changes: 14 additions & 0 deletions Sources/IO/Geometry/STLReader/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export interface vtkSTLReader extends vtkSTLReaderBase {
*/
getUrl(): string;

/**
* Get tolerance when removeDuplicateVertices is set
*/
getRemoveDuplicateVertices(): number;

/**
* Load the object data.
* @param {ISTLReaderOptions} [options]
Expand Down Expand Up @@ -94,6 +99,15 @@ export interface vtkSTLReader extends vtkSTLReaderBase {
* @param {ISTLReaderOptions} [option] The STL reader options.
*/
setUrl(url: string, option?: ISTLReaderOptions): Promise<string | any>;

/**
* Turn on/off automatic removeDuplicateVertices
Comment thread
jreyero12 marked this conversation as resolved.
* After reading the STL file, if `tolerance` is >= 0, then points with the same coordinates at 10 power tolerance are merged.
* For a smooth rendering, you might want to compute normals with vtkPolyDataNormals.
*
* @param {Number} tolerance
*/
setRemoveDuplicateVertices(tolerance: number): boolean;
}

/**
Expand Down
72 changes: 71 additions & 1 deletion Sources/IO/Geometry/STLReader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,64 @@ function vtkSTLReader(publicAPI, model) {
});
}

function removeDuplicateVertices(tolerance) {
const polydata = model.output[0];

const points = polydata.getPoints().getData();
const faces = polydata.getPolys().getData();

if (!points || !faces) {
console.warn('No valid polydata.');
return;
}

const vMap = new Map();
const vIndexMap = new Map();
let vInc = 0;
let pointsChanged = false;
for (let i = 0; i < points.length; i += 3) {
const k1 = (points[i] * 10 ** tolerance).toFixed(0);
const k2 = (points[i + 1] * 10 ** tolerance).toFixed(0);
const k3 = (points[i + 2] * 10 ** tolerance).toFixed(0);
const key = `${k1},${k2},${k3}`;
if (vMap.get(key) !== undefined) {
vIndexMap.set(i / 3, vMap.get(key));
pointsChanged = true;
} else {
vIndexMap.set(i / 3, vInc);
vMap.set(key, vInc);
vInc++;
}
}

const outVerts = new Float32Array(vMap.size * 3);
const keys = Array.from(vMap.keys());

for (let i = 0; i < keys.length; i++) {
const k = keys[i];
const j = vMap.get(k) * 3;
const coords = k.split(',').map((e) => +e * 10 ** -tolerance);
outVerts[j] = coords[0];
outVerts[j + 1] = coords[1];
outVerts[j + 2] = coords[2];
}

const outFaces = new Int32Array(faces);
for (let i = 0; i < faces.length; i += 4) {
outFaces[i] = 3;
outFaces[i + 1] = vIndexMap.get(faces[i + 1]);
outFaces[i + 2] = vIndexMap.get(faces[i + 2]);
outFaces[i + 3] = vIndexMap.get(faces[i + 3]);
}

polydata.getPoints().setData(outVerts);
polydata.getPolys().setData(outFaces);

if (pointsChanged) {
publicAPI.modified();
}
}

// Set DataSet url
publicAPI.setUrl = (url, option = { binary: true }) => {
model.url = url;
Expand Down Expand Up @@ -289,6 +347,10 @@ function vtkSTLReader(publicAPI, model) {

// Add new output
model.output[0] = polydata;

if (model.removeDuplicateVertices >= 0) {
removeDuplicateVertices(model.removeDuplicateVertices);
}
};

publicAPI.parseAsText = (content) => {
Expand Down Expand Up @@ -326,6 +388,10 @@ function vtkSTLReader(publicAPI, model) {

// Add new output
model.output[0] = polydata;

if (model.removeDuplicateVertices >= 0) {
removeDuplicateVertices(model.removeDuplicateVertices);
}
};

publicAPI.requestData = (inData, outData) => {
Expand All @@ -341,6 +407,7 @@ const DEFAULT_VALUES = {
// baseURL: null,
// dataAccessHelper: null,
// url: null,
removeDuplicateVertices: 0,
Comment thread
jreyero12 marked this conversation as resolved.
Outdated
};

// ----------------------------------------------------------------------------
Expand All @@ -351,7 +418,10 @@ export function extend(publicAPI, model, initialValues = {}) {
// Build VTK API
macro.obj(publicAPI, model);
macro.get(publicAPI, model, ['url', 'baseURL']);
macro.setGet(publicAPI, model, ['dataAccessHelper']);
macro.setGet(publicAPI, model, [
'dataAccessHelper',
'removeDuplicateVertices',
]);
macro.algo(publicAPI, model, 0, 1);

// vtkSTLReader methods
Expand Down