I am working with registration and multiple vtkObject’s all inheriting from vtkDataSet. Currently, I add orientations as field data. It is really heavy to transform data explicitly and I would like to have a property on all data. Locally, I have added this to my own clone of vtkDataSet.
Most often, I end up using this transform as the user transform of an actor. Would it be an idea to add a transform to vtkDataSet in general? I know that you have already added an orientation to vtkImageDataSet.
Well, vtkDataSet is abstract. I mean, it doesn’t have all possible geometric attributes (e.g. vertex normal vectors, face normal vectors, etc.) found in its concrete implementations. A transform on vtkDataSet would have an ill-defined behavior.
Sorry, my bad. It is of course, vtkPointSet, then I have it available on vtkStructuredGrid and vtkPolyData etc. Of course, then it won’t be available on vtkRectilinearGrid, which I sometimes use due to its smaller memory footprint than vtkStructuredGrid.
Well, please, check out the vtkPointSetAlgorithm family of point set algorithms: VTK: vtkPointSetAlgorithm Class Reference . There exists quite a number of algorithms for point sets. One likely suits your need.
I am working with multiple registrations (real-time) and for all vtkPolyData, vtkStructuredGrid, I interpret their positions always as the result of transforming them from a local reference frame to a global reference frame. When registering, I only update their transformation. As far as I am aware of, only the plain vanilla point-to-point ICP is available in VTK so obviously you have not have this need yet. More specifically, I work on registration algorithms for vtkPointSet, where I for vtkPolyData exploit if normals are defined.
Thanks for replying. For now, I will check if field data has a entry “UserTransform” and update this when I register.
In 3D Slicer, we opted to add a higher-level container class (vtkMRMLNode and its vtkMRMLTransformableNode) that can store a VTK data object (vtkImageData, vtkPolyData, vtkUnstructedGrid, vtkGeneralTransform, point set, curve, plane, etc.) and reference a parent transform. This transform can be a composite, inverse, and/or non-linear transform. The design is quite simple, clean, compatible with filter and transform pipelines, and works well for real-time display. This design might not be optimal for all use cases, but it is definitely an option if we want to keep VTK simple.
If we are ready to make VTK more complex the I would go beyond just allowing specifying translation/rotation for vtkDataSet. Instead, scene graph support could be added to VTK, and there any transform could be used to transform a branch of the tree. It should be designed so that it could replace the current scene graph that is implemented in VTK-based applications (at least in ParaView and 3D Slicer).
That is an option - to wrap many filters using a container - not a fan. Working on a Robust ICP with a symmetric cost function capable of registering a source to a target, where either can be any vtkPointSet. Normals will be computed by other means if they are absent. I think the cleanest and minimal solution for me is to keep a “local-to-global” 4x4 matrix as part of the field data and when present they will be used. Also, the option to perform implicit/explicit registration, where in the case of implicit registration only the ‘local-to-global’ matrix of the source will be updated.
Only supporting linear transforms would be a very significant limitation. What are you going to do when in the next phase of your project you’ll need to go beyond linear transforms and you have to write a registration algorithm that produces a warping transform?
Maybe a better solution would be to derive vtkAbstractTransform from vtkDataSet so that they can propagate between filter connections.
@dgobbi Do you know why VTK filters cannot provide transforms on their output ports (that could be pipelined to other filters input connections)?
VTK transforms aren’t derived from vtkDataObject and therefore can’t be pipelined via VTK algorithms. Sometime around 2001 there was some discussion about making either vtkTransform or vtkMatrix4x4 into a vtkDataObject but nothing came out of it. All the developers had other priorities.
I ended up implementing a vtkPointSetRegistrationTransform inheriting from vtkAlgorithm without any connections. It has a SetSource and SetTarget method and provide functionality for finding correspondences and normal vectors using SMPTools. For this, I have implemented a threadsafe vtkImplicitPolyDataIntersection. The reason why I need an interface is that I have a real-time pipeline and I would to be able to re-use the logic for the real-time aspects and be able to change the registration algorithm.
My plan is to implement ICP (point-to-point), ICP (point-to-plane), ICP (bi-directional point-to-plane). All of them robust and using Gauss-Newton.
Thank you for your insight @dgobbi - it is good to know that there is no fundamental design issue with unifying transform pipelines with filter pipelines. Somebody would just need the resources to implement it.
Currently, in 3D Slicer we manually update transforms whenever any transform input changes. This is very simple, but not optimal in the sense that the transform may be recomputed more frequently than needed (inputs may change more frequently than we need the output for rendering or analysis). However, this is not a strong enough motivation to invest a lot of time into improving the VTK pipeline infrastructure.