[vtkusers] need desperately any help with interactor and MFC
Renaud Isabelle
renauisa at yahoo.fr
Mon Aug 22 16:34:19 EDT 2005
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 interactors 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 le ici !
---------------------------------
Appel audio GRATUIT partout dans le monde avec le nouveau Yahoo! Messenger
Téléchargez le ici !
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20050822/0085637d/attachment.htm>
More information about the vtkusers
mailing list