Mercurial > hg > orthanc-stone
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 } |