[vtkusers] need desperately any help with interactor and MFC

John Platt jcplatt at lineone.net
Mon Aug 22 19:51:21 EDT 2005


Hi Isabelle,

 

I am not sure where you are calling Pipeline(). Perhaps you could try
all your interactor stuff in your CView’s OnInitialUpdate() – assuming
it needs to be done only once.

 

  interactor->SetRenderWindow(m_RenderWindow);

  interactor->SetInteractorStyle(NULL);

  interactor->SetInstallMessageProc(false);

  interactor->Initialize();

 

  // Change the size of the VTK window to match the client area of the
View.

  CRect rect;

  GetClientRect( &rect );

  interactor->UpdateSize( rect.right-rect.left, rect.bottom-rect.top );


 

Also, can you check if you are getting LBDown in your WindowProc(). 

 

HTH

 

John.

 

-----Original Message-----
From: Renaud Isabelle [mailto:renauisa at yahoo.fr] 
Sent: 22 August 2005 21:34
To: John Platt
Cc: vtkusers at vtk.org
Subject: RE: [vtkusers] need desperately any help with interactor and
MFC

 

Hi John,

 

Thanks for having replied. 

 

- First of all, sure that I am very interested in your vtkGlyph2DMapper;
I think this is very convenient to use and is exactly what I am looking
for. 

 

- Then, my actual work is inspiring from the example
LiverTumorSegmentation application and I think that maybe I don't really
need to use vtkPointPicker but just handling LeftButtonPressEvent event
instead. Indeed, I took a look on the Pick() method of this class and it
calls SetDisplayPoint(), DisplayToWorld() and GetWorldPoint() methods as
I was already doing in my own class. 

 

- So, this is what is done for now: as in LiverTumorSegmentation, I have
2 classes: one for MFC handling CView and the other for viewing slices
vtkSliceViewer:

 

void CView::Pipeline()
{
 viewer.SetInput(image); //vtkSliceViewer viewer

 viewer.SetInteractor( interactor ); 
 interactor->SetInstallMessageProc(false);
 interactor->Initialize();

}

 

LRESULT CView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_LBUTTONDOWN)

{

  if ( this->interactor->GetInitialized() )
  {
   return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam,
this->interactor);
  }

 }

else 
 return CFormView::WindowProc(message, wParam, lParam);
}

 

the other class vtkSliceviewer:

 

void vtkSliceViewer::SetInteractor( vtkRenderWindowInteractor *
interactor )
{
  interactor->SetRenderWindow(m_RenderWindow);

  interactor->SetInteractorStyle(NULL);

 

 //create a callback for the left mouseclick
  MyInteractorCallback* m_pInteractorCallback =
MyInteractorCallback::New();
  m_pInteractorCallback->SetImageSliceViewer(this); 
  interactor->AddObserver( vtkCommand::LeftButtonPressEvent,
m_pInteractorCallback);
}

 

class MyInteractorCallback : public vtkCommand
{
public:
 static MyInteractorCallback *New() { return new MyInteractorCallback;}
 
    virtual void Execute(vtkObject *caller, unsigned long eventId, void
*callData)
    {
  vtkWin32RenderWindowInteractor  *interactor =
reinterpret_cast<vtkWin32RenderWindowInteractor *>(caller);
        int x = interactor->GetEventPosition()[0];
        int y = interactor->GetEventPosition()[1];
  m_viewer->SelectPoint(x,y);
    }
 
 void SetImageSliceViewer(vtkSliceViewer* viewer){m_viewer = viewer;}

private:
    MyInteractorCallback(){m_viewer = NULL;}
    vtkSliceViewer* m_viewer; 
};

 

void vtkSliceViewer::SelectPoint( int x, int y )
{
  TRACE("ds SelectPoint\n"); //check if my observer is called

        --> displayed only when point clicked is outside the render
window!!!!!!!!

 

 // Convert display point to world point

  double world_point[4];
  m_Renderer->SetDisplayPoint( x, y, 0 );
  m_Renderer->DisplayToWorld();
  m_Renderer->GetWorldPoint( world_point );

  double realz = m_SliceNum * spacing[2] + origin[2];
  world_point[2] = realz;

  //mark point clicked on viewer
  this->SelectPoint(world_point[0], world_point[1], world_point[2]);
}


- But I am really confused with something strange: my renderwindow is
just a part of the MFC window (CView). Yet, when I pressed left button
mouse in the window class, SelectPoint() is called only when my clicked
point is not in the render window. I checked out if my interactor size
was set to correct dimensions and it is actually the case. But I can't
figure out why my function is called only when I clicked outside the
render window. 

 

Any idea???

 

Isabelle

 


John Platt <jcplatt at lineone.net> a écrit :

Hi Isabelle,

 

As far as I can see, the pick events are fired by the Pick() method of
the interactor’s picker. If you want to observe these events, you must
add the observers to the picker, not the interactor. You must also
arrange for the Pick() method to be called.

 

As a start, in the check for LeftButtonPressEvent, call Pick() with the
current mouse event position and then get the point id -

 

         int x = interactor->GetEventPosition()[0];

         int y = interactor->GetEventPosition()[1];

         vtkPointPicker* picker = interactor->GetPicker(); 

         picker->Pick( (double)x, (double)y, 0, renderer );

         int pointId = picker->GetPointId();

 

and print the point Id using the TRACE macro. If you cannot get the
LeftButtonPressEvent, see the recent thread on “handle right mouse
click”.

 

I have drawn various 2D shapes, by first creating a polydata object, and
then, as each point is clicked, add the point as a vertex to the
polydata. The polydata is set as input to vtkGlyph2DMapper (very similar
to vtkTextMapper). This mapper takes vtkGlyphSource2D as a source and
copies the specified shape (diamond, circle, square etc.) to each of the
points in the polydata. The mapper then feeds a single vtkActor2D.
Something like 


 

   vtkGlyphSource2D* vtkGlyphSource = vtkGlyphSource2D::New();

   vtkGlyphSource->SetGlyphTypeToCircle();

   m_vtkGlyphMapper = vtkGlyph2DMapper::New();

   m_vtkGlyphMapper->SetInput( m_vtkInputPolyData );

   m_vtkGlyphMapper->SetSource( vtkGlyphSource->GetOutput() );

   vtkGlyphSource->Delete();

   m_vtkGlyphActor = vtkActor2D::New();

   m_vtkGlyphActor->SetMapper( m_vtkGlyphMapper );

 

I can let you have the mapper if you think it would be helpful.

 

John.

 

-----Original Message-----
From: vtkusers-bounces+jcplatt=lineone.net at vtk.org
[mailto:vtkusers-bounces+jcplatt=lineone.net at vtk.org] On Behalf Of
Renaud Isabelle
Sent: 18 August 2005 16:32
To: vtkusers at public.kitware.com
Subject: [vtkusers] help with interactor and MFC

 

Hi guys, 

 

I have to implement user interaction with my renderwindow in MFC: 

 

user picks points on the displayed medical image and notices them with
spheres. I saw that I have to use vtkHandleMessage2 with
vtkWin32RenderWindowInteractor to handle a left button mouse click and
interactor->AddObserver() to call a function to handle it. 

 

But now, I see that vtkPointPicker exists and that is doing the same
thing. I am really a bit confused with all the options. Here is what I
did:

 

  interactor->SetRenderWindow(m_RenderWindow);

  interactor->SetInteractorStyle(NULL);

 

  vtkPointPicker *picker = vtkPointPicker::New();

  interactor->SetPicker(picker);

  

  vtkMyCallback* how_execute = vtkMyCallback::New();
  interactor->AddObserver( vtkCommand::LeftButtonPressEvent, how_execute
);
  interactor->AddObserver( vtkCommand::EndPickEvent,  how_execute);
  

  interactor->SetInstallMessageProc(false);
  interactor->Initialize();

 

LRESULT CMyView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
 // TODO: Add your specialized code here and/or call the base class
 switch ( message )
 {
 case WM_LBUTTONDOWN:
  if ( this->interactor->GetInitialized() )
  {
   return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam,
this->interactor);
  }
  break;
 }
 return CFormView::WindowProc(message, wParam, lParam);
}

 

class vtkMyCallback : public vtkCommand
{

public:

  static vtkMyCallback *New()  { return new vtkMyCallback; }
  
  virtual void Execute(vtkObject *caller, unsigned long eventId, void*)
    {
      vtkRenderWindowInteractor* interactor =
reinterpret_cast<vtkRenderWindowInteractor*>(caller);

      

     if(eventId == vtkCommand::LeftButtonPressEvent)
     {  
          int point[2];
          interactor->GetEventPosition(point);
          m_viewer->SelectPoint(point[0],point[1]);
   }

 

   if(eventId == vtkCommand::EndPickEvent)
   {  
          vtkPointPicker* picker = (vtkPointPicker*)
interactor->GetPicker();
          if(picker->GetPointId() != -1)
         {
            float* position = picker->GetPickPosition();

            m_sphereActor->SetPosition(position);
         }
   }
}

 

- This seems not to work. I think that I have to choose between handling
one of the event: LeftButtonPressEvent or EndPickEvent. But I don't know
what is the best option. Could someone tell me what is best? 

 

- Btw, my purpose is to add a circle on each point that user picked. Do
I have to handle a array of vtkSphereSource to display so many spheres?

 

Thanks for replyiong, guys,

 

Isabelle


  _____  


Appel audio GRATUIT partout dans le monde avec le nouveau Yahoo!
Messenger
Téléchargez
<http://us.rd.yahoo.com/messenger/mail_taglines/default/*http:/fr.messen
ger.yahoo.com>  le ici ! 

  _____  

Appel audio GRATUIT partout dans le monde avec le nouveau Yahoo!
Messenger
Téléchargez
<http://us.rd.yahoo.com/messenger/mail_taglines/default/*http:/fr.messen
ger.yahoo.com>  le ici ! 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20050823/df761711/attachment.htm>


More information about the vtkusers mailing list