Skip to content

Commit

Permalink
feat(LineHandleRepresentation): Add hole width property
Browse files Browse the repository at this point in the history
Duplicate all lines and change the settings to be able to put a hole at the center of the line
The width of the hole is in world coordinates or screen coordinates depending on `scaleInPixels`
  • Loading branch information
bruyeret authored and finetjul committed Jul 31, 2024
1 parent d88b328 commit d1efcee
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import vtkGlyphRepresentation from 'vtk.js/Sources/Widgets/Representations/Glyph
import vtkPixelSpaceCallbackMapper from 'vtk.js/Sources/Rendering/Core/PixelSpaceCallbackMapper';
import vtkCylinderSource from 'vtk.js/Sources/Filters/Sources/CylinderSource';
import { allocateArray } from 'vtk.js/Sources/Widgets/Representations/WidgetRepresentation';
import { getPixelWorldHeightAtCoord } from 'vtk.js/Sources/Widgets/Core/WidgetManager';
import { vec3 } from 'gl-matrix';

const INFINITE_RATIO = 100000;

Expand Down Expand Up @@ -64,6 +66,63 @@ function vtkLineHandleRepresentation(publicAPI, model) {
model.displayMapper.setCallback(callback ? callbackProxy : null);
};

const superPublicAPI = { ...publicAPI };
publicAPI.requestData = (inData, outData) => {
superPublicAPI.requestData(inData, outData);
const internalPolyData = outData[0];

// Duplicate points and point data
const points = internalPolyData.getPoints();
const dataArrays = internalPolyData.getPointData().getArrays();
[points, ...dataArrays].forEach((array) => {
const oldNumberOfValues = array.getNumberOfValues();
array.resize(2 * array.getNumberOfTuples());
const arrayData = array.getData();
for (let i = 0; i < oldNumberOfValues; ++i) {
arrayData[i + oldNumberOfValues] = arrayData[i];
}
});

// Change the scale and origin of each line
const states = publicAPI.getRepresentationStates(inData[0]);
const nStates = states.length;
const scaleArray = dataArrays.find((array) => array.getName() === 'scale');
const orientationArray = dataArrays.find(
(array) => array.getName() === 'orientation'
);
for (let i = 0; i < nStates; ++i) {
const j = i + nStates;
const scale = scaleArray.getTuple(i);
const orientationMatrix = orientationArray.getTuple(i);
const originalPoint = points.getTuple(i);

// Divide the scale by two in the direction of the cylinder, as we duplicate the line
scale[2] *= 0.5;
scaleArray.setTuple(i, scale);
scaleArray.setTuple(j, scale);

// Add or subtract an offset to each point depending on the hole width
const offset = vec3.fromValues(0, 0, 0.5);
vec3.mul(offset, offset, scale);
let holeWidth = model.holeWidth;
if (publicAPI.getScaleInPixels()) {
holeWidth *= getPixelWorldHeightAtCoord(
originalPoint,
model.displayScaleParams
);
}
vec3.add(offset, offset, vec3.fromValues(0, 0, holeWidth));
vec3.transformMat3(offset, offset, orientationMatrix);
points.setTuple(i, vec3.add(vec3.create(), originalPoint, offset));
points.setTuple(j, vec3.sub(vec3.create(), originalPoint, offset));
}
};

publicAPI.getSelectedState = (prop, compositeID) => {
const representationStates = publicAPI.getRepresentationStates();
return representationStates[compositeID % representationStates.length];
};

/**
* Overwrite scale3 to optionally make lines infinite
*/
Expand Down Expand Up @@ -93,6 +152,7 @@ function defaultValues(initialValues) {
return {
infiniteLine: true,
glyphResolution: 4,
holeWidth: 0,
_pipeline: {
glyph: vtkCylinderSource.newInstance({
resolution: initialValues.glyphResolution ?? 4,
Expand All @@ -108,7 +168,11 @@ function defaultValues(initialValues) {

export function extend(publicAPI, model, initialValues = {}) {
vtkGlyphRepresentation.extend(publicAPI, model, defaultValues(initialValues));
macro.setGet(publicAPI, model, ['infiniteLine', 'glyphResolution']);
macro.setGet(publicAPI, model, [
'infiniteLine',
'glyphResolution',
'holeWidth',
]);

// Object specific methods
vtkLineHandleRepresentation(publicAPI, model);
Expand Down
8 changes: 8 additions & 0 deletions Sources/Widgets/Widgets3D/ResliceCursorWidget/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ export interface vtkResliceCursorWidget<

getScaleInPixels(): boolean;

setHoleWidth(holeWidth: number): boolean;

getHoleWidth(): number;

setInfiniteLine(infiniteLine: boolean): boolean;

getInfiniteLine(): boolean;

setRotationHandlePosition(position: number): boolean;

getRotationHandlePosition(): number;
Expand Down
2 changes: 1 addition & 1 deletion Sources/Widgets/Widgets3D/ResliceCursorWidget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const { vtkErrorMacro } = macro;
function vtkResliceCursorWidget(publicAPI, model) {
model.classHierarchy.push('vtkResliceCursorWidget');

model.methodsToLink = ['scaleInPixels'];
model.methodsToLink = ['scaleInPixels', 'holeWidth', 'infiniteLine'];

// --------------------------------------------------------------------------
// Private methods
Expand Down

0 comments on commit d1efcee

Please sign in to comment.