Resample to Hyper Tree Grid: cell version
vtkResampleToHyperTreeGrid
currently only supports point data input. The way the filter is implemented really fits this kind of data. One can dump each new input in a vtkAbstractAccumulator
either by summing a function of the input (using a vtkArithmeticAccumulator
), by sorting each point in an array to extract a quantile (using a vtkQuantileAccumulator
), or by incrementing by one bins, for the entropy for example (using a vtkBinsAccumulator
).
Then classes based on vtkAbstractArrayMeasurement
can take the output of those vtkAbstractAccumulator
and produce the desired measure.
I refactored the code a bit in !3625 (merged), which should be merged soon. The naming in the previous paragraph matches this new implementation.
However, obviously, cell data cannot directly fit in this framework. Let's see how we can modify the paradigm to make it happen. Let's only consider vtkCell3D
for the moment. The challenge is to make the resampling filter a unified framework for points and volumetric cells. If one has that, generalizing to 2D cells or 1D cells should be a piece of cake.
The most straightforward way to make this filter perform the same action as with the point-wise version is to consider points as volumetric objects, which is possible using 3D Dirac distributions \delta_{p_i}
, centered at point p_i
, such that
\left\{
\begin{array}{l}
\delta_{p_i}((x,y,z) = \not \ p_i) = 0\\
\int\int\int \delta_{p_i}(x,y,z)dxdydz = 1
\end{array}
\right.
If one can translate the point-wise computation to a computation dealing with volumes, it is very straightforward to feed any volumetric cell as inputs instead. Let us note \delta_i
such that if the input is formed of points, \delta_i=\delta_{p_i}
, and if the input is a volumetric cell c_i
, \delta_i(p) = 1
if p\in c_i
, and \delta_i(p)=0
elsewhere.
Let us note \omega_i(C)
the intersection volume between a hyper tree cell C
and the point / cell i
. By definition:
\omega_i(C) =\int\int\int_{(x,y,z)\in C} \delta_i(x,y,z)dxdydz
Thus, for example, what is actually calculated for vtkArithmeticAccumulator
, is the integral over the cells of a function f
of Dirac distributions scaled by their associated value \alpha_i
, weighted by \omega_i(C)
. In other words, this accumulated value \mathcal A(c)
has the expression:
\mathcal A(C) = \sum_i \omega_i(C) f(\alpha_i)
What is incremented in the bin for v_i
of vtkBinsAccumulator
is the intersection volume between those Diracs and the current hyper tree cell. Thus, given a regular discretization (b_j)_{j\in\mathbb Z}
of the space of values, the bin \mathcal B_{[b_j, b_{j+1}[}(C)
follows:
\mathcal B_{[b_j, b_{j+1}[}(C) = \sum_{\alpha_i\in[b_j,b_{j+1}[} \omega_i(C)
Similarly this intersection volume is what is used in to compute the quantile as a width of each element. The quantile \mathcal Q_x(C)
is then defined as:
\begin{array}{ll}
\mathcal Q_x(C) =& \text{argmin}_{\alpha_i} \left(x - \frac{\sum_{\alpha_j \le \alpha_i}\omega_j(C)}{\sum_j \omega_j(C)} \ge 0\right)
\end{array}
In addition to this, it should be possible to resample vtkPolyData
with cells of different inner dimension. This can be dealt with by picturing the co-dimensions of those cells to be Diracs. One would also need to add a parameter to scale the influence of points / lines / polygons / polyhedron that could be hidden in the advanced parameters in the GUI. If one plays with such scale factors while dealing with cells of the same inner dimension, the result of the resampling would not be altered.
So basically the goal in this update is to compute the intersected volume between 3D cells / hyper tree grid cells, which would be set as the weight \omega_i(c)
. The version for 2D or 1D cells will respectively be the intersected area / length of the cell and the hyper tree grid cell.
@patchett2002 @ethan.stam Are we in the same page? @demarle FYI