Fraxinus  16.5.0-fx-rc1
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxInteractiveCropper.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 /*
34  * cxInteractiveCropper.cpp
35  *
36  * \date Aug 24, 2010
37  * \author christiana
38  */
39 #include "cxInteractiveCropper.h"
40 
41 #include "cxView.h"
42 
43 #include <vector>
44 #include <vtkTransform.h>
45 #include <vtkAbstractVolumeMapper.h>
46 #include <vtkVolumeMapper.h>
47 #include <vtkRenderWindow.h>
48 #include <vtkRenderer.h>
49 #include <vtkImageData.h>
50 #include <vtkCommand.h>
51 #include <vtkBoxWidget2.h>
52 #include <vtkBoxWidget.h>
53 #include "cxTypeConversions.h"
54 #include "cxBoundingBox3D.h"
55 #include "cxImage.h"
56 #include "cxTransform3D.h"
57 #include "cxVolumetricRep.h"
58 
59 #include "cxActiveImageProxy.h"
60 #include "cxActiveData.h"
61 
62 namespace cx
63 {
64 
65 class CropBoxCallback: public vtkCommand
66 {
67 public:
69  {
70  }
71  static CropBoxCallback* New()
72  {
73  return new CropBoxCallback;
74  }
76  {
77  mCropper = cropper;
78  }
79  virtual void Execute(vtkObject* caller, unsigned long, void*)
80  {
81  DoubleBoundingBox3D bb_new = mCropper->getBoxWidgetSize();
82  mCropper->setCroppingRegion(bb_new);
83  }
85 };
86 
87 class CropBoxEnableCallback: public vtkCommand
88 {
89 public:
91  {
92  }
94  {
95  return new CropBoxEnableCallback;
96  }
97  void SetCropper(bool val, InteractiveCropper* cropper)
98  {
99  mValue = val;
100  mCropper = cropper;
101  }
102  virtual void Execute(vtkObject* caller, unsigned long, void*)
103  {
104  DoubleBoundingBox3D bb_new = mCropper->getBoxWidgetSize();
105  mCropper->boxWasShown(mValue);
106  }
107  bool mValue;
109 };
110 
111 //---------------------------------------------------------
112 //---------------------------------------------------------
113 //---------------------------------------------------------
114 
115 
117  mActiveData(activeData)
118 {
119  mActiveImageProxy = ActiveImageProxy::New(mActiveData);
120  connect(mActiveImageProxy.get(), &ActiveImageProxy::activeImageChanged, this, &InteractiveCropper::imageChangedSlot);
121  connect(mActiveImageProxy.get(), SIGNAL(cropBoxChanged()), this, SLOT(imageCropChangedSlot()));
122 }
123 
124 void InteractiveCropper::initialize()
125 {
126  if (mBoxWidget) // already initialized
127  return;
128 
129  mBoxWidget = vtkBoxWidgetPtr::New();
130  mBoxWidget->RotationEnabledOff();
131 
132  double bb_hard[6] =
133  { -1, 1, -1, 1, -1, 1 };
134  mBoxWidget->PlaceWidget(bb_hard);
135 
136  mCropBoxCallback = CropBoxCallbackPtr::New();
137  mCropBoxCallback->SetCropper(this);
138  mCropBoxEnableCallback = CropBoxEnableCallbackPtr::New();
139  mCropBoxEnableCallback->SetCropper(true, this);
140  mCropBoxDisableCallback = CropBoxEnableCallbackPtr::New();
141  mCropBoxDisableCallback->SetCropper(false, this);
142 
143  mBoxWidget->SetInteractor(mView->getRenderWindow()->GetInteractor());
144 
145  mBoxWidget->SetEnabled(false);
146 }
147 
149 {
150  mView = view;
151  this->updateBoxWidgetInteractor();
152 }
153 
154 void InteractiveCropper::updateBoxWidgetInteractor()
155 {
156  if (!mView)
157  return;
158 
159  this->initialize();
160 
161  if (this->getUseCropping())
162  {
163  mBoxWidget->SetInteractor(mView->getRenderWindow()->GetInteractor());
164  mBoxWidget->AddObserver(vtkCommand::InteractionEvent, mCropBoxCallback);
165  mBoxWidget->AddObserver(vtkCommand::EnableEvent, mCropBoxEnableCallback);
166  mBoxWidget->AddObserver(vtkCommand::DisableEvent, mCropBoxDisableCallback);
167  }
168  else
169  {
170  mBoxWidget->RemoveObserver(vtkCommand::InteractionEvent);
171  mBoxWidget->RemoveObserver(vtkCommand::EnableEvent);
172  mBoxWidget->RemoveObserver(vtkCommand::DisableEvent);
173  }
174 }
175 
177 {
178  if (!mImage)
179  return;
180  if (!mBoxWidget)
181  return;
182  if (this->getShowBoxWidget() == on)
183  return;
184 
185  //Turn on cropping if not on to save user from pressing two boxes
186  if (!mImage->getCropping() && on)
187  this->useCropping(true);
188 
189  mBoxWidget->SetEnabled(on);
190  emit changed();
191 }
192 
196 {
197  if (!mImage || !mBoxWidget)
198  return DoubleBoundingBox3D(0,0,0,0,0,0);
199  return mImage->getCroppingBox();
200 }
201 
203 {
204  this->setCroppingRegion(bb_d);
205  this->setBoxWidgetSize(bb_d);
206 }
207 
209 {
210  if (this->getUseCropping() == on)
211  return;
212 
213  if (!mImage)
214  return;
215 
216  mImage->setCropping(on);
217 }
218 
219 void InteractiveCropper::imageCropChangedSlot()
220 {
221  if (!mImage)
222  return;
223 
224  DoubleBoundingBox3D bb_d = this->getBoundingBox();
225  this->setBoxWidgetSize(bb_d);
226  this->updateBoxWidgetInteractor();
227 
228  if (!mImage->getCropping())
229  this->showBoxWidget(false);
230 
231  emit changed();
232 }
233 
235 {
236  emit changed();
237 }
238 
239 void InteractiveCropper::imageChangedSlot()
240 {
241 // mImage = mPatientModelService->getActiveImage();
242  mImage = mActiveData->getActive<Image>();
243 
244  this->imageCropChangedSlot();
245  emit changed();
246 }
247 
249 {
250  if (!mImage)
251  return false;
252  return mImage->getCropping();
253 }
254 
256 {
257  if (!mBoxWidget)
258  return false;
259  return mBoxWidget->GetEnabled();
260 }
261 
263 {
264  std::vector<int> dimensions;
265  if(!mImage)
266  return dimensions;
267 
268  double spacing_x = 1;
269  double spacing_y = 1;
270  double spacing_z = 1;
271  mImage->getBaseVtkImageData()->GetSpacing(spacing_x, spacing_y, spacing_z);
272 
273  DoubleBoundingBox3D bb = getBoxWidgetSize();
274  int dim_x = (bb.begin()[1] - bb.begin()[0])/spacing_x + 1; //adding 1 because of some rounding errors, is there a better way to do this?
275  int dim_y = (bb.begin()[3] - bb.begin()[2])/spacing_y + 1;
276  int dim_z = (bb.begin()[5] - bb.begin()[4])/spacing_z + 1;
277  dimensions.push_back(dim_x);
278  dimensions.push_back(dim_y);
279  dimensions.push_back(dim_z);
280 
281  return dimensions;
282 }
283 
286 void InteractiveCropper::setBoxWidgetSize(const DoubleBoundingBox3D& bb_d)
287 {
288  if (!mImage || !mBoxWidget)
289  return;
290 
291  double bb_hard[6] =
292  { -0.5, 0.5, -0.5, 0.5, -0.5, 0.5 };
293  DoubleBoundingBox3D bb_unit(bb_hard);
294  Transform3D M = createTransformNormalize(bb_unit, bb_d);
295  Transform3D rMd = mImage->get_rMd();
296  M = rMd * M;
297 
298  vtkTransformPtr transform = vtkTransformPtr::New();
299  transform->SetMatrix(M.getVtkMatrix());
300  mBoxWidget->SetTransform(transform);
301 }
302 
305 DoubleBoundingBox3D InteractiveCropper::getBoxWidgetSize()
306 {
307  if (!mImage || !mBoxWidget)
308  {
309  return DoubleBoundingBox3D::zero();
310  }
311 
312  double bb_hard[6] =
313  { -0.5, 0.5, -0.5, 0.5, -0.5, 0.5 };
314  DoubleBoundingBox3D bb_unit(bb_hard);
315 
316  vtkTransformPtr transform = vtkTransformPtr::New();
317  mBoxWidget->GetTransform(transform);
318  Transform3D M(transform->GetMatrix());
319 
320  Transform3D rMd = mImage->get_rMd();
321  M = rMd.inv() * M;
322 
323  DoubleBoundingBox3D bb_new_r = cx::transform(M, bb_unit);
324 
325  return bb_new_r;
326 }
327 
328 void InteractiveCropper::setCroppingRegion(DoubleBoundingBox3D bb_d)
329 {
330  if (!mImage)
331  return;
332  mImage->setCroppingBox(bb_d);
333  emit changed();
334 }
335 
336 void InteractiveCropper::boxWasShown(bool val)
337 {
338  emit changed();
339 }
340 
345 {
346  if (!mImage)
347  return DoubleBoundingBox3D::zero();
348  return mImage->boundingBox();
349 }
350 
351 } // namespace cx
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
virtual void Execute(vtkObject *caller, unsigned long, void *)
static CropBoxEnableCallback * New()
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
DoubleBoundingBox3D getBoundingBox()
get BB in data space
boost::shared_ptr< class ActiveData > ActiveDataPtr
Definition: cxColorWidget.h:42
boost::shared_ptr< class View > ViewPtr
vtkSmartPointer< class vtkTransform > vtkTransformPtr
Definition: cxMathBase.h:62
void SetCropper(InteractiveCropper *cropper)
Transform3D createTransformNormalize(const DoubleBoundingBox3D &in, const DoubleBoundingBox3D &out)
InteractiveCropper * mCropper
DoubleBoundingBox3D getMaxBoundingBox()
static ActiveImageProxyPtr New(ActiveDataPtr activeData)
virtual void Execute(vtkObject *caller, unsigned long, void *)
static DoubleBoundingBox3D zero()
A volumetric data set.
Definition: cxImage.h:66
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
void resetBoundingBox()
set bounding box back to initial size (entire volume)
void setView(ViewPtr view)
adds an interactive box widget to the view. Press 'I' to show
InteractiveCropper(ActiveDataPtr activeData)
void SetCropper(bool val, InteractiveCropper *cropper)
void activeImageChanged(const QString &uid)
The original image changed signal from DataManager.
void setBoundingBox(const DoubleBoundingBox3D &bb_d)
set BB in reference space
static CropBoxCallback * New()
std::vector< int > getDimensions()