125 lines
3.5 KiB
Plaintext
125 lines
3.5 KiB
Plaintext
import { vec3 } from 'gl-matrix'
|
|
|
|
/**
|
|
* For each point in the image (If boundsIJK is not provided, otherwise, for each
|
|
* point in the provided bounding box), It runs the provided callback IF the point
|
|
* passes the provided criteria to be inside the shape (which is defined by the
|
|
* provided pointInShapeFn)
|
|
*
|
|
* @param imageData - The image data object.
|
|
* @param dimensions - The dimensions of the image.
|
|
* @param pointInShapeFn - A function that takes a point in LPS space and returns
|
|
* true if the point is in the shape and false if it is not.
|
|
* @param callback - A function that will be called for
|
|
* every point in the shape.
|
|
* @param boundsIJK - The bounds of the volume in IJK coordinates.
|
|
*/
|
|
function pointInShapeCallback(
|
|
imageData,
|
|
pointInShapeFn,
|
|
callback,
|
|
boundsIJK
|
|
) {
|
|
let iMin, iMax, jMin, jMax, kMin, kMax
|
|
|
|
let scalarData
|
|
|
|
// if getScalarData is a method on imageData
|
|
if ((imageData).getScalarData) {
|
|
scalarData = (ImageData).getScalarData()
|
|
} else {
|
|
scalarData = (imageData)
|
|
.getPointData()
|
|
.getScalars()
|
|
.getData()
|
|
}
|
|
|
|
const dimensions = imageData.getDimensions()
|
|
|
|
if (!boundsIJK) {
|
|
iMin = 0
|
|
iMax = dimensions[0]
|
|
jMin = 0
|
|
jMax = dimensions[1]
|
|
kMin = 0
|
|
kMax = dimensions[2]
|
|
} else {
|
|
[[iMin, iMax], [jMin, jMax], [kMin, kMax]] = boundsIJK
|
|
}
|
|
|
|
const start = vec3.fromValues(iMin, jMin, kMin)
|
|
|
|
const direction = imageData.getDirection()
|
|
const rowCosines = direction.slice(0, 3)
|
|
const columnCosines = direction.slice(3, 6)
|
|
const scanAxisNormal = direction.slice(6, 9)
|
|
|
|
const spacing = imageData.getSpacing()
|
|
const [rowSpacing, columnSpacing, scanAxisSpacing] = spacing
|
|
|
|
// @ts-ignore will be fixed in vtk-master
|
|
const worldPosStart = imageData.indexToWorld(start)
|
|
|
|
const rowStep = vec3.fromValues(
|
|
rowCosines[0] * rowSpacing,
|
|
rowCosines[1] * rowSpacing,
|
|
rowCosines[2] * rowSpacing
|
|
)
|
|
|
|
const columnStep = vec3.fromValues(
|
|
columnCosines[0] * columnSpacing,
|
|
columnCosines[1] * columnSpacing,
|
|
columnCosines[2] * columnSpacing
|
|
)
|
|
|
|
const scanAxisStep = vec3.fromValues(
|
|
scanAxisNormal[0] * scanAxisSpacing,
|
|
scanAxisNormal[1] * scanAxisSpacing,
|
|
scanAxisNormal[2] * scanAxisSpacing
|
|
)
|
|
|
|
const yMultiple = dimensions[0]
|
|
const zMultiple = dimensions[0] * dimensions[1]
|
|
|
|
const pointsInShape = []
|
|
for (let k = kMin; k <= kMax; k++) {
|
|
for (let j = jMin; j <= jMax; j++) {
|
|
for (let i = iMin; i <= iMax; i++) {
|
|
const pointIJK = [i, j, k]
|
|
const dI = i - iMin
|
|
const dJ = j - jMin
|
|
const dK = k - kMin
|
|
|
|
const startWorld = worldPosStart
|
|
|
|
const pointLPS = [
|
|
startWorld[0] +
|
|
dI * rowStep[0] +
|
|
dJ * columnStep[0] +
|
|
dK * scanAxisStep[0],
|
|
startWorld[1] +
|
|
dI * rowStep[1] +
|
|
dJ * columnStep[1] +
|
|
dK * scanAxisStep[1],
|
|
startWorld[2] +
|
|
dI * rowStep[2] +
|
|
dJ * columnStep[2] +
|
|
dK * scanAxisStep[2]
|
|
]
|
|
|
|
if (pointInShapeFn(pointLPS, pointIJK)) {
|
|
const index = k * zMultiple + j * yMultiple + i
|
|
const value = scalarData[index]
|
|
|
|
pointsInShape.push({ value, index, pointIJK, pointLPS })
|
|
if (callback !== null) {
|
|
callback({ value, index, pointIJK, pointLPS })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return pointsInShape
|
|
}
|
|
export { pointInShapeCallback }
|