CustusX  16.5.0-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxViewGroupData.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 #include "cxViewGroupData.h"
34 
35 #include <QMenu>
36 #include "vtkCamera.h"
37 
38 #include "cxPatientModelService.h"
39 #include "cxMesh.h"
40 #include "cxTypeConversions.h"
41 #include "cxCameraControl.h"
42 #include "cxImageAlgorithms.h"
43 #include "cxDataMetric.h"
44 #include "cxView.h"
45 #include "cxImage.h"
46 #include "cxTrackedStream.h"
47 #include "cxInteractiveClipper.h"
48 #include "boost/bind.hpp"
49 #include "cxXMLNodeWrapper.h"
50 #include "cxSyncedValue.h"
51 #include "cxCoreServices.h"
52 #include "cxLogger.h"
53 #include "cxDefinitionStrings.h"
54 #include "cxStringListProperty.h"
55 
56 namespace cx
57 {
58 
60 {
61  DataViewProperties retval;
62  retval.mVolume3D = true;
63  retval.mSlice3D = false;
64  retval.mSlice2D = true;
65  return retval;
66 }
68 {
69  DataViewProperties retval;
70  retval.mVolume3D = true;
71  retval.mSlice3D = true;
72  retval.mSlice2D = true;
73  return retval;
74 }
75 
77 {
78  DataViewProperties retval;
79  retval.mVolume3D = true;
80  retval.mSlice3D = false;
81  retval.mSlice2D = false;
82  return retval;
83 }
84 
86 {
87  DataViewProperties retval;
88  retval.mVolume3D = false;
89  retval.mSlice3D = true;
90  retval.mSlice2D = false;
91  return retval;
92 }
93 
95 {
96  DataViewProperties retval;
97  retval.mVolume3D = false;
98  retval.mSlice3D = false;
99  retval.mSlice2D = true;
100  return retval;
101 }
102 
104 {
105  DataViewProperties retval;
106  retval.mVolume3D = true;
107  retval.mSlice3D = true;
108  retval.mSlice2D = false;
109  return retval;
110 }
111 
112 
113 void DataViewProperties::addXml(QDomNode& dataNode)
114 {
115  QDomElement elem = dataNode.toElement();
116  elem.setAttribute("volume3D", mVolume3D);
117  elem.setAttribute("slice3D", mSlice3D);
118  elem.setAttribute("slice2D", mSlice2D);
119 }
120 
121 void DataViewProperties::parseXml(QDomNode dataNode)
122 {
123  QDomElement elem = dataNode.toElement();
124  mVolume3D = elem.attribute("volume3D", QString::number(mVolume3D)).toInt();
125  mSlice3D = elem.attribute("slice3D", QString::number(mSlice3D)).toInt();
126  mSlice2D = elem.attribute("slice2D", QString::number(mSlice2D)).toInt();
127 }
128 
130 {
131  return !(mVolume3D || mSlice3D || mSlice2D);
132 }
133 
135 {
136  DataViewProperties retval;
137  retval.mSlice2D = mSlice2D || rhs.mSlice2D;
138  retval.mSlice3D = mSlice3D || rhs.mSlice3D;
139  retval.mVolume3D = mVolume3D || rhs.mVolume3D;
140  return retval;
141 }
142 
144 {
145  DataViewProperties retval;
146  retval.mSlice2D = mSlice2D && !rhs.mSlice2D;
147  retval.mSlice3D = mSlice3D && !rhs.mSlice3D;
148  retval.mVolume3D = mVolume3D && !rhs.mVolume3D;
149  return retval;
150 }
151 
153 {
154  if (required.mSlice2D && mSlice2D) return true;
155  if (required.mSlice3D && mSlice3D) return true;
156  if (required.mVolume3D && mVolume3D) return true;
157  return false;
158 }
159 
160 
161 
165 
166 bool dataTypeSort(const DataPtr data1, const DataPtr data2)
167 {
168  return getPriority(data1) < getPriority(data2);
169 }
170 
172 {
173  if (data->getType()=="mesh")
174  return 6;
175  DataMetricPtr metric = boost::dynamic_pointer_cast<DataMetric>(data);
176  if (metric)
177  return 7;
178 
179  ImagePtr image = boost::dynamic_pointer_cast<Image>(data);
180  if (image)
181  {
182  if (image->getModality().toUpper().contains("US"))
183  {
184  if (image->getImageType().toUpper().contains("B-MODE"))
185  return 4;
186  else // angio types
187  return 5;
188  }
189  else if (image->getModality().toUpper().contains("MR"))
190  {
191  // MR, CT, SC, others
192  return 2;
193  }
194  else if (image->getModality().toUpper().contains("CT"))
195  {
196  // MR, CT, SC, others
197  return 1;
198  }
199  else
200  {
201  return 0;
202  }
203  }
204 
205  return 3;
206 }
207 
211 
213  mShowLandmarks(false), mShowPointPickerProbe(false),
214  mPickerGlyph(new Mesh("PickerGlyph"))
215 {
216 }
217 
219  mServices(services),
220  mCamera3D(CameraData::create())
221 {
222  if(mServices)
223  connect(mServices->patient().get(), &PatientModelService::dataAddedOrRemoved, this, &ViewGroupData::purgeDataNotExistingInPatientModelService);
224  mVideoSource = "active";
225  mGroup2DZoom = SyncedValue::create(1);
226  mGlobal2DZoom = mGroup2DZoom;
227 
228  this->createSliceDefinitionProperty();
229 }
230 
231 //Remove all data, and wait to emit signals until all data is removed
232 void ViewGroupData::purgeDataNotExistingInPatientModelService()
233 {
234  QStringList purged;
235  for (unsigned i = 0; i < mData.size(); )
236  {
237  QString uid = mData[i].first;
238  if (!mServices->patient()->getData(uid))
239  {
240  if (this->contains(uid))
241  {
242  purged << uid;
243  mData.erase(std::find_if(mData.begin(), mData.end(), data_equals(uid)));
244  }
245  }
246  else
247  ++i;
248  }
249  //Emit delayed signals
250  for(unsigned i = 0; i < purged.size(); ++i)
251  emit dataViewPropertiesChanged(purged[i]);
252 }
253 
254 
256 {
257  emit initialized();
258 }
259 
260 void ViewGroupData::addData(QString uid)
261 {
262  DataViewProperties properties = this->getProperties(uid);
263  properties = properties.addFlagsIn(DataViewProperties::createDefault());
264  this->setProperties(uid, properties);
265 }
266 
268 {
269  if (this->contains(uid))
270  return;
271 
273  DataAndViewProperties item(uid, properties);
274 
275  for (int i=int(mData.size())-1; i>=0; --i)
276  {
277  if (!dataTypeSort(this->getData(uid), this->getData(mData[i].first)))
278  {
279  mData.insert(mData.begin()+i+1, item);
280  break;
281  }
282  }
283  if (!this->contains(uid))
284  mData.insert(mData.begin(), item);
285  emit dataViewPropertiesChanged(uid);
286 }
287 
289 {
290  if (this->contains(uid))
291  return std::find_if(mData.begin(), mData.end(), data_equals(uid))->second;
292  return DataViewProperties();
293 }
294 
296 {
297  if (uid.isEmpty())
298  return;
299 
300  if (properties.empty())
301  {
302  this->removeData(uid);
303  return;
304  }
305 
306  if (!this->contains(uid))
307  {
308  DataAndViewProperties item(uid, properties);
309  mData.push_back(item);
310  }
311  else
312  {
313  std::find_if(mData.begin(), mData.end(), data_equals(uid))->second = properties;
314  }
315 
316  emit dataViewPropertiesChanged(uid);
317 }
318 
319 bool ViewGroupData::contains(QString uid) const
320 {
321  return std::count_if(mData.begin(), mData.end(), data_equals(uid));
322 }
323 
324 bool ViewGroupData::removeData(QString uid)
325 {
326  if (!this->contains(uid))
327  return false;
328  mData.erase(std::find_if(mData.begin(), mData.end(), data_equals(uid)));
329  emit dataViewPropertiesChanged(uid);
330  return true;
331 }
332 
334 {
335  while (!mData.empty())
336  this->removeData(mData.front().first);
337  this->setVideoSource("active");
338 
339  mGroup2DZoom->set(1.0);
340  mGlobal2DZoom->set(1.0);
341 }
342 
343 DataPtr ViewGroupData::getData(QString uid) const
344 {
345  DataPtr data = mServices->patient()->getData(uid);
346  if (!data)
347  {
348  reportError("Couldn't find the data: [" + uid + "] in the datamanager.");
349  return DataPtr();
350  }
351  return data;
352 }
353 
355 {
356  if (mVideoSource==uid)
357  return;
358  mVideoSource = uid;
359  emit videoSourceChanged(mVideoSource);
360 }
361 
363 {
364  return mVideoSource;
365 }
366 
367 std::vector<DataPtr> ViewGroupData::getData(DataViewProperties properties) const
368 {
369  return this->getDataOfType<Data>(properties);
370 }
371 
372 template<class DATA_TYPE>
373 std::vector<boost::shared_ptr<DATA_TYPE> > ViewGroupData::getDataOfType(DataViewProperties requiredProperties) const
374 {
375  typedef boost::shared_ptr<DATA_TYPE> DATA_PTR;
376  std::vector<DATA_PTR> retval;
377  for (unsigned i = 0; i < mData.size(); ++i)
378  {
379  DATA_PTR data = boost::dynamic_pointer_cast<DATA_TYPE>(this->getData(mData[i].first));
380  if (!data)
381  continue;
382  DataViewProperties properties = mData[i].second;
383  if (!properties.containsAnyFlagsIn(requiredProperties))
384  continue;
385  retval.push_back(data);
386  }
387  return retval;
388 }
389 
390 std::vector<ImagePtr> ViewGroupData::getImages(DataViewProperties properties) const
391 {
392  return this->getDataOfType<Image>(properties);
393 }
394 
395 std::vector<MeshPtr> ViewGroupData::getMeshes(DataViewProperties properties) const
396 {
397  return this->getDataOfType<Mesh>(properties);
398 }
399 
400 std::vector<TrackedStreamPtr> ViewGroupData::getTrackedStreams(DataViewProperties properties) const
401 {
402  return this->getDataOfType<TrackedStream>(properties);
403 }
404 
405 std::vector<TrackedStreamPtr> ViewGroupData::getTracked2DStreams(DataViewProperties properties) const
406 {
407  std::vector<TrackedStreamPtr> streams = this->getTrackedStreams(properties);
408  std::vector<TrackedStreamPtr> retval;
409 
410  for(int i = 0; i < streams.size(); ++i)
411  {
412  if(streams[i]->is2D() )
413  retval.push_back(streams[i]);
414  }
415  return retval;
416 }
417 
418 std::vector<ImagePtr> ViewGroupData::getImagesAndChangingImagesFromTrackedStreams(DataViewProperties properties, bool include2D) const
419 {
420  std::vector<ImagePtr> images = this->getImages(properties);
421  std::vector<TrackedStreamPtr> streams = this->getTrackedStreams(properties);
422 
423  for(int i = 0; i < streams.size(); ++i)
424  {
425  ImagePtr changingImage = streams[i]->getChangingImage();
426  if(streams[i]->is3D())
427  images.push_back(changingImage);
428  if(include2D && streams[i]->is2D())
429  images.push_back(changingImage);
430  }
431  return images;
432 }
433 
435 {
436  return mOptions;
437 }
438 
440 {
441  mOptions = options;
442  emit optionsChanged();
443 }
444 
446 {
447  mGlobal2DZoom = val;
448 }
449 
451 {
452  return mGroup2DZoom;
453 }
455 {
456  return mGlobal2DZoom;
457 }
458 
459 void ViewGroupData::createSliceDefinitionProperty()
460 {
461  QStringList slicedefs;
462  for (int i=0; i<ptCOUNT; ++i)
463  slicedefs << enum2string(PLANE_TYPE(i));
464  QStringList slicedefaults;
466  mSliceDefinitionProperty = StringListProperty::initialize("slice_definition_3D",
467  "3D Slices",
468  "Select slice planes to view in 3D",
469  slicedefaults,
470  slicedefs);
471  connect(mSliceDefinitionProperty.get(), &Property::changed, this, &ViewGroupData::optionsChanged);
472 }
473 
475 {
476  QStringList val = mSliceDefinitionProperty->getValue();
477  return PlaneTypeCollection::fromString(val.join("/"));
478 }
479 
481 {
482  QStringList val_list = val.toString().split("/");
483  mSliceDefinitionProperty->setValue(val_list);
484 }
485 
487 {
488  return mSliceDefinitionProperty;
489 }
490 
491 void ViewGroupData::addXml(QDomNode& dataNode)
492 {
493  XMLNodeAdder base(dataNode);
494 
495  for (unsigned i = 0; i < mData.size(); ++i)
496  {
497  QDomElement elem;
498  elem = base.addTextToElement("data", mData[i].first);
499  mData[i].second.addXml(elem);
500  }
501 
502  base.addObjectToElement("camera3D", this->getCamera3D());
503  base.addTextToElement("slicesPlanes3D", this->getSliceDefinitions().toString());
504 }
505 
506 void ViewGroupData::parseXml(QDomNode dataNode)
507 {
508  XMLNodeParser base(dataNode);
509 
510  QString sliceText = base.parseTextFromElement("slicesPlanes3D");
512 
513  std::vector<QDomElement> dataElems = base.getDuplicateElements("data");
514  for (unsigned i=0; i<dataElems.size(); ++i)
515  {
516  QDomElement elem = dataElems[i];
517  QString uid = elem.text();
519  properties.parseXml(elem);
520 
521  this->addData(uid);
522  this->setProperties(uid, properties);
523  }
524 
525  base.parseObjectFromElement("camera3D", this->getCamera3D());
526 }
527 
528 void ViewGroupData::setRegistrationMode(REGISTRATION_STATUS mode)
529 {
530  ViewGroupData::Options options = this->getOptions();
531 
532  options.mShowLandmarks = false;
533  options.mShowPointPickerProbe = false;
534 
535  if (mode == rsIMAGE_REGISTRATED)
536  {
537  options.mShowLandmarks = true;
538  options.mShowPointPickerProbe = true;
539  }
540  if (mode == rsPATIENT_REGISTRATED)
541  {
542  options.mShowLandmarks = true;
543  options.mShowPointPickerProbe = false;
544  }
545 
546  this->setOptions(options);
547 }
548 
549 
550 } // namespace cx
int getPriority(DataPtr data)
static DataViewProperties createSlice3D()
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:56
void reportError(QString msg)
Definition: cxLogger.cpp:92
void initializeGlobal2DZoom(SyncedValuePtr val)
A mesh data set.
Definition: cxMesh.h:61
CameraDataPtr getCamera3D()
void addXml(QDomNode &dataNode)
static DataViewProperties createDefault()
PlaneTypeCollection getSliceDefinitions()
boost::shared_ptr< DataMetric > DataMetricPtr
Definition: cxDataMetric.h:95
void parseXml(QDomNode dataNode)
std::vector< QDomElement > getDuplicateElements(QString name)
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
std::vector< ImagePtr > getImagesAndChangingImagesFromTrackedStreams(DataViewProperties properties, bool include2D=false) const
SyncedValuePtr getGroup2DZoom()
void parseXml(QDomNode dataNode)
SyncedValuePtr getGlobal2DZoom()
DataViewProperties getProperties(QString uid)
ptAXIAL
a slice seen from the top of the patient
Definition: cxDefinitions.h:56
void setProperties(QString uid, DataViewProperties properties)
static DataViewProperties createSlice2D()
static StringListPropertyPtr initialize(const QString &uid, QString name, QString help, QStringList value, QStringList range, QDomNode root=QDomNode())
void addObjectToElement(QString name, T object)
static DataViewProperties create3D()
boost::shared_ptr< class Data > DataPtr
std::vector< MeshPtr > getMeshes(DataViewProperties properties) const
ptSAGITTAL
a slice seen from the side of the patient
Definition: cxDefinitions.h:56
static PlaneTypeCollection fromString(QString input, PlaneTypeCollection defVal=PlaneTypeCollection())
void addData(QString uid)
void addDataSorted(QString uid)
add data in a predefined ordering: CT/MR/SC/US/USA/Mesh/Metrics
std::vector< TrackedStreamPtr > getTracked2DStreams(DataViewProperties properties) const
static SyncedValuePtr create(QVariant val=QVariant())
A volumetric data set.
Definition: cxImage.h:66
QDomElement addTextToElement(QString name, QString text)
Options getOptions() const
void addXml(QDomNode &dataNode)
bool containsAnyFlagsIn(DataViewProperties required) const
static DataViewProperties createFull()
std::vector< ImagePtr > getImages(DataViewProperties properties) const
std::vector< TrackedStreamPtr > getTrackedStreams(DataViewProperties properties) const
void dataViewPropertiesChanged(QString uid)
void changed()
emit when the underlying data value is changed: The user interface will be updated.
static DataViewProperties createVolume3D()
bool dataTypeSort(const DataPtr data1, const DataPtr data2)
bool removeData(QString uid)
boost::shared_ptr< class StringListProperty > StringListPropertyPtr
QString parseTextFromElement(QString name)
void setVideoSource(QString uid)
boost::shared_ptr< class CoreServices > CoreServicesPtr
Definition: cxCameraStyle.h:59
DataViewProperties removeFlagsIn(DataViewProperties rhs) const
void parseObjectFromElement(QString name, T object)
DataViewProperties addFlagsIn(DataViewProperties rhs) const
void videoSourceChanged(QString uid)
boost::shared_ptr< class SyncedValue > SyncedValuePtr
Definition: cxViewGroup.h:51
void setRegistrationMode(REGISTRATION_STATUS mode)
StringListPropertyPtr getSliceDefinitionProperty()
ViewGroupData(CoreServicesPtr services)
std::vector< DataPtr > getData(DataViewProperties properties=DataViewProperties::createFull()) const
Base class for all Data Metrics.
Definition: cxDataMetric.h:64
void setSliceDefinitions(PlaneTypeCollection val)
QString enum2string(const ENUM &val)
QString getVideoSource() const
void setOptions(Options options)
rsIMAGE_REGISTRATED