comparison OrthancStone/Sources/Toolbox/DicomStructuredReport.cpp @ 2098:4288d635d77e dicom-sr

first rendering of dicom-sr
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 08 Nov 2023 17:23:31 +0100
parents a9e23ef9ee09
children 129cb165ea8d
comparison
equal deleted inserted replaced
2097:a9e23ef9ee09 2098:4288d635d77e
116 } 116 }
117 117
118 118
119 namespace OrthancStone 119 namespace OrthancStone
120 { 120 {
121 void DicomStructuredReport::ReferencedInstance::AddFrame(unsigned int frame) 121 void DicomStructuredReport::Structure::Copy(const Structure& other)
122 { 122 {
123 frames_.insert(frame); 123 if (other.HasFrameNumber())
124 } 124 {
125 125 SetFrameNumber(other.GetFrameNumber());
126 126 }
127 class DicomStructuredReport::Structure : public boost::noncopyable 127
128 { 128 if (other.HasProbabilityOfCancer())
129 private: 129 {
130 std::string sopInstanceUid_; 130 SetProbabilityOfCancer(other.GetProbabilityOfCancer());
131 bool hasFrameNumber_; 131 }
132 unsigned int frameNumber_; 132 }
133 bool hasProbabilityOfCancer_; 133
134 float probabilityOfCancer_; 134
135 135 DicomStructuredReport::Structure::Structure(const std::string& sopInstanceUid) :
136 protected: 136 sopInstanceUid_(sopInstanceUid),
137 void Copy(const Structure& other) 137 hasFrameNumber_(false),
138 { 138 hasProbabilityOfCancer_(false)
139 if (other.HasFrameNumber()) 139 {
140 { 140 }
141 SetFrameNumber(other.GetFrameNumber()); 141
142 } 142
143 143 void DicomStructuredReport::Structure::SetFrameNumber(unsigned int frame)
144 if (other.HasProbabilityOfCancer()) 144 {
145 { 145 hasFrameNumber_ = true;
146 SetProbabilityOfCancer(other.GetProbabilityOfCancer()); 146 frameNumber_ = frame;
147 } 147 }
148 } 148
149 149
150 public: 150 void DicomStructuredReport::Structure::SetProbabilityOfCancer(float probability)
151 Structure(const std::string& sopInstanceUid) : 151 {
152 sopInstanceUid_(sopInstanceUid), 152 if (probability < 0 ||
153 hasFrameNumber_(false), 153 probability > 100)
154 hasProbabilityOfCancer_(false) 154 {
155 { 155 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
156 } 156 }
157 157 else
158 virtual ~Structure() 158 {
159 { 159 hasProbabilityOfCancer_ = true;
160 } 160 probabilityOfCancer_ = probability;
161 161 }
162 virtual Structure* Clone() const = 0; 162 }
163 163
164 const std::string& GetSopInstanceUid() const 164
165 { 165 unsigned int DicomStructuredReport::Structure::GetFrameNumber() const
166 return sopInstanceUid_; 166 {
167 } 167 if (hasFrameNumber_)
168 168 {
169 void SetFrameNumber(unsigned int frame) 169 return frameNumber_;
170 { 170 }
171 hasFrameNumber_ = true; 171 else
172 frameNumber_ = frame; 172 {
173 } 173 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
174 174 }
175 void SetProbabilityOfCancer(float probability) 175 }
176 { 176
177 if (probability < 0 || 177 float DicomStructuredReport::Structure::GetProbabilityOfCancer() const
178 probability > 100) 178 {
179 { 179 if (hasProbabilityOfCancer_)
180 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 180 {
181 } 181 return probabilityOfCancer_;
182 else 182 }
183 { 183 else
184 hasProbabilityOfCancer_ = true; 184 {
185 probabilityOfCancer_ = probability; 185 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
186 } 186 }
187 } 187 }
188 188
189 bool HasFrameNumber() const 189
190 { 190 DicomStructuredReport::Point::Point(const std::string& sopInstanceUid,
191 return hasFrameNumber_; 191 double x,
192 } 192 double y) :
193 193 Structure(sopInstanceUid),
194 bool HasProbabilityOfCancer() const 194 point_(x, y)
195 { 195 {
196 return hasProbabilityOfCancer_; 196 }
197 } 197
198 198
199 unsigned int GetFrameNumber() const 199 DicomStructuredReport::Structure* DicomStructuredReport::Point::Clone() const
200 { 200 {
201 if (hasFrameNumber_) 201 std::unique_ptr<Point> cloned(new Point(GetSopInstanceUid(), point_.GetX(), point_.GetY()));
202 { 202 cloned->Copy(*this);
203 return frameNumber_; 203 return cloned.release();
204 } 204 }
205 else 205
206 { 206
207 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 207 DicomStructuredReport::Polyline::Polyline(const std::string& sopInstanceUid,
208 } 208 const float* points,
209 } 209 unsigned long pointsCount) :
210 210 Structure(sopInstanceUid)
211 float GetProbabilityOfCancer() const 211 {
212 { 212 if (pointsCount % 2 != 0)
213 if (hasProbabilityOfCancer_) 213 {
214 { 214 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
215 return probabilityOfCancer_; 215 }
216 } 216
217 else 217 points_.reserve(pointsCount / 2);
218 { 218
219 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 219 for (unsigned long i = 0; i < pointsCount; i += 2)
220 } 220 {
221 } 221 points_.push_back(ScenePoint2D(points[i], points[i + 1]));
222 }; 222 }
223 223 }
224 224
225 class DicomStructuredReport::Point : public Structure 225
226 { 226 DicomStructuredReport::Polyline::Polyline(const std::string& sopInstanceUid,
227 private: 227 const std::vector<ScenePoint2D>& points) :
228 ScenePoint2D point_; 228 Structure(sopInstanceUid),
229 229 points_(points)
230 public: 230 {
231 Point(const std::string& sopInstanceUid, 231 }
232 double x, 232
233 double y) : 233
234 Structure(sopInstanceUid), 234 DicomStructuredReport::Structure* DicomStructuredReport::Polyline::Clone() const
235 point_(x, y) 235 {
236 { 236 std::unique_ptr<Polyline> cloned(new Polyline(GetSopInstanceUid(), points_));
237 } 237 cloned->Copy(*this);
238 238 return cloned.release();
239 virtual Structure* Clone() const 239 }
240 { 240
241 std::unique_ptr<Point> cloned(new Point(GetSopInstanceUid(), point_.GetX(), point_.GetY())); 241
242 cloned->Copy(*this); 242 const ScenePoint2D& DicomStructuredReport::Polyline::GetPoint(size_t i) const
243 return cloned.release(); 243 {
244 } 244 if (i >= points_.size())
245 245 {
246 const ScenePoint2D& GetPoint() const 246 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
247 { 247 }
248 return point_; 248 else
249 } 249 {
250 }; 250 return points_[i];
251 251 }
252 252 }
253 class DicomStructuredReport::Polyline : public Structure
254 {
255 private:
256 std::vector<ScenePoint2D> points_;
257
258 public:
259 Polyline(const std::string& sopInstanceUid,
260 const float* points,
261 unsigned long pointsCount) :
262 Structure(sopInstanceUid)
263 {
264 if (pointsCount % 2 != 0)
265 {
266 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
267 }
268
269 points_.reserve(pointsCount / 2);
270
271 for (unsigned long i = 0; i < pointsCount; i += 2)
272 {
273 points_.push_back(ScenePoint2D(points[i], points[i + 1]));
274 }
275 }
276
277 Polyline(const std::string& sopInstanceUid,
278 const std::vector<ScenePoint2D>& points) :
279 Structure(sopInstanceUid),
280 points_(points)
281 {
282 }
283
284 virtual Structure* Clone() const
285 {
286 std::unique_ptr<Polyline> cloned(new Polyline(GetSopInstanceUid(), points_));
287 cloned->Copy(*this);
288 return cloned.release();
289 }
290
291 size_t GetSize() const
292 {
293 return points_.size();
294 }
295
296 const ScenePoint2D& GetPoint(size_t i) const
297 {
298 if (i >= points_.size())
299 {
300 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
301 }
302 else
303 {
304 return points_[i];
305 }
306 }
307 };
308 253
309 254
310 void DicomStructuredReport::AddStructure(const std::string& sopInstanceUid, 255 void DicomStructuredReport::AddStructure(const std::string& sopInstanceUid,
311 DcmItem& group, 256 DcmItem& group,
312 bool hasFrameNumber, 257 bool hasFrameNumber,
571 { 516 {
572 assert(it->second != NULL); 517 assert(it->second != NULL);
573 instancesInformation_[it->first] = new ReferencedInstance(*it->second); 518 instancesInformation_[it->first] = new ReferencedInstance(*it->second);
574 } 519 }
575 520
576 for (std::list<Structure*>::const_iterator it = other.structures_.begin(); it != other.structures_.end(); ++it) 521 for (std::deque<Structure*>::const_iterator it = other.structures_.begin(); it != other.structures_.end(); ++it)
577 { 522 {
578 assert(*it != NULL); 523 assert(*it != NULL);
579 structures_.push_back((*it)->Clone()); 524 structures_.push_back((*it)->Clone());
580 } 525 }
581 } 526 }
582 527
583 528
584 DicomStructuredReport::~DicomStructuredReport() 529 DicomStructuredReport::~DicomStructuredReport()
585 { 530 {
586 for (std::list<Structure*>::iterator it = structures_.begin(); it != structures_.end(); ++it) 531 for (std::deque<Structure*>::iterator it = structures_.begin(); it != structures_.end(); ++it)
587 { 532 {
588 assert(*it != NULL); 533 assert(*it != NULL);
589 delete *it; 534 delete *it;
590 } 535 }
591 536
646 orderedInstances_[i], 591 orderedInstances_[i],
647 found->second->GetSopClassUid(), *frame)); 592 found->second->GetSopClassUid(), *frame));
648 } 593 }
649 } 594 }
650 } 595 }
651 } 596
597
598 const DicomStructuredReport::Structure& DicomStructuredReport::GetStructure(size_t index) const
599 {
600 if (index >= structures_.size())
601 {
602 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
603 }
604 else
605 {
606 assert(structures_[index] != NULL);
607 return *structures_[index];
608 }
609 }
610 }