-
-
Notifications
You must be signed in to change notification settings - Fork 382
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #511 from agirault/range-manipulator
Range manipulator
- Loading branch information
Showing
6 changed files
with
330 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
Sources/Interaction/Manipulators/MouseManipulator/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import macro from 'vtk.js/Sources/macro'; | ||
|
||
// ---------------------------------------------------------------------------- | ||
// vtkMouseManipulator methods | ||
// ---------------------------------------------------------------------------- | ||
|
||
function vtkMouseManipulator(publicAPI, model) { | ||
// Set our className | ||
model.classHierarchy.push('vtkMouseManipulator'); | ||
|
||
publicAPI.startInteraction = () => {}; | ||
publicAPI.endInteraction = () => {}; | ||
publicAPI.onButtonDown = (interactor) => {}; | ||
publicAPI.onButtonUp = (interactor) => {}; | ||
publicAPI.onAnimation = (interactor, renderer) => {}; | ||
publicAPI.onKeyUp = (interactor) => {}; | ||
publicAPI.onKeyDown = (interactor) => {}; | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// Object factory | ||
// ---------------------------------------------------------------------------- | ||
|
||
const DEFAULT_VALUES = { | ||
manipulatorName: 'goldschlager', | ||
|
||
button: 1, | ||
shift: false, | ||
control: false, | ||
alt: false, | ||
pinch: false, | ||
}; | ||
|
||
// ---------------------------------------------------------------------------- | ||
|
||
export function extend(publicAPI, model, initialValues = {}) { | ||
Object.assign(model, DEFAULT_VALUES, initialValues); | ||
|
||
// Object methods | ||
macro.obj(publicAPI, model); | ||
|
||
// Create get-set macros | ||
macro.setGet(publicAPI, model, [ | ||
'manipulatorName', | ||
'button', | ||
'shift', | ||
'control', | ||
'alt', | ||
'pinch', | ||
]); | ||
|
||
// Object specific methods | ||
vtkMouseManipulator(publicAPI, model); | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
|
||
export const newInstance = macro.newInstance(extend, 'vtkMouseManipulator'); | ||
|
||
// ---------------------------------------------------------------------------- | ||
|
||
export default Object.assign({ newInstance, extend }); |
81 changes: 81 additions & 0 deletions
81
Sources/Interaction/Manipulators/RangeManipulator/example/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import 'vtk.js/Sources/favicon'; | ||
|
||
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow'; | ||
import vtkRTAnalyticSource from 'vtk.js/Sources/Filters/Sources/RTAnalyticSource'; | ||
import vtkImageMapper from 'vtk.js/Sources/Rendering/Core/ImageMapper'; | ||
import vtkImageSlice from 'vtk.js/Sources/Rendering/Core/ImageSlice'; | ||
import vtkInteractorStyleManipulator from 'vtk.js/Sources/Interaction/Style/InteractorStyleManipulator'; | ||
|
||
import Manipulators from 'vtk.js/Sources/Interaction/Manipulators'; | ||
|
||
// ---------------------------------------------------------------------------- | ||
// Standard rendering code setup | ||
// ---------------------------------------------------------------------------- | ||
|
||
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance(); | ||
const renderer = fullScreenRenderer.getRenderer(); | ||
const renderWindow = fullScreenRenderer.getRenderWindow(); | ||
|
||
// ---------------------------------------------------------------------------- | ||
// Example code | ||
// ---------------------------------------------------------------------------- | ||
|
||
const rtSource = vtkRTAnalyticSource.newInstance(); | ||
rtSource.setWholeExtent(0, 200, 0, 200, 0, 200); | ||
rtSource.setCenter(100, 100, 100); | ||
rtSource.setStandardDeviation(0.3); | ||
|
||
const mapper = vtkImageMapper.newInstance(); | ||
mapper.setInputConnection(rtSource.getOutputPort()); | ||
|
||
const actor = vtkImageSlice.newInstance(); | ||
actor.getProperty().setColorWindow(100); | ||
actor.getProperty().setColorLevel(50); | ||
actor.setMapper(mapper); | ||
|
||
const data = rtSource.getOutputData(); | ||
const range = data | ||
.getPointData() | ||
.getScalars() | ||
.getRange(); | ||
const wMin = 1; | ||
const wMax = range[1] - range[0]; | ||
const wCurrent = actor.getProperty().getColorWindow(); | ||
const wCallback = actor.getProperty().setColorWindow; | ||
const lMin = range[0]; | ||
const lMax = range[1]; | ||
const lCurrent = actor.getProperty().getColorLevel(); | ||
const lCallback = actor.getProperty().setColorLevel; | ||
const bounds = data.getBounds(); | ||
const zMin = bounds[4]; | ||
const zMax = bounds[5]; | ||
const zCurrent = mapper.getZSlice(); | ||
const zCallback = mapper.setZSlice; | ||
|
||
const rangeManipulator = Manipulators.vtkRangeManipulator.newInstance({ | ||
button: 1, | ||
pinch: true, | ||
}); | ||
rangeManipulator.setVerticalListener(wMin, wMax, wCurrent, 1, wCallback); | ||
rangeManipulator.setHorizontalListener(lMin, lMax, lCurrent, 1, lCallback); | ||
rangeManipulator.setScrollListener(zMin, zMax, zCurrent, 1, zCallback); | ||
|
||
const iStyle = vtkInteractorStyleManipulator.newInstance(); | ||
iStyle.addManipulator(rangeManipulator); | ||
renderWindow.getInteractor().setInteractorStyle(iStyle); | ||
|
||
renderer.getActiveCamera().setParallelProjection(true); | ||
renderer.addActor(actor); | ||
renderer.resetCamera(); | ||
renderWindow.render(); | ||
|
||
// ----------------------------------------------------------- | ||
// Make some variables global so that you can inspect and | ||
// modify objects in your browser's developer console: | ||
// ----------------------------------------------------------- | ||
|
||
global.source = rtSource; | ||
global.mapper = mapper; | ||
global.actor = actor; | ||
global.renderer = renderer; | ||
global.renderWindow = renderWindow; |
158 changes: 158 additions & 0 deletions
158
Sources/Interaction/Manipulators/RangeManipulator/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import macro from 'vtk.js/Sources/macro'; | ||
import vtkMouseManipulator from 'vtk.js/Sources/Interaction/Manipulators/MouseManipulator'; | ||
|
||
// ---------------------------------------------------------------------------- | ||
// vtkRangeManipulator methods | ||
// ---------------------------------------------------------------------------- | ||
|
||
function vtkRangeManipulator(publicAPI, model) { | ||
// Set our className | ||
model.classHierarchy.push('vtkRangeManipulator'); | ||
|
||
//------------------------------------------------------------------------- | ||
function processDelta(listener, delta) { | ||
let normDelta = delta; | ||
normDelta *= (listener.max - listener.min) / listener.step + 1; | ||
let value = listener.value + normDelta; | ||
|
||
const difference = value - listener.min; | ||
const stepsToDifference = Math.round(difference / listener.step); | ||
value = listener.min + listener.step * stepsToDifference; | ||
value = Math.max(value, listener.min); | ||
value = Math.min(value, listener.max); | ||
|
||
listener.callback(value); | ||
listener.value = value; | ||
} | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.setHorizontalListener = (min, max, value, step, callback) => { | ||
model.horizontalListener = { min, max, value, step, callback }; | ||
publicAPI.modified(); | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.setVerticalListener = (min, max, value, step, callback) => { | ||
model.verticalListener = { min, max, value, step, callback }; | ||
publicAPI.modified(); | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.setScrollListener = (min, max, value, step, callback) => { | ||
model.scrollListener = { min, max, value, step, callback }; | ||
publicAPI.modified(); | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.removeHorizontalListener = () => { | ||
if (model.verticalListener) { | ||
delete model.verticalListener; | ||
publicAPI.modified(); | ||
} | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.removeVerticalListener = () => { | ||
if (model.horizontalListener) { | ||
delete model.horizontalListener; | ||
publicAPI.modified(); | ||
} | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.removeScrollListener = () => { | ||
if (model.scrollListener) { | ||
delete model.scrollListener; | ||
publicAPI.modified(); | ||
} | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.removeAllListeners = () => { | ||
publicAPI.removeHorizontalListener(); | ||
publicAPI.removeVerticalListener(); | ||
publicAPI.removesCrollListener(); | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.onAnimation = (interactor, renderer) => { | ||
if (!model.verticalListener && !model.horizontalListener) { | ||
return; | ||
} | ||
|
||
const lastPtr = interactor.getPointerIndex(); | ||
const pos = interactor.getAnimationEventPosition(lastPtr); | ||
const lastPos = interactor.getLastAnimationEventPosition(lastPtr); | ||
|
||
if (!pos || !lastPos || !renderer) { | ||
return; | ||
} | ||
|
||
// Scale by viewport size | ||
const size = interactor.getView().getViewportSize(renderer); | ||
|
||
if (model.horizontalListener) { | ||
const dx = (pos.x - lastPos.x) / size[0]; | ||
processDelta(model.horizontalListener, dx); | ||
} | ||
if (model.verticalListener) { | ||
const dy = (pos.y - lastPos.y) / size[1]; | ||
processDelta(model.verticalListener, dy); | ||
} | ||
}; | ||
|
||
//------------------------------------------------------------------------- | ||
publicAPI.onPinch = (interactor) => { | ||
if (!model.scrollListener) { | ||
return; | ||
} | ||
|
||
const interactorStyle = interactor.getInteractorStyle(); | ||
let renderer = interactorStyle.getCurrentRenderer(); | ||
|
||
if (!renderer) { | ||
const pos = interactor.getAnimationEventPosition( | ||
interactor.getPointerIndex() | ||
); | ||
renderer = interactor.findPokedRenderer(pos); | ||
if (!renderer) { | ||
return; | ||
} | ||
} | ||
|
||
const scale = interactor.getScale(); | ||
const lastScale = interactor.getLastScale(); | ||
const delta = 1.0 - scale / lastScale; | ||
processDelta(model.scrollListener, delta); | ||
}; | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// Object factory | ||
// ---------------------------------------------------------------------------- | ||
|
||
const DEFAULT_VALUES = { | ||
horizontalListener: null, | ||
verticalListener: null, | ||
scrollListener: null, | ||
}; | ||
|
||
// ---------------------------------------------------------------------------- | ||
|
||
export function extend(publicAPI, model, initialValues = {}) { | ||
Object.assign(model, DEFAULT_VALUES, initialValues); | ||
|
||
// Inheritance | ||
vtkMouseManipulator.extend(publicAPI, model, initialValues); | ||
|
||
// Object specific methods | ||
vtkRangeManipulator(publicAPI, model); | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
|
||
export const newInstance = macro.newInstance(extend, 'vtkRangeManipulator'); | ||
|
||
// ---------------------------------------------------------------------------- | ||
|
||
export default Object.assign({ newInstance, extend }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.