[vtkusers] Adding event observer to a vtkRenderWindowInteractor changing application behavior?

Mark Waligora mark.waligora at gmail.com
Fri Jan 18 10:09:29 EST 2008


The three events, in order, are: 31, 3, and 2.  Based on the vtkCommand
documentation, that is a ModifiedEvent, a DeleteEvent, and an AnyEvent...

The code for my main function is below.  It is basically one of the vtk
medical examples with some extra volume rendering code.  The
VirtualWindowInteractorStyle is a custom interactor class I made.  It has no
functionality implemented, I made it so that I could start an application
loop using iren->Start(), but I don't want the user to have any keyboard or
mouse interaction with the object, so no actual controls are implemented.
Let me know if for some reason you guys need to see that code.

///
/// MAIN.CPP
///

// Create the renderer, the render window, and the interactor. The renderer
// draws into the render window, the interactor enables mouse- and
// keyboard-based interaction with the data within the render window.
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
VirtualWindowInteractorStyle *virtualWindowInteractorStyle =
VirtualWindowInteractorStyle::New();

renWin->AddRenderer(aRenderer);
iren->SetInteractorStyle(virtualWindowInteractorStyle);
iren->CreateTimer(VTKI_TIMER_UPDATE);
iren->SetRenderWindow(renWin);

// The following reader is used to read a series of 2D slices (images)
// that compose the volume. The slice dimensions are set, and the
// pixel spacing. The data Endianness must also be specified. The reader
// usese the FilePrefix in combination with the slice number to construct
// filenames using the format FilePrefix.%d. (In this case the FilePrefix
// is the root name of the file: quarter.)
vtkVolume16Reader *v16 = vtkVolume16Reader::New();
v16->SetDataDimensions(64,64);
v16->SetDataByteOrderToLittleEndian();
v16->SetFilePrefix (argv[1]);
v16->SetImageRange(1, 93);
v16->SetDataSpacing (3.2, 3.2, 1.5);

// An isosurface, or contour value of 500 is known to correspond to the
// skin of the patient. Once generated, a vtkPolyDataNormals filter is
// is used to create normals for smooth surface shading during rendering.
// The triangle stripper is used to create triangle strips from the
// isosurface; these render much faster on may systems.
vtkContourFilter *skinExtractor = vtkContourFilter::New();
skinExtractor->SetInputConnection(v16->GetOutputPort());
skinExtractor->SetValue(0, 500);

vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInputConnection(skinExtractor->GetOutputPort());
skinNormals->SetFeatureAngle(60.0);

vtkStripper *skinStripper = vtkStripper::New();
skinStripper->SetInputConnection(skinNormals->GetOutputPort());

vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInputConnection(skinStripper->GetOutputPort());
skinMapper->ScalarVisibilityOff();

vtkActor *skin = vtkActor::New();
skin->SetMapper(skinMapper);
skin->GetProperty()->SetDiffuseColor(1, .49, .25);
skin->GetProperty()->SetSpecular(.3);
skin->GetProperty()->SetSpecularPower(20);
skin->GetProperty()->SetOpacity(1.0);

// An isosurface, or contour value of 1150 is known to correspond to the
// skin of the patient. Once generated, a vtkPolyDataNormals filter is
// is used to create normals for smooth surface shading during rendering.
// The triangle stripper is used to create triangle strips from the
// isosurface; these render much faster on may systems.
vtkContourFilter *boneExtractor = vtkContourFilter::New();
boneExtractor->SetInputConnection(v16->GetOutputPort());
boneExtractor->SetValue(0, 1150);

vtkPolyDataNormals *boneNormals = vtkPolyDataNormals::New();
boneNormals->SetInputConnection(boneExtractor->GetOutputPort());
boneNormals->SetFeatureAngle(60.0);

vtkStripper *boneStripper = vtkStripper::New();
boneStripper->SetInputConnection(boneNormals->GetOutputPort());

vtkPolyDataMapper *boneMapper = vtkPolyDataMapper::New();
boneMapper->SetInputConnection(boneStripper->GetOutputPort());
boneMapper->ScalarVisibilityOff();

vtkActor *bone = vtkActor::New();
bone->SetMapper(boneMapper);
bone->GetProperty()->SetDiffuseColor(1, 1, .9412);

///
/// Render the volume of the inputted dataset
///
vtkVolumeTextureMapper2D *volumeMapper = vtkVolumeTextureMapper2D::New();
volumeMapper->SetInputConnection(v16->GetOutputPort());

vtkPiecewiseFunction *volumeOpacity = vtkPiecewiseFunction::New();
volumeOpacity->AddPoint(  0.0, 0.0);
volumeOpacity->AddPoint(255.0, 0.1);

vtkColorTransferFunction *volumeColor = vtkColorTransferFunction::New();
volumeColor->AddRGBPoint(64, 1.0, 1.0, 1.0);
volumeColor->AddRGBPoint(128, 0.0, 0.0, 1.0);
volumeColor->AddRGBPoint(196, 0.0, 1.0, 0.0);

vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();
volumeProperty->SetColor(volumeColor);
volumeProperty->SetScalarOpacity(volumeOpacity);

vtkVolume *volume = vtkVolume::New();
volume->SetMapper(volumeMapper);
volume->SetProperty(volumeProperty);

aRenderer->AddProp(volume);

// It is convenient to create an initial view of the data. The FocalPoint
// and Position form a vector direction. Later on (ResetCamera() method)
// this vector is used to position the camera to look at the data in
// this direction.
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp (0, 0, -1);
aCamera->SetPosition (0, 1, 0);
aCamera->SetFocalPoint (0, 0, 0);
aCamera->ComputeViewPlaneNormal();

// Actors are added to the renderer. An initial camera view is created.
// The Dolly() method moves the camera towards the FocalPoint,
// thereby enlarging the image.
aRenderer->AddActor(skin);
aRenderer->AddActor(bone);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera ();

aCamera->Dolly(1.5);

// Set a background color for the renderer and set the size of the
// render window (expressed in pixels).
aRenderer->SetBackground(0,0,0);

renWin->SetSize(1280, 1024);

// Note that when camera movement occurs (as it does in the Dolly()
// method), the clipping planes often need adjusting. Clipping planes
// consist of two planes: near and far along the view direction. The
// near plane clips out objects in front of the plane; the far plane
// clips out objects behind the plane. This way only what is drawn
// between the planes is actually rendered.
aRenderer->ResetCameraClippingRange ();

///
/// Add an update callback for our application
///
vtkUpdateCallback* onUpdate = vtkUpdateCallback::New();
iren->AddObserver(vtkCommand::AnyEvent, onUpdate);

// Set a background color for the renderer and set the size of the
// render window (expressed in pixels).
iren->Initialize();
iren->Start();

/// Deletion Code Excluded for this email...

And now here is the code for my observer:

///
/// OBSERVER CLASS
///

class vtkUpdateCallback : public vtkCommand
{
    public:
        static vtkUpdateCallback *New()
        {
            return new vtkUpdateCallback;
        }

        void Delete()
        {
            delete this;
        }

        virtual void Execute(vtkObject *caller, unsigned long eventId, void*
arguments)
        {
            printf("Update\n");
        }
};

On Jan 18, 2008 6:15 AM, David Cole <david.cole at kitware.com> wrote:

> Is the 3rd event, by any chance, the "ExitEvent"?
>
> If not, what are the 3 events you do receive?
>
> What does the rest of your code in main look like? Do you have your own
> event loop, or do you call Start on the RenderWindowInteractor?
>
> Post some more info and somebody will help you get to the bottom of
> this...
>
>
> David
>
>
> On 1/17/08, Mark Waligora < mark.waligora at gmail.com> wrote:
>
> > Hey all,
> > I'm having a problem with setting up an event handler.  I create a class
> > called UpdateCallback which inherits from vtkCommand.  I override the
> > Execute function from vtkCommand.  My Execute function simply contains a
> > print statement for the time being.
> >
> > In my main function, I create an instance of my class and add it as an
> > observer to my vtkRenderWindowInteractor for the "AnyEvent" event.
> >
> > UpdateCallback* onUpdate = UpdateCallback::New();
> > iren->AddObserver(vtkCommand::AnyEvent, onUpdate);
> >
> > When I do this, my program prints the statement in my Execute function 3
> > times, and then exits.  If I comment out the line of code that adds my
> > UpdateCallback as an observer:
> >
> > // iren->AddObserver(vtkCommand::AnyEvent, onUpdate);
> >
> > then the program runs as normal until you close it.  I've searched the
> > mailing list, googled the problem, and I've read through the code in
> > vtkCommand and vtkObject trying to see if adding an observer somehow changes
> > the behavior of the event handling.  From what I can tell, any observer
> > class should get called on the appropriate event, so adding my observer
> > shouldn't create any additional side effects besides what the code in my
> > observer does.  Can anyone tell me what might be going on?
> >
> > Thanks a bunch in advance everyone!
> >
> > -Mark
> >
> > _______________________________________________
> > This is the private VTK discussion list.
> > Please keep messages on-topic. Check the 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/20080118/a2b87903/attachment.htm>


More information about the vtkusers mailing list