[vtkusers] Difficulty keeping volume within vtkBoxWidget

Jérôme jerome.velut at gmail.com
Fri Dec 11 04:14:48 EST 2009


Hi,
there is a thread that deals with this problem: look for "Creating an
ImageData from the bounds of a PolyData".

I posted a class that outputs a volume cropped from an input volume and the
bounding box of the polydata. Maybe you can use the box widget to produce
the cube polydata and use it as bounds. This process will then appears as a
simple VTK pipeline in your code.

HTH
Jerome


2009/12/10 Zamir Khan <zkhan at modusmed.com>

> I think I have found a solution to my problem and, although it does not
> feel elegant (it's actually rather ugly), I am posting back to the mailing
> list for archival purposes, in case someone else is trying to accomplish a
> similar goal.
>
> To recap: I have a volume, which I want to allow the user to interactively
> crop. So I used a vtkBoxWidget to bound the volume and was intending to use
> the bounds of the box as the cropping planes. The simplistic approach in my
> first post did not work, in retrospect because I was operating on a false
> assumption: that when I associated the volume actor and box widget with each
> other, they would be anchored about the center of the box widget. The reason
> I assumed this was that when I rotated the box, I saw that the volume
> rotated with it, seemingly about the center of the box. However, further
> investigation showed me that my objects were actually anchored to another
> position and that, when certain actions happened to the box (scaling,
> translation induced by scaling of the individual box faces), if I wanted to
> see my desired behaviour, I needed to re-position the volume to maintain a
> constant positioning between the center of the box and the volume.
>
> I have attached the callback code I used to accomplish this with some
> comments. This is the callback that gets invoked on the boxWidget's
> InteractionEvt. The objects and helper methods are hopefully named
> reasonably enough to figure out what they are/do (e.g. I call my
> vtkBoxWidget a croppingBox). It's not a pretty solution and I'm
> half-expecting a response with a much easier and more elegant way to do
> this. If so, I would love to be enlightened and, regardless, it's been a
> good learning experience =)
>
> Zamir Khan wrote:
>
>> I should add: even purely scaling the box to a smaller size, with the
>> right mouse button, will cause the volume to leave the box. It seems
>> that they are not centered on the same point. I have verified that the
>> volume remains in place - both position and origin remain at (0,0,0) -
>> is it possible that the box's scaling is not centered on (0,0,0), even
>> though it was bounded to the volume through SetProp3D()?
>>
>> Zamir Khan wrote:
>> > Thanks for the response. I would like to continue to allow rotation,
>> > could I perhaps apply an inverse of the box transform to its bounds and
>> > then use that for cropping? Also, the reason that translation fails, I
>> > believe, is that when you grow or shrink one of the faces of the box,
>> > this appears to be a scaling & translation operation and, perhaps
>> > because I am always negating the scaling operation in my transform on
>> > the volume, by moving the faces of the box back and forth, I can get the
>> > volume to leave the bounds of the box.
>> >
>> > I will keep trying some different solutions (unfortunately disabling
>> > rotation is not an acceptable one for my application), but if anyone has
>> > accomplished this task before (with or without a vtkBoxWidget!) -
>> > example code would be much appreciated.
>> >
>> > Thanks,
>> > Zamir
>> >
>> > Karthik Krishnan wrote:
>> > > On Mon, Dec 7, 2009 at 5:26 PM, Zamir Khan <zkhan at modusmed.com>
>> <mailto:zkhan at modusmed.com%3E>
>> > <mailto:zkhan at modusmed.com%3E> <mailto:zkhan at modusmed.com%3E%3E>
>> > > <mailto:zkhan at modusmed.com%3E> <mailto:zkhan at modusmed.com%3E%3E>
>> <mailto:zkhan at modusmed.com%3E%3E> <mailto:zkhan at modusmed.com%3E%3E%3E>
>> wrote:
>> > > > Hi all,
>> > > >
>> > > > I have been attempting to use a vtkBoxWidget for what appears to be
>> > > a fairly
>> > > > common task: bounding and cropping a volume. My end goal is to have
>> > > the all
>> > > > user actions (translation, rotation) on the box be passed onto the
>> > > volume
>> > > > within, except for scaling. When the box is scaled, I need the
>> > > volume within
>> > > > to remain the same size, but be cropped by the planes of the box.
>> > > >
>> > > > I have been attempting to accomplish this with the following code
>> (C#
>> > > > snippets, using Activiz.NET personal edition):
>> > > >
>> > > > // this callback gets called on the vtkBoxWidget's (outlineBox)
>> > > > InteractionEvt
>> > > > private void transformCallback( vtkObject sender,
>> > > vtkObjectEventArgs e
>> > > > )
>> > > > {
>> > > > vtkTransform boxTransform = vtkTransform.New();
>> > > > outlineBox.GetTransform( boxTransform );
>> > > >
>> > > > // remove the scaling from the transform before passing it on
>> > > > double[] scale = boxTransform.GetScale();
>> > > > boxTransform.Scale( 1.0 / scale[ 0 ], 1.0 / scale[ 1 ], 1.0 /
>> > > > scale[ 2 ] );
>> > > > volume.SetUserTransform( ( vtkLinearTransform )
>> > > boxTransform );
>> > > >
>> > > > // crop the volume
>> > > > vtkPlanes planes = vtkPlanes.New();
>> > > > outlineBox.GetPlanes(planes);
>> > > > double[] bounds = planes.GetPoints().GetBounds();
>> > > > volumeMapper.SetCroppingRegionPlanes( bounds[ 0 ], bounds[ 1 ],
>> > > bounds[ 2 ],
>> > > > bounds[ 3 ], bounds[ 4 ], bounds[ 5 ] ); }
>> > > >
>> > > > Now, a few things go wrong with this (probably over-simplified)
>> > > > implementation.
>> > > >
>> > > > 1) The volume does not stay within the box for all manipulations.
>> > I have
>> > > > tried various approaches to remedy this, including not allowing
>> > > translation
>> > > > on the box (which is not critical to my application), but even so, I
>> > > have
>> > > > not been able to come up with a solution that guarantees that the
>> > volume
>> > > > stays inside the box.
>> > >
>> > > See answer to (2) below..
>> > >
>> > >
>> > > >
>> > > > 2) The cropping does not always occur on the expected plane. When I
>> > > take a
>> > > > particular plane on the box and shrink the box w.r.t. that plane,
>> > > especially
>> > > > after having rotated the box, the volume will be cropped, but on
>> it's
>> > > > corresponding plane. It appears that the "bounds" coordinates of
>> > the box
>> > > > that I am passing to the mapper are not in agreement with the volume
>> > > - am I
>> > > > missing a transformation?
>> > >
>> > > The bounds specified via
>> > > volumeMapper.SetCroppingRegionPlanes()
>> > >
>> > > specify an axis-aligned aligned bounding box. You mention below that
>> > > they are out of sync after rotating the box, which is natural, since
>> > > the box widget no longer remains axis-aligned. Disable rotation on it.
>> > >
>> > > Translation should have worked just fine.. Perhaps a bug in your
>> code..
>> > >
>> ------------------------------------------------------------------------
>> >
>> > _______________________________________________
>> > Powered by www.kitware.com
>> >
>> > Visit other Kitware open-source projects at
>> > http://www.kitware.com/opensource/opensource.html
>> >
>> > Please keep messages on-topic and check the VTK FAQ at:
>> > http://www.vtk.org/Wiki/VTK_FAQ
>> >
>> > Follow this link to subscribe/unsubscribe:
>> > http://www.vtk.org/mailman/listinfo/vtkusers
>> > ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Please keep messages on-topic and check the VTK FAQ at:
>> http://www.vtk.org/Wiki/VTK_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.vtk.org/mailman/listinfo/vtkusers
>> ------------------------------------------------------------------------
>>
>>
>
>        private void transformCallback( vtkObject sender, vtkObjectEventArgs
> e )
>        {
>            if( pipelineExists )
>            {
>                // Get the transform currently being applied to the cropping
> box
>                vtkTransform boxTransform = vtkTransform.New();
>                croppingBox.GetTransform( boxTransform );
>
>                // Get the planes that define the faces of the cropping box
>                vtkPlanes planes = vtkPlanes.New();
>                croppingBox.GetPlanes( planes );
>
>                // Apply the inverse transform to the planes, so we have
> axis-aligned planes
>                vtkPoints transformedPoints = vtkPoints.New();
>                boxTransform.GetInverse().TransformPoints(
> planes.GetPoints(), transformedPoints );
>
>                // Remember the cropping box center before scaling occurred,
> in order to keep all other scene
>                // objects anchored to the cropping box center
>                double[] preScalingBoxCenter = GetBoundsCenter(
> transformedPoints.GetBounds() );
>
>                // Now get the scaled the bounds of the cropping box, this
> moves the center of the box since
>                // scaling is anchored to the origin, not the center
>                vtkTransform scalingTransform = vtkTransform.New();
>
>                double[] scale = boxTransform.GetScale();
>                scalingTransform.Scale( scale[ 0 ], scale[ 1 ], scale[ 2 ]
> );
>
>                vtkPoints scaledPoints = vtkPoints.New();
>                scalingTransform.TransformPoints( transformedPoints,
> scaledPoints );
>
>                double[] bounds = scaledPoints.GetBounds();
>
>                // calculate the post-scaling center of the cropping box
>                double[] postScalingBoxCenter = GetBoundsCenter( bounds );
>
>                // on the first invocation only, store the vector relating
> the position of the volume
>                // to the center of the cropping box. We want to maintain
> this relation at all times.
>                if( null == vectorFromBoxCenter )
>                {
>                    vectorFromBoxCenter = new double[ 3 ];
>                    vectorFromBoxCenter[ 0 ] = volume.GetPosition()[ 0 ] -
> postScalingBoxCenter[ 0 ];
>                    vectorFromBoxCenter[ 1 ] = volume.GetPosition()[ 1 ] -
> postScalingBoxCenter[ 1 ];
>                    vectorFromBoxCenter[ 2 ] = volume.GetPosition()[ 2 ] -
> postScalingBoxCenter[ 2 ];
>                }
>
>                // This transform will be passed on to the other scene
> objects, but scaling should be removed
>                // since only the cropping box should be allowed to change
> size.
>                boxTransform.Scale( 1.0 / scale[ 0 ], 1.0 / scale[ 1 ], 1.0
> / scale[ 2 ] );
>
>                // Re-position the other scene objects relative to the new
> cropping box center
>                SetScenePosition( postScalingBoxCenter[ 0 ] +
> vectorFromBoxCenter[ 0 ], postScalingBoxCenter[ 1 ] + vectorFromBoxCenter[ 1
> ], postScalingBoxCenter[ 2 ] + vectorFromBoxCenter[ 2 ] );
>                SetSceneOrigin( postScalingBoxCenter[ 0 ] +
> vectorFromBoxCenter[ 0 ], postScalingBoxCenter[ 1 ] + vectorFromBoxCenter[ 1
> ], postScalingBoxCenter[ 2 ] + vectorFromBoxCenter[ 2 ] );
>
>                // Adjust the cropping box bounds relative to the current
> cropping box center
>                bounds[ 0 ] += ( preScalingBoxCenter[ 0 ] -
> postScalingBoxCenter[ 0 ] );
>                bounds[ 1 ] += ( preScalingBoxCenter[ 0 ] -
> postScalingBoxCenter[ 0 ] );
>                bounds[ 2 ] += ( preScalingBoxCenter[ 1 ] -
> postScalingBoxCenter[ 1 ] );
>                bounds[ 3 ] += ( preScalingBoxCenter[ 1 ] -
> postScalingBoxCenter[ 1 ] );
>                bounds[ 4 ] += ( preScalingBoxCenter[ 2 ] -
> postScalingBoxCenter[ 2 ] );
>                bounds[ 5 ] += ( preScalingBoxCenter[ 2 ] -
> postScalingBoxCenter[ 2 ] );
>
>                // Set the new cropping planes based on the adjusted bounds
>                volumeMapper.SetCroppingRegionPlanes( bounds[ 0 ], bounds[ 1
> ], bounds[ 2 ], bounds[ 3 ], bounds[ 4 ], bounds[ 5 ] );
>
>                // Apply the cropping box transform (that has had scaling
> removed) to the other scene members
>                TransformScene( boxTransform );
>            }
>        }
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the VTK FAQ at:
> http://www.vtk.org/Wiki/VTK_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtkusers
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20091211/dad13e3c/attachment.htm>


More information about the vtkusers mailing list