Skip to content

ENH: Add vtkScatteredBSplineTransform - #76

Open
lassoan wants to merge 1 commit into
Slicer:mainfrom
lassoan:scattered-bspline-transform
Open

lassoan wants to merge 1 commit into
Slicer:mainfrom
lassoan:scattered-bspline-transform

Conversation

@lassoan

@lassoan lassoan commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Adds vtkScatteredBSplineTransform, a cubic B-spline transform fitted to displacement vectors given at the points of any vtkPointSet (surface mesh, volumetric mesh, or point cloud). Once fitted, the transform can be evaluated and inverted anywhere in space, not only at the input points.

This is needed to show a displacement field that is only known at the points of a mesh, for example in Slicer slice views. vtkProbeFilter can only interpolate inside the cells of a volumetric mesh, so it returns nothing for a surface mesh or a point cloud.

Method

  • Fitting: coefficients are computed with the multilevel B-spline approximation (MBA) of Lee, Wolberg and Shin (IEEE TVCG 1997). A coarse control point lattice is fitted first, then the lattice is repeatedly refined (halving the spacing) and fitted to the remaining residual. Refinement stops when the largest residual at the input points is below Tolerance, or when MaximumNumberOfLevels or MinimumControlPointSpacing is reached.
  • Basis: the implementation follows the algorithm in the ScatteredTransform extension, specialized to 3D. It writes the coefficients directly into the vtkImageData that vtkBSplineTransform uses, with no reindexing, because VTK and MBA use the same cubic B-spline basis functions in the same order.
  • Base class: it derives from vtkOrientedBSplineTransform, so the result can be stored in a vtkMRMLBSplineTransformNode and written to an ITK transform file.

Options

  • DisplacementArrayName: the point data array to fit. If it is not set, the active vectors are used.
  • ControlPointSpacing: the spacing of the coarsest lattice. The default is 1/10 of the fitting domain.
  • MinimumControlPointSpacing, MaximumNumberOfLevels, Tolerance: these limit refinement.
  • UseLinearApproximation: seeds the coarsest level with a least-squares linear fit, so the transform extrapolates the overall trend outside the sampled region instead of flattening out.
  • GridBounds / AutomaticGridBounds: the fitting domain. By default it is the bounds of the input points.
  • GetResidual() and GetNumberOfLevels(): report the accuracy and depth of the last fit.

The transform refits automatically when the input point set is modified. Invalid input is reported, and the transform is then left as identity.

Testing

vtkScatteredBSplineTransformTest1 uses a smooth analytic warp as ground truth on a surface mesh and on a hexahedral volumetric mesh. It checks:

  • the fit at the mesh points, and that the reported residual matches the actual error;
  • the approximation between the mesh points;
  • the inverse transform;
  • fallback to the active vectors;
  • linear approximation;
  • explicit and minimum control point spacing;
  • explicit fitting bounds;
  • refitting when the mesh is modified;
  • DeepCopy / MakeTransform;
  • handling of invalid input.

The test passes in a Slicer Release build on Windows (MSVC 2022, VTK 9.6.2).

🤖 Generated with Claude Code

Add a cubic b-spline transform that is fitted to displacements defined at
the points of a surface or volumetric mesh (any vtkPointSet, such as
vtkPolyData or vtkUnstructuredGrid) with a 3-component displacement vector
as point data.

The coefficients are computed with the multilevel b-spline approximation
(MBA) algorithm of Lee, Wolberg and Shin: a coarse control point lattice is
fitted first, then the lattice is repeatedly refined and fitted to the
remaining residual, until the residual drops below the requested tolerance
or a refinement limit is reached. All three displacement components are
fitted into a single lattice, because the b-spline weights only depend on
the position and so the three components share the same denominator.

The implementation is based on the algorithm used by the ScatteredTransform
extension (https://github.com/Sunderlandkyl/ScatteredTransform), but it is
specialized to 3D and writes the coefficients directly into the vtkImageData
that vtkBSplineTransform consumes. VTK and MBA use the same cubic b-spline
basis functions in the same order, therefore the control point coefficients
transfer without reindexing.

The class derives from vtkOrientedBSplineTransform, so the fitted transform
can be stored in a vtkMRMLBSplineTransformNode and written to an ITK
transform file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant