CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxProbeDefinitionFromStringMessages.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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
13 
14 #include <vtkXMLDataElement.h>
15 #include <vtkXMLUtilities.h>
16 #include <vtkImageData.h>
17 #include <igtlioUsSectorDefinitions.h>
18 
19 #include "cxLogger.h"
20 
21 namespace cx
22 {
23 
24 
25 bool validSpacing(Vector3D spacing)
26 {
27  //Assuming (1, 1, 1) is an invalid spacing
28  if((similar(spacing[0], 1.0) && similar(spacing[0], 1.0) && similar(spacing[0], 1.0)) ||
29  similar(spacing[0], 0.0) || similar(spacing[1], 0.0) || similar(spacing[2], 0.0) )
30  return false;
31  return true;
32 }
33 
41 struct SectorInfo
42 {
43  const int tooLarge = 100000;
44 
45  ProbeDefinition::TYPE mProbeType; //0 = unknown, 1 = sector, 2 = linear
46 
48 
49  //Spacing are sent as separate messages, should be sent with image in the future.
50  double mSpacingX;
51  double mSpacingY;
52  double mSpacingZ;
53 
54  //new standard
55  std::vector<double> mOrigin;
56  std::vector<double> mAngles;
57  std::vector<double> mBoundingBox;
58  std::vector<double> mDepths;
59  double mLinearWidth;
60 
62 
64  {
65  reset();
66  }
67  void reset()
68  {
69  mHaveChanged = true;
70  mProbeType = ProbeDefinition::tNONE;
71 
72  //new standard
73  mOrigin.clear();
74  mAngles.clear();
75  mBoundingBox.clear();
76  mDepths.clear();
77  mLinearWidth = tooLarge;
78 
79  mSpacingX = tooLarge;
80  mSpacingY = tooLarge;
81  mSpacingZ = 1.0; //Spacing z may not be received
82 
83  mImage = ImagePtr();
84  }
85  bool isValid()
86  {
87  if(!mImage)
88  return false;
89 
90  bool retval = true;
91  retval = retval && mImage;
92  retval = retval && ((mProbeType == ProbeDefinition::tSECTOR) || (mProbeType == ProbeDefinition::tLINEAR));
93  retval = retval && (mOrigin.size() == 3);
94  retval = retval && ((mAngles.size() == 2) || (mAngles.size() == 4));//2D == 2, 3D == 4
95  retval = retval && ((mBoundingBox.size() == 4) || (mBoundingBox.size() == 6)); //2D == 4, 3D == 6
96  retval = retval && (mDepths.size() == 2);
97  if(mProbeType == ProbeDefinition::tLINEAR)
98  retval = retval && (mLinearWidth < tooLarge);//Only for linear probes
99 
100  Vector3D spacing = mImage->getSpacing();
101  if(!validSpacing(spacing))
102  {
103  retval = retval && (mSpacingX < tooLarge);
104  retval = retval && (mSpacingY < tooLarge);
105  retval = retval && !similar(mSpacingX, 0);
106  retval = retval && !similar(mSpacingY, 0);
107  retval = retval && !similar(mSpacingZ, 0);
108  }
109 
110  return retval;
111  }
112 
113  bool haveChanged()
114  {
115  return mHaveChanged;
116  }
117 
118 };
119 
120 
122  mSectorInfo(new SectorInfo)
123 {}
124 
126 {
127  mSectorInfo->reset();
128 }
129 
130 void ProbeDefinitionFromStringMessages::parseStringMessage(igtlioBaseConverter::HeaderData header, QString message)
131 {
132  QString name = QString(header.deviceName.c_str());
133  QString value = message;
134  this->parseValue(name, value);
135 }
136 
147 std::vector<double> ProbeDefinitionFromStringMessages::toDoubleVector(QString values, QString separator) const
148 {
149  std::vector<double> retval;
150  QStringList valueList = values.split(separator);
151  for (int i = 0; i < valueList.size(); ++i)
152  {
153  double doublevalue = valueList[i].toDouble();
154  retval.push_back(doublevalue);
155  }
156  return retval;
157 }
158 
159 void ProbeDefinitionFromStringMessages::parseValue(QString name, QString value)
160 {
161  int intValue = value.toInt();
162  double doubleValue = value.toDouble();
163  std::vector<double> doubleVector = toDoubleVector(value);
164 
165  //if(!doubleVector.empty())
166  //{
167  // std::cout << "parseStringMessage name: " << name << " Vector: ";
168  // for (int i = 0; i < doubleVector.size(); ++i)
169  // std::cout << doubleVector[i] << " ";
170  // std::cout << endl;
171  //}
172 
173  if (name == IGTLIO_KEY_PROBE_TYPE)
174  {
175  if (mSectorInfo->mProbeType != intValue)
176  {
177  mSectorInfo->mProbeType = static_cast<ProbeDefinition::TYPE>(intValue);
178  }
179  }
180  //New standard
181  else if (name == IGTLIO_KEY_ORIGIN)
182  {
183  if(mSectorInfo->mOrigin != doubleVector)
184  {
185  mSectorInfo->mHaveChanged = true;
186  mSectorInfo->mOrigin = doubleVector;
187  }
188  }
189  else if (name == IGTLIO_KEY_ANGLES)
190  {
191  if(mSectorInfo->mAngles != doubleVector)
192  {
193  mSectorInfo->mHaveChanged = true;
194  mSectorInfo->mAngles = doubleVector;
195  }
196  }
197  else if (name == IGTLIO_KEY_BOUNDING_BOX)
198  {
199  if(mSectorInfo->mBoundingBox != doubleVector)
200  {
201  mSectorInfo->mHaveChanged = true;
202  mSectorInfo->mBoundingBox = doubleVector;
203  }
204  }
205  else if (name == IGTLIO_KEY_DEPTHS)
206  {
207  if(mSectorInfo->mDepths != doubleVector)
208  {
209  mSectorInfo->mHaveChanged = true;
210  mSectorInfo->mDepths = doubleVector;
211  }
212  }
213  else if (name == IGTLIO_KEY_LINEAR_WIDTH)
214  {
215  if(mSectorInfo->mLinearWidth != doubleValue)
216  {
217  mSectorInfo->mHaveChanged = true;
218  mSectorInfo->mLinearWidth = doubleValue;
219  }
220  }
221  else if (name == IGTLIO_KEY_SPACING_X)
222  {
223  if(mSectorInfo->mSpacingX != doubleValue)
224  {
225  mSectorInfo->mHaveChanged = true;
226  mSectorInfo->mSpacingX = doubleValue;
227  }
228 
229  }
230  else if (name == IGTLIO_KEY_SPACING_Y)
231  {
232  if(mSectorInfo->mSpacingY != doubleValue)
233  {
234  mSectorInfo->mHaveChanged = true;
235  mSectorInfo->mSpacingY = doubleValue;
236  }
237  }
238  else if (name == "SpacingZ") //IGTLIO_KEY_SPACING_Z
239  {
240  if(mSectorInfo->mSpacingZ != doubleValue)
241  {
242  mSectorInfo->mHaveChanged = true;
243  mSectorInfo->mSpacingZ = doubleValue;
244  }
245  }
246 }
247 
249 {
250  mSectorInfo->mImage = image;
251 }
252 
254 {
255  return mSectorInfo->isValid();
256 }
257 
259 {
260  return mSectorInfo->haveChanged();
261 }
262 
264 {
265  mSectorInfo->mHaveChanged = false;
266 
267  if(!this->haveValidValues())
268  return ProbeDefinitionPtr();
269 
270  Vector3D spacing = mSectorInfo->mImage->getSpacing();
271  //CX_LOG_DEBUG() << "Spacing from image: " << spacing;
272  //Send spacing as messages for now. Should be sent together with image.
273  //The default should be to use the spacing from the image,
274  //not from meta info or string messages
275  // BK don't change image spacing in image when depth is changed
276  //if(validSpacing(spacing))
277  //{
278  // CX_LOG_DEBUG() << "Using spacing from image: " << spacing
279  // << " instead of spacing from meta data: " << mSectorInfo->mSpacingX << " " << mSectorInfo->mSpacingY << " " << mSectorInfo->mSpacingZ;
280  //}
281  //else
282  {
283  //Use spacing from meta data if not correct spacing in image.
284  //NB: Current implementation of igtlioImageConverter::IGTLToVTKImageData discards incoming spacing.
285  //It is being set to (1, 1, 1)
286  mSectorInfo->mImage->getBaseVtkImageData()->SetSpacing(mSectorInfo->mSpacingX, mSectorInfo->mSpacingY, mSectorInfo->mSpacingZ);
287  spacing = mSectorInfo->mImage->getSpacing();
288  }
289  Vector3D origin_p(mSectorInfo->mOrigin[0], mSectorInfo->mOrigin[1], mSectorInfo->mOrigin[2]);
290 
291  ProbeDefinitionPtr probeDefinition = this->initProbeDefinition();
292  probeDefinition->setUid(uid);
293  probeDefinition->setOrigin_p(origin_p);
294  probeDefinition->setSpacing(spacing);
295  probeDefinition->setClipRect_p(this->getBoundinBox());
296  probeDefinition->setSector(mSectorInfo->mDepths[0], mSectorInfo->mDepths[1], this->getWidth());
297  probeDefinition->setSize(this->getSize());
298  probeDefinition->setUseDigitalVideo(true);
299 
300  return probeDefinition;
301 }
302 
303 ProbeDefinitionPtr ProbeDefinitionFromStringMessages::initProbeDefinition()
304 {
305  ProbeDefinitionPtr probeDefinition;
306  probeDefinition = ProbeDefinitionPtr(new ProbeDefinition(mSectorInfo->mProbeType));
307 
308  if (mSectorInfo->mProbeType == ProbeDefinition::tNONE)
309  {
310  CX_LOG_ERROR() << "ProbeDefinitionFromStringMessages::initProbeDefinition: Incorrect probe type: " << mSectorInfo->mProbeType;
311  }
312  return probeDefinition;
313 }
314 
315 double ProbeDefinitionFromStringMessages::getWidth()
316 {
317  double width = 0;
318  if(mSectorInfo->mProbeType == ProbeDefinition::tLINEAR)
319  {
320  width = mSectorInfo->mLinearWidth;
321  }
322  else if (mSectorInfo->mProbeType == ProbeDefinition::tSECTOR)
323  {
324  width = mSectorInfo->mAngles[1] - mSectorInfo->mAngles[0];
325  }
326  return width;
327 }
328 
329 QSize ProbeDefinitionFromStringMessages::getSize()
330 {
331  Eigen::Array3i dimensions(mSectorInfo->mImage->getBaseVtkImageData()->GetDimensions());
332  QSize size(dimensions[0], dimensions[1]);
333  return size;
334 }
335 
336 DoubleBoundingBox3D ProbeDefinitionFromStringMessages::getBoundinBox() const
337 {
338  DoubleBoundingBox3D retval(mSectorInfo->mBoundingBox[0], mSectorInfo->mBoundingBox[1],
339  mSectorInfo->mBoundingBox[2], mSectorInfo->mBoundingBox[3],
340  this->getBoundingBoxThirdDimensionStart(),
341  this->getBoundingBoxThirdDimensionEnd());
342  return retval;
343 }
344 
345 double ProbeDefinitionFromStringMessages::getBoundingBoxThirdDimensionStart() const
346 {
347  if(mSectorInfo->mBoundingBox.size() == 6)
348  return mSectorInfo->mBoundingBox[4];
349  else
350  return 0;
351 }
352 
353 double ProbeDefinitionFromStringMessages::getBoundingBoxThirdDimensionEnd() const
354 {
355  if(mSectorInfo->mBoundingBox.size() == 6)
356  return mSectorInfo->mBoundingBox[5];
357  else
358  return 0;
359 }
360 
361 }//cx
US beam is emitted straight forward.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
bool validSpacing(Vector3D spacing)
US beam is emitted radially in a flat cone.
#define CX_LOG_ERROR
Definition: cxLogger.h:99
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.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
void parseStringMessage(igtlioBaseConverter::HeaderData header, QString message)
Definition of characteristics for an Ultrasound Probe Sector.
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
boost::shared_ptr< class ProbeDefinition > ProbeDefinitionPtr
Namespace for all CustusX production code.