@itk-viewer/viewer
Advanced tools
Comparing version 0.5.3 to 0.6.0
# @itk-viewer/viewer | ||
## 0.6.0 | ||
### Minor Changes | ||
- dae0e89: Add opacity function editor to View 3D. | ||
## 0.5.3 | ||
@@ -4,0 +10,0 @@ |
@@ -132,1 +132,2 @@ /// <reference types="gl-matrix/index.js" /> | ||
export {}; | ||
//# sourceMappingURL=camera.d.ts.map |
@@ -8,1 +8,2 @@ import { AnyActorLogic, AnyActorRef } from 'xstate'; | ||
}; | ||
//# sourceMappingURL=children.d.ts.map |
@@ -11,1 +11,2 @@ export declare const fpsWatcher: import("xstate").StateMachine<{ | ||
}, import("xstate").ProvidedActor, import("xstate").ParameterizedObject, import("xstate").ParameterizedObject, string, string>>; | ||
//# sourceMappingURL=fps-watcher.d.ts.map |
@@ -1,4 +0,5 @@ | ||
import { ActorRefFrom } from 'xstate'; | ||
import { ActorRefFrom, AnyActorRef } from 'xstate'; | ||
import { BuiltImage, MultiscaleSpatialImage } from '@itk-viewer/io/MultiscaleSpatialImage.js'; | ||
import { Ranges } from '@itk-viewer/io/types.js'; | ||
type Point = readonly [number, number]; | ||
type Context = { | ||
@@ -9,4 +10,9 @@ image: MultiscaleSpatialImage; | ||
normalizedColorRanges: Ranges; | ||
opacityPoints: Point[][]; | ||
normalizedOpacityPoints: Point[][]; | ||
}; | ||
export declare const image: import("xstate").StateMachine<Context, { | ||
type: 'getWorker'; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: 'builtImage'; | ||
@@ -18,3 +24,7 @@ builtImage: BuiltImage; | ||
component: number; | ||
}, Record<string, import("xstate").AnyActorRef>, { | ||
} | { | ||
type: 'normalizedOpacityPoints'; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, { | ||
src: string; | ||
@@ -26,2 +36,5 @@ logic: import("xstate").UnknownActorLogic; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
@@ -31,2 +44,5 @@ type: string; | ||
}, string, "active", string, MultiscaleSpatialImage, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: 'getWorker'; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: 'builtImage'; | ||
@@ -38,2 +54,6 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: 'normalizedOpacityPoints'; | ||
points: [number, number][]; | ||
component: number; | ||
}, { | ||
@@ -46,2 +66,5 @@ src: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
@@ -54,1 +77,2 @@ type: string; | ||
export {}; | ||
//# sourceMappingURL=image.d.ts.map |
import { assign, setup } from 'xstate'; | ||
const NORMALIZED_RANGE_DEFAULT = [0.2, 0.8]; | ||
const NORMALIZED_OPACITY_POINTS_DEFAULT = [ | ||
[0.2, 0.1], | ||
[0.8, 0.8], | ||
]; | ||
const computeColorRange = (dataRange, normalizedRange) => { | ||
@@ -15,2 +19,14 @@ const delta = dataRange[1] - dataRange[0]; | ||
}; | ||
const computeNormalizedOpacityPoints = (dataRange, opacityPoints) => { | ||
return opacityPoints.map(([x, y]) => { | ||
const delta = dataRange[1] - dataRange[0]; | ||
return [(x - dataRange[0]) / delta, y]; | ||
}); | ||
}; | ||
const computeOpacityPoints = (dataRange, normalizedPoints) => { | ||
const delta = dataRange[1] - dataRange[0]; | ||
return normalizedPoints.map(([x, y]) => { | ||
return [x * delta + dataRange[0], y]; | ||
}); | ||
}; | ||
export const image = setup({ | ||
@@ -26,5 +42,12 @@ types: {}, | ||
}), | ||
updateOpacityPoints: assign({ | ||
opacityPoints: ({ context: { dataRanges, normalizedOpacityPoints } }) => { | ||
return dataRanges.map((range, component) => { | ||
return computeOpacityPoints(range, normalizedOpacityPoints[component]); | ||
}); | ||
}, | ||
}), | ||
}, | ||
}).createMachine({ | ||
id: 'camera', | ||
id: 'image', | ||
initial: 'active', | ||
@@ -36,2 +59,4 @@ context: ({ input: image }) => ({ | ||
normalizedColorRanges: [], | ||
opacityPoints: [], | ||
normalizedOpacityPoints: [], | ||
}), | ||
@@ -72,4 +97,16 @@ states: { | ||
}, | ||
normalizedOpacityPoints: ({ context }) => { | ||
return context.dataRanges.map((dataRange, component) => { | ||
if (!context.normalizedOpacityPoints[component]) | ||
return NORMALIZED_OPACITY_POINTS_DEFAULT; | ||
// if data range changes | ||
// scale normalizedPoints so opacityPoints doesn't change | ||
const points = context.opacityPoints[component]; | ||
const normalized = computeNormalizedOpacityPoints(dataRange, points); | ||
return normalized; | ||
}); | ||
}, | ||
}), | ||
'updateColorRanges', | ||
'updateOpacityPoints', | ||
], | ||
@@ -88,2 +125,13 @@ }, | ||
}, | ||
normalizedOpacityPoints: { | ||
actions: [ | ||
assign({ | ||
normalizedOpacityPoints: ({ context, event }) => { | ||
context.normalizedOpacityPoints[event.component] = event.points; | ||
return context.normalizedOpacityPoints; | ||
}, | ||
}), | ||
'updateOpacityPoints', | ||
], | ||
}, | ||
}, | ||
@@ -90,0 +138,0 @@ }, |
import { Actor, AnyActorRef } from 'xstate'; | ||
import { MultiscaleSpatialImage, BuiltImage } from '@itk-viewer/io/MultiscaleSpatialImage.js'; | ||
import { ValueOf } from '@itk-viewer/io/types.js'; | ||
import { CreateChild } from './children.js'; | ||
import { ViewportActor } from './viewport.js'; | ||
export declare const Axis: { | ||
readonly I: "I"; | ||
readonly J: "J"; | ||
readonly K: "K"; | ||
}; | ||
export type AxisType = ValueOf<typeof Axis>; | ||
import { AxisType } from './slice-utils.js'; | ||
import { ImageBuilder } from './image-builder.js'; | ||
export declare const view2d: import("xstate").StateMachine<{ | ||
@@ -59,3 +54,8 @@ slice: number; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -67,3 +67,10 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -75,3 +82,8 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
imageBuilders: Array<ImageBuilder>; | ||
}, CreateChild | { | ||
@@ -132,2 +144,124 @@ type: 'setImage'; | ||
}>; | ||
} | { | ||
type: 'imageBuilt'; | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
actor: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
slice: number; | ||
axis: AxisType; | ||
scale: number; | ||
image: MultiscaleSpatialImage; | ||
imageActor?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
builtImage?: BuiltImage | undefined; | ||
worker?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | undefined; | ||
}, import("xstate").AnyEventObject, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "done" | "building" | "findingSliceIndex", string, import("xstate").NonReducibleUnknown>, import("xstate").AnyEventObject>; | ||
}, { | ||
@@ -139,3 +273,8 @@ [x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -147,3 +286,10 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -155,15 +301,125 @@ builtImage: BuiltImage; | ||
component: number; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
slice: number; | ||
axis: AxisType; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<"I" | "J" | "K", { | ||
scale: number; | ||
image: MultiscaleSpatialImage; | ||
imageActor?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
builtImage?: BuiltImage | undefined; | ||
worker?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | undefined; | ||
}, import("xstate").AnyEventObject, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "done" | "building" | "findingSliceIndex", string, import("xstate").NonReducibleUnknown>, import("xstate").AnyEventObject> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<"I" | "J" | "K", { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
@@ -181,3 +437,8 @@ }>, { | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -189,2 +450,6 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, { | ||
@@ -197,2 +462,5 @@ src: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
@@ -202,2 +470,5 @@ type: string; | ||
}, string, "active", string, MultiscaleSpatialImage, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -209,2 +480,6 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, { | ||
@@ -217,2 +492,5 @@ src: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
@@ -225,11 +503,369 @@ type: string; | ||
src: "imageBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
logic: import("xstate").StateMachine<{ | ||
slice: number; | ||
axis: AxisType; | ||
scale: number; | ||
image: MultiscaleSpatialImage; | ||
imageActor?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
builtImage?: BuiltImage | undefined; | ||
worker?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | undefined; | ||
}, import("xstate").AnyEventObject, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, { | ||
src: "imageWorker"; | ||
logic: import("xstate").StateMachine<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "idle" | "buildingImage", string, { | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
} | { | ||
src: "findSliceIndex"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "done" | "building" | "findingSliceIndex", string, { | ||
image: MultiscaleSpatialImage; | ||
imageActor: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}>; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>; | ||
}, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("xstate").AnyEventObject, { | ||
src: "imageWorker"; | ||
logic: import("xstate").StateMachine<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "idle" | "buildingImage", string, { | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
} | { | ||
src: "findSliceIndex"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
@@ -253,3 +889,3 @@ } | { | ||
}, string, { | ||
view2d?: "idle" | "findingNewImageDefaults" | "buildingImage" | undefined; | ||
view2d?: "idle" | "buildingImage" | "findingNewImageDefaults" | undefined; | ||
}, string, unknown, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, CreateChild | { | ||
@@ -310,2 +946,124 @@ type: 'setImage'; | ||
}>; | ||
} | { | ||
type: 'imageBuilt'; | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
actor: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
slice: number; | ||
axis: AxisType; | ||
scale: number; | ||
image: MultiscaleSpatialImage; | ||
imageActor?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
builtImage?: BuiltImage | undefined; | ||
worker?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | undefined; | ||
}, import("xstate").AnyEventObject, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "done" | "building" | "findingSliceIndex", string, import("xstate").NonReducibleUnknown>, import("xstate").AnyEventObject>; | ||
}, { | ||
@@ -318,3 +1076,8 @@ src: "image"; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -326,2 +1089,6 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, { | ||
@@ -334,2 +1101,5 @@ src: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
@@ -339,2 +1109,5 @@ type: string; | ||
}, string, "active", string, MultiscaleSpatialImage, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
@@ -346,2 +1119,6 @@ builtImage: BuiltImage; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, { | ||
@@ -354,2 +1131,5 @@ src: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
@@ -362,11 +1142,369 @@ type: string; | ||
src: "imageBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
logic: import("xstate").StateMachine<{ | ||
slice: number; | ||
axis: AxisType; | ||
scale: number; | ||
image: MultiscaleSpatialImage; | ||
imageActor?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
builtImage?: BuiltImage | undefined; | ||
worker?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | undefined; | ||
}, import("xstate").AnyEventObject, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, "idle" | "buildingImage", string, import("xstate").NonReducibleUnknown>, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, { | ||
src: "imageWorker"; | ||
logic: import("xstate").StateMachine<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "idle" | "buildingImage", string, { | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
} | { | ||
src: "findSliceIndex"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "done" | "building" | "findingSliceIndex", string, { | ||
image: MultiscaleSpatialImage; | ||
imageActor: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}>; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>; | ||
}, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("xstate").AnyEventObject, { | ||
src: "imageWorker"; | ||
logic: import("xstate").StateMachine<{ | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>, { | ||
[k: string]: unknown; | ||
type: string; | ||
}> | undefined; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "idle" | "buildingImage", string, { | ||
image: MultiscaleSpatialImage; | ||
listeners: AnyActorRef[]; | ||
}, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "buildImageInImageSpace"; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}, { | ||
src: "imageSpaceBuilder"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
imageType: import("itk-wasm").ImageType; | ||
name: string; | ||
origin: number[]; | ||
spacing: number[]; | ||
direction: Float64Array; | ||
size: number[]; | ||
data: ArrayBuffer; | ||
ranges: import("@itk-viewer/io/types.js").Ranges | number[][] | undefined; | ||
metadata: Map<any, any>; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
normalizedImageBounds: import("@itk-viewer/utils/bounding-box.js").Bounds; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
} | { | ||
src: "findSliceIndex"; | ||
logic: import("xstate").PromiseActorLogic<{ | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
}, { | ||
image: MultiscaleSpatialImage; | ||
builtImage: BuiltImage; | ||
scale: number; | ||
slice: number; | ||
axis: AxisType; | ||
}>; | ||
id: string | undefined; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
@@ -391,1 +1529,2 @@ } | { | ||
export type View2dActor = Actor<typeof view2d>; | ||
//# sourceMappingURL=view-2d.d.ts.map |
@@ -7,19 +7,6 @@ import { assign, enqueueActions, fromPromise, setup, stateIn, } from 'xstate'; | ||
import { image } from './image.js'; | ||
import { mat3, mat4, quat, vec3 } from 'gl-matrix'; | ||
export const Axis = { | ||
I: 'I', | ||
J: 'J', | ||
K: 'K', | ||
}; | ||
const axisToIndex = { | ||
I: 0, | ||
J: 1, | ||
K: 2, | ||
}; | ||
// To MultiScaleImage dimension | ||
const axisToDim = { | ||
I: 'x', | ||
J: 'y', | ||
K: 'z', | ||
}; | ||
import { mat3, quat, vec3 } from 'gl-matrix'; | ||
import { Axis } from './slice-utils.js'; | ||
import { imageBuilder } from './image-builder.js'; | ||
const IMAGE_BUILDERS_LIMIT = 4; | ||
const toRotation = (direction, axis) => { | ||
@@ -63,45 +50,4 @@ const direction3d = ensure3dDirection(direction); | ||
actors: { | ||
imageBuilder: fromPromise(async ({ input: { image, scale, slice, axis }, }) => { | ||
const normalizedImageBounds = [0, 1, 0, 1, 0, 1]; | ||
if (axis === Axis.I) { | ||
normalizedImageBounds[0] = slice; | ||
normalizedImageBounds[1] = slice; | ||
} | ||
else if (axis === Axis.J) { | ||
normalizedImageBounds[2] = slice; | ||
normalizedImageBounds[3] = slice; | ||
} | ||
else if (axis === Axis.K) { | ||
normalizedImageBounds[4] = slice; | ||
normalizedImageBounds[5] = slice; | ||
} | ||
const builtImage = (await image.getImageInImageSpace(scale, normalizedImageBounds)); | ||
if (builtImage.imageType.dimension === 2) { | ||
return { builtImage, sliceIndex: 0 }; | ||
} | ||
// buildImage could be larger than slice if cached so | ||
// find index of slice in builtImage | ||
const indexToWorld = await image.scaleIndexToWorld(scale); | ||
const worldToIndex = mat4.invert(mat4.create(), indexToWorld); | ||
const wholeImageOrigin = [...(await image.scaleOrigin(scale))]; | ||
if (wholeImageOrigin.length == 2) { | ||
wholeImageOrigin[2] = 0; | ||
} | ||
vec3.transformMat4(wholeImageOrigin, wholeImageOrigin, worldToIndex); | ||
const buildImageOrigin = [...builtImage.origin]; | ||
if (buildImageOrigin.length == 2) { | ||
buildImageOrigin[2] = 0; | ||
} | ||
vec3.transformMat4(buildImageOrigin, buildImageOrigin, worldToIndex); | ||
// vector from whole image origin to build image origin | ||
const wholeImageToBuildImageOrigin = vec3.subtract(buildImageOrigin, buildImageOrigin, wholeImageOrigin); | ||
const builtOriginIndex = wholeImageToBuildImageOrigin[axisToIndex[axis]]; | ||
const axisIndexSize = image.scaleInfos[scale].arrayShape.get(axisToDim[axis]) ?? 1; | ||
const fullImageSliceIndex = slice * axisIndexSize; | ||
const sliceIndexInBuildImageFloat = fullImageSliceIndex - builtOriginIndex; | ||
const sliceIndexFloat = Math.round(sliceIndexInBuildImageFloat); | ||
// Math.round goes up with .5, so clamp to max index | ||
const sliceIndex = Math.max(0, Math.min(sliceIndexFloat, builtImage.size[axisToIndex[axis]] - 1)); | ||
return { builtImage, sliceIndex }; | ||
}), | ||
image, | ||
imageBuilder, | ||
findDefaultAxis: fromPromise(async ({ input: { image, scale }, }) => { | ||
@@ -117,3 +63,2 @@ const ijkSpacing = await image.scaleSpacing(scale); | ||
}), | ||
image, | ||
}, | ||
@@ -161,2 +106,3 @@ actions: { | ||
}).createMachine({ | ||
id: 'view2d', | ||
context: () => { | ||
@@ -168,5 +114,5 @@ return { | ||
spawned: {}, | ||
imageBuilders: [], | ||
}; | ||
}, | ||
id: 'view2d', | ||
initial: 'view2d', | ||
@@ -339,36 +285,50 @@ states: { | ||
buildingImage: { | ||
invoke: { | ||
input: ({ context }) => { | ||
const { image, scale, slice, axis } = context; | ||
if (!image) | ||
throw new Error('No image available'); | ||
return { | ||
image, | ||
scale, | ||
slice, | ||
axis, | ||
}; | ||
}, | ||
src: 'imageBuilder', | ||
onDone: { | ||
entry: [ | ||
assign({ | ||
imageBuilders: ({ context: { imageBuilders, scale, slice, axis, image, imageActor, }, spawn, }) => { | ||
if (!image || !imageActor) | ||
throw new Error('No image available'); | ||
const actor = spawn('imageBuilder', { | ||
input: { scale, slice, axis, image, imageActor }, | ||
}); | ||
const cancelCount = imageBuilders.length - IMAGE_BUILDERS_LIMIT; | ||
if (cancelCount > 0) { | ||
const staleActors = imageBuilders.splice(0, cancelCount); | ||
staleActors.forEach((actor) => { | ||
actor.send({ type: 'cancel' }); | ||
}); | ||
} | ||
return [...imageBuilders, actor]; | ||
}, | ||
}), | ||
], | ||
on: { | ||
imageBuilt: { | ||
actions: [ | ||
enqueueActions(({ context, enqueue, event: { output } }) => { | ||
Object.values(context.spawned).forEach((actor) => { | ||
enqueueActions(({ context: { imageBuilders, spawned, imageActor }, enqueue, event: { builtImage, sliceIndex, actor }, }) => { | ||
const actorIndex = imageBuilders.indexOf(actor); | ||
const isStale = actorIndex === -1; | ||
if (isStale) | ||
return; | ||
Object.values(spawned).forEach((actor) => { | ||
enqueue.sendTo(actor, { | ||
type: 'imageBuilt', | ||
image: output.builtImage, | ||
sliceIndex: output.sliceIndex, | ||
image: builtImage, | ||
sliceIndex: sliceIndex, | ||
}); | ||
}); | ||
}), | ||
({ context, event: { output } }) => { | ||
context.imageActor.send({ | ||
enqueue.sendTo(imageActor, { | ||
type: 'builtImage', | ||
builtImage: output.builtImage, | ||
builtImage: builtImage, | ||
}); | ||
}, | ||
const staleActors = imageBuilders.splice(0, actorIndex + 1); | ||
staleActors.forEach((actor) => { | ||
enqueue.sendTo(actor, { type: 'cancel' }); | ||
}); | ||
enqueue.assign({ | ||
imageBuilders: [...imageBuilders], | ||
}); | ||
}), | ||
], | ||
}, | ||
}, | ||
on: { | ||
setScale: { | ||
@@ -375,0 +335,0 @@ actions: [ |
@@ -46,2 +46,39 @@ import { Actor, AnyActorLogic, AnyActorRef } from 'xstate'; | ||
autoCameraReset: boolean; | ||
} & { | ||
imageActor?: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | undefined; | ||
}, CreateChild | { | ||
@@ -103,4 +140,39 @@ type: 'setImage'; | ||
}, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").PromiseSnapshot<BuiltImage, { | ||
[x: string]: import("xstate").ActorRef<import("xstate").MachineSnapshot<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, "active", string, import("xstate").NonReducibleUnknown>, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}> | import("xstate").ActorRef<import("xstate").PromiseSnapshot<BuiltImage, { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
@@ -112,2 +184,67 @@ }>, { | ||
}, { | ||
src: "image"; | ||
logic: import("xstate").StateMachine<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, { | ||
src: string; | ||
logic: import("xstate").UnknownActorLogic; | ||
id: string | undefined; | ||
}, { | ||
type: "updateColorRanges"; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "active", string, MultiscaleSpatialImage, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, { | ||
src: string; | ||
logic: import("xstate").UnknownActorLogic; | ||
id: string | undefined; | ||
}, { | ||
type: "updateColorRanges"; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
} | { | ||
src: "imageBuilder"; | ||
@@ -186,2 +323,67 @@ logic: import("xstate").PromiseActorLogic<BuiltImage, { | ||
}, { | ||
src: "image"; | ||
logic: import("xstate").StateMachine<{ | ||
image: MultiscaleSpatialImage; | ||
dataRanges: import("@itk-viewer/io/types.js").Ranges; | ||
colorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
normalizedColorRanges: import("@itk-viewer/io/types.js").Ranges; | ||
opacityPoints: (readonly [number, number])[][]; | ||
normalizedOpacityPoints: (readonly [number, number])[][]; | ||
}, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, Record<string, AnyActorRef>, { | ||
src: string; | ||
logic: import("xstate").UnknownActorLogic; | ||
id: string | undefined; | ||
}, { | ||
type: "updateColorRanges"; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, "active", string, MultiscaleSpatialImage, import("xstate").NonReducibleUnknown, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, { | ||
type: "getWorker"; | ||
receiver: AnyActorRef; | ||
} | { | ||
type: "builtImage"; | ||
builtImage: BuiltImage; | ||
} | { | ||
type: "normalizedColorRange"; | ||
range: readonly [number, number]; | ||
component: number; | ||
} | { | ||
type: "normalizedOpacityPoints"; | ||
points: [number, number][]; | ||
component: number; | ||
}, { | ||
src: string; | ||
logic: import("xstate").UnknownActorLogic; | ||
id: string | undefined; | ||
}, { | ||
type: "updateColorRanges"; | ||
params: import("xstate").NonReducibleUnknown; | ||
} | { | ||
type: "updateOpacityPoints"; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, { | ||
type: string; | ||
params: import("xstate").NonReducibleUnknown; | ||
}, string, string>>; | ||
id: string | undefined; | ||
} | { | ||
src: "imageBuilder"; | ||
@@ -204,1 +406,2 @@ logic: import("xstate").PromiseActorLogic<BuiltImage, { | ||
export type View3dActor = Actor<typeof view3d>; | ||
//# sourceMappingURL=view-3d.d.ts.map |
import { assign, enqueueActions, fromPromise, setup, } from 'xstate'; | ||
import { image } from './image.js'; | ||
import { reset3d } from './camera.js'; | ||
@@ -14,2 +15,3 @@ const viewContext = { | ||
actors: { | ||
image, | ||
imageBuilder: fromPromise(async ({ input: { image, scale }, }) => { | ||
@@ -58,3 +60,5 @@ const builtImage = await image.getImage(scale); | ||
// @ts-expect-error cannot spawn actor of type that is not in setup() | ||
const child = spawn(logic, { input: { viewport } }); | ||
const child = spawn(logic, { | ||
input: { viewport }, | ||
}); | ||
if (camera) | ||
@@ -77,2 +81,3 @@ child.send({ type: 'setCamera', camera }); | ||
scale: ({ event }) => event.image.coarsestScale, | ||
imageActor: ({ event, spawn }) => spawn('image', { input: event.image }), | ||
}), | ||
@@ -86,2 +91,6 @@ 'resetCameraPose', | ||
}); | ||
enqueue.sendTo(actor, { | ||
type: 'setImageActor', | ||
image: context.imageActor, | ||
}); | ||
}); | ||
@@ -153,2 +162,6 @@ }), | ||
}); | ||
context.imageActor?.send({ | ||
type: 'builtImage', | ||
builtImage: output, | ||
}); | ||
}), | ||
@@ -155,0 +168,0 @@ ], |
@@ -61,1 +61,2 @@ import { ActorRefFrom, AnyActorRef } from 'xstate'; | ||
export {}; | ||
//# sourceMappingURL=viewer.d.ts.map |
@@ -64,1 +64,2 @@ /// <reference types="gl-matrix/index.js" /> | ||
export {}; | ||
//# sourceMappingURL=viewport.d.ts.map |
{ | ||
"name": "@itk-viewer/viewer", | ||
"version": "0.5.3", | ||
"version": "0.6.0", | ||
"description": "Multi-dimensional web-based image, mesh, and point set viewer", | ||
@@ -46,4 +46,4 @@ "type": "module", | ||
"xstate": "5.5.2", | ||
"@itk-viewer/io": "^0.4.2", | ||
"@itk-viewer/utils": "^0.1.3" | ||
"@itk-viewer/utils": "^0.1.3", | ||
"@itk-viewer/io": "^0.4.2" | ||
}, | ||
@@ -50,0 +50,0 @@ "scripts": { |
@@ -1,2 +0,2 @@ | ||
import { ActorRefFrom, assign, setup } from 'xstate'; | ||
import { ActorRefFrom, AnyActorRef, assign, setup } from 'xstate'; | ||
import { | ||
@@ -9,2 +9,6 @@ BuiltImage, | ||
const NORMALIZED_RANGE_DEFAULT = [0.2, 0.8] as const; | ||
const NORMALIZED_OPACITY_POINTS_DEFAULT = [ | ||
[0.2, 0.1] as const, | ||
[0.8, 0.8] as const, | ||
]; | ||
@@ -31,2 +35,24 @@ const computeColorRange = ( | ||
type Point = readonly [number, number]; | ||
const computeNormalizedOpacityPoints = ( | ||
dataRange: ReadonlyRange, | ||
opacityPoints: Point[], | ||
) => { | ||
return opacityPoints.map(([x, y]) => { | ||
const delta = dataRange[1] - dataRange[0]; | ||
return [(x - dataRange[0]) / delta, y]; | ||
}) as Point[]; | ||
}; | ||
const computeOpacityPoints = ( | ||
dataRange: ReadonlyRange, | ||
normalizedPoints: Point[], | ||
) => { | ||
const delta = dataRange[1] - dataRange[0]; | ||
return normalizedPoints.map(([x, y]) => { | ||
return [x * delta + dataRange[0], y] as Point; | ||
}); | ||
}; | ||
type Context = { | ||
@@ -37,2 +63,4 @@ image: MultiscaleSpatialImage; | ||
normalizedColorRanges: Ranges; | ||
opacityPoints: Point[][]; | ||
normalizedOpacityPoints: Point[][]; | ||
}; | ||
@@ -45,2 +73,3 @@ | ||
events: | ||
| { type: 'getWorker'; receiver: AnyActorRef } | ||
| { type: 'builtImage'; builtImage: BuiltImage } | ||
@@ -51,2 +80,7 @@ | { | ||
component: number; | ||
} | ||
| { | ||
type: 'normalizedOpacityPoints'; | ||
points: [number, number][]; | ||
component: number; | ||
}; | ||
@@ -62,5 +96,15 @@ }, | ||
}), | ||
updateOpacityPoints: assign({ | ||
opacityPoints: ({ context: { dataRanges, normalizedOpacityPoints } }) => { | ||
return dataRanges.map((range, component) => { | ||
return computeOpacityPoints( | ||
range, | ||
normalizedOpacityPoints[component], | ||
); | ||
}); | ||
}, | ||
}), | ||
}, | ||
}).createMachine({ | ||
id: 'camera', | ||
id: 'image', | ||
initial: 'active', | ||
@@ -72,2 +116,4 @@ context: ({ input: image }) => ({ | ||
normalizedColorRanges: [], | ||
opacityPoints: [], | ||
normalizedOpacityPoints: [], | ||
}), | ||
@@ -109,4 +155,19 @@ states: { | ||
}, | ||
normalizedOpacityPoints: ({ context }) => { | ||
return context.dataRanges.map((dataRange, component) => { | ||
if (!context.normalizedOpacityPoints[component]) | ||
return NORMALIZED_OPACITY_POINTS_DEFAULT; | ||
// if data range changes | ||
// scale normalizedPoints so opacityPoints doesn't change | ||
const points = context.opacityPoints[component]; | ||
const normalized = computeNormalizedOpacityPoints( | ||
dataRange, | ||
points, | ||
); | ||
return normalized; | ||
}); | ||
}, | ||
}), | ||
'updateColorRanges', | ||
'updateOpacityPoints', | ||
], | ||
@@ -125,2 +186,13 @@ }, | ||
}, | ||
normalizedOpacityPoints: { | ||
actions: [ | ||
assign({ | ||
normalizedOpacityPoints: ({ context, event }) => { | ||
context.normalizedOpacityPoints[event.component] = event.points; | ||
return context.normalizedOpacityPoints; | ||
}, | ||
}), | ||
'updateOpacityPoints', | ||
], | ||
}, | ||
}, | ||
@@ -127,0 +199,0 @@ }, |
@@ -15,5 +15,4 @@ import { | ||
} from '@itk-viewer/io/MultiscaleSpatialImage.js'; | ||
import { ValueOf } from '@itk-viewer/io/types.js'; | ||
import { XYZ, ensuredDims } from '@itk-viewer/io/dimensionUtils.js'; | ||
import { Bounds, getCorners } from '@itk-viewer/utils/bounding-box.js'; | ||
import { getCorners } from '@itk-viewer/utils/bounding-box.js'; | ||
import { CreateChild } from './children.js'; | ||
@@ -23,25 +22,8 @@ import { Camera, reset2d } from './camera.js'; | ||
import { ViewportActor } from './viewport.js'; | ||
import { mat3, mat4, quat, vec3 } from 'gl-matrix'; | ||
import { mat3, quat, vec3 } from 'gl-matrix'; | ||
import { AxisType, Axis } from './slice-utils.js'; | ||
import { ImageBuilder, imageBuilder } from './image-builder.js'; | ||
export const Axis = { | ||
I: 'I', | ||
J: 'J', | ||
K: 'K', | ||
} as const; | ||
const IMAGE_BUILDERS_LIMIT = 4; | ||
export type AxisType = ValueOf<typeof Axis>; | ||
const axisToIndex = { | ||
I: 0, | ||
J: 1, | ||
K: 2, | ||
} as const; | ||
// To MultiScaleImage dimension | ||
const axisToDim = { | ||
I: 'x', | ||
J: 'y', | ||
K: 'z', | ||
} as const; | ||
const toRotation = (direction: Float64Array, axis: AxisType) => { | ||
@@ -96,2 +78,3 @@ const direction3d = ensure3dDirection(direction); | ||
imageActor?: Image; | ||
imageBuilders: Array<ImageBuilder>; | ||
}; | ||
@@ -106,75 +89,13 @@ events: | ||
| { type: 'setCamera'; camera: Camera } | ||
| { | ||
type: 'imageBuilt'; | ||
builtImage: BuiltImage; | ||
sliceIndex: number; | ||
actor: ImageBuilder; | ||
} | ||
| CreateChild; | ||
}, | ||
actors: { | ||
imageBuilder: fromPromise( | ||
async ({ | ||
input: { image, scale, slice, axis }, | ||
}: { | ||
input: { | ||
image: MultiscaleSpatialImage; | ||
scale: number; | ||
slice: number; // 0 to 1 for depth on slice axis | ||
axis: AxisType; | ||
}; | ||
}) => { | ||
const normalizedImageBounds = [0, 1, 0, 1, 0, 1] as Bounds; | ||
if (axis === Axis.I) { | ||
normalizedImageBounds[0] = slice; | ||
normalizedImageBounds[1] = slice; | ||
} else if (axis === Axis.J) { | ||
normalizedImageBounds[2] = slice; | ||
normalizedImageBounds[3] = slice; | ||
} else if (axis === Axis.K) { | ||
normalizedImageBounds[4] = slice; | ||
normalizedImageBounds[5] = slice; | ||
} | ||
const builtImage = (await image.getImageInImageSpace( | ||
scale, | ||
normalizedImageBounds, | ||
)) as BuiltImage; | ||
if (builtImage.imageType.dimension === 2) { | ||
return { builtImage, sliceIndex: 0 }; | ||
} | ||
// buildImage could be larger than slice if cached so | ||
// find index of slice in builtImage | ||
const indexToWorld = await image.scaleIndexToWorld(scale); | ||
const worldToIndex = mat4.invert(mat4.create(), indexToWorld); | ||
const wholeImageOrigin = [...(await image.scaleOrigin(scale))] as vec3; | ||
if (wholeImageOrigin.length == 2) { | ||
wholeImageOrigin[2] = 0; | ||
} | ||
vec3.transformMat4(wholeImageOrigin, wholeImageOrigin, worldToIndex); | ||
const buildImageOrigin = [...builtImage.origin] as vec3; | ||
if (buildImageOrigin.length == 2) { | ||
buildImageOrigin[2] = 0; | ||
} | ||
vec3.transformMat4(buildImageOrigin, buildImageOrigin, worldToIndex); | ||
// vector from whole image origin to build image origin | ||
const wholeImageToBuildImageOrigin = vec3.subtract( | ||
buildImageOrigin, | ||
buildImageOrigin, | ||
wholeImageOrigin, | ||
); | ||
const builtOriginIndex = | ||
wholeImageToBuildImageOrigin[axisToIndex[axis]]; | ||
const axisIndexSize = | ||
image.scaleInfos[scale].arrayShape.get(axisToDim[axis]) ?? 1; | ||
const fullImageSliceIndex = slice * axisIndexSize; | ||
const sliceIndexInBuildImageFloat = | ||
fullImageSliceIndex - builtOriginIndex; | ||
const sliceIndexFloat = Math.round(sliceIndexInBuildImageFloat); | ||
// Math.round goes up with .5, so clamp to max index | ||
const sliceIndex = Math.max( | ||
0, | ||
Math.min(sliceIndexFloat, builtImage.size[axisToIndex[axis]] - 1), | ||
); | ||
return { builtImage, sliceIndex }; | ||
}, | ||
), | ||
image, | ||
imageBuilder, | ||
findDefaultAxis: fromPromise( | ||
@@ -199,3 +120,2 @@ async ({ | ||
), | ||
image, | ||
}, | ||
@@ -249,2 +169,3 @@ actions: { | ||
}).createMachine({ | ||
id: 'view2d', | ||
context: () => { | ||
@@ -256,5 +177,5 @@ return { | ||
spawned: {}, | ||
imageBuilders: [], | ||
}; | ||
}, | ||
id: 'view2d', | ||
initial: 'view2d', | ||
@@ -430,35 +351,68 @@ states: { | ||
buildingImage: { | ||
invoke: { | ||
input: ({ context }) => { | ||
const { image, scale, slice, axis } = context; | ||
if (!image) throw new Error('No image available'); | ||
return { | ||
image, | ||
scale, | ||
slice, | ||
axis, | ||
}; | ||
}, | ||
src: 'imageBuilder', | ||
onDone: { | ||
entry: [ | ||
assign({ | ||
imageBuilders: ({ | ||
context: { | ||
imageBuilders, | ||
scale, | ||
slice, | ||
axis, | ||
image, | ||
imageActor, | ||
}, | ||
spawn, | ||
}) => { | ||
if (!image || !imageActor) | ||
throw new Error('No image available'); | ||
const actor = spawn('imageBuilder', { | ||
input: { scale, slice, axis, image, imageActor }, | ||
}); | ||
const cancelCount = imageBuilders.length - IMAGE_BUILDERS_LIMIT; | ||
if (cancelCount > 0) { | ||
const staleActors = imageBuilders.splice(0, cancelCount); | ||
staleActors.forEach((actor) => { | ||
actor.send({ type: 'cancel' }); | ||
}); | ||
} | ||
return [...imageBuilders, actor]; | ||
}, | ||
}), | ||
], | ||
on: { | ||
imageBuilt: { | ||
actions: [ | ||
enqueueActions(({ context, enqueue, event: { output } }) => { | ||
Object.values(context.spawned).forEach((actor) => { | ||
enqueue.sendTo(actor, { | ||
type: 'imageBuilt', | ||
image: output.builtImage, | ||
sliceIndex: output.sliceIndex, | ||
enqueueActions( | ||
({ | ||
context: { imageBuilders, spawned, imageActor }, | ||
enqueue, | ||
event: { builtImage, sliceIndex, actor }, | ||
}) => { | ||
const actorIndex = imageBuilders.indexOf(actor); | ||
const isStale = actorIndex === -1; | ||
if (isStale) return; | ||
Object.values(spawned).forEach((actor) => { | ||
enqueue.sendTo(actor, { | ||
type: 'imageBuilt', | ||
image: builtImage, | ||
sliceIndex: sliceIndex, | ||
}); | ||
}); | ||
}); | ||
}), | ||
({ context, event: { output } }) => { | ||
context.imageActor!.send({ | ||
type: 'builtImage', | ||
builtImage: output.builtImage, | ||
}); | ||
}, | ||
enqueue.sendTo(imageActor!, { | ||
type: 'builtImage', | ||
builtImage: builtImage, | ||
}); | ||
const staleActors = imageBuilders.splice(0, actorIndex + 1); | ||
staleActors.forEach((actor) => { | ||
enqueue.sendTo(actor, { type: 'cancel' }); | ||
}); | ||
enqueue.assign({ | ||
imageBuilders: [...imageBuilders], | ||
}); | ||
}, | ||
), | ||
], | ||
}, | ||
}, | ||
on: { | ||
setScale: { | ||
@@ -465,0 +419,0 @@ actions: [ |
@@ -14,2 +14,3 @@ import { | ||
} from '@itk-viewer/io/MultiscaleSpatialImage.js'; | ||
import { image, Image } from './image.js'; | ||
import { CreateChild } from './children.js'; | ||
@@ -30,3 +31,5 @@ import { Camera, reset3d } from './camera.js'; | ||
types: {} as { | ||
context: typeof viewContext; | ||
context: typeof viewContext & { | ||
imageActor?: Image; | ||
}; | ||
events: | ||
@@ -43,2 +46,3 @@ | { type: 'setImage'; image: MultiscaleSpatialImage } | ||
actors: { | ||
image, | ||
imageBuilder: fromPromise( | ||
@@ -102,3 +106,5 @@ async ({ | ||
// @ts-expect-error cannot spawn actor of type that is not in setup() | ||
const child = spawn(logic, { input: { viewport } }); | ||
const child = spawn(logic, { | ||
input: { viewport }, | ||
}) as AnyActorRef; | ||
if (camera) child.send({ type: 'setCamera', camera }); | ||
@@ -120,2 +126,4 @@ const id = Object.keys(spawned).length.toString(); | ||
scale: ({ event }) => event.image.coarsestScale, | ||
imageActor: ({ event, spawn }) => | ||
spawn('image', { input: event.image }), | ||
}), | ||
@@ -129,2 +137,6 @@ 'resetCameraPose', | ||
}); | ||
enqueue.sendTo(actor, { | ||
type: 'setImageActor', | ||
image: context.imageActor, | ||
}); | ||
}); | ||
@@ -194,2 +206,6 @@ }), | ||
}); | ||
context.imageActor?.send({ | ||
type: 'builtImage', | ||
builtImage: output, | ||
}); | ||
}), | ||
@@ -196,0 +212,0 @@ ], |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
292224
59
5633