7 #include "visuVTKAdaptor/SProbeCursor.hpp" 9 #include <fwCom/Slot.hpp> 10 #include <fwCom/Slot.hxx> 11 #include <fwCom/Slots.hpp> 12 #include <fwCom/Slots.hxx> 14 #include <fwData/Image.hpp> 15 #include <fwData/Integer.hpp> 16 #include <fwData/TransferFunction.hpp> 18 #include <fwDataTools/fieldHelper/Image.hpp> 19 #include <fwDataTools/fieldHelper/MedicalImageHelpers.hpp> 20 #include <fwDataTools/helper/Image.hpp> 22 #include <fwRenderVTK/vtk/Helpers.hpp> 24 #include <fwServices/macros.hpp> 26 #include <boost/format.hpp> 28 #include <vtkAbstractPropPicker.h> 30 #include <vtkCellArray.h> 31 #include <vtkCellData.h> 32 #include <vtkCommand.h> 33 #include <vtkInteractorStyleImage.h> 34 #include <vtkPolyData.h> 35 #include <vtkPolyDataMapper.h> 36 #include <vtkProperty.h> 37 #include <vtkRenderWindowInteractor.h> 38 #include <vtkTextActor.h> 39 #include <vtkTextMapper.h> 40 #include <vtkTextProperty.h> 41 #include <vtkTransform.h> 45 #define START_PROBE_EVENT vtkCommand::LeftButtonPressEvent 46 #define STOP_PROBE_EVENT vtkCommand::LeftButtonReleaseEvent 64 m_mouseMoveObserved(
false)
66 this->PassiveObserverOff();
75 virtual void Execute( vtkObject* ,
unsigned long eventId,
void*)
77 assert(m_priority >= 0);
78 SLM_ASSERT(
"m_adaptor not instanced", m_adaptor);
79 SLM_ASSERT(
"m_picker not instanced", m_picker);
80 if ( m_mouseMoveObserved || !m_adaptor->getInteractor()->GetShiftKey() )
82 if ( eventId == vtkCommand::MouseMoveEvent )
84 SLM_ASSERT(
"m_mouseMoveObserved not instanced", m_mouseMoveObserved);
87 else if ( eventId == START_PROBE_EVENT)
89 assert(m_mouseMoveObserved ==
false );
90 if ( pickSomething() )
92 m_mouseMoveObserved =
true;
94 m_adaptor->setVisibility(
true);
95 m_adaptor->startSProbeCursor();
97 m_adaptor->getInteractor()->AddObserver(vtkCommand::MouseMoveEvent,
this, m_priority);
100 else if ( eventId == STOP_PROBE_EVENT && m_mouseMoveObserved)
102 SLM_ASSERT(
"m_mouseMoveObserved not instanced", m_mouseMoveObserved);
103 m_adaptor->setVisibility(
false);
104 m_adaptor->getInteractor()->RemoveObservers(vtkCommand::MouseMoveEvent,
this);
105 m_mouseMoveObserved =
false;
117 m_adaptor->getInteractor()->GetEventPosition(x, y);
122 return m_picker->Pick( display, m_adaptor->getRenderer() );
129 double world[3] = {-1, 0, 0};
130 if ( pickSomething() )
132 ::fwRenderVTK::vtk::getNearestPickedPosition(m_picker, m_adaptor->getRenderer(), world);
133 OSLM_TRACE(
"PICK" << world[0] <<
" ," << world[1] <<
" ," << world[2] );
134 m_adaptor->updateView( world);
136 m_adaptor->updateView(world);
141 void setAdaptor( SProbeCursor::sptr adaptor)
148 void setPicker( vtkAbstractPropPicker* adaptor)
155 void setPriority(
float priority )
157 m_priority = priority;
161 SProbeCursor::sptr m_adaptor;
162 vtkAbstractPropPicker* m_picker;
165 bool m_mouseMoveObserved;
169 const ::fwCom::Slots::SlotKeyType SProbeCursor::s_UPDATE_SLICE_INDEX_SLOT =
"updateSliceIndex";
171 static const ::fwServices::IService::KeyType s_IMAGE_INOUT =
"image";
175 SProbeCursor::SProbeCursor() noexcept :
177 m_vtkObserver(
nullptr),
178 m_textActor(vtkActor2D::New()),
179 m_textMapper(vtkTextMapper::New()),
180 m_cursorPolyData( vtkPolyData::New() ),
181 m_cursorMapper(vtkPolyDataMapper::New() ),
182 m_cursorActor(vtkActor::New() )
184 newSlot(s_UPDATE_SLICE_INDEX_SLOT, &SProbeCursor::updateSliceIndex,
this);
189 SProbeCursor::~SProbeCursor() noexcept
191 m_textMapper->Delete();
192 m_textActor->Delete();
194 m_cursorActor->Delete();
195 m_cursorActor =
nullptr;
196 m_cursorMapper->Delete();
197 m_cursorMapper =
nullptr;
198 m_cursorPolyData->Delete();
202 void SProbeCursor::setVisibility(
bool visibility )
204 m_textActor->SetVisibility(visibility);
205 m_cursorActor->SetVisibility(visibility);
206 this->setVtkPipelineModified();
207 this->requestRender();
214 this->configureParams();
219 void SProbeCursor::buildTextActor()
221 vtkTextProperty* textprop = m_textMapper->GetTextProperty();
222 textprop->SetColor(1, 1, 1);
223 textprop->SetFontFamilyToArial();
224 textprop->SetFontSize(20);
226 textprop->ItalicOff();
227 textprop->ShadowOn();
228 textprop->SetJustificationToLeft();
229 textprop->SetVerticalJustificationToTop();
231 m_textActor->SetMapper( m_textMapper );
233 vtkCoordinate* coord = m_textActor->GetPositionCoordinate();
234 coord->SetCoordinateSystemToNormalizedViewport();
235 coord->SetValue(.01, .98);
236 this->setVtkPipelineModified();
245 this->buildTextActor();
246 this->addToRenderer(m_textActor );
248 this->buildPolyData();
249 m_cursorMapper->SetInputData( m_cursorPolyData );
250 m_cursorActor->SetMapper(m_cursorMapper);
251 m_cursorActor->GetProperty()->SetColor(1, 0, 0);
252 m_cursorActor->GetProperty()->SetOpacity(0.9);
253 if(!this->getTransformId().empty())
255 m_cursorActor->SetUserTransform(this->getTransform());
257 this->addToRenderer(m_cursorActor);
260 observer->setAdaptor( SProbeCursor::dynamicCast(this->getSptr()) );
261 observer->setPicker(this->getPicker());
262 observer->setPriority( m_priority );
264 m_vtkObserver = observer;
266 this->getInteractor()->AddObserver(START_PROBE_EVENT, m_vtkObserver, m_priority);
267 this->getInteractor()->AddObserver(STOP_PROBE_EVENT, m_vtkObserver, m_priority);
276 ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
279 this->updateImageInfos(image);
280 this->setVisibility(
false);
281 this->requestRender();
288 this->getInteractor()->RemoveObservers(START_PROBE_EVENT, m_vtkObserver);
289 this->getInteractor()->RemoveObservers(STOP_PROBE_EVENT, m_vtkObserver);
290 m_vtkObserver->Delete();
291 m_vtkObserver =
nullptr;
292 this->removeAllPropFromRenderer();
293 this->requestRender();
298 void SProbeCursor::updateSliceIndex(
int axial,
int frontal,
int sagittal)
300 m_axialIndex->value() = axial;
301 m_frontalIndex->value() = frontal;
302 m_sagittalIndex->value() = sagittal;
307 void SProbeCursor::startSProbeCursor( )
313 void SProbeCursor::updateView(
double world[3] )
315 ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
319 this->worldToImageSliceIndex( world, index );
320 OSLM_TRACE(
"index=" << index[0] <<
"," << index[1] <<
"," << index[2] <<
"," );
324 if ( world[0] < image->getOrigin()[0] || world[1] < image->getOrigin()[1] || world[2] < image->getOrigin()[2] ||
325 index[0] < 0 || index[1] < 0 || index[2] < 0 ||
326 index[0] >=
static_cast<int>(image->getSize()[0]) ||
327 index[1] >= static_cast<int>(image->getSize()[1]) ||
328 index[2] >= static_cast<int>(image->getSize()[2])
331 txt =
"(---,---,---)";
332 m_textMapper->SetInput(txt.c_str());
337 const size_t x =
static_cast<size_t>(index[0]);
338 const size_t y =
static_cast<size_t>(index[1]);
339 const size_t z =
static_cast<size_t>(index[2]);
341 txt = (::boost::format(
"(% 4li,% 4li, % 4li) : %s ") % index[0] % index[1] % index[2] % greyLevel ).str();
343 m_textMapper->SetInput(txt.c_str());
346 double worldCross[4][3];
347 this->computeCrossExtremity(image, index, worldCross);
349 vtkPoints* points = m_cursorPolyData->GetPoints();
350 for (
int i = 0; i < 4; ++i)
352 OSLM_TRACE(
"p=" << worldCross[i][0] <<
"," << worldCross[i][2] <<
"," << worldCross[i][2] <<
"," );
353 points->SetPoint(i, worldCross[i]);
355 m_cursorPolyData->Modified();
357 this->setVtkPipelineModified();
358 this->requestRender();
363 void SProbeCursor::computeCrossExtremity(::fwData::Image::csptr image,
const int probeSlice[3],
364 double worldCross[4][3] )
368 sliceIndex[2] = m_axialIndex->value();
369 sliceIndex[1] = m_frontalIndex->value();
370 sliceIndex[0] = m_sagittalIndex->value();
372 double probeWorld[3];
373 for (
unsigned int dim = 0; dim < 3; ++dim )
375 if ( probeSlice[dim] == sliceIndex[dim] )
377 this->setOrientation(static_cast<int>(dim));
379 probeWorld[dim] = probeSlice[dim]*image->getSpacing()[dim] + image->getOrigin().at(dim);
382 for (
unsigned int p = 0; p < 2; ++p )
384 for (
unsigned int dim = 0; dim < 3; ++dim )
386 worldCross[p][dim] = probeWorld[dim];
387 worldCross[p+2][dim] = probeWorld[dim];
388 if ( (dim + p + 1)%3 == m_orientation )
390 worldCross[p][dim] = image->getOrigin().at(dim);
391 const ::fwData::Image::SizeType::value_type size = image->getSize().at(dim)-1;
392 const ::fwData::Image::SpacingType::value_type spacing = image->getSpacing().at(dim);
393 worldCross[p+2][dim] = size * spacing + image->getOrigin().at(dim);
401 void SProbeCursor::buildPolyData()
405 vtkPoints* points = vtkPoints::New(VTK_DOUBLE);
406 points->SetNumberOfPoints(nbPoints);
408 for (i = 0; i < nbPoints; i++)
410 points->SetPoint(i, 0.0, 0.0, 0.0);
413 vtkCellArray* cells = vtkCellArray::New();
414 cells->Allocate(cells->EstimateSize(nbPoints, 2));
417 pts[0] = 0; pts[1] = 2;
418 cells->InsertNextCell(2, pts);
419 pts[0] = 1; pts[1] = 3;
420 cells->InsertNextCell(2, pts);
422 m_cursorPolyData->SetPoints(points);
424 m_cursorPolyData->SetLines(cells);
426 this->setVtkPipelineModified();
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_SLICE_INDEX_MODIFIED_SIG
Type of signal when image's buffer is added.
This class is a helper to define the connections of a service and its data.
The namespace visuVTKAdaptor contains the list of adaptors available for the generic scene...
Cursor management: displays a red cross representing the image picked point.
VISUVTKADAPTOR_API void starting() override
Initialize the service activity.
#define OSLM_TRACE(message)
virtual VISUVTKADAPTOR_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
VISUVTKADAPTOR_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_BUFFER_MODIFIED_SIG
Type of signal when image's buffer is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
VISUVTKADAPTOR_API void configuring() override
Configure the service before starting. Apply the configuration to service.
VISUVTKADAPTOR_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
Base class for VTK adaptors.