38 #include "vtkSphereWidget.h"
39 #include "vtkSplineWidget.h"
40 #include "vtkSplineWidget2.h"
41 #include "vtkSplineRepresentation.h"
42 #include "vtkRenderWindow.h"
43 #include <vtkSphere.h>
44 #include <vtkClipPolyData.h>
45 #include <vtkImageData.h>
69 mPreviousCenter(0,0,0),
72 mPatientModelService(patientModelService),
73 mViewService(viewService),
74 mActiveData(patientModelService->getActiveData())
77 QVBoxLayout* layout =
new QVBoxLayout(
this);
78 this->setToolTip(
"Erase parts of volumes/models");
80 mContinousEraseTimer =
new QTimer(
this);
81 connect(mContinousEraseTimer, SIGNAL(timeout()),
this, SLOT(continousRemoveSlot()));
83 QHBoxLayout* buttonLayout =
new QHBoxLayout;
84 layout->addLayout(buttonLayout);
85 QHBoxLayout* buttonLayout2 =
new QHBoxLayout;
86 layout->addLayout(buttonLayout2);
88 mShowEraserCheckBox =
new QCheckBox(
"Show");
89 mShowEraserCheckBox->setToolTip(
"Show eraser sphere in the views.");
90 connect(mShowEraserCheckBox, SIGNAL(toggled(
bool)),
this, SLOT(toggleShowEraser(
bool)));
91 buttonLayout->addWidget(mShowEraserCheckBox);
93 mContinousEraseCheckBox =
new QCheckBox(
"Continous");
94 mContinousEraseCheckBox->setToolTip(
"Erase continously using the sphere. (might be slow)");
95 connect(mContinousEraseCheckBox, SIGNAL(toggled(
bool)),
this, SLOT(toggleContinous(
bool)));
96 buttonLayout2->addWidget(mContinousEraseCheckBox);
98 mDuplicateAction = this->
createAction(
this, QIcon(),
"Duplicate",
"Duplicate active volume - do this before erasing!",
99 SLOT(duplicateSlot()), buttonLayout);
101 mSaveAction = this->
createAction(
this, QIcon(),
"Save",
"Save modified image to disk",
102 SLOT(saveSlot()), buttonLayout);
104 mRemoveAction = this->
createAction(
this, QIcon(),
"Erase",
"Erase everything inside sphere",
105 SLOT(removeSlot()), buttonLayout2);
108 double sphereRadius = 10;
112 layout->addWidget(mSphereSize);
117 eraseValue = image->
getMin();
124 layout->addWidget(mEraseValueWidget);
126 layout->addStretch();
128 this->enableButtons();
131 void EraserWidget::activeImageChangedSlot()
137 mEraseValueAdapter->setValueRange(
DoubleRange(image->getVTKMinValue(), image->getVTKMaxValue(), 1));
138 mEraseValueAdapter->setValue(image->getMin());
141 void EraserWidget::enableButtons()
143 bool e = mShowEraserCheckBox->isChecked();
145 mContinousEraseCheckBox->setEnabled(e);
148 mRemoveAction->setEnabled(e);
149 mSphereSize->setEnabled(e);
156 void EraserWidget::toggleContinous(
bool on)
160 mContinousEraseTimer->start(300);
164 mContinousEraseTimer->stop();
168 void EraserWidget::continousRemoveSlot()
170 Transform3D rMd = mViewService->getGroup(0)->getOptions().mPickerGlyph->get_rMd();
174 double r = mSphere->GetRadius();
183 void EraserWidget::duplicateSlot()
185 ImagePtr original = mActiveData->getActive<Image>();
188 mPatientModelService->insertData(duplicate);
189 mActiveData->setActive(duplicate);
193 for (
unsigned i = 0; i < mViewService->groupCount(); ++i)
195 if (mViewService->getGroup(i)->removeData(original->getUid()))
196 mViewService->getGroup(i)->addData(duplicate->getUid());
200 void EraserWidget::sphereSizeChangedSlot()
204 mSphere->SetRadius(mSphereSizeAdapter->getValue());
213 void EraserWidget::saveSlot()
215 mPatientModelService->insertData(mActiveData->getActive<Image>());
219 template <
class TYPE>
220 void EraserWidget::eraseVolume(TYPE* volumePointer)
222 ImagePtr image = mActiveData->getActive<Image>();
226 Eigen::Array3i dim(img->GetDimensions());
227 Vector3D spacing(img->GetSpacing());
229 Transform3D rMd = mViewService->getGroup(0)->getOptions().mPickerGlyph->get_rMd();
232 double r = mSphere->GetRadius();
236 DoubleBoundingBox3D bb_r(c[0]-r, c[0]+r, c[1]-r, c[1]+r, c[2]-r, c[2]+r);
242 double r_d = dMr.vector(r * Vector3D::UnitX()).length();
244 r = rawMr.vector(r * Vector3D::UnitX()).length();
245 DoubleBoundingBox3D bb0_raw =
transform(rawMr, bb_r);
246 IntBoundingBox3D bb1_raw(0, dim[0], 0, dim[1], 0, dim[2]);
251 for (
int i=0; i<3; ++i)
253 bb1_raw[2*i] = std::max<double>(bb1_raw[2*i], bb0_raw[2*i]);
254 bb1_raw[2*i+1] = std::min<double>(bb1_raw[2*i+1], bb0_raw[2*i+1]);
257 int replaceVal = mEraseValueAdapter->getValue();
259 for (
int x = bb1_raw[0]; x < bb1_raw[1]; ++x)
260 for (
int y = bb1_raw[2]; y < bb1_raw[3]; ++y)
261 for (
int z = bb1_raw[4]; z < bb1_raw[5]; ++z)
263 int index = x + y * dim[0] + z * dim[0] * dim[1];
264 if ((
Vector3D(x*spacing[0], y*spacing[1], z*spacing[2]) - c_d).
length() < r_d)
265 volumePointer[index] = replaceVal;
284 void EraserWidget::removeSlot()
289 ImagePtr image = mActiveData->getActive<Image>();
292 int vtkScalarType = img->GetScalarType();
294 if (vtkScalarType==VTK_CHAR)
295 this->eraseVolume(static_cast<char*> (img->GetScalarPointer()));
296 else if (vtkScalarType==VTK_UNSIGNED_CHAR)
297 this->eraseVolume(static_cast<unsigned char*> (img->GetScalarPointer()));
298 else if (vtkScalarType==VTK_SIGNED_CHAR)
299 this->eraseVolume(static_cast<signed char*> (img->GetScalarPointer()));
300 else if (vtkScalarType==VTK_UNSIGNED_SHORT)
301 this->eraseVolume(static_cast<unsigned short*> (img->GetScalarPointer()));
302 else if (vtkScalarType==VTK_SHORT)
303 this->eraseVolume(static_cast<short*> (img->GetScalarPointer()));
304 else if (vtkScalarType==VTK_UNSIGNED_INT)
305 this->eraseVolume(static_cast<unsigned int*> (img->GetScalarPointer()));
306 else if (vtkScalarType==VTK_INT)
307 this->eraseVolume(static_cast<int*> (img->GetScalarPointer()));
309 reportError(QString(
"Unknown VTK ScalarType: %1").arg(vtkScalarType));
316 image->setVtkImageData(img);
319 image->setLookupTable2D(tf2D);
320 image->setTransferFunctions3D(tf3D);
323 void EraserWidget::toggleShowEraser(
bool on)
328 mSphere = vtkSphereSourcePtr::New();
330 mSphere->SetRadius(40);
331 mSphere->SetThetaResolution(16);
332 mSphere->SetPhiResolution(12);
333 mSphere->LatLongTessellationOn();
335 double a = mSphereSizeAdapter->getValue();
336 mSphere->SetRadius(a);
338 MeshPtr glyph = mViewService->getGroup(0)->getOptions().mPickerGlyph;
339 glyph->setVtkPolyData(mSphere->GetOutput());
340 glyph->setColor(QColor(255, 204, 0));
341 glyph->setIsWireframe(
true);
344 for (
unsigned i=0; i<mViewService->groupCount(); ++i)
346 ViewGroupData::Options options = mViewService->getGroup(i)->getOptions();
347 options.mPickerGlyph = glyph;
348 mViewService->getGroup(i)->setOptions(options);
353 mViewService->getGroup(0)->getOptions().mPickerGlyph->setVtkPolyData(NULL);
354 mContinousEraseCheckBox->setChecked(
false);
357 this->enableButtons();
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
void reportError(QString msg)
Transform3D createTransformScale(const Vector3D &scale_)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Utility class for describing a bounded numeric range.
boost::shared_ptr< class Image > ImagePtr
boost::shared_ptr< class ActiveImageProxy > ActiveImageProxyPtr
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
ImagePtr duplicateImage(PatientModelServicePtr dataManager, ImagePtr image)
boost::shared_ptr< class ImageLUT2D > ImageLUT2DPtr
static ActiveImageProxyPtr New(ActiveDataPtr activeData)
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
void changed()
emit when the underlying data value is changed: The user interface will be updated.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
cxLogicManager_EXPORT ViewServicePtr viewService()
void setDeepModified(vtkImageDataPtr image)
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
RealScalar length() const
EraserWidget(PatientModelServicePtr patientModelService, ViewServicePtr viewService, QWidget *parent)
void activeImageChanged(const QString &uid)
The original image changed signal from DataManager.
boost::shared_ptr< class Mesh > MeshPtr
boost::shared_ptr< class ImageTF3D > ImageTF3DPtr