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"
27 using namespace qglviewer;
38 template <
typename Space,
typename KSpace>
41 DGtal::Viewer3D<>::init();
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)" );
53 template <
typename Space,
typename KSpace>
56 my3dImage = an3DImage;
60 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"BoundingBox");
63 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"InterGrid");
66 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"Grid");
69 (*this) << DGtal::SetMode3D(
"ConstImageAdapter",
"");
73 myImageOrigin = my3dImage->domain().lowerBound();
74 (*this).updateList(
false);
77 mySliceXPos=myImageOrigin[0];
78 mySliceYPos=myImageOrigin[1];
79 mySliceZPos=myImageOrigin[2];
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()));
87 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorX(0, my3dImage->domain(), mySliceXPos,2, myAngleRotation );
88 const DGtal::functors::Identity identityFunctor{};
91 std::cout <<
"image:" << sliceImageX.className();
92 (*this) << sliceImageX;
93 (*this) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, mySliceXPos,myImageOrigin[1], myImageOrigin[2]);
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()));
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]);
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()));
115 DGtal::Z3i::Point centerZ((my3dImage->domain().upperBound())[0]/2, (my3dImage->domain().upperBound())[1]/2, mySliceZPos);
117 DGtal::functors::SliceRotator2D<DGtal::Z3i::Domain> aSliceFunctorZ(2, my3dImage->domain(), mySliceZPos, 2, myAngleRotation, centerZ );
119 (*this) << sliceImageZ;
120 (*this) << DGtal::UpdateImagePosition< Space, KSpace > (2, DGtal::Viewer3D<>::zDirection, myImageOrigin[0], myImageOrigin[1], mySliceZPos);
121 (*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)
DGtal::ConstImageAdapter< Image3D, DGtal::Z2i::Domain, DGtal::functors::SliceRotator2D< DGtal::Z3i::Domain >, Image3D::Value, DGtal::functors::Identity > MyRotatorSliceImageAdapter
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
virtual QString helpString() const
void setVolImage(Image3D *an3DImage)