comparison Framework/Loaders/DicomStructureSetLoader.cpp @ 1381:f4a06ad1580b

Branch broker is now the new default
author Benjamin Golinvaux <bgo@osimis.io>
date Wed, 22 Apr 2020 14:05:47 +0200
parents 8a0a62189f46 0d6a01ffa1dd
children ffe9beb7c5d3
comparison
equal deleted inserted replaced
1375:4431ffdcc2a4 1381:f4a06ad1580b
27 27
28 #include <Core/Toolbox.h> 28 #include <Core/Toolbox.h>
29 29
30 #include <algorithm> 30 #include <algorithm>
31 31
32 #if 0
33 bool logbgo233 = false;
34 bool logbgo115 = false;
35 #endif
36
37 namespace OrthancStone 32 namespace OrthancStone
38 { 33 {
39 34
40 #if 0 35 #if 0
41 void DumpDicomMap(std::ostream& o, const Orthanc::DicomMap& dicomMap) 36 void DumpDicomMap(std::ostream& o, const Orthanc::DicomMap& dicomMap)
65 State(that), 60 State(that),
66 instanceId_(instanceId) 61 instanceId_(instanceId)
67 { 62 {
68 } 63 }
69 64
70 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) 65 virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
71 { 66 {
72 Json::Value tags; 67 Json::Value tags;
73 message.ParseJsonBody(tags); 68 message.ParseJsonBody(tags);
74 69
75 Orthanc::DicomMap dicom; 70 Orthanc::DicomMap dicom;
76 dicom.FromDicomAsJson(tags); 71 dicom.FromDicomAsJson(tags);
77 72
78 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>(); 73 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>();
79 74
80 loader.content_->AddReferencedSlice(dicom); 75 loader.content_->AddReferencedSlice(dicom);
81
82 loader.countProcessedInstances_ ++; 76 loader.countProcessedInstances_ ++;
83 assert(loader.countProcessedInstances_ <= loader.countReferencedInstances_); 77 assert(loader.countProcessedInstances_ <= loader.countReferencedInstances_);
78
79 loader.revision_++;
80 loader.SetStructuresUpdated();
84 81
85 if (loader.countProcessedInstances_ == loader.countReferencedInstances_) 82 if (loader.countProcessedInstances_ == loader.countReferencedInstances_)
86 { 83 {
87 // All the referenced instances have been loaded, finalize the RT-STRUCT 84 // All the referenced instances have been loaded, finalize the RT-STRUCT
88 loader.content_->CheckReferencedSlices(); 85 loader.content_->CheckReferencedSlices();
105 State(that), 102 State(that),
106 sopInstanceUid_(sopInstanceUid) 103 sopInstanceUid_(sopInstanceUid)
107 { 104 {
108 } 105 }
109 106
110 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) 107 virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
111 { 108 {
112 #if 0 109 #if 0
113 LOG(TRACE) << "DicomStructureSetLoader::LookupInstance::Handle() (SUCCESS)"; 110 LOG(TRACE) << "DicomStructureSetLoader::LookupInstance::Handle() (SUCCESS)";
114 #endif 111 #endif
115 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>(); 112 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>();
125 lookup[0]["ID"].type() != Json::stringValue || 122 lookup[0]["ID"].type() != Json::stringValue ||
126 lookup[0]["Type"].asString() != "Instance") 123 lookup[0]["Type"].asString() != "Instance")
127 { 124 {
128 std::stringstream msg; 125 std::stringstream msg;
129 msg << "Unknown resource! message.GetAnswer() = " << message.GetAnswer() << " message.GetAnswerHeaders() = "; 126 msg << "Unknown resource! message.GetAnswer() = " << message.GetAnswer() << " message.GetAnswerHeaders() = ";
130 for (OrthancRestApiCommand::HttpHeaders::const_iterator it = message.GetAnswerHeaders().begin(); 127 for (OrthancStone::OrthancRestApiCommand::HttpHeaders::const_iterator it = message.GetAnswerHeaders().begin();
131 it != message.GetAnswerHeaders().end(); ++it) 128 it != message.GetAnswerHeaders().end(); ++it)
132 { 129 {
133 msg << "\nkey: \"" << it->first << "\" value: \"" << it->second << "\"\n"; 130 msg << "\nkey: \"" << it->first << "\" value: \"" << it->second << "\"\n";
134 } 131 }
135 const std::string msgStr = msg.str(); 132 const std::string msgStr = msg.str();
138 } 135 }
139 136
140 const std::string instanceId = lookup[0]["ID"].asString(); 137 const std::string instanceId = lookup[0]["ID"].asString();
141 138
142 { 139 {
143 std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); 140 std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
144 command->SetHttpHeader("Accept-Encoding", "gzip"); 141 command->SetHttpHeader("Accept-Encoding", "gzip");
145 std::string uri = "/instances/" + instanceId + "/tags"; 142 std::string uri = "/instances/" + instanceId + "/tags";
146 command->SetUri(uri); 143 command->SetUri(uri);
147 command->SetPayload(new AddReferencedInstance(loader, instanceId)); 144 command->AcquirePayload(new AddReferencedInstance(loader, instanceId));
148 Schedule(command.release()); 145 Schedule(command.release());
149 } 146 }
150 } 147 }
151 }; 148 };
152 149
157 LoadStructure(DicomStructureSetLoader& that) : 154 LoadStructure(DicomStructureSetLoader& that) :
158 State(that) 155 State(that)
159 { 156 {
160 } 157 }
161 158
162 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) 159 virtual void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
163 { 160 {
164 #if 0
165 if (logbgo115)
166 LOG(TRACE) << "DicomStructureSetLoader::LoadStructure::Handle() (SUCCESS)";
167 #endif
168 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>(); 161 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>();
169 162
170 { 163 {
171 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer()); 164 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer());
172 loader.content_.reset(new DicomStructureSet(dicom)); 165 loader.content_.reset(new OrthancStone::DicomStructureSet(dicom));
173 size_t structureCount = loader.content_->GetStructuresCount(); 166 size_t structureCount = loader.content_->GetStructuresCount();
174 loader.structureVisibility_.resize(structureCount); 167 loader.structureVisibility_.resize(structureCount);
175 bool everythingVisible = false; 168 bool everythingVisible = false;
176 if ((loader.initiallyVisibleStructures_.size() == 1) 169 if ((loader.initiallyVisibleStructures_.size() == 1)
177 && (loader.initiallyVisibleStructures_[0].size() == 1) 170 && (loader.initiallyVisibleStructures_[0].size() == 1)
225 static_cast<unsigned int>(nonEmptyInstances.size()); 218 static_cast<unsigned int>(nonEmptyInstances.size());
226 219
227 for (std::set<std::string>::const_iterator 220 for (std::set<std::string>::const_iterator
228 it = nonEmptyInstances.begin(); it != nonEmptyInstances.end(); ++it) 221 it = nonEmptyInstances.begin(); it != nonEmptyInstances.end(); ++it)
229 { 222 {
230 std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); 223 std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
231 command->SetUri("/tools/lookup"); 224 command->SetUri("/tools/lookup");
232 command->SetMethod(Orthanc::HttpMethod_Post); 225 command->SetMethod(Orthanc::HttpMethod_Post);
233 command->SetBody(*it); 226 command->SetBody(*it);
234 command->SetPayload(new LookupInstance(loader, *it)); 227 command->AcquirePayload(new LookupInstance(loader, *it));
235 Schedule(command.release()); 228 Schedule(command.release());
236 } 229 }
237 } 230 }
238 }; 231 };
239 232
240 233
241 class DicomStructureSetLoader::Slice : public IExtractedSlice 234 class DicomStructureSetLoader::Slice : public IExtractedSlice
242 { 235 {
243 private: 236 private:
244 const DicomStructureSet& content_; 237 const OrthancStone::DicomStructureSet& content_;
245 uint64_t revision_; 238 uint64_t revision_;
246 bool isValid_; 239 bool isValid_;
247 std::vector<bool> visibility_; 240 std::vector<bool> visibility_;
248 241
249 public: 242 public:
255 structure set. 248 structure set.
256 In the first case (empty vector), all the structures are displayed. 249 In the first case (empty vector), all the structures are displayed.
257 In the second case, the visibility of each structure is defined by the 250 In the second case, the visibility of each structure is defined by the
258 content of the vector at the corresponding index. 251 content of the vector at the corresponding index.
259 */ 252 */
260 Slice(const DicomStructureSet& content, 253 Slice(const OrthancStone::DicomStructureSet& content,
261 uint64_t revision, 254 uint64_t revision,
262 const CoordinateSystem3D& cuttingPlane, 255 const OrthancStone::CoordinateSystem3D& cuttingPlane,
263 std::vector<bool> visibility = std::vector<bool>()) 256 std::vector<bool> visibility = std::vector<bool>())
264 : content_(content) 257 : content_(content)
265 , revision_(revision) 258 , revision_(revision)
266 , visibility_(visibility) 259 , visibility_(visibility)
267 { 260 {
268 ORTHANC_ASSERT((visibility_.size() == content_.GetStructuresCount()) 261 ORTHANC_ASSERT((visibility_.size() == content_.GetStructuresCount())
269 || (visibility_.size() == 0u)); 262 || (visibility_.size() == 0u));
270 263
271 bool opposite; 264 bool opposite;
272 265
273 const Vector normal = content.GetNormal(); 266 const OrthancStone::Vector normal = content.GetNormal();
274 isValid_ = ( 267 isValid_ = (
275 GeometryToolbox::IsParallelOrOpposite(opposite, normal, cuttingPlane.GetNormal()) || 268 OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, normal, cuttingPlane.GetNormal()) ||
276 GeometryToolbox::IsParallelOrOpposite(opposite, normal, cuttingPlane.GetAxisX()) || 269 OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, normal, cuttingPlane.GetAxisX()) ||
277 GeometryToolbox::IsParallelOrOpposite(opposite, normal, cuttingPlane.GetAxisY())); 270 OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, normal, cuttingPlane.GetAxisY()));
278 } 271 }
279 272
280 virtual bool IsValid() 273 virtual bool IsValid()
281 { 274 {
282 return isValid_; 275 return isValid_;
285 virtual uint64_t GetRevision() 278 virtual uint64_t GetRevision()
286 { 279 {
287 return revision_; 280 return revision_;
288 } 281 }
289 282
290 virtual ISceneLayer* CreateSceneLayer(const ILayerStyleConfigurator* configurator, 283 virtual OrthancStone::ISceneLayer* CreateSceneLayer(
291 const CoordinateSystem3D& cuttingPlane) 284 const OrthancStone::ILayerStyleConfigurator* configurator,
285 const OrthancStone::CoordinateSystem3D& cuttingPlane)
292 { 286 {
293 assert(isValid_); 287 assert(isValid_);
294 288
295 std::unique_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer); 289 std::unique_ptr<OrthancStone::PolylineSceneLayer> layer(new OrthancStone::PolylineSceneLayer);
296 layer->SetThickness(2); 290 layer->SetThickness(2);
297 291
298 for (size_t i = 0; i < content_.GetStructuresCount(); i++) 292 for (size_t i = 0; i < content_.GetStructuresCount(); i++)
299 { 293 {
300 if ((visibility_.size() == 0) || visibility_.at(i)) 294 if ((visibility_.size() == 0) || visibility_.at(i))
301 { 295 {
302 const Color& color = content_.GetStructureColor(i); 296 const OrthancStone::Color& color = content_.GetStructureColor(i);
303 297
304 #ifdef USE_BOOST_UNION_FOR_POLYGONS 298 #ifdef USE_BOOST_UNION_FOR_POLYGONS
305 std::vector< std::vector<Point2D> > polygons; 299 std::vector< std::vector<OrthancStone::Point2D> > polygons;
306 300
307 if (content_.ProjectStructure(polygons, i, cuttingPlane)) 301 if (content_.ProjectStructure(polygons, i, cuttingPlane))
308 { 302 {
309 for (size_t j = 0; j < polygons.size(); j++) 303 for (size_t j = 0; j < polygons.size(); j++)
310 { 304 {
318 312
319 layer->AddChain(chain, true /* closed */, color); 313 layer->AddChain(chain, true /* closed */, color);
320 } 314 }
321 } 315 }
322 #else 316 #else
323 std::vector< std::pair<Point2D, Point2D> > segments; 317 std::vector< std::pair<OrthancStone::Point2D, OrthancStone::Point2D> > segments;
324 318
325 if (content_.ProjectStructure(segments, i, cuttingPlane)) 319 if (content_.ProjectStructure(segments, i, cuttingPlane))
326 { 320 {
327 for (size_t j = 0; j < segments.size(); j++) 321 for (size_t j = 0; j < segments.size(); j++)
328 { 322 {
329 PolylineSceneLayer::Chain chain; 323 OrthancStone::PolylineSceneLayer::Chain chain;
330 chain.resize(2); 324 chain.resize(2);
331 325
332 chain[0] = ScenePoint2D(segments[j].first.x, segments[j].first.y); 326 chain[0] = OrthancStone::ScenePoint2D(segments[j].first.x, segments[j].first.y);
333 chain[1] = ScenePoint2D(segments[j].second.x, segments[j].second.y); 327 chain[1] = OrthancStone::ScenePoint2D(segments[j].second.x, segments[j].second.y);
334 328
335 layer->AddChain(chain, false /* NOT closed */, color); 329 layer->AddChain(chain, false /* NOT closed */, color);
336 } 330 }
337 } 331 }
338 #endif 332 #endif
342 return layer.release(); 336 return layer.release();
343 } 337 }
344 }; 338 };
345 339
346 340
347 DicomStructureSetLoader::DicomStructureSetLoader(IOracle& oracle, 341 DicomStructureSetLoader::DicomStructureSetLoader(
348 IObservable& oracleObservable) : 342 OrthancStone::ILoadersContext& loadersContext)
349 LoaderStateMachine(oracle, oracleObservable), 343 : LoaderStateMachine(loadersContext)
350 IObservable(oracleObservable.GetBroker()), 344 , loadersContext_(loadersContext)
351 revision_(0), 345 , revision_(0)
352 countProcessedInstances_(0), 346 , countProcessedInstances_(0)
353 countReferencedInstances_(0), 347 , countReferencedInstances_(0)
354 structuresReady_(false) 348 , structuresReady_(false)
355 { 349 {
356 } 350 }
351
357 352
358 353 boost::shared_ptr<OrthancStone::DicomStructureSetLoader> DicomStructureSetLoader::Create(OrthancStone::ILoadersContext& loadersContext)
354 {
355 boost::shared_ptr<DicomStructureSetLoader> obj(
356 new DicomStructureSetLoader(
357 loadersContext));
358 obj->LoaderStateMachine::PostConstructor();
359 return obj;
360
361 }
362
359 void DicomStructureSetLoader::SetStructureDisplayState(size_t structureIndex, bool display) 363 void DicomStructureSetLoader::SetStructureDisplayState(size_t structureIndex, bool display)
360 { 364 {
361 structureVisibility_.at(structureIndex) = display; 365 structureVisibility_.at(structureIndex) = display;
362 revision_++; 366 revision_++;
363 } 367 }
375 379
376 instanceId_ = instanceId; 380 instanceId_ = instanceId;
377 initiallyVisibleStructures_ = initiallyVisibleStructures; 381 initiallyVisibleStructures_ = initiallyVisibleStructures;
378 382
379 { 383 {
380 std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); 384 std::unique_ptr<OrthancStone::OrthancRestApiCommand> command(new OrthancStone::OrthancRestApiCommand);
381 command->SetHttpHeader("Accept-Encoding", "gzip"); 385 command->SetHttpHeader("Accept-Encoding", "gzip");
382 386
383 std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3006-0050"; 387 std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3006-0050";
384 388
385 command->SetUri(uri); 389 command->SetUri(uri);
386 command->SetPayload(new LoadStructure(*this)); 390 command->AcquirePayload(new LoadStructure(*this));
387 Schedule(command.release()); 391 Schedule(command.release());
388 } 392 }
389 } 393 }
390 394
391 395
392 IVolumeSlicer::IExtractedSlice* DicomStructureSetLoader::ExtractSlice(const CoordinateSystem3D& cuttingPlane) 396 OrthancStone::IVolumeSlicer::IExtractedSlice* DicomStructureSetLoader::ExtractSlice(const OrthancStone::CoordinateSystem3D& cuttingPlane)
393 { 397 {
394 if (content_.get() == NULL) 398 if (content_.get() == NULL)
395 { 399 {
396 // Geometry is not available yet 400 // Geometry is not available yet
397 return new IVolumeSlicer::InvalidSlice; 401 return new OrthancStone::IVolumeSlicer::InvalidSlice;
398 } 402 }
399 else 403 else
400 { 404 {
401 return new Slice(*content_, revision_, cuttingPlane, structureVisibility_); 405 return new Slice(*content_, revision_, cuttingPlane, structureVisibility_);
402 } 406 }
407 }
408
409 void DicomStructureSetLoader::SetStructuresUpdated()
410 {
411 BroadcastMessage(DicomStructureSetLoader::StructuresUpdated(*this));
403 } 412 }
404 413
405 void DicomStructureSetLoader::SetStructuresReady() 414 void DicomStructureSetLoader::SetStructuresReady()
406 { 415 {
407 ORTHANC_ASSERT(!structuresReady_); 416 ORTHANC_ASSERT(!structuresReady_);