/*========================================================================= Program: bbtk Module: $RCSfile: bbvtkImagePlanes.cxx,v $ Language: C++ Date: $Date: 2012/07/04 08:38:21 $ Version: $Revision: 1.36 $ =========================================================================*/ /* --------------------------------------------------------------------- * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale) * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux * * This software is governed by the CeCILL-B license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL-B * license as circulated by CEA, CNRS and INRIA at the following URL * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html * or in the file LICENSE.txt. * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-B license and that you accept its terms. * ------------------------------------------------------------------------ */ /** * \file * \brief */ #ifdef _USE_VTK_ #include "bbvtkImagePlanes.h" #include "bbvtkPackage.h" #include "vtkCellPicker.h" #include "vtkProperty.h" #include "vtkPolyData.h" #include "vtkMetaImageWriter.h" #include "vtkPNGWriter.h" #include "bbstdCast.h" #include #include "vtkImageData.h" //#include "vtkOutlineFilter.h" //#include "vtkPolyDataMapper.h" //#include "vtkActor.h" #include "vtkImagePlaneWidget.h" #include "vtkCellPicker.h" //#include "vtkProperty.h" //#include "vtkRenderer.h" //#include "vtkCamera.h" #include "vtkPlaneWidget.h" #include #include "bbstdRelay.h" #include "vtkObjectFactory.h" namespace bbstd { //==================================================================== BBTK_BLACK_BOX_TEMPLATE2_IMPLEMENTATION(Cast, bbtk::AtomicBlackBox); //==================================================================== //==================================================================== // BBTK_BLACK_BOX_TEMPLATE_IMPLEMENTATION(Relay, // bbtk::AtomicBlackBox); //==================================================================== } using namespace bbstd; /* namespace bbtk { typedef vtkImageData::Pointer vtkImageDataPointer; BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(vtkImageDataPointer, "vtkImageDataPointer"); } */ namespace bbvtk { //==================================================================== // Add the specialized adaptors to the package typedef vtkImagePlaneWidget* I; typedef vtkInteractorObserver* O; BBTK_ADD_TEMPLATE2_BLACK_BOX_TO_PACKAGE(vtk,Cast,I,O); BBTK_DEFINE_RELAY_BLACK_BOX(vtkImageDataPointer,vtk,vtkImageDataPointerRelay); BBTK_BLACK_BOX_IMPLEMENTATION(vtkImageDataPointerRelay,bbtk::AtomicBlackBox); BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,vtkImageDataPointerRelay); // BBTK_ADD_TEMPLATE_BLACK_BOX_TO_PACKAGE(vtk,Relay,vtkImageDataPointer); //Pointer); } namespace bbvtk { //================================================================ class ImagePlanes::VtkCallbackType : public vtkCommand { public: static VtkCallbackType *New() { return new VtkCallbackType; } //vtkTypeRevisionMacro(VtkCallbackType,vtkCommand); virtual void Execute(vtkObject *caller, unsigned long, void*) { mBlackBox->Process(); mBlackBox->bbSignalOutputModification(); } void SetBlackBox(ImagePlanes *BB) { mBlackBox = BB;}; // void SetVtkPlaneWidget( vtkImagePlaneWidget *planeWidget ); VtkCallbackType() {}; private: // vtkPlaneWidget *planeWidget; ImagePlanes *mBlackBox; }; //================================================================ //vtkCxxRevisionMacro(ImagePlanes::VtkCallbackType, "$Revision: 1.36 $"); //================================================================ BBTK_ADD_BLACK_BOX_TO_PACKAGE(vtk,ImagePlanes) BBTK_BLACK_BOX_IMPLEMENTATION(ImagePlanes,bbtk::AtomicBlackBox); void ImagePlanes::bbUserSetDefaultValues() { bbSetOutputPlaneX(0); bbSetOutputPlaneY(0); bbSetOutputPlaneZ(0); bbSetOutputImageX(0); bbSetOutputImageY(0); bbSetOutputImageZ(0); bbSetInputIn(0); std::vector vect; vect.push_back(0); vect.push_back(0); bbSetInputWindowLevel (vect); mVtkCallback = 0; std::vector vectpoints; bbSetOutputPlane3Pts(0); bbSetOutputImage3Pts(0); bbSetInputPointsX(vectpoints); bbSetInputPointsY(vectpoints); bbSetInputPointsZ(vectpoints); _imageReslicer = NULL; image = NULL; _transform = NULL; _matrix = NULL; bbSetInputInterpolation(1); } void ImagePlanes::bbUserInitializeProcessing() { /// CREATION DES WIDGETS if (bbGetOutputPlaneX() != 0) return; // The shared picker enables us to use 3 planes at one time // and gets the picking order right vtkCellPicker* picker = vtkCellPicker::New(); picker->SetTolerance(0.005); // The 3 image plane widgets vtkImagePlaneWidget* planeWidgetX = GetPlaneWidget('x', 1, 0, 0, picker); vtkImagePlaneWidget* planeWidgetY = GetPlaneWidget('y', 1, 1, 0, picker); planeWidgetY->SetLookupTable(planeWidgetX->GetLookupTable()); vtkImagePlaneWidget* planeWidgetZ = GetPlaneWidget('z', 0, 0, 1, picker); planeWidgetZ->SetLookupTable(planeWidgetX->GetLookupTable()); vtkImagePlaneWidget* planeWidget3Pts = GetPlaneWidget('3', 0, 1, 1, picker); planeWidget3Pts->SetLookupTable(planeWidgetX->GetLookupTable()); bbSetOutputPlaneX(planeWidgetX); bbSetOutputPlaneY(planeWidgetY); bbSetOutputPlaneZ(planeWidgetZ); bbSetOutputPlane3Pts(planeWidget3Pts); bbSetOutputImageX(planeWidgetX->GetResliceOutput()); bbSetOutputImageY(planeWidgetY->GetResliceOutput()); bbSetOutputImageZ(planeWidgetZ->GetResliceOutput()); bbSetInputInteractor(0); //bbSetOutputImage3Pts(planeWidget3Pts->GetResliceOutput()); if(picker != 0) picker->UnRegister(NULL); mVtkCallback = VtkCallbackType::New(); mVtkCallback->SetBlackBox(this); planeWidgetX->AddObserver(vtkCommand::InteractionEvent,mVtkCallback); planeWidgetY->AddObserver(vtkCommand::InteractionEvent,mVtkCallback); planeWidgetZ->AddObserver(vtkCommand::InteractionEvent,mVtkCallback); } //--------------------------------------------------------------------- void ImagePlanes::bbUserFinalizeProcessing() { if (bbGetOutputPlaneX()) { /* bbGetOutputPlaneX()->RemoveObserver(mVtkCallback); bbGetOutputPlaneY()->RemoveObserver(mVtkCallback); bbGetOutputPlaneZ()->RemoveObserver(mVtkCallback); bbGetOutputPlaneX()->Delete(); bbGetOutputPlaneY()->Delete(); bbGetOutputPlaneZ()->Delete(); mVtkCallback->Delete(); */ //bbGetOutputPlaneX()->SetInput(NULL); //bbGetOutputPlaneY()->SetInput(NULL); //bbGetOutputPlaneZ()->SetInput(NULL); } } //--------------------------------------------------------------------- void ImagePlanes::Process() { if (bbGetInputIn()!=0) { int xMin, xMax, yMin, yMax, zMin, zMax; bbGetInputIn()->GetExtent(xMin, xMax, yMin, yMax, zMin, zMax); if ( image != bbGetInputIn()){//bbGetInputStatus("In") != bbtk::UPTODATE ){ // Input image has changed : reinitialize planes image = bbGetInputIn(); // Initial values : center of the volume (in real world, not in pixels!) double xSpacing, ySpacing, zSpacing; bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing); bbGetOutputPlaneX()->SetInput(bbGetInputIn()); bbGetOutputPlaneX()->SetPlaneOrientationToXAxes(); bbGetOutputPlaneX()->SetSlicePosition((xMax+xMin)/2.*xSpacing); // bbGetOutputPlaneX()->SetOrigin( 58*xSpacing , 80*ySpacing , 82*zSpacing ); // bbGetOutputPlaneX()->SetPoint1( 0*xSpacing, 146*ySpacing, 186*zSpacing); // bbGetOutputPlaneX()->SetPoint2( 126*xSpacing, 146*ySpacing, 0*zSpacing); bbGetOutputPlaneY()->SetInput(bbGetInputIn()); bbGetOutputPlaneY()->SetPlaneOrientationToYAxes(); bbGetOutputPlaneY()->SetSlicePosition((yMax+yMin)/2.*ySpacing); bbGetOutputPlaneZ()->SetInput(bbGetInputIn()); bbGetOutputPlaneZ()->SetPlaneOrientationToZAxes(); bbGetOutputPlaneZ()->SetSlicePosition((zMax+zMin)/2.*zSpacing); if (bbGetInputWindowLevel()[0]!=0) { bbGetOutputPlaneZ()->SetWindowLevel(bbGetInputWindowLevel()[0], bbGetInputWindowLevel()[1]); } else { double *range = image->GetScalarRange(); bbGetOutputPlaneZ()->SetWindowLevel(range[1]-range[0], 0.5*(range[1]+range[0])); } updateInteractor(); } // UPDATE DES SORTIES bbGetOutputPlaneX()->SetResliceInterpolate( bbGetInputInterpolation() ); bbGetOutputPlaneY()->SetResliceInterpolate( bbGetInputInterpolation() ); bbGetOutputPlaneZ()->SetResliceInterpolate( bbGetInputInterpolation() ); bbGetOutputPlaneX()->GetResliceOutput()->Update(); bbGetOutputPlaneY()->GetResliceOutput()->Update(); bbGetOutputPlaneZ()->GetResliceOutput()->Update(); std::vector pointsx = bbGetInputPointsX(); std::vector pointsy = bbGetInputPointsY(); std::vector pointsz = bbGetInputPointsZ(); //std::cout<=3) { //Get the corresponding three points out of the vectors double origin[3]; origin[0] = pointsx[0]; origin[1] = pointsy[0]; origin[2] = pointsz[0]; double point1[3]; point1[0] = pointsx[1]; point1[1] = pointsy[1]; point1[2] = pointsz[1]; double point2[3]; point2[0]= pointsx[2]; point2[1]= pointsy[2]; point2[2]= pointsz[2]; //With the three points we create the corresponding X, Y and Z vectors all orthogonal to each other double* vect1= getNormal(makeVector(origin, point1)); double* vect2= getNormal(makeVector(origin, point2)); double* crossp = getCrossProduct(vect1, vect2); double *newx = getCrossProduct(vect2, crossp); int ext[6],factor=0; bbGetInputIn()->GetExtent(ext); factor = ext[0]SetInput(bbGetInputIn()); double xSpacing, ySpacing, zSpacing; bbGetInputIn()->GetSpacing(xSpacing, ySpacing, zSpacing); plane3pts->SetOrigin(pointsx[0]*xSpacing,pointsy[0]*ySpacing,pointsz[0]*zSpacing); plane3pts->SetPoint1((origin[0]+newx[0]*factor)*xSpacing, (origin[1]+newx[1]*factor)*ySpacing, (origin[2]+newx[2]*factor)*zSpacing); plane3pts->SetPoint2((origin[0]+vect2[0]*factor)*xSpacing, (origin[1]+vect2[1]*factor)*ySpacing, (origin[2]+vect2[2]*factor)*zSpacing); plane3pts->GetResliceOutput()->Update(); //To get the slice of image out of the selected volume if (_imageReslicer==NULL){ _imageReslicer = vtkImageReslice::New(); _imageReslicer->SetOutputDimensionality(2); _transform = vtkTransform::New(); _matrix = vtkMatrix4x4::New(); } _imageReslicer->SetInterpolationMode( bbGetInputInterpolation() ); _imageReslicer->SetInput( bbGetInputIn() ); _imageReslicer->SetInformationInput(bbGetInputIn()); //fill out the information with the created vectors and using the spacing of the image _imageReslicer->SetResliceAxesDirectionCosines(newx[0]*xSpacing,newx[1]*xSpacing,newx[2]*xSpacing, vect2[0]*ySpacing,vect2[1]*ySpacing,vect2[2]*ySpacing, crossp[0]*zSpacing,crossp[1]*zSpacing,crossp[2]*zSpacing); _imageReslicer->SetResliceAxesOrigin(origin[0]*xSpacing,origin[1]*ySpacing,origin[2]*zSpacing); _imageReslicer->GetOutput()->Update(); _imageReslicer->GetOutput()->UpdateInformation(); bbSetOutputImage3Pts(_imageReslicer->GetOutput()); _matrix->Identity(); _matrix->SetElement(0,0,newx[0]*xSpacing); _matrix->SetElement(1,0,newx[1]*xSpacing); _matrix->SetElement(2,0,newx[2]*xSpacing); _matrix->SetElement(0,1,vect2[0]*ySpacing); _matrix->SetElement(1,1,vect2[1]*ySpacing); _matrix->SetElement(2,1,vect2[2]*ySpacing); _matrix->SetElement(0,2,crossp[0]*zSpacing); _matrix->SetElement(1,2,crossp[1]*zSpacing); _matrix->SetElement(2,2,crossp[2]*zSpacing); _matrix->SetElement(0,3,origin[0]*xSpacing); _matrix->SetElement(1,3,origin[1]*ySpacing); _matrix->SetElement(2,3,origin[2]*zSpacing); _transform->SetMatrix(_matrix); //set the transformation out to be used by other bbBoxes bbSetOutputTransform3Pts((vtkLinearTransform*)_transform); } // pointsx pointsy pointsz } // bbGetInputIn } void ImagePlanes::updateInteractor(){ vtkRenderWindowInteractor* interactor = bbGetInputInteractor(); if(interactor){ bbGetOutputPlaneX()->SetInteractor(interactor); bbGetOutputPlaneX()->EnabledOn(); bbGetOutputPlaneY()->SetInteractor(interactor); bbGetOutputPlaneY()->EnabledOn(); bbGetOutputPlaneZ()->SetInteractor(interactor); bbGetOutputPlaneZ()->EnabledOn(); bbGetOutputPlane3Pts()->SetInteractor(interactor); bbGetOutputPlane3Pts()->EnabledOn(); } } //----------------------------------------------------------------- void vtkImageDataPointerRelay::bbUserSetDefaultValues() { } //----------------------------------------------------------------- void vtkImageDataPointerRelay::bbUserInitializeProcessing() { } //----------------------------------------------------------------- void vtkImageDataPointerRelay::bbUserFinalizeProcessing() { } vtkImagePlaneWidget* ImagePlanes::GetPlaneWidget(unsigned char activationkey, double r, double g, double b, vtkCellPicker* picker) { vtkProperty* prop1 = 0; vtkImagePlaneWidget* planeWidget = 0; planeWidget = vtkImagePlaneWidget::New(); planeWidget->DisplayTextOn(); planeWidget->SetPicker(picker); planeWidget->SetKeyPressActivationValue(activationkey); prop1 = planeWidget->GetPlaneProperty(); prop1->SetColor(r, g, b); return planeWidget; } double* ImagePlanes::getCrossProduct(double* vect0,double* vect1){ double* vectCross; vectCross = new double[3]; vectCross[0] = vect0[1]*vect1[2]-(vect0[2]*vect1[1]); vectCross[1] = -(vect0[0]*vect1[2]-(vect0[2]*vect1[0])); vectCross[2] = vect0[0]*vect1[1]-(vect0[1]*vect1[0]); return vectCross; } /** ** Returns the magnitud of the given vector **/ double ImagePlanes::getMagnitud(double* vect){ double mag; mag = sqrt(pow(vect[0],2) + pow(vect[1],2) + pow(vect[2],2)); //std::cout<<"mag "<