EllipseWidget

Source

behavior.js
import shapeBehavior from 'vtk.js/Sources/Widgets/Widgets3D/ShapeWidget/behavior';
import { vec3 } from 'gl-matrix';
import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox';

export default function widgetBehavior(publicAPI, model) {
// We inherit shapeBehavior
shapeBehavior(publicAPI, model);
const superClass = Object.assign({}, publicAPI);

model.classHierarchy.push('vtkEllipseWidgetProp');

publicAPI.setBounds = (bounds) => {
if (superClass.setBounds) {
superClass.setBounds(bounds);
}

const center = vtkBoundingBox.getCenter(bounds);
const scale3 = vtkBoundingBox.computeScale3(bounds);

model.shapeHandle.setOrigin(center);
model.shapeHandle.setScale3(scale3);
};

publicAPI.setBoundsFromRadius = (center, pointOnCircle) => {
const radius = vec3.distance(center, pointOnCircle);

publicAPI.setBounds([
center[0] - radius,
center[0] + radius,
center[1] - radius,
center[1] + radius,
center[2] - radius,
center[2] + radius,
]);
};

publicAPI.setBoundsFromDiameter = (point1, point2) => {
const center = [
0.5 * (point1[0] + point2[0]),
0.5 * (point1[1] + point2[1]),
0.5 * (point1[2] + point2[2]),
];

publicAPI.setBoundsFromRadius(center, point1);
};
}
index.js
import macro from 'vtk.js/Sources/macro';
import vtkAbstractWidgetFactory from 'vtk.js/Sources/Widgets/Core/AbstractWidgetFactory';
import vtkPlanePointManipulator from 'vtk.js/Sources/Widgets/Manipulators/PlaneManipulator';
import vtkSphereHandleRepresentation from 'vtk.js/Sources/Widgets/Representations/SphereHandleRepresentation';
import vtkCircleContextRepresentation from 'vtk.js/Sources/Widgets/Representations/CircleContextRepresentation';
import widgetBehavior from 'vtk.js/Sources/Widgets/Widgets3D/EllipseWidget/behavior';
import stateGenerator from 'vtk.js/Sources/Widgets/Widgets3D/EllipseWidget/state';

import SHAPE_DEFAULT_VALUES from 'vtk.js/Sources/Widgets/Widgets3D/ShapeWidget';

import {
BehaviorCategory,
ShapeBehavior,
} from 'vtk.js/Sources/Widgets/Widgets3D/ShapeWidget/Constants';

import { ViewTypes } from 'vtk.js/Sources/Widgets/Core/WidgetManager/Constants';

// ----------------------------------------------------------------------------
// Factory
// ----------------------------------------------------------------------------

function vtkEllipseWidget(publicAPI, model) {
model.classHierarchy.push('vtkEllipseWidget');

// --- Widget Requirement ---------------------------------------------------

model.methodsToLink = [
'activeScaleFactor',
'activeColor',
'useActiveColor',
'glyphResolution',
'defaultScale',
'drawBorder',
'drawFace',
'opacity',
];

model.behavior = widgetBehavior;
publicAPI.getRepresentationsForViewType = (viewType) => {
switch (viewType) {
case ViewTypes.DEFAULT:
case ViewTypes.GEOMETRY:
case ViewTypes.SLICE:
case ViewTypes.VOLUME:
default:
return [
{ builder: vtkSphereHandleRepresentation, labels: ['moveHandle'] },
{
builder: vtkCircleContextRepresentation,
labels: ['ellipseHandle'],
},
];
}
};

// --------------------------------------------------------------------------
// initialization
// --------------------------------------------------------------------------

// Default manipulator
model.manipulator = vtkPlanePointManipulator.newInstance();
model.widgetState = stateGenerator();
model.shapeHandle = model.widgetState.getEllipseHandle();
model.point1Handle = model.widgetState.getPoint1Handle();
model.point2Handle = model.widgetState.getPoint2Handle();
model.point1Handle.setManipulator(model.manipulator);
model.point2Handle.setManipulator(model.manipulator);
}

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

const DEFAULT_VALUES = {
modifierBehavior: {
None: {
[BehaviorCategory.PLACEMENT]:
ShapeBehavior[BehaviorCategory.PLACEMENT].CLICK_AND_DRAG,
[BehaviorCategory.POINTS]:
ShapeBehavior[BehaviorCategory.POINTS].CENTER_TO_CORNER,
[BehaviorCategory.RATIO]: ShapeBehavior[BehaviorCategory.RATIO].FREE,
},
Shift: {
[BehaviorCategory.RATIO]: ShapeBehavior[BehaviorCategory.RATIO].FIXED,
},
Control: {
[BehaviorCategory.POINTS]:
ShapeBehavior[BehaviorCategory.POINTS].CORNER_TO_CORNER,
},
},
};

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

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(
model,
Object.assign({}, SHAPE_DEFAULT_VALUES.DEFAULT_VALUES, DEFAULT_VALUES),
initialValues
);

vtkAbstractWidgetFactory.extend(publicAPI, model, initialValues);
macro.setGet(publicAPI, model, ['manipulator', 'widgetState']);

vtkEllipseWidget(publicAPI, model);
}

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

export const newInstance = macro.newInstance(extend, 'vtkEllipseWidget');

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

export default { newInstance, extend };
state.js
import vtkStateBuilder from 'vtk.js/Sources/Widgets/Core/StateBuilder';

export default function generateState() {
return vtkStateBuilder
.createBuilder()
.addStateFromMixin({
labels: ['moveHandle'],
mixins: ['origin', 'color', 'scale1', 'visible', 'manipulator'],
name: 'point1Handle',
initialValues: {
scale1: 10,
origin: [0, 0, 0],
visible: false,
},
})
.addStateFromMixin({
labels: ['moveHandle'],
mixins: ['origin', 'color', 'scale1', 'visible', 'manipulator'],
name: 'point2Handle',
initialValues: {
scale1: 10,
origin: [0, 0, 0],
visible: false,
},
})
.addStateFromMixin({
labels: ['ellipseHandle'],
mixins: ['origin', 'color', 'scale3', 'visible', 'direction'],
name: 'ellipseHandle',
initialValues: {
visible: false,
direction: [0, 0, 1],
scale3: [1, 1, 1],
},
})
.build();
}