16 #include "Viewer3DImage.h" 17 #include "DGtal/io/DrawWithDisplay3DModifier.h" 18 #include "DGtal/images/ImageHelper.h" 19 #include "DGtal/images/ConstImageAdapter.h" 20 #include "DGtal/images/ImageSelector.h" 38 template <
typename Space,
typename KSpace>
41 DGtal::Viewer3D<>::init();
42 QGLViewer::setKeyDescription ( Qt::Key_X,
"Change the current axis to X for the current 2D image slice setting." );
43 QGLViewer::setKeyDescription ( Qt::Key_Y,
"Change the current axis to Y for the current 2D image slice setting." );
44 QGLViewer::setKeyDescription ( Qt::Key_Z,
"Change the current axis to Z for the current 2D image slice setting." );
45 QGLViewer::setKeyDescription ( Qt::Key_Up,
"Move the current 2D image slice to 5 in the positive direction of the current axis." );
46 QGLViewer::setKeyDescription ( Qt::Key_Down,
"Move the current 2D image slice to 5 in the negative direction of the current axis." );
47 QGLViewer::setKeyDescription ( Qt::Key_Shift,
"Change the slice move with step 1 (5 by default)" );
48 QGLViewer::setKeyDescription ( Qt::Key_M,
"Hide/Display message informations (slice numbers, selected axis)" );
52 template <
typename Space,
typename KSpace>
55 my3dImage = an3DImage;
59 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"BoundingBox");
62 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"InterGrid");
65 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"Grid");
68 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"");
72 myImageOrigin = my3dImage->domain().lowerBound();
73 (*this).updateList(
false);
76 mySliceXPos=myImageOrigin[0];
77 mySliceYPos=myImageOrigin[1];
78 mySliceZPos=myImageOrigin[2];
81 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorX; invFunctorX.initRemoveOneDim(0);
82 DGtal::Z2i::Domain domain2DX(invFunctorX(my3dImage->domain().lowerBound()),
83 invFunctorX(my3dImage->domain().upperBound()));
86 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorX(0, my3dImage->domain(), mySliceXPos,2, myAngleRotation );
87 const DGtal::functors::Identity identityFunctor{};
90 std::cout <<
"image:" << sliceImageX.className();
91 (*this) << sliceImageX;
92 (*this) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, mySliceXPos,myImageOrigin[1], myImageOrigin[2]);
96 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorY; invFunctorY.initRemoveOneDim(1);
97 DGtal::Z2i::Domain domain2DY(invFunctorY(my3dImage->domain().lowerBound()),
98 invFunctorY(my3dImage->domain().upperBound()));
100 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctorY(mySliceYPos); aSliceFunctorY.initAddOneDim(1);
101 SliceImageAdapter sliceImageY(*my3dImage, domain2DY, aSliceFunctorY, identityFunctor );
102 (*this) << sliceImageY;
103 (*this) << DGtal::UpdateImagePosition< Space, KSpace >(1, DGtal::Viewer3D<>::yDirection, myImageOrigin[0], mySliceYPos, myImageOrigin[2]);
110 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorZ; invFunctorZ.initRemoveOneDim(2);
111 DGtal::Z2i::Domain domain2DZ(invFunctorZ(my3dImage->domain().lowerBound()),
112 invFunctorZ(my3dImage->domain().upperBound()));
114 DGtal::Z3i::Point centerZ((my3dImage->domain().upperBound())[0]/2, (my3dImage->domain().upperBound())[1]/2, mySliceZPos);
116 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorZ(2, my3dImage->domain(), mySliceZPos, 2, myAngleRotation, centerZ );
118 (*this) << sliceImageZ;
119 (*this) << DGtal::UpdateImagePosition< Space, KSpace > (2, DGtal::Viewer3D<>::zDirection, myImageOrigin[0], myImageOrigin[1], mySliceZPos);
122 (*this) << DGtal::Viewer3D<>::updateDisplay;
126 template <
typename Space,
typename KSpace>
130 QString text (
"<h2> Viewer3DImage</h2>" );
131 text +=
"Use the mouse to move the camera around the object. ";
132 text +=
"You can respectively revolve around, zoom and translate with the three mouse buttons. ";
133 text +=
"Left and middle buttons pressed together rotate around the camera view direction axis<br><br>";
134 text +=
"Pressing <b>Alt</b> and one of the function keys (<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
135 text +=
"Simply press the function key again to restore it. Several keyFrames define a ";
136 text +=
"camera path. Paths are saved when you quit the application and restored at next start.<br><br>";
137 text +=
"Press <b>F</b> to display the frame rate, <b>A</b> for the world axis, ";
138 text +=
"<b>Alt+Return</b> for full screen mode and <b>Control+S</b> to save a snapshot. ";
139 text +=
"See the <b>Keyboard</b> tab in this window for a complete shortcut list.<br><br>";
140 text +=
"Double clicks automates single click actions: A left button double click aligns the closer axis with the camera (if close enough). ";
141 text +=
"A middle button double click fits the zoom of the camera and the right button re-centers the scene.<br><br>";
142 text +=
"A left button double click while holding right button pressed defines the camera <i>Revolve Around Point</i>. ";
143 text +=
"See the <b>Mouse</b> tab and the documentation web pages for details.<br><br>";
144 text +=
"Press <b>Escape</b> to exit the viewer.";
152 template <
typename Space,
typename KSpace>
157 bool handled =
false;
158 if( e->key() == Qt::Key_M){
159 myDisplayingInfo = !myDisplayingInfo;
162 if( e->key() == Qt::Key_I){
163 std::cout <<
"Image generation" << std::endl;
167 if( e->key() == Qt::Key_X){
168 std::cout <<
"Current axis set to X" << std::endl;
169 (*this).displayMessage(QString(
"Current axis set to X"), 100000);
173 if( e->key() == Qt::Key_Y){
174 (*this).displayMessage(QString(
"Current axis set to Y"), 100000);
178 if( e->key() == Qt::Key_Z){
179 (*this).displayMessage(QString(
"Current axis set to Z"), 100000);
183 if( e->key() == Qt::Key_Up || e->key() == Qt::Key_Down){
184 int dirStep = (e->key() == Qt::Key_Up)? 5: -5;
185 if((e->modifiers() & Qt::ShiftModifier)){
188 if((e->modifiers() & Qt::MetaModifier)){
189 myAngleRotation =(e->key() == Qt::Key_Down)? 0.1: -0.1;
197 if(myCurrentSliceDim==0){
198 aSliceMax=my3dImage->domain().upperBound()[0]+1;
199 if(mySliceXPos+dirStep<aSliceMax&&mySliceXPos+dirStep>=myImageOrigin[0]){
200 mySliceXPos+=dirStep;
205 aSliceNum=mySliceXPos;
206 }
else if(myCurrentSliceDim==1){
207 aSliceMax=my3dImage->domain().upperBound()[1]+1;
208 if(mySliceYPos+dirStep<aSliceMax&&mySliceYPos+dirStep>=myImageOrigin[1]){
209 mySliceYPos+=dirStep;
213 aSliceNum=mySliceYPos;
214 }
else if(myCurrentSliceDim==2){
215 aSliceMax=my3dImage->domain().upperBound()[2]+1;
216 if(mySliceZPos+dirStep<aSliceMax&&mySliceZPos+dirStep>=myImageOrigin[2]){
217 mySliceZPos+=dirStep;
221 aSliceNum=mySliceZPos;
225 double myTotalAngleRotation=0.0;
226 if(myCurrentSliceDim==0){
227 myTotalAngleRotationX+=myAngleRotation;
228 myTotalAngleRotation = myTotalAngleRotationX;
229 }
else if (myCurrentSliceDim==1){
230 myTotalAngleRotationY+=myAngleRotation;
231 myTotalAngleRotation = myTotalAngleRotationY;
232 }
else if (myCurrentSliceDim==2){
233 myTotalAngleRotationZ+=myAngleRotation;
234 myTotalAngleRotation = myTotalAngleRotationZ;
237 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctor(myCurrentSliceDim, my3dImage->domain(),
238 aSliceNum, 2, myTotalAngleRotation);
240 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(myCurrentSliceDim);
241 DGtal::Z2i::Domain domain2D(invFunctor(my3dImage->domain().lowerBound()),
242 invFunctor(my3dImage->domain().upperBound()));
244 const DGtal::functors::Identity identityFunctor{};
247 (*this) << DGtal::UpdateImageData<MyRotatorSliceImageAdapter>(myCurrentSliceDim, sliceImage,
248 (myCurrentSliceDim==0)? dirStep: 0.0,
249 (myCurrentSliceDim==1)? dirStep: 0.0,
250 (myCurrentSliceDim==2)? dirStep: 0.0,
251 myAngleRotation, DGtal::Viewer3D<>::zDirection);
252 (*this).updateList(
false);
255 if(myDisplayingInfo){
256 std::stringstream sstring;
257 sstring <<
"slice X: " << mySliceXPos ;
258 sstring <<
" slice Y: " << mySliceYPos ;
259 sstring <<
" slice Z: " << mySliceZPos ;
260 (*this).displayMessage(QString(sstring.str().c_str()), 100000);
270 DGtal::Viewer3D<>::keyPressEvent ( e );
virtual void keyPressEvent(QKeyEvent *e)
virtual QString helpString() const
DGtal::ConstImageAdapter< Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space >, Image3D::Value, DGtal::functors::Identity > SliceImageAdapter
DGtal::ImageContainerBySTLVector< DGtal::Z3i::Domain, unsigned char > Image3D
DGtal::ConstImageAdapter< Image3D, DGtal::Z2i::Domain, DGtal::functors::SliceRotator2D< DGtal::Z3i::Domain >, Image3D::Value, DGtal::functors::Identity > MyRotatorSliceImageAdapter
void setVolImage(Image3D *an3DImage)