Fraxinus  2023.01.05-dev+develop.0da12
An IGT application
cxProbeDefinition.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 
12 
13 #include "cxProbeDefinition.h"
14 #include <QDomNode>
15 #include "cxTypeConversions.h"
16 #include <iostream>
17 #include "cxLogger.h"
18 #include "cxImage.h"
19 
20 namespace cx
21 {
22 
23 namespace
24 {
25  double loadAttribute(QDomNode dataNode, QString name, double defVal)
26  {
27  QString text = dataNode.toElement().attribute(name);
28  bool ok;
29  double val = text.toDouble(&ok);
30  if (ok)
31  return val;
32  return defVal;
33  }
34 }
35 
36 // --------------------------------------------------------
37 // --------------------------------------------------------
38 // --------------------------------------------------------
39 
40 
42  mType(type), mDepthStart(0), mDepthEnd(0), mWidth(0),
43  mTemporalCalibration(0), mCenterOffset(0), mSoundSpeedCompensationFactor(1.0),
44  mUid("default"),
45  mOrigin_p(0, 0, 0), mSpacing(-1, -1, -1), mClipRect_p(0, 0, 0, 0), mSize(0, 0),
46  mDigital(false)
47 {}
48 
49 void ProbeDefinition::addXml(QDomNode dataNode) const
50 {
51  QDomElement elem = dataNode.toElement();
52  elem.setAttribute("type", qstring_cast(mType));
53  elem.setAttribute("depthStart", qstring_cast(mDepthStart));
54  elem.setAttribute("depthEnd", qstring_cast(mDepthEnd));
55  elem.setAttribute("width", qstring_cast(mWidth));
56 
57  elem.setAttribute("temporalCalibration", qstring_cast(mTemporalCalibration));
58  elem.setAttribute("centerOffset", qstring_cast(mCenterOffset));
59 
60  elem.setAttribute("uid", qstring_cast(mUid));
61 
62  QDomElement imageNode = dataNode.ownerDocument().createElement(Image::getTypeName());
63  this->addImageXml(imageNode);
64  dataNode.appendChild(imageNode);
65 }
66 
67 void ProbeDefinition::parseXml(QDomNode dataNode)
68 {
69  QDomElement elem = dataNode.toElement();
70 
71  mType = static_cast<TYPE>(elem.attribute("type").toInt());
72  mDepthStart = loadAttribute(elem, "depthStart", 0);
73  mDepthEnd = loadAttribute(elem, "depthEnd", 0);
74  mWidth = loadAttribute(elem, "width", 0);
75 
76  mTemporalCalibration = loadAttribute(elem, "temporalCalibration", 0);
77  mCenterOffset = loadAttribute(elem, "centerOffset", 0);
78  mUid = elem.attribute("uid");
79 
80  QDomNode imageNode = dataNode.namedItem(Image::getTypeName());
81  this->parseImageXml(imageNode);
82 }
83 
84 void ProbeDefinition::addImageXml(QDomNode dataNode) const
85 {
86  QDomElement elem = dataNode.toElement();
87 
88  elem.setAttribute("origin_p", qstring_cast(mOrigin_p));
89  elem.setAttribute("spacing", qstring_cast(mSpacing));
90  elem.setAttribute("clipRect_p", qstring_cast(mClipRect_p));
91  elem.setAttribute("width", qstring_cast(mSize.width()));
92  elem.setAttribute("height", qstring_cast(mSize.height()));
93 }
94 
95 void ProbeDefinition::parseImageXml(QDomNode dataNode)
96 {
97  QDomElement elem = dataNode.toElement();
98 
99  mOrigin_p = Vector3D::fromString(elem.attribute("origin_p"));
100  mSpacing = Vector3D::fromString(elem.attribute("spacing"));
101  mClipRect_p = DoubleBoundingBox3D::fromString(elem.attribute("clipRect_p"));
102  mSize.setWidth(loadAttribute(elem, "width", 0));
103  mSize.setHeight(loadAttribute(elem, "height", 0));
104 }
105 
107 {
108  mTemporalCalibration = value;
109 }
110 
112 {
113  mType = type;
114 }
115 
116 void ProbeDefinition::setSector(double depthStart, double depthEnd, double width, double centerOffset)
117 {
118  mDepthStart=depthStart;
119  mDepthEnd=depthEnd;
120  mWidth=width;
121  mCenterOffset=centerOffset;
122 }
123 
125 {
126  return mType;
127 }
128 
130 {
131  return mDepthStart;
132 }
133 
135 {
136  return mDepthEnd;
137 }
138 
140 {
141  return mWidth;
142 }
143 
145 {
146  return mTemporalCalibration;
147 }
148 
150 {
151  return mCenterOffset;
152 }
153 
154 void ProbeDefinition::resample(QSize newSize)
155 {
156  if (newSize==mSize)
157  return;
158 
159  Vector3D factor(double(newSize.width())/mSize.width(), double(newSize.height())/mSize.height(), 1);
160 
161  mOrigin_p = multiply_elems(mOrigin_p, factor);
162  mSpacing = divide_elems(mSpacing, factor);
163 
164  Vector3D cr0 = multiply_elems(mClipRect_p.corner(0,0,0), factor);
165  Vector3D cr1 = multiply_elems(mClipRect_p.corner(1,1,1), factor);
166  mClipRect_p = DoubleBoundingBox3D(cr0, cr1);
167 
168  mSize = newSize;
169 }
170 
171 QString ProbeDefinition::getUid() const
172 {
173  return mUid;
174 }
175 
176 void ProbeDefinition::setUid(QString uid)
177 {
178  mUid = uid;
179 }
180 
182 {
183  // cliprect and sector data are connected to linear probes:
184  if (mType==tLINEAR)
185  {
186  mClipRect_p[0] = mOrigin_p[0] - mWidth/2/mSpacing[0];
187  mClipRect_p[1] = mOrigin_p[0] + mWidth/2/mSpacing[0];
188 
189  mClipRect_p[2] = mOrigin_p[1] + mDepthStart/mSpacing[1];
190  mClipRect_p[3] = mOrigin_p[1] + mDepthEnd/mSpacing[1];
191  }
192 }
193 
195 {
196  // cliprect and sector data are connected to linear probes:
197  if (mType==tLINEAR)
198  {
199  mWidth = 2*std::max(fabs(mClipRect_p[0] - mOrigin_p[0]), fabs(mClipRect_p[1] - mOrigin_p[0])) * mSpacing[0];
200  mDepthStart = (mClipRect_p[2] - mOrigin_p[1]) * mSpacing[1];
201  mDepthEnd = (mClipRect_p[3] - mOrigin_p[1]) * mSpacing[1];
202  }
203 }
204 
206 {
207  if(similar(factor, 1.0))
208  return;
209  mSpacing[1] = mSpacing[1] * factor / mSoundSpeedCompensationFactor;
210  mSoundSpeedCompensationFactor = factor;
211 
212  if (this->getType() != ProbeDefinition::tLINEAR)
213  reportWarning("Sound speed compensation is applied to spacing[1], i.e. it is correct for linear probes and approxomate for other probes. Factor: " + qstring_cast(factor));
214 }
215 
217 {
218  return mSoundSpeedCompensationFactor;
219 }
220 
221 //Should be transform_uMv(p) (input in pixels, output in mm)
222 Vector3D ProbeDefinition::transform_p_to_u(const Vector3D& q_p) const
223 {
224  Vector3D c(q_p[0], double(mSize.height()) - q_p[1] - 1, -q_p[2]);
225  c = multiply_elems(c, mSpacing);
226  return c;
227 }
228 
230 {
231  return this->transform_p_to_u(mOrigin_p);
232 }
233 
235 {
236  Vector3D p0 = transform_p_to_u(mClipRect_p.corner(0,0,0));
237  Vector3D p1 = transform_p_to_u(mClipRect_p.corner(1,1,1));
238  return DoubleBoundingBox3D(p0,p1);
239 }
240 
242 {
243  return mOrigin_p;
244 }
245 
247 {
248  return mSpacing;
249 }
250 
252 {
253  return mClipRect_p;
254 }
255 
257 {
258  return mSize;
259 }
260 
262 {
263  mOrigin_p = origin_p;
264 }
265 
267 {
268  mSpacing = spacing;
269 }
270 
272 {
273  mClipRect_p = clipRect_p;
274 }
275 
276 void ProbeDefinition::setSize(QSize size)
277 {
278  mSize = size;
279 }
280 
282 {
283  mDigital = val;
284 }
285 
287 {
288  return mDigital;
289 }
290 
291 void ProbeDefinition::setVariable(QString variableName, QVariant value)
292 {
293  mAdditionalVariables[variableName] = value;
294 }
295 
296 QVariant ProbeDefinition::getVariable(QString variableName)
297 {
298  if(!mAdditionalVariables.contains(variableName))
299  CX_LOG_ERROR(QString("Variable %1 don't exist in ProbeDefinition with uid %2").arg(variableName).arg(this->mUid));
300  return mAdditionalVariables[variableName];
301 }
302 
303 } //cx
QString qstring_cast(const T &val)
double getWidth() const
void addXml(QDomNode dataNode) const
Vector3D corner(int x, int y, int z) const
Vector3D divide_elems(const Vector3D &a, const Vector3D &b)
perform element-wise division of a and b.
Definition: cxVector3D.cpp:36
void setSpacing(Vector3D spacing)
double getCenterOffset() const
QVariant getVariable(QString variableName)
US beam is emitted straight forward.
static DoubleBoundingBox3D fromString(const QString &text)
construct a bb from a string containing 6 whitespace-separated numbers
void resample(QSize mSize)
Set a new image size. Resample all other parameters to match this new image size, keeping sizes in mi...
double getSoundSpeedCompensationFactor() const
QString getUid() const
void setSector(double depthStart, double depthEnd, double width, double centerOffset=0)
double getDepthStart() const
void parseXml(QDomNode dataNode)
double getDepthEnd() const
Vector3D getOrigin_p() const
void setOrigin_p(Vector3D origin_p)
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
void setTemporalCalibration(double value)
void setUid(QString uid)
#define CX_LOG_ERROR
Definition: cxLogger.h:99
void setUseDigitalVideo(bool val)
RTSource is digital (eg. US sector is set digitally, not read from .xml file)
void setClipRect_p(DoubleBoundingBox3D clipRect_p)
static QString getTypeName()
Definition: cxImage.h:126
DoubleBoundingBox3D getClipRect_u() const
sector clipping rect in image space u. (lower-left corner origin)
void applySoundSpeedCompensationFactor(double factor)
Compensate for soundspeed for linear probes.
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.
ProbeDefinition(TYPE type=tNONE)
Vector3D getOrigin_u() const
probe origin in image space u. (lower-left corner origin)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
Vector3D multiply_elems(const Vector3D &a, const Vector3D &b)
perform element-wise multiplication of a and b.
Definition: cxVector3D.cpp:31
Vector3D getSpacing() const
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
double getTemporalCalibration() const
void setVariable(QString variableName, QVariant value)
bool getUseDigitalVideo() const
DoubleBoundingBox3D getClipRect_p() const
void setSize(QSize size)
Namespace for all CustusX production code.