Improvements to the transform pipeline (3 vtkTransform derived classes).

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Improvements to the transform pipeline (3 vtkTransform derived classes).

drjustice

Hi everyone.


I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 


Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.



GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------


I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  



PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.


This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline


In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.


xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor


In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*


That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?



SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------


As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.


Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).


In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)



ADVANTAGES

-------------------


With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.


In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]


Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 







PROBLEM (2/3)

---------------------


With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).


But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)


In other words, I want: 


widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.


While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?



SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------


This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)


In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.








PROBLEM (3/3)

--------------------


Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].


Indeed, that concatenation is (roughly) the equivalent of: 


Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].


In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.


What I want instead is consider the concatenation of the scale, orientation, and transformation :


Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].




SOLUTION (3/3) -- Introducing vtkMutableTransform
---------------------------------------------------------------------

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 





CONCLUSION: 
--------------------

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.


 

Let me know if there is interest in me submitting these 3 classes.

Regards
Patrick Bergeron



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

Andras Lasso

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 

 


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers




--

+1 919 869 8849


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

David Gobbi
Hi Andras, Patrick,

I'd just like to add that vtkTransform itself supports dynamic concatenation, it isn't necessary to use vtkGeneralTransform unless you want to concatenate nonlinear transformations.

Here's an example (unfortunately it was auto-converted to Python from Tcl so it's poorly formatted):

 - David



On Tue, Jun 5, 2018 at 9:06 AM, Andras Lasso <[hidden email]> wrote:

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

drjustice
In reply to this post by Andras Lasso

Ha. Look at that. I had been searching and I somehow missed the general transform (it took me a 2nd look to even see beyond “SetInput”, and I can call “Concatenate” to add any number of inputs.   I’ll update my code to test that.

 

This does indeed seem to replace the purpose of my vtkDualInputTransform.

 

However:

 

For problem 2, I still need to make an Actor-to-Transform adapter, unless there is something I don’t see?

 

For problem 3, I’m not bypassing a transform, I’m muting parts of a single transform (eg: the scale, orientation or translation portions). Not sure if this is what you had meant?

 

 

Patrick.

 

 

 

 

 

From: vtk-developers <[hidden email]> on behalf of Andras Lasso <[hidden email]>
Date: Tuesday, June 5, 2018 at 11:06 AM
To: "[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <
[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "
[hidden email]" <[hidden email]>


Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 

 


_______________________________________________
Powered by
www.kitware.com

Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html

Search the list archives at:
http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers





--

+1 919 869 8849


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

drjustice
In reply to this post by David Gobbi

Ok, yes, I just saw that too.

 

If you can do transform mixes using concatenations, why is there an input ?

 

 

From: vtk-developers <[hidden email]> on behalf of David Gobbi <[hidden email]>
Date: Tuesday, June 5, 2018 at 11:13 AM
To: Andras Lasso <[hidden email]>
Cc: "[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

 

I'd just like to add that vtkTransform itself supports dynamic concatenation, it isn't necessary to use vtkGeneralTransform unless you want to concatenate nonlinear transformations.

 

Here's an example (unfortunately it was auto-converted to Python from Tcl so it's poorly formatted):

 

 - David

 

 

 

On Tue, Jun 5, 2018 at 9:06 AM, Andras Lasso <[hidden email]> wrote:

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <
[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "
[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

David Gobbi
When I contributed the "transform concatenation" feature to VTK (long, long ago) there was some discussion about how it should be done.  I wanted to have just concatenation, and didn't really see much need for SetInput().

Ken Martin thought SetInput() was more consistent with VTK's design (at least I think it was him, this was a long time ago).

Lisa Avila thought it would be better for transforms (or perhaps matrices) to be lightweight data objects, and to add special filter classes for dynamic transform concatenation, rather than to have the dynamic features built into the transforms themselves.

The final design was a compromise: both Concatenate(vtkTransform *) and SetInput(vtkTransform *) were added.  In retrospect, I think Lisa's suggestion of having an explicit set of "transform filters" would have resulted in a cleaner design.  The concatenation feature adds a fair bit of weight and complexity to vtkTransform even though it's a feature that people rarely use.

 - David
 

On Tue, Jun 5, 2018 at 9:25 AM, Patrick Bergeron <[hidden email]> wrote:

Ok, yes, I just saw that too.

 

If you can do transform mixes using concatenations, why is there an input ?

 

 

From: vtk-developers <[hidden email]> on behalf of David Gobbi <[hidden email]>
Date: Tuesday, June 5, 2018 at 11:13 AM
To: Andras Lasso <[hidden email]>
Cc: "[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

 

I'd just like to add that vtkTransform itself supports dynamic concatenation, it isn't necessary to use vtkGeneralTransform unless you want to concatenate nonlinear transformations.

 

Here's an example (unfortunately it was auto-converted to Python from Tcl so it's poorly formatted):

 

 - David

 

 

 

On Tue, Jun 5, 2018 at 9:06 AM, Andras Lasso <[hidden email]> wrote:

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <
[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "
[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

drjustice
In reply to this post by David Gobbi

And, here’s another thing that could be done to vtkTransform to eliminate my actor-to-transform adapter class. It would be super easy to do, and be backwards compatible.

 

Currently: vtkTransform::SetInput(vtkAbstractTransform*)

Suggestion: vtkTransform::SetInput(vtkObject*)

 

vtkTransform::InternalUpdate()

If (this->Input)

{

     vtkAbstractTransform *transform = vtkAbstractTransform::SafeDownCast(this->Input);

     vtkProp3D *prop3D = vtkProp3D::SafeDownCast(this->Input);

 

     If (transform != nullptr)

                this->Matrix->DeepCopy(transform->GetMatrix());

     else if (prop3D != nullptr)

              this->Matrix->DeepCopy(prop3D->GetMatrix());

     else

              vtkWarningMacro(“InternalUpdate: Bad object type passed as input”);

 

     …

     …

}

 

This way, actors can directly be an input into the transformation pipeline, the same way as is a normal transform.

 

 

 

 

 

From: vtk-developers <[hidden email]> on behalf of David Gobbi <[hidden email]>
Date: Tuesday, June 5, 2018 at 11:13 AM
To: Andras Lasso <[hidden email]>
Cc: "[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

 

I'd just like to add that vtkTransform itself supports dynamic concatenation, it isn't necessary to use vtkGeneralTransform unless you want to concatenate nonlinear transformations.

 

Here's an example (unfortunately it was auto-converted to Python from Tcl so it's poorly formatted):

 

 - David

 

 

 

On Tue, Jun 5, 2018 at 9:06 AM, Andras Lasso <[hidden email]> wrote:

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <
[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "
[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

David Gobbi
Hi Patrick,

That's not possible since vtkTransform is in "Common" while vtkProp3D is in "Rendering".  It's expected that "Rendering" should depend on "Common", but not vice-versa.

An adapter is better.  It allows a Prop3D to be used anywhere in VTK that a transform can be used, without requiring modifications to any other VTK classes.

 - David


On Tue, Jun 5, 2018 at 9:52 AM, Patrick Bergeron <[hidden email]> wrote:

And, here’s another thing that could be done to vtkTransform to eliminate my actor-to-transform adapter class. It would be super easy to do, and be backwards compatible.

 

Currently: vtkTransform::SetInput(vtkAbstractTransform*)

Suggestion: vtkTransform::SetInput(vtkObject*)

 

vtkTransform::InternalUpdate()

If (this->Input)

{

     vtkAbstractTransform *transform = vtkAbstractTransform::SafeDownCast(this->Input);

     vtkProp3D *prop3D = vtkProp3D::SafeDownCast(this->Input);

 

     If (transform != nullptr)

                this->Matrix->DeepCopy(transform->GetMatrix());

     else if (prop3D != nullptr)

              this->Matrix->DeepCopy(prop3D->GetMatrix());

     else

              vtkWarningMacro(“InternalUpdate: Bad object type passed as input”);

 

     …

     …

}

 

This way, actors can directly be an input into the transformation pipeline, the same way as is a normal transform.

 

 

 

 

 

From: vtk-developers <[hidden email]> on behalf of David Gobbi <[hidden email]>
Date: Tuesday, June 5, 2018 at 11:13 AM
To: Andras Lasso <[hidden email]>
Cc: "[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

 

I'd just like to add that vtkTransform itself supports dynamic concatenation, it isn't necessary to use vtkGeneralTransform unless you want to concatenate nonlinear transformations.

 

Here's an example (unfortunately it was auto-converted to Python from Tcl so it's poorly formatted):

 

 - David

 

 

 

On Tue, Jun 5, 2018 at 9:06 AM, Andras Lasso <[hidden email]> wrote:

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <
[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "
[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Improvements to the transform pipeline (3 vtkTransform derived classes).

drjustice

Ok, too bad. Then the question remains, is the VTK group interested in

 

  • My vtkProp3D-to-vtkTransform adapter class.
  • My mutable vtkTransform class (mute part of the transform, let the rest flow through)

 

 

From: David Gobbi <[hidden email]>
Date: Tuesday, June 5, 2018 at 12:06 PM
To: Patrick Bergeron <[hidden email]>
Cc: Andras Lasso <[hidden email]>, "[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

Hi Patrick,

 

That's not possible since vtkTransform is in "Common" while vtkProp3D is in "Rendering".  It's expected that "Rendering" should depend on "Common", but not vice-versa.

 

An adapter is better.  It allows a Prop3D to be used anywhere in VTK that a transform can be used, without requiring modifications to any other VTK classes.

 

 - David

 

 

On Tue, Jun 5, 2018 at 9:52 AM, Patrick Bergeron <[hidden email]> wrote:

And, here’s another thing that could be done to vtkTransform to eliminate my actor-to-transform adapter class. It would be super easy to do, and be backwards compatible.

 

Currently: vtkTransform::SetInput(vtkAbstractTransform*)

Suggestion: vtkTransform::SetInput(vtkObject*)

 

vtkTransform::InternalUpdate()

If (this->Input)

{

     vtkAbstractTransform *transform = vtkAbstractTransform::SafeDownCast(this->Input);

     vtkProp3D *prop3D = vtkProp3D::SafeDownCast(this->Input);

 

     If (transform != nullptr)

                this->Matrix->DeepCopy(transform->GetMatrix());

     else if (prop3D != nullptr)

              this->Matrix->DeepCopy(prop3D->GetMatrix());

     else

              vtkWarningMacro(“InternalUpdate: Bad object type passed as input”);

 

     …

     …

}

 

This way, actors can directly be an input into the transformation pipeline, the same way as is a normal transform.

 

 

 

 

 

From: vtk-developers <[hidden email]> on behalf of David Gobbi <[hidden email]>
Date: Tuesday, June 5, 2018 at 11:13 AM
To: Andras Lasso <
[hidden email]>
Cc: "
[hidden email]" <[hidden email]>
Subject: Re: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).

 

 

I'd just like to add that vtkTransform itself supports dynamic concatenation, it isn't necessary to use vtkGeneralTransform unless you want to concatenate nonlinear transformations.

 

Here's an example (unfortunately it was auto-converted to Python from Tcl so it's poorly formatted):

 

 - David

 

 

 

On Tue, Jun 5, 2018 at 9:06 AM, Andras Lasso <[hidden email]> wrote:

Hi Patrick,

 

I think these problems are already solved, since you can dynamically concatenate any number of transforms in any combinations (including inverting them) using vtkGeneralTransform.

 

Regarding your solution proposed for “problem” 3: Ability to temporarily bypass a transform without changing the pipeline would be a feature that I would find useful. Some warping transforms already have scale parameter for enabling/disabling (or slightly emphasizing or de-emphasizing) a transformation, which comes very handy for visualizing the effect of the transformation. This feature could be generalized and moved to vtkAbstractTransform class.

 

Andras

 

---------- Forwarded message ----------
From: Patrick Bergeron <
[hidden email]>
Date: Tue, Jun 5, 2018 at 10:33 AM
Subject: [vtk-developers] Improvements to the transform pipeline (3 vtkTransform derived classes).
To: "
[hidden email]" <[hidden email]>

Hi everyone.

 

I've been using VTK for a bit now, and I've made a few improvements I'd like to contribute to the community. 

 

Before I do, however, I'd like to know if there is interest in me doing so before I go through the hassles of submission.

 

 

GENERAL PROBLEM STATEMENT  (MOTIVATION)

---------------------------------------------------------------

 

I have a list of objects that I'd like to transform using a single widget. Widgets take a single vtkProp3D as target. For (multiple) reasons beyond the scope of this discussion, I couldn't use vtkAssembly to target my multiple actors. Plus, I wanted each actor to transform according to their local reference frame, not the reference frame of the vtkAssembly.  

 

 

PROBLEM (1/3)

---------------------

vtkTransform can take as input another vtkTransform, to which it concatenates its own SRT values,  its output being it the concatenation of the input transform and itself.

 

This is useful and allows for multiple scenarios, including this common pattern of parent-child hierarchical chain of transforms, as is shown in this Robot-Arm example. 

https://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/TransformPipeline

 

In the example above, 3 transforms are chained together, and   

xform1 --to--> xform2's input ,   xform2's output -- to --> xform3's input.

 

xform1 is set as the user transform of the root actor

xform2 is set as the user transform of the mid actor

xform3 is set as the user transform of the leaf actor

 

In other words, the *parent's transform* is inherited, and each actor's *local transformation* is controlled by calling the normal functions, such as TranslateX, RotateY, etc, and when concatenated provides the actor's *global transform*

 

That's all fine, as long as you want to, or can, control each of the local transform directly.  But what if you'd like to also control the *local transform* via another transformation pipeline?  The vtkTransform's input is already taken by the parent transform, were would I plug the local transform's input?

 

 

SOLUTION (1/3) --  Introducing vtkDualInputTransform

------------------------------------------------------------------------

 

As its name implies, vtkDualInput transform adds a second input (Input2) to the standard vtkTransform.

 

Whereas the vtkTransform's output was :   GetMatrix() = [INPUT][MYSELF],  

Then vtkDualInputTransform's putput is : GetMatrix() = [INPUT][INPUT2] [MYSELF]

(with adaptations wrt Pre-Post multiply flag).

 

In vtkDualInputTransform, both Input1 and Input2 can be muted, so that they are skipped, just as if there was no input connected.  (It's like closing a gate)

 

 

ADVANTAGES

-------------------

 

With the vtkDualInputTransform, you can create complex chains of transforms that allows for direct control of different parts of the transform multiple actors from a single source.

 

In my case, Input1 is the parent transform, Input2 is the local transform, and  I leave the internals alone (set to Identity).

The result is thus GetMatrix() = [INPUT][INPUT2][IDENTITY]  = [INPUT][INPUT2]

 

Using this pattern, I have 100 actors driven by different pipelines, yet I can affect all of them at once by changing a common transformation pipeline that is plugged into the second input. 

 

 

 

 

 

 

PROBLEM (2/3)

---------------------

 

With the vtkDualInputTransform in place, which I could plug into an Actor's UserTransform, I could now effect the global transform using 2 transformation pipelines (its parent tranform, and its local transform).

 

But, what if I wanted to transform my actors by setting affecting their local transforms using another actor as the driver? 

(why? because a widget targets a prop/actor, and I want the changes to the targetted actor's transformation to propagate down to a transformation pipeline to affect other actors)

 

In other words, I want: 

 

widget -> actorA's transform -> input of vtkTransform --> input of vtkTransform --> input of vtkTansform --> input of actorB, actorC, actorD (etc)'s UserTransform.

 

While we can do actorA's GetMatrix() (which is the concat of its input and own pos/ori/scale/origin/etc), there is unfortunately, there is no way to do actor->GetTransform() (since it might get pushed/popped from the stack, it might not always be valid, might disappear etc).   So how do I drive a transform pipeline from an actor?

 

 

SOLUTION (2/3) --  Introducing vtkProp3DTransformAdapter

-------------------------------------------------------------------------------

 

This is another derivative of vtkTransform. It has a SetProp3D method, which serves the same purpose as the vtkTransform's input.

(in fact, vtkProp3DTransformAdapter's input is not used, and a warning is issued if it is)

 

In vtkProp3DTransformAdapter, in the InternalUpdate method, instead of calling Input->GetMatrix(), we simply call prop3D->GetMatrix(), which ensures is always valid.

 

 

 

 

 

 

 

PROBLEM (3/3)

--------------------

 

Finally, there's a catch: I want to affect multiple actors's global transform but control the local transform, but there's a catch when doing [INPUT][INPUT2].

 

Indeed, that concatenation is (roughly) the equivalent of: 

 

Result = [IN_scl] x [IN_ori] x [IN_trs] x [IN2_scl] x [IN2_ori] x [IN2_trs].

 

In other words, by the time we multiply IN2, IN's translation is already considered, so scale and rotation of the 2nd input will have their transformation center set to IN's translation, which a problem.

 

What I want instead is consider the concatenation of the scale, orientation, and transformation :

 

Result = [IN_scl] x [IN2_scl]   x   [IN_ori] x [IN2_ori]   x   [IN_trs] x [IN2_trs].

 

 

 

SOLUTION (3/3) -- Introducing vtkMutableTransform

---------------------------------------------------------------------

 

Unfortunately, I did not find a proper name for this one, as "mutable" can imply "changeable".   But I meant it to mean that you could "mute" portions of the transform. 

 

The goal of this derived class is that you feed it a transform, and out comes the same transform without the muted portions. For example, the transform's output is the same as the input, with scaling, orientation, or translation stripped out. 

 

 

 

 

 

CONCLUSION: 

--------------------

 

Using the proper combination of the 3 vtkTransform derivatives described above, and chained together in the proper order, you can make a transformation graph that is fully automated and controllable from any point or any source in the transform pipeline.

 

 

 

Let me know if there is interest in me submitting these 3 classes.

 

Regards

Patrick Bergeron

 

 


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers