Skip to content

Commit d570bb6

Browse files
committed
feat: add Geometry2DRepresentation
1 parent 9a91034 commit d570bb6

File tree

3 files changed

+223
-0
lines changed

3 files changed

+223
-0
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import vtkActor2D, {
2+
IActor2DInitialValues,
3+
} from '@kitware/vtk.js/Rendering/Core/Actor2D';
4+
import { ICoordinateInitialValues } from '@kitware/vtk.js/Rendering/Core/Coordinate';
5+
import { Coordinate } from '@kitware/vtk.js/Rendering/Core/Coordinate/Constants';
6+
import vtkMapper2D, {
7+
IMapper2DInitialValues,
8+
} from '@kitware/vtk.js/Rendering/Core/Mapper2D';
9+
import { IProperty2DInitialValues } from '@kitware/vtk.js/Rendering/Core/Property2D';
10+
import { Vector2 } from '@kitware/vtk.js/types';
11+
import {
12+
forwardRef,
13+
PropsWithChildren,
14+
useEffect,
15+
useImperativeHandle,
16+
useMemo,
17+
useState,
18+
} from 'react';
19+
import { IDownstream, IRepresentation } from '../types';
20+
import { compareShallowObject } from '../utils-ts/comparators';
21+
import useBooleanAccumulator from '../utils-ts/useBooleanAccumulator';
22+
import useComparableEffect from '../utils-ts/useComparableEffect';
23+
import { useOrderedUnmountContext } from '../utils-ts/useOrderedUnmountEffect';
24+
import { DownstreamContext, RepresentationContext, useView } from './contexts';
25+
import useColorTransferFunction from './modules/useColorTransferFunction';
26+
import useCoordinate from './modules/useCoordinate';
27+
import useMapper from './modules/useMapper';
28+
import useProp from './modules/useProp';
29+
30+
interface Props extends PropsWithChildren {
31+
/**
32+
* The ID used to identify this component.
33+
*/
34+
id?: string;
35+
36+
/**
37+
* Properties to set to the actor
38+
*/
39+
actor?: IActor2DInitialValues;
40+
41+
/**
42+
* Properties to set to the actor
43+
*/
44+
mapper?: IMapper2DInitialValues;
45+
46+
/**
47+
* Properties to set to the actor.property
48+
*/
49+
property?: IProperty2DInitialValues;
50+
51+
/**
52+
* Preset name for the lookup table color map
53+
*/
54+
colorMapPreset?: string;
55+
56+
/**
57+
* Data range use for the colorMap
58+
*/
59+
colorDataRange?: [number, number];
60+
61+
/**
62+
* The coordinate system in which the input dataset resides.
63+
*/
64+
transformCoordinate?: ICoordinateInitialValues;
65+
}
66+
67+
const DefaultProps = {
68+
colorMapPreset: 'erdc_rainbow_bright',
69+
colorDataRange: [0, 1] as Vector2,
70+
transformCoordinate: {
71+
coordinateSystem: Coordinate.DISPLAY,
72+
},
73+
};
74+
75+
export default forwardRef(function Geometry2DRepresentation(
76+
props: Props,
77+
fwdRef
78+
) {
79+
const OrderedUnmountContext = useOrderedUnmountContext();
80+
81+
const view = useView();
82+
const [modifiedRef, trackModified, resetModified] = useBooleanAccumulator();
83+
const [dataAvailable, setDataAvailable] = useState(false);
84+
85+
// --- LUT --- //
86+
87+
const getLookupTable = useColorTransferFunction(
88+
props.colorMapPreset ?? DefaultProps.colorMapPreset,
89+
props.colorDataRange ?? DefaultProps.colorDataRange,
90+
trackModified
91+
);
92+
93+
// --- coordinate --- //
94+
95+
const { transformCoordinate = DefaultProps.transformCoordinate } = props;
96+
const getCoordinate = useCoordinate(transformCoordinate, trackModified);
97+
98+
// --- mapper --- //
99+
100+
const getMapper = useMapper<vtkMapper2D, IMapper2DInitialValues>(
101+
() =>
102+
vtkMapper2D.newInstance({
103+
lookupTable: getLookupTable(),
104+
useLookupTableScalarRange: false,
105+
scalarVisibility: false,
106+
transformCoordinate: getCoordinate(),
107+
} as IMapper2DInitialValues),
108+
props.mapper,
109+
trackModified
110+
);
111+
112+
// --- actor --- //
113+
114+
const actorProps = {
115+
...props.actor,
116+
visibility: dataAvailable && (props.actor?.visibility ?? true),
117+
};
118+
const getActor = useProp<vtkActor2D, IActor2DInitialValues>({
119+
constructor: () => vtkActor2D.newInstance({ visibility: false }),
120+
view,
121+
id: props.id,
122+
props: actorProps,
123+
trackModified,
124+
});
125+
126+
useEffect(() => {
127+
// TODO type hack; upgrade vtk.js
128+
const actor = getActor() as vtkActor2D & {
129+
setMapper(mapper: vtkMapper2D): boolean;
130+
};
131+
actor.setMapper(getMapper());
132+
}, [getActor, getMapper]);
133+
134+
// set actor property props
135+
const { property: propertyProps } = props;
136+
useComparableEffect(
137+
() => {
138+
if (!propertyProps) return;
139+
trackModified(getActor().getProperty().set(propertyProps));
140+
},
141+
[propertyProps],
142+
([cur], [prev]) => compareShallowObject(cur, prev)
143+
);
144+
145+
// --- //
146+
147+
useEffect(() => {
148+
if (view && modifiedRef.current) {
149+
view.requestRender();
150+
resetModified();
151+
}
152+
});
153+
154+
const representation = useMemo<IRepresentation>(
155+
() => ({
156+
dataChanged: () => {
157+
view.requestRender();
158+
},
159+
dataAvailable: () => {
160+
setDataAvailable(true);
161+
representation.dataChanged();
162+
},
163+
}),
164+
[view]
165+
);
166+
167+
const downstream = useMemo<IDownstream>(
168+
() => ({
169+
setInputData: (...args) => getMapper().setInputData(...args),
170+
setInputConnection: (...args) => getMapper().setInputConnection(...args),
171+
}),
172+
[getMapper]
173+
);
174+
175+
useImperativeHandle(fwdRef, () => representation);
176+
177+
return (
178+
<OrderedUnmountContext.Provider>
179+
<RepresentationContext.Provider value={representation}>
180+
<DownstreamContext.Provider value={downstream}>
181+
{props.children}
182+
</DownstreamContext.Provider>
183+
</RepresentationContext.Provider>
184+
</OrderedUnmountContext.Provider>
185+
);
186+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import vtkCoordinate, {
2+
ICoordinateInitialValues,
3+
} from '@kitware/vtk.js/Rendering/Core/Coordinate';
4+
import { compareShallowObject } from '../../utils-ts/comparators';
5+
import { BooleanAccumulator } from '../../utils-ts/useBooleanAccumulator';
6+
import useComparableEffect from '../../utils-ts/useComparableEffect';
7+
import useGetterRef from '../../utils-ts/useGetterRef';
8+
import useUnmount from '../../utils-ts/useUnmount';
9+
10+
export default function useCoordinate(
11+
props: ICoordinateInitialValues,
12+
trackModified: BooleanAccumulator
13+
) {
14+
const [ref, getCoordinate] = useGetterRef(() =>
15+
vtkCoordinate.newInstance(props)
16+
);
17+
18+
useComparableEffect(
19+
() => {
20+
if (!props) return;
21+
getCoordinate().set(props);
22+
trackModified(true);
23+
},
24+
[props],
25+
([cur], [prev]) => compareShallowObject(cur, prev)
26+
);
27+
28+
useUnmount(() => {
29+
if (ref.current) {
30+
ref.current.delete();
31+
ref.current = null;
32+
}
33+
});
34+
35+
return getCoordinate;
36+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import '@kitware/vtk.js/Rendering/OpenGL/Profiles/Volume';
55

66
export { default as Algorithm } from './core-ts/Algorithm';
77
export { default as DataArray } from './core-ts/DataArray';
8+
export { default as Geometry2DRepresentation } from './core-ts/Geometry2DRepresentation';
89
export { default as GeometryRepresentation } from './core-ts/GeometryRepresentation';
910
export { default as ImageData } from './core-ts/ImageData';
1011
export { default as PointData } from './core-ts/PointData';

0 commit comments

Comments
 (0)