Skip to content

Commit

Permalink
Merge pull request #545 from PaulHax/transfer-editor
Browse files Browse the repository at this point in the history
Swap vtkPiecewiseGaussianWidget for itk-viewer-transfer-function-editor
  • Loading branch information
thewtex authored Aug 18, 2022
2 parents 13a948a + 3dff79e commit 6d2883d
Show file tree
Hide file tree
Showing 36 changed files with 1,471 additions and 3,157 deletions.
10 changes: 9 additions & 1 deletion dist/testConglomerate.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,18 @@
images
)
const container = document.querySelector('#viewport')
itkVtkViewer.createViewer(container, {
const viewer = await itkVtkViewer.createViewer(container, {
image,
rotate: false,
})

const newPoints = [
[0, 0],
[0.5, 0.5],
[1, 1],
]
viewer.setImagePiecewiseFunctionPoints(newPoints, 0)
window.viewer = viewer
}

main()
Expand Down
21 changes: 19 additions & 2 deletions doc/content/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,35 @@ image component identified by name.
Set/get the [min, max] range of intensity values for color maps that provide a bounds
for user inputs.

### setImageColorMap(colorMap, componentIndex, name)
### setImageColorMap(colorMap, component, name)

### getImageColorMap(componentIndex, name)
### getImageColorMap(component, name)

Set/get the color map for the given component/channel.

<!---
### setImagePiecewiseFunctionGaussians(gaussians, component, name)
### getImagePiecewiseFunctionGaussians(component, name)
Set/get the gaussian parameters that define the piecewise function used to define
the volume rendering opacity transfer function and multi-component slice blending.
-->

### setImagePiecewiseFunctionPoints(points, component, name = current)

### getImagePiecewiseFunctionPoints(component, name)

Set/get the points defining the piecewise volume opacity transfer and multi-component
slice blending function. Parameter points is of type `[intensity: number, opacity:number][]` with
intensity and opacity values going from 0 to 1. The 0 to 1 intensity values are scaled between
the component's range of intensity values.
Example: If the intensity values for component 0 go from 100 to 200,
`viewer.setImagePiecewiseFunctionPoints([[0, 0], [.5, 1]], 0)` puts a point at intensity 100 and another at intensity 150.
For volume rendering, intensities above or below the range of points have 0 opacity.
For 2D or slice rendering, intensities above or below the range of points take the last color of the color map.
With 2 or more components in 2D or slice rendering, the `y` value of points controls the contribution of matching intensities.
Intensities before the start point take the `y`/mix-factor of the start point, intensities after the end point take the end point `y` value.

### setImageShadowEnabled(enabled, name)

Expand Down
6 changes: 3 additions & 3 deletions doc/content/docs/shortcuts.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ the mouse must be over the viewer.
**Left click + drag** | Rotate
**Right click + drag** or **shift + left click + drag** | Pan
**Mouse wheel** or **control + left click + drag** or **pinch** | Zoom
**Alt + left click + drag left-right** | Change color transfer function window
**Shift + left click + drag top-bottom** | Change color transfer function level
**Shift + alt + left click + drag top-bottom** | Change primary Gaussian volume opacity transfer function magnitude
**Alt + left click + drag left-right** | Change color transfer function level
**Alt + left click + drag top-bottom** | Change color transfer function window
**Alt + right click + drag top-bottom** | Change primary volume opacity transfer function magnitude
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"itk-image-io": "^1.0.0-b.15",
"itk-mesh-io": "^1.0.0-b.15",
"itk-viewer-icons": "^11.12.0",
"itk-viewer-transfer-function-editor": "^1.1.2",
"itk-wasm": "^1.0.0-b.17",
"mobx": "^5.15.7",
"mousetrap": "^1.6.5",
Expand Down Expand Up @@ -137,7 +138,7 @@
"test:downloadData": "node test/downloadData.mjs",
"test:headless": "./test/run.sh",
"test:headless-debug": "./test/run.sh -d",
"test:debug": "karma start ./karma.conf.js --no-single-run"
"test:debug": "npm run build:test-ui && karma start ./karma.conf.js --no-single-run"
},
"config": {
"commitizen": {
Expand Down
6 changes: 6 additions & 0 deletions src/Context/ImageActorContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class ImageActorContext {
// piecewise functions
piecewiseFunctionGaussians = new Map()

// Map of x,y point in 0 to 1 range. Scaled by colorRanges.
piecewiseFunctionPoints = new Map()

// Use gradient-based shadows in the volume rendering
shadowEnabled = true

Expand Down Expand Up @@ -94,6 +97,9 @@ class ImageActorContext {
// Label index selected for changes in the UI, or special 'all' value that
// identifies all non-backgound (index 0) labels
selectedLabel = 'all'

// Cached histogram by component for use by UI when switching selected component
histograms = new Map()
}

export default ImageActorContext
2 changes: 1 addition & 1 deletion src/Rendering/Images/createImagesRenderingMachine.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function createImagesRenderingMachine(options, context) {
},
UPDATE_IMAGE_HISTOGRAM: {
actions: send((_, e) => e, {
to: (c, e) => `imageRenderingActor-${e.data}`,
to: (c, e) => `imageRenderingActor-${e.data.name}`,
}),
},
LABEL_IMAGE_LOOKUP_TABLE_CHANGED: {
Expand Down
41 changes: 0 additions & 41 deletions src/Rendering/VTKJS/Images/applyColorMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,6 @@ function applyColorMap(context, event) {
const lookupTableProxy = context.images.lookupTableProxies.get(component)
const colorTransferFunction = lookupTableProxy.getLookupTable()

// Todo:
//const transferFunctionWidget = store.imageUI.transferFunctionWidget

//if (colorMap.startsWith('Custom')) {
//lookupTableProxy.setMode(vtkLookupTableProxy.Mode.RGBPoints)
//const colorDataRange = transferFunctionWidget.getOpacityRange()
//if (!!colorDataRange) {
//colorTransferFunction.setMappingRange(...colorDataRange)
//}
//colorTransferFunction.updateRange()

//const isIcons = iconSelector.getIcons()
//if (!!!customIcon) {
//const colorMapIcon = customColorMapIcon(
//colorTransferFunction,
//colorDataRange
//)
//customIcon = { iconFilePath: colorMapIcon, iconValue: colorMap }
//icons.push(customIcon)
//iconSelector.refresh(icons)
//} else if (isIcons[isIcons.length - 1].iconValue !== colorMap) {
//const colorMapIcon = customColorMapIcon(
//colorTransferFunction,
//colorDataRange
//)
//isIcons[isIcons.length - 1].element.src = colorMapIcon
//isIcons[isIcons.length - 1].iconFilePath = colorMapIcon
//isIcons[isIcons.length - 1].iconValue = colorMap
//isIcons[isIcons.length - 1].element.setAttribute('icon-value', colorMap)
//isIcons[isIcons.length - 1].element.setAttribute('alt', colorMap)
//isIcons[isIcons.length - 1].element.setAttribute('title', colorMap)
//}
//} else {
const currentColorMap = lookupTableProxy.getPresetName()
if (currentColorMap !== colorMap) {
lookupTableProxy.setPresetName(colorMap)
Expand Down Expand Up @@ -77,14 +44,6 @@ function applyColorMap(context, event) {
}
applyPiecewiseFunction(context, fauxEvent)

//const colorDataRange = transferFunctionWidget.getOpacityRange()
//if (!!colorDataRange) {
//colorTransferFunction.setMappingRange(...colorDataRange)
//}
//colorTransferFunction.updateRange()
//}
//transferFunctionWidget.render()

context.service.send('RENDER')
}

Expand Down
13 changes: 2 additions & 11 deletions src/Rendering/VTKJS/Images/applyPiecewiseFunction.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import filterAndProcessOpacityNodes from './filterAndProcessOpacityNodes'

function applyPiecewiseFunction(context, event) {
const name = event.data.name
const component = event.data.component
Expand All @@ -16,15 +14,8 @@ function applyPiecewiseFunction(context, event) {

volumePiecewiseFunction.setNodes(nodes)

const numberOfComponents = actorContext.componentVisibilities.reduce(
(a, c) => +a + c,
0
)
const filteredNodes = filterAndProcessOpacityNodes(
numberOfComponents,
nodes
)
slicePiecewiseFunction.setNodes(filteredNodes)
const sliceNodes = nodes.length > 2 ? nodes.slice(1, -1) : nodes // if more than 2, remove "window" nodes with y = 0
slicePiecewiseFunction.setNodes(sliceNodes)

const lookupTableProxy = context.images.lookupTableProxies.get(component)
const lookupTable = lookupTableProxy.getLookupTable()
Expand Down
30 changes: 0 additions & 30 deletions src/Rendering/VTKJS/Images/filterAndProcessOpacityNodes.js

This file was deleted.

2 changes: 2 additions & 0 deletions src/Rendering/VTKJS/Images/updateHistogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ async function updateHistogram(context, event) {
histogram[ii] /= maxHistogram
}

actorContext.histograms.set(component, histogram)

context.service.send({
type: 'IMAGE_HISTOGRAM_UPDATED',
data: { name, component, histogram },
Expand Down
4 changes: 0 additions & 4 deletions src/Rendering/VTKJS/vtk/AxesLabelsWidget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ function vtkAxesLabelsWidget(publicAPI, model) {
(bounds[4] + bounds[5]) * 0.5,
]
})

// Default manipulator
//model.manipulator = vtkPlanePointManipulator.newInstance()
}

// ----------------------------------------------------------------------------
Expand All @@ -66,7 +63,6 @@ export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues)

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

vtkAxesLabelsWidget(publicAPI, model)
}
Expand Down
6 changes: 3 additions & 3 deletions src/Rendering/createRenderingMachine.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,6 @@ const createRenderingMachine = (options, context) => {
IMAGE_BLEND_MODE_CHANGED: {
actions: forwardTo('images'),
},
IMAGE_HISTOGRAM_UPDATED: {
actions: forwardTo('images'),
},
LABEL_IMAGE_ASSIGNED: {
actions: forwardTo('images'),
},
Expand All @@ -198,6 +195,9 @@ const createRenderingMachine = (options, context) => {
LABEL_IMAGE_SELECTED_LABEL_CHANGED: {
actions: forwardTo('images'),
},
UPDATE_IMAGE_HISTOGRAM: {
actions: forwardTo('images'),
},
},
},
},
Expand Down
17 changes: 17 additions & 0 deletions src/UI/Images/createImagesUIMachine.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ const assignPiecewiseFunctionGaussians = assign({
},
})

const assignPiecewiseFunctionPoints = assign({
images: ({ images }, { data: { component, points, name } }) => {
const actorContext = images.actorContext.get(name)
actorContext.piecewiseFunctionPoints.set(component, points)
return images
},
})

const assignColorRange = assign({
images: (context, event) => {
const images = context.images
Expand Down Expand Up @@ -300,6 +308,15 @@ function createImagesUIMachine(options, context) {
'applyPiecewiseFunctionGaussians',
],
},
IMAGE_PIECEWISE_FUNCTION_POINTS_CHANGED: {
actions: assignPiecewiseFunctionPoints,
},
IMAGE_PIECEWISE_FUNCTION_POINTS_SET: {
actions: [
assignPiecewiseFunctionPoints,
'applyPiecewiseFunctionPointsToEditor',
],
},
IMAGE_COLOR_RANGE_CHANGED: {
actions: [assignColorRange, 'applyColorRange'],
},
Expand Down
Loading

0 comments on commit 6d2883d

Please sign in to comment.