DGtalTools  1.2.0
Viewer3DImage.cpp
1 
15 
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"
21 #include <sstream>
22 #include <QKeyEvent>
23 
25 
26 using namespace std;
27 using namespace qglviewer;
28 
29 
31 // class Viewer3DImage
33 
35 // Standard services - public :
36 
37 
38 template < typename Space, typename KSpace>
39 void
41  DGtal::Viewer3D<>::init();
42 
43  QGLViewer::setKeyDescription ( Qt::Key_X, "Change the current axis to X for the current 2D image slice setting." );
44  QGLViewer::setKeyDescription ( Qt::Key_Y, "Change the current axis to Y for the current 2D image slice setting." );
45  QGLViewer::setKeyDescription ( Qt::Key_Z, "Change the current axis to Z for the current 2D image slice setting." );
46  QGLViewer::setKeyDescription ( Qt::Key_Up, "Move the current 2D image slice to 5 in the positive direction of the current axis." );
47  QGLViewer::setKeyDescription ( Qt::Key_Down, "Move the current 2D image slice to 5 in the negative direction of the current axis." );
48  QGLViewer::setKeyDescription ( Qt::Key_Shift, "Change the slice move with step 1 (5 by default)" );
49  QGLViewer::setKeyDescription ( Qt::Key_M, "Hide/Display message informations (slice numbers, selected axis)" );
50 }
51 
52 
53 template < typename Space, typename KSpace>
54 void
56  my3dImage = an3DImage;
57 
58  switch (myMode) {
59  case BoundingBox:
60  (*this) << DGtal::SetMode3D("ConstImageAdapter", "BoundingBox");
61  break;
62  case InterGrid:
63  (*this) << DGtal::SetMode3D("ConstImageAdapter", "InterGrid");
64  break;
65  case Grid:
66  (*this) << DGtal::SetMode3D("ConstImageAdapter", "Grid");
67  break;
68  case Empty:
69  (*this) << DGtal::SetMode3D("ConstImageAdapter", "");
70  break;
71  }
72 
73  myImageOrigin = my3dImage->domain().lowerBound();
74  (*this).updateList(false);
75  (*this).update();
76 
77  mySliceXPos=myImageOrigin[0];
78  mySliceYPos=myImageOrigin[1];
79  mySliceZPos=myImageOrigin[2];
80 
81  // Adding X slice in the viewer.
82  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorX; invFunctorX.initRemoveOneDim(0);
83  DGtal::Z2i::Domain domain2DX(invFunctorX(my3dImage->domain().lowerBound()),
84  invFunctorX(my3dImage->domain().upperBound()));
85 
86 
87  DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorX(0, my3dImage->domain(), mySliceXPos,2, myAngleRotation );
88  const DGtal::functors::Identity identityFunctor{};
89  MyRotatorSliceImageAdapter sliceImageX( *my3dImage, domain2DX, aSliceFunctorX, identityFunctor );
90 
91  std::cout << "image:" << sliceImageX.className();
92  (*this) << sliceImageX;
93  (*this) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, mySliceXPos,myImageOrigin[1], myImageOrigin[2]);
94 
95 
96  // Adding Y slice in the viewer.
97  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorY; invFunctorY.initRemoveOneDim(1);
98  DGtal::Z2i::Domain domain2DY(invFunctorY(my3dImage->domain().lowerBound()),
99  invFunctorY(my3dImage->domain().upperBound()));
100 
101  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctorY(mySliceYPos); aSliceFunctorY.initAddOneDim(1);
102  SliceImageAdapter sliceImageY(*my3dImage, domain2DY, aSliceFunctorY, identityFunctor );
103  (*this) << sliceImageY;
104  (*this) << DGtal::UpdateImagePosition< Space, KSpace >(1, DGtal::Viewer3D<>::yDirection, myImageOrigin[0], mySliceYPos, myImageOrigin[2]);
105 
106 
107 
108 
109 
110  // Adding Z slice in the viewer.
111  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctorZ; invFunctorZ.initRemoveOneDim(2);
112  DGtal::Z2i::Domain domain2DZ(invFunctorZ(my3dImage->domain().lowerBound()),
113  invFunctorZ(my3dImage->domain().upperBound()));
114 
115  DGtal::Z3i::Point centerZ((my3dImage->domain().upperBound())[0]/2, (my3dImage->domain().upperBound())[1]/2, mySliceZPos);
116 
117  DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorZ(2, my3dImage->domain(), mySliceZPos, 2, myAngleRotation, centerZ );
118  MyRotatorSliceImageAdapter sliceImageZ( *my3dImage, domain2DZ, aSliceFunctorZ, identityFunctor );
119  (*this) << sliceImageZ;
120  (*this) << DGtal::UpdateImagePosition< Space, KSpace > (2, DGtal::Viewer3D<>::zDirection, myImageOrigin[0], myImageOrigin[1], mySliceZPos);
121  (*this) << DGtal::Viewer3D<>::updateDisplay;
122 
123 }
124 
125 
126 template < typename Space, typename KSpace>
127 QString
129 {
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.";
145  return text;
146 }
147 
148 
149 
150 
151 
152 template < typename Space, typename KSpace>
153 void
155 {
156 
157  bool handled = false;
158  if( e->key() == Qt::Key_M){
159  myDisplayingInfo = !myDisplayingInfo;
160  handled=true;
161  }
162  if( e->key() == Qt::Key_I){
163  std::cout << "Image generation" << std::endl;
164  handled=true;
165  }
166 
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);
170  myCurrentSliceDim=0;
171  handled=true;
172  }
173  if( e->key() == Qt::Key_Y){
174  (*this).displayMessage(QString("Current axis set to Y"), 100000);
175  myCurrentSliceDim=1;
176  handled=true;
177  }
178  if( e->key() == Qt::Key_Z){
179  (*this).displayMessage(QString("Current axis set to Z"), 100000);
180  myCurrentSliceDim=2;
181  handled=true;
182  }
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)){
186  dirStep/=5;
187  }
188  if((e->modifiers() & Qt::MetaModifier)){
189  myAngleRotation =(e->key() == Qt::Key_Down)? 0.1: -0.1;
190  dirStep=0;
191  }else{
192  myAngleRotation=0.0;
193  }
194  int aSliceNum=0;
195  int aSliceMax=0;
196  bool stoped=false;
197  if(myCurrentSliceDim==0){
198  aSliceMax=my3dImage->domain().upperBound()[0]+1;
199  if(mySliceXPos+dirStep<aSliceMax&&mySliceXPos+dirStep>=myImageOrigin[0]){
200  mySliceXPos+=dirStep;
201  }else{
202  stoped=true;
203  }
204 
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;
210  }else{
211  stoped=true;
212  }
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;
218  }else{
219  stoped=true;
220  }
221  aSliceNum=mySliceZPos;
222  }
223 
224  if(!stoped){
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;
235  }
236 
237  DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctor(myCurrentSliceDim, my3dImage->domain(),
238  aSliceNum, 2, myTotalAngleRotation);
239  // Adding X slice in the viewer.
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()));
243 
244  const DGtal::functors::Identity identityFunctor{};
245  MyRotatorSliceImageAdapter sliceImage( *my3dImage, domain2D, aSliceFunctor, identityFunctor );
246 
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);
253  (*this).update();
254  }
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);
261  }
262 
263 
264 
265 
266  handled=true;
267  }
268 
269  if ( !handled )
270  DGtal::Viewer3D<>::keyPressEvent ( e );
271 
272 }
273 
274 
275 
virtual void keyPressEvent(QKeyEvent *e)
DGtal::ConstImageAdapter< Image3D, DGtal::Z2i::Domain, DGtal::functors::SliceRotator2D< DGtal::Z3i::Domain >, Image3D::Value, DGtal::functors::Identity > MyRotatorSliceImageAdapter
Definition: Viewer3DImage.h:33
DGtal::ConstImageAdapter< Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space >, Image3D::Value, DGtal::functors::Identity > SliceImageAdapter
Definition: Viewer3DImage.h:30
virtual void init()
DGtal::ImageContainerBySTLVector< DGtal::Z3i::Domain, unsigned char > Image3D
Definition: Viewer3DImage.h:26
virtual QString helpString() const
void setVolImage(Image3D *an3DImage)