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)