comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 2097:a9e23ef9ee09 dicom-sr

preparing to extract dicom-sr annotations
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 08 Nov 2023 16:31:49 +0100
parents 79e984a89a38
children 4288d635d77e
comparison
equal deleted inserted replaced
2096:79e984a89a38 2097:a9e23ef9ee09
224 224
225 virtual bool FindClosestFrame(size_t& frameIndex, 225 virtual bool FindClosestFrame(size_t& frameIndex,
226 const OrthancStone::Vector& point, 226 const OrthancStone::Vector& point,
227 double maximumDistance) const = 0; 227 double maximumDistance) const = 0;
228 228
229 virtual OrthancStone::ISceneLayer* ExtractAnnotations(const std::string& sopInstanceUid,
230 unsigned int frameNumber,
231 double originX,
232 double originY,
233 double pixelSpacingX,
234 double pixelSpacingY) const = 0;
235
229 static OrthancStone::CoordinateSystem3D GetFrameGeometry(const IFramesCollection& frames, 236 static OrthancStone::CoordinateSystem3D GetFrameGeometry(const IFramesCollection& frames,
230 size_t frameIndex) 237 size_t frameIndex)
231 { 238 {
232 return frames.GetInstanceOfFrame(frameIndex).GetFrameGeometry(frames.GetFrameNumberInInstance(frameIndex)); 239 return frames.GetInstanceOfFrame(frameIndex).GetFrameGeometry(frames.GetFrameNumberInInstance(frameIndex));
233 } 240 }
277 virtual bool FindClosestFrame(size_t& frameIndex, 284 virtual bool FindClosestFrame(size_t& frameIndex,
278 const OrthancStone::Vector& point, 285 const OrthancStone::Vector& point,
279 double maximumDistance) const ORTHANC_OVERRIDE 286 double maximumDistance) const ORTHANC_OVERRIDE
280 { 287 {
281 return frames_->FindClosestFrame(frameIndex, point, maximumDistance); 288 return frames_->FindClosestFrame(frameIndex, point, maximumDistance);
282 }; 289 }
290
291 virtual OrthancStone::ISceneLayer* ExtractAnnotations(const std::string& sopInstanceUid,
292 unsigned int frameNumber,
293 double originX,
294 double originY,
295 double pixelSpacingX,
296 double pixelSpacingY) const ORTHANC_OVERRIDE
297 {
298 return NULL;
299 }
283 }; 300 };
284 301
285 302
286 class DicomStructuredReportFrames : public IFramesCollection 303 class DicomStructuredReportFrames : public IFramesCollection
287 { 304 {
319 const OrthancStone::DicomInstanceParameters& GetParameters() const 336 const OrthancStone::DicomInstanceParameters& GetParameters() const
320 { 337 {
321 return *parameters_; 338 return *parameters_;
322 } 339 }
323 }; 340 };
324 341
325 std::string studyInstanceUid_; 342 std::unique_ptr<OrthancStone::DicomStructuredReport> sr_;
326 std::string seriesInstanceUid_; 343 std::vector<Frame*> frames_;
327 std::vector<Frame*> frames_;
328 344
329 void Finalize() 345 void Finalize()
330 { 346 {
331 for (size_t i = 0; i < frames_.size(); i++) 347 for (size_t i = 0; i < frames_.size(); i++)
332 { 348 {
351 return *frames_[index]; 367 return *frames_[index];
352 } 368 }
353 } 369 }
354 370
355 public: 371 public:
356 DicomStructuredReportFrames(OrthancStone::DicomStructuredReport& sr, 372 DicomStructuredReportFrames(const OrthancStone::DicomStructuredReport& sr,
357 const OrthancStone::LoadedDicomResources& instances) : 373 const OrthancStone::LoadedDicomResources& instances) :
358 studyInstanceUid_(sr.GetStudyInstanceUid()), 374 sr_(new OrthancStone::DicomStructuredReport(sr))
359 seriesInstanceUid_(sr.GetSeriesInstanceUid())
360 { 375 {
361 std::list<OrthancStone::DicomStructuredReport::ReferencedFrame> tmp; 376 std::list<OrthancStone::DicomStructuredReport::ReferencedFrame> tmp;
362 sr.ExportReferencedFrames(tmp); 377 sr_->ExportReferencedFrames(tmp);
363 378
364 frames_.reserve(tmp.size()); 379 frames_.reserve(tmp.size());
365 for (std::list<OrthancStone::DicomStructuredReport::ReferencedFrame>::const_iterator 380 for (std::list<OrthancStone::DicomStructuredReport::ReferencedFrame>::const_iterator
366 it = tmp.begin(); it != tmp.end(); ++it) 381 it = tmp.begin(); it != tmp.end(); ++it)
367 { 382 {
431 frameIndex = i; 446 frameIndex = i;
432 } 447 }
433 } 448 }
434 449
435 return found; 450 return found;
451 }
452
453 virtual OrthancStone::ISceneLayer* ExtractAnnotations(const std::string& sopInstanceUid,
454 unsigned int frameNumber,
455 double originX,
456 double originY,
457 double pixelSpacingX,
458 double pixelSpacingY) const ORTHANC_OVERRIDE
459 {
460 size_t frameIndex;
461 if (!LookupFrame(frameIndex, sopInstanceUid, frameNumber))
462 {
463 return NULL;
464 }
465
466 const OrthancStone::DicomInstanceParameters& parameters = GetInstanceOfFrame(frameIndex);
467
468 const double x = originX - pixelSpacingX / 2.0;
469 const double y = originY - pixelSpacingY / 2.0;
470 const double w = parameters.GetWidth() * pixelSpacingX;
471 const double h = parameters.GetHeight() * pixelSpacingY;
472
473 std::unique_ptr<OrthancStone::MacroSceneLayer> layer(new OrthancStone::MacroSceneLayer);
474
475 {
476 std::unique_ptr<OrthancStone::PolylineSceneLayer> polyline(new OrthancStone::PolylineSceneLayer);
477 {
478 OrthancStone::PolylineSceneLayer::Chain chain;
479 chain.push_back(OrthancStone::ScenePoint2D(x, y));
480 chain.push_back(OrthancStone::ScenePoint2D(x + pixelSpacingX, y));
481 chain.push_back(OrthancStone::ScenePoint2D(x + pixelSpacingX, y + pixelSpacingY));
482 chain.push_back(OrthancStone::ScenePoint2D(x, y + pixelSpacingY));
483
484 polyline->AddChain(chain, true, 255, 0, 0);
485 }
486
487 layer->AddLayer(polyline.release());
488 }
489
490 {
491 std::unique_ptr<OrthancStone::PolylineSceneLayer> polyline(new OrthancStone::PolylineSceneLayer);
492 {
493 OrthancStone::PolylineSceneLayer::Chain chain;
494 chain.push_back(OrthancStone::ScenePoint2D(x, y));
495 chain.push_back(OrthancStone::ScenePoint2D(x + w, y));
496 chain.push_back(OrthancStone::ScenePoint2D(x + w, y + h));
497 chain.push_back(OrthancStone::ScenePoint2D(x, y + h));
498
499 polyline->AddChain(chain, true, 255, 0, 0);
500 }
501
502 layer->AddLayer(polyline.release());
503 }
504
505 return layer.release();
436 } 506 }
437 }; 507 };
438 508
439 509
440 class VirtualSeries : public boost::noncopyable 510 class VirtualSeries : public boost::noncopyable
1964 static const int LAYER_OVERLAY = 1; 2034 static const int LAYER_OVERLAY = 1;
1965 static const int LAYER_ORIENTATION_MARKERS = 2; 2035 static const int LAYER_ORIENTATION_MARKERS = 2;
1966 static const int LAYER_REFERENCE_LINES = 3; 2036 static const int LAYER_REFERENCE_LINES = 3;
1967 static const int LAYER_ANNOTATIONS_OSIRIX = 4; 2037 static const int LAYER_ANNOTATIONS_OSIRIX = 4;
1968 static const int LAYER_ANNOTATIONS_STONE = 5; 2038 static const int LAYER_ANNOTATIONS_STONE = 5;
2039 static const int LAYER_STRUCTURED_REPORT = 6;
1969 2040
1970 2041
1971 class ICommand : public Orthanc::IDynamicObject 2042 class ICommand : public Orthanc::IDynamicObject
1972 { 2043 {
1973 private: 2044 private:
2648 text->SetAnchor(OrthancStone::BitmapAnchor_CenterRight); 2719 text->SetAnchor(OrthancStone::BitmapAnchor_CenterRight);
2649 orientationMarkers->AddLayer(text.release()); 2720 orientationMarkers->AddLayer(text.release());
2650 } 2721 }
2651 2722
2652 2723
2724 std::unique_ptr<OrthancStone::ISceneLayer> structuredReportAnnotations;
2725
2726 if (frames_.get() != NULL)
2727 {
2728 structuredReportAnnotations.reset(frames_->ExtractAnnotations(instance.GetSopInstanceUid(), frameIndex,
2729 layer->GetOriginX(), layer->GetOriginY(),
2730 layer->GetPixelSpacingX(), layer->GetPixelSpacingY()));
2731 }
2732
2733
2653 { 2734 {
2654 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); 2735 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
2655 2736
2656 OrthancStone::Scene2D& scene = lock->GetController().GetScene(); 2737 OrthancStone::Scene2D& scene = lock->GetController().GetScene();
2657 2738
2680 scene.SetLayer(LAYER_ORIENTATION_MARKERS, orientationMarkers.release()); 2761 scene.SetLayer(LAYER_ORIENTATION_MARKERS, orientationMarkers.release());
2681 } 2762 }
2682 else 2763 else
2683 { 2764 {
2684 scene.DeleteLayer(LAYER_ORIENTATION_MARKERS); 2765 scene.DeleteLayer(LAYER_ORIENTATION_MARKERS);
2766 }
2767
2768 if (orientationMarkers.get() != NULL)
2769 {
2770 scene.SetLayer(LAYER_ORIENTATION_MARKERS, orientationMarkers.release());
2771 }
2772 else
2773 {
2774 scene.DeleteLayer(LAYER_ORIENTATION_MARKERS);
2775 }
2776
2777 if (structuredReportAnnotations.get() != NULL)
2778 {
2779 scene.SetLayer(LAYER_STRUCTURED_REPORT, structuredReportAnnotations.release());
2780 }
2781 else
2782 {
2783 scene.DeleteLayer(LAYER_STRUCTURED_REPORT);
2685 } 2784 }
2686 2785
2687 stoneAnnotations_->Render(scene); // Necessary for "FitContent()" to work 2786 stoneAnnotations_->Render(scene); // Necessary for "FitContent()" to work
2688 2787
2689 if (fitNextContent_) 2788 if (fitNextContent_)