comparison Samples/Common/RtViewer.cpp @ 1386:dfb48f0794b1

Ongoing splitting SDL vs WASM (preparing RtViewer WASM)
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 27 Apr 2020 16:48:19 +0200
parents ab871499ed30
children 5c83be3a6be5
comparison
equal deleted inserted replaced
1385:ffe9beb7c5d3 1386:dfb48f0794b1
16 * 16 *
17 * You should have received a copy of the GNU Affero General Public License 17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/ 19 **/
20 20
21 // Sample app
21 #include "RtViewer.h" 22 #include "RtViewer.h"
22 23
23 #include <stdio.h> 24 // Stone of Orthanc
24
25 #include <boost/shared_ptr.hpp>
26 #include <boost/weak_ptr.hpp>
27 #include <boost/make_shared.hpp>
28
29 #include <Core/Images/Image.h>
30 #include <Core/Images/ImageProcessing.h>
31 #include <Core/Images/PngWriter.h>
32 #include <Core/Logging.h>
33 #include <Core/OrthancException.h>
34
35 #include <Framework/OpenGL/SdlOpenGLContext.h> 25 #include <Framework/OpenGL/SdlOpenGLContext.h>
36 #include <Framework/StoneInitialization.h> 26 #include <Framework/StoneInitialization.h>
37
38 #include <Framework/Scene2D/CairoCompositor.h> 27 #include <Framework/Scene2D/CairoCompositor.h>
39 #include <Framework/Scene2D/ColorTextureSceneLayer.h> 28 #include <Framework/Scene2D/ColorTextureSceneLayer.h>
40 #include <Framework/Scene2D/OpenGLCompositor.h> 29 #include <Framework/Scene2D/OpenGLCompositor.h>
41 #include <Framework/Scene2D/PanSceneTracker.h> 30 #include <Framework/Scene2D/PanSceneTracker.h>
42 #include <Framework/Scene2D/ZoomSceneTracker.h> 31 #include <Framework/Scene2D/ZoomSceneTracker.h>
54 #include <Framework/Oracle/ThreadedOracle.h> 43 #include <Framework/Oracle/ThreadedOracle.h>
55 #include <Framework/Scene2D/GrayscaleStyleConfigurator.h> 44 #include <Framework/Scene2D/GrayscaleStyleConfigurator.h>
56 #include <Framework/Scene2D/LookupTableStyleConfigurator.h> 45 #include <Framework/Scene2D/LookupTableStyleConfigurator.h>
57 #include <Framework/Volumes/DicomVolumeImageMPRSlicer.h> 46 #include <Framework/Volumes/DicomVolumeImageMPRSlicer.h>
58 #include <Framework/StoneException.h> 47 #include <Framework/StoneException.h>
48
49 // Orthanc
50 #include <Core/Images/Image.h>
51 #include <Core/Images/ImageProcessing.h>
52 #include <Core/Images/PngWriter.h>
53 #include <Core/Logging.h>
54 #include <Core/OrthancException.h>
55
56 // System
57 #include <boost/shared_ptr.hpp>
58 #include <boost/weak_ptr.hpp>
59 #include <boost/make_shared.hpp>
60
61 #include <stdio.h>
62
59 63
60 namespace OrthancStone 64 namespace OrthancStone
61 { 65 {
62 const char* RtViewerGuiToolToString(size_t i) 66 const char* RtViewerGuiToolToString(size_t i)
63 { 67 {
261 if (!activeTracker_->IsAlive()) 265 if (!activeTracker_->IsAlive())
262 activeTracker_.reset(); 266 activeTracker_.reset();
263 } 267 }
264 break; 268 break;
265 269
270 case SDLK_r:
271 UpdateLayers();
272 {
273 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
274 lock->Invalidate();
275 }
276 break;
277
278 case SDLK_s:
279 compositor.FitContent(scene);
280 break;
281
266 case SDLK_t: 282 case SDLK_t:
267 if (!activeTracker_) 283 if (!activeTracker_)
268 SelectNextTool(); 284 SelectNextTool();
269 else 285 else
270 { 286 {
271 LOG(WARNING) << "You cannot change the active tool when an interaction" 287 LOG(WARNING) << "You cannot change the active tool when an interaction"
272 " is taking place"; 288 " is taking place";
273 } 289 }
274 break;
275 case SDLK_s:
276 compositor.FitContent(scene);
277 break; 290 break;
278 291
279 case SDLK_z: 292 case SDLK_z:
280 LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; 293 LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod;
281 if (event.key.keysym.mod & KMOD_CTRL) 294 if (event.key.keysym.mod & KMOD_CTRL)
464 } 477 }
465 } 478 }
466 479
467 480
468 RtViewerApp::RtViewerApp() 481 RtViewerApp::RtViewerApp()
469 : oracle_(*this) 482 : currentTool_(RtViewerGuiTool_Rotate)
470 , currentTool_(RtViewerGuiTool_Rotate)
471 , undoStack_(new UndoStack) 483 , undoStack_(new UndoStack)
472 , currentPlane_(0) 484 , currentPlane_(0)
473 , projection_(VolumeProjection_Coronal) 485 , projection_(VolumeProjection_Coronal)
474 { 486 {
475 loadersContext_.reset(new GenericLoadersContext(1, 4, 1));
476 loadersContext_->StartOracle();
477
478 // False means we do NOT let Windows treat this as a legacy application that needs to be scaled 487 // False means we do NOT let Windows treat this as a legacy application that needs to be scaled
479 viewport_ = SdlOpenGLViewport::Create("CT RTDOSE RTSTRUCT viewer", 1024, 1024, false); 488 viewport_ = SdlOpenGLViewport::Create("CT RTDOSE RTSTRUCT viewer", 1024, 1024, false);
480 489
481 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); 490 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
482 ViewportController& controller = lock->GetController(); 491 ViewportController& controller = lock->GetController();
483 Scene2D& scene = controller.GetScene(); 492 Scene2D& scene = controller.GetScene();
484 493
485 //oracleObservable.RegisterObserverCallback 494 // Create the volumes that will be filled later on
486 //(new Callable 495 ctVolume_ = boost::make_shared<DicomVolumeImage>();
487 // <RtViewerApp, SleepOracleCommand::TimeoutMessage>(*this, &RtViewerApp::Handle)); 496 doseVolume_ = boost::make_shared<DicomVolumeImage>();
488
489 //oracleObservable.RegisterObserverCallback
490 //(new Callable
491 // <Toto, GetOrthancImageCommand::SuccessMessage>(*this, &RtViewerApp::Handle));
492
493 //oracleObservable.RegisterObserverCallback
494 //(new Callable
495 // <RtViewerApp, GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &ToRtViewerAppto::Handle));
496
497 497
498 TEXTURE_2x2_1_ZINDEX = 1; 498 TEXTURE_2x2_1_ZINDEX = 1;
499 TEXTURE_1x1_ZINDEX = 2; 499 TEXTURE_1x1_ZINDEX = 2;
500 TEXTURE_2x2_2_ZINDEX = 3; 500 TEXTURE_2x2_2_ZINDEX = 3;
501 LINESET_1_ZINDEX = 4; 501 LINESET_1_ZINDEX = 4;
507 void RtViewerApp::RegisterMessages() 507 void RtViewerApp::RegisterMessages()
508 { 508 {
509 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); 509 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
510 ViewportController& controller = lock->GetController(); 510 ViewportController& controller = lock->GetController();
511 Scene2D& scene = controller.GetScene(); 511 Scene2D& scene = controller.GetScene();
512 Register<OracleCommandExceptionMessage>(oracleObservable_, &RtViewerApp::Handle);
513 Register<ViewportController::SceneTransformChanged>(controller, &RtViewerApp::OnSceneTransformChanged); 512 Register<ViewportController::SceneTransformChanged>(controller, &RtViewerApp::OnSceneTransformChanged);
514 } 513 }
515 514
516 boost::shared_ptr<RtViewerApp> RtViewerApp::Create() 515 boost::shared_ptr<RtViewerApp> RtViewerApp::Create()
517 { 516 {
518 boost::shared_ptr<RtViewerApp> thisOne(new RtViewerApp()); 517 boost::shared_ptr<RtViewerApp> thisOne(new RtViewerApp());
519 thisOne->RegisterMessages(); 518 thisOne->RegisterMessages();
520 return thisOne; 519 return thisOne;
521 } 520 }
522 521
522 #if 0
523 void RtViewerApp::PrepareScene() 523 void RtViewerApp::PrepareScene()
524 { 524 {
525 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); 525 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
526 ViewportController& controller = lock->GetController(); 526 ViewportController& controller = lock->GetController();
527 Scene2D& scene = controller.GetScene(); 527 Scene2D& scene = controller.GetScene();
549 p[5] = 0; 549 p[5] = 0;
550 550
551 scene.SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); 551 scene.SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i));
552 } 552 }
553 } 553 }
554 #endif
554 555
555 void RtViewerApp::DisableTracker() 556 void RtViewerApp::DisableTracker()
556 { 557 {
557 if (activeTracker_) 558 if (activeTracker_)
558 { 559 {
586 boost::shared_ptr<IFlexiblePointerTracker> RtViewerApp::TrackerHitTest(const PointerEvent& e) 587 boost::shared_ptr<IFlexiblePointerTracker> RtViewerApp::TrackerHitTest(const PointerEvent& e)
587 { 588 {
588 // std::vector<boost::shared_ptr<MeasureTool>> measureTools_; 589 // std::vector<boost::shared_ptr<MeasureTool>> measureTools_;
589 return boost::shared_ptr<IFlexiblePointerTracker>(); 590 return boost::shared_ptr<IFlexiblePointerTracker>();
590 } 591 }
591 592
592 static void GLAPIENTRY 593 void RtViewerApp::PrepareLoadersAndSlicers()
593 OpenGLMessageCallback(GLenum source, 594 {
594 GLenum type, 595
595 GLuint id, 596 //{
596 GLenum severity, 597 // Orthanc::WebServiceParameters p;
597 GLsizei length, 598 // //p.SetUrl("http://localhost:8043/");
598 const GLchar* message, 599 // p.SetCredentials("orthanc", "orthanc");
599 const void* userParam) 600 // oracle_.SetOrthancParameters(p);
600 { 601 //}
601 if (severity != GL_DEBUG_SEVERITY_NOTIFICATION)
602 {
603 fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
604 (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
605 type, severity, message);
606 }
607 }
608
609 static bool g_stopApplication = false;
610
611
612 void RtViewerApp::Handle(const DicomVolumeImage::GeometryReadyMessage& message)
613 {
614 RetrieveGeometry();
615 }
616
617
618 void RtViewerApp::Handle(const OracleCommandExceptionMessage& message)
619 {
620 const OracleCommandBase& command = dynamic_cast<const OracleCommandBase&>(message.GetOrigin());
621
622 printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), command.GetType());
623
624 switch (command.GetType())
625 {
626 case IOracleCommand::Type_GetOrthancWebViewerJpeg:
627 printf("URI: [%s]\n", dynamic_cast<const GetOrthancWebViewerJpegCommand&>(command).GetUri().c_str());
628 break;
629
630 default:
631 break;
632 }
633 }
634
635
636 void RtViewerApp::HandleCTLoaded(const OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality& message)
637 {
638 UpdateLayers();
639 }
640
641 void RtViewerApp::HandleCTContentUpdated(const DicomVolumeImage::ContentUpdatedMessage& message)
642 {
643 UpdateLayers();
644 }
645
646 void RtViewerApp::HandleDoseLoaded(const DicomVolumeImage::ContentUpdatedMessage& message)
647 {
648 //TODO: compute dose extent, with outlier rejection
649 UpdateLayers();
650 }
651
652 void RtViewerApp::HandleStructuresReady(const DicomStructureSetLoader::StructuresReady& message)
653 {
654 UpdateLayers();
655 }
656
657 void RtViewerApp::HandleStructuresUpdated(const DicomStructureSetLoader::StructuresUpdated& message)
658 {
659 UpdateLayers();
660 }
661
662 void RtViewerApp::SetCtVolume(int depth,
663 const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume,
664 OrthancStone::ILayerStyleConfigurator* style)
665 {
666 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
667 ViewportController& controller = lock->GetController();
668 Scene2D& scene = controller.GetScene();
669
670 ctVolumeLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume));
671
672 if (style != NULL)
673 {
674 ctVolumeLayerSource_->SetConfigurator(style);
675 }
676 }
677
678 void RtViewerApp::SetDoseVolume(int depth,
679 const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume,
680 OrthancStone::ILayerStyleConfigurator* style)
681 {
682 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
683 ViewportController& controller = lock->GetController();
684 Scene2D& scene = controller.GetScene();
685
686 doseVolumeLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume));
687
688 if (style != NULL)
689 {
690 doseVolumeLayerSource_->SetConfigurator(style);
691 }
692 }
693
694 void RtViewerApp::SetStructureSet(int depth,
695 const boost::shared_ptr<OrthancStone::DicomStructureSetLoader>& volume)
696 {
697 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
698 ViewportController& controller = lock->GetController();
699 Scene2D& scene = controller.GetScene();
700
701 structLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume));
702 }
703
704 void RtViewerApp::Run()
705 {
706 {
707 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
708 ViewportController& controller = lock->GetController();
709 Scene2D& scene = controller.GetScene();
710 ICompositor& compositor = lock->GetCompositor();
711
712 // False means we do NOT let Windows treat this as a legacy application
713 // that needs to be scaled
714 controller.FitContent(compositor.GetCanvasWidth(), compositor.GetCanvasHeight());
715
716 glEnable(GL_DEBUG_OUTPUT);
717 glDebugMessageCallback(OpenGLMessageCallback, 0);
718
719 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT,
720 FONT_SIZE_0, Orthanc::Encoding_Latin1);
721 compositor.SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT,
722 FONT_SIZE_1, Orthanc::Encoding_Latin1);
723 }
724 //////// from loader
725 {
726 Orthanc::WebServiceParameters p;
727 //p.SetUrl("http://localhost:8043/");
728 p.SetCredentials("orthanc", "orthanc");
729 oracle_.SetOrthancParameters(p);
730 }
731
732 //////// from Run
733
734 boost::shared_ptr<DicomVolumeImage> ctVolume(new DicomVolumeImage);
735 boost::shared_ptr<DicomVolumeImage> doseVolume(new DicomVolumeImage);
736
737
738 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> ctLoader;
739 boost::shared_ptr<OrthancMultiframeVolumeLoader> doseLoader;
740 boost::shared_ptr<DicomStructureSetLoader> rtstructLoader;
741 602
742 { 603 {
743 // "true" means use progressive quality (jpeg 50 --> jpeg 90 --> 16-bit raw) 604 // "true" means use progressive quality (jpeg 50 --> jpeg 90 --> 16-bit raw)
744 ctLoader = OrthancSeriesVolumeProgressiveLoader::Create(*loadersContext_, ctVolume, false); 605 // "false" means only using hi quality
745 606 // TODO: add flag for quality
607 ctLoader_ = OrthancSeriesVolumeProgressiveLoader::Create(*loadersContext_, ctVolume_, false);
608
746 // we need to store the CT loader to ask from geometry details later on when geometry is loaded 609 // we need to store the CT loader to ask from geometry details later on when geometry is loaded
747 geometryProvider_ = ctLoader; 610 geometryProvider_ = ctLoader_;
748 611
749 doseLoader = OrthancMultiframeVolumeLoader::Create(*loadersContext_, doseVolume); 612 doseLoader_ = OrthancMultiframeVolumeLoader::Create(*loadersContext_, doseVolume_);
750 rtstructLoader = DicomStructureSetLoader::Create(*loadersContext_); 613 rtstructLoader_ = DicomStructureSetLoader::Create(*loadersContext_);
751 } 614 }
752 615
753 Register<DicomVolumeImage::GeometryReadyMessage>(*ctLoader, &RtViewerApp::Handle); 616 /**
754 Register<OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality>(*ctLoader, &RtViewerApp::HandleCTLoaded); 617 Register for notifications issued by the loaders
755 Register<DicomVolumeImage::ContentUpdatedMessage>(*ctLoader, &RtViewerApp::HandleCTContentUpdated); 618 */
756 Register<DicomVolumeImage::ContentUpdatedMessage>(*doseLoader, &RtViewerApp::HandleDoseLoaded); 619
757 Register<DicomStructureSetLoader::StructuresReady>(*rtstructLoader, &RtViewerApp::HandleStructuresReady); 620 Register<DicomVolumeImage::GeometryReadyMessage>
758 Register<DicomStructureSetLoader::StructuresUpdated>(*rtstructLoader, &RtViewerApp::HandleStructuresUpdated); 621 (*ctLoader_, &RtViewerApp::HandleGeometryReady);
622
623 Register<OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality>
624 (*ctLoader_, &RtViewerApp::HandleCTLoaded);
625
626 Register<DicomVolumeImage::ContentUpdatedMessage>
627 (*ctLoader_, &RtViewerApp::HandleCTContentUpdated);
628
629 Register<DicomVolumeImage::ContentUpdatedMessage>
630 (*doseLoader_, &RtViewerApp::HandleDoseLoaded);
631
632 Register<DicomStructureSetLoader::StructuresReady>
633 (*rtstructLoader_, &RtViewerApp::HandleStructuresReady);
634
635 Register<DicomStructureSetLoader::StructuresUpdated>
636 (*rtstructLoader_, &RtViewerApp::HandleStructuresUpdated);
637
638 /**
639 Configure the CT
640 */
641
759 642
760 std::auto_ptr<GrayscaleStyleConfigurator> style(new GrayscaleStyleConfigurator); 643 std::auto_ptr<GrayscaleStyleConfigurator> style(new GrayscaleStyleConfigurator);
761 style->SetLinearInterpolation(true); 644 style->SetLinearInterpolation(true);
762 645
763 this->SetCtVolume(LAYER_POSITION + 0, ctLoader, style.release()); 646 this->SetCtVolumeSlicer(LAYER_POSITION + 0, ctLoader_, style.release());
764 647
765 { 648 {
766 std::unique_ptr<LookupTableStyleConfigurator> config(new LookupTableStyleConfigurator); 649 std::unique_ptr<LookupTableStyleConfigurator> config(new LookupTableStyleConfigurator);
767 config->SetLookupTable(Orthanc::EmbeddedResources::COLORMAP_HOT); 650 config->SetLookupTable(Orthanc::EmbeddedResources::COLORMAP_HOT);
768 651
769 boost::shared_ptr<DicomVolumeImageMPRSlicer> tmp(new DicomVolumeImageMPRSlicer(doseVolume)); 652 boost::shared_ptr<DicomVolumeImageMPRSlicer> tmp(new DicomVolumeImageMPRSlicer(doseVolume_));
770 this->SetDoseVolume(LAYER_POSITION + 1, tmp, config.release()); 653 this->SetDoseVolumeSlicer(LAYER_POSITION + 1, tmp, config.release());
771 } 654 }
772 655
773 this->SetStructureSet(LAYER_POSITION + 2, rtstructLoader); 656 this->SetStructureSet(LAYER_POSITION + 2, rtstructLoader_);
774 657
775 #if 1 658 #if 1
659 LOG(INFO) << "About to load:";
660 LOG(INFO) << " CT : " << ctSeriesId_;;
661 LOG(INFO) << " RTDOSE : " << doseInstanceId_;
662 LOG(INFO) << " RTSTRUCT : " << rtStructInstanceId_;
663 ctLoader_->LoadSeries(ctSeriesId_);
664 doseLoader_->LoadInstance(doseInstanceId_);
665 rtstructLoader_->LoadInstanceFullVisibility(rtStructInstanceId_);
666
667 #elif 0
776 /* 668 /*
777 BGO data 669 BGO data
778 http://localhost:8042/twiga-orthanc-viewer-demo/twiga-orthanc-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa 670 http://localhost:8042/twiga-orthanc-viewer-demo/twiga-orthanc-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa
779 & 671 &
780 dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb 672 dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb
781 & 673 &
782 struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 674 struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9
783 */ 675 */
784 ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT 676 ctLoader_->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT
785 doseLoader->LoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // RT-DOSE 677 doseLoader_->LoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // RT-DOSE
786 rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT 678 rtstructLoader_->LoadInstanceFullVisibility("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT
787 #else 679 #else
680 //SJO data
788 //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT 681 //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT
789 //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE 682 //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE
790 //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT 683 //rtstructLoader->LoadInstanceFullVisibility("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT
791 684
792 // 2017-05-16 685 // 2017-05-16
793 ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT 686 ctLoader_->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT
794 doseLoader->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE 687 doseLoader_->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE
795 rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT 688 rtstructLoader_->LoadInstanceFullVisibility("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT
796 #endif 689 #endif
797 690 }
798 oracle_.Start(); 691
799 692 #if 0
800 //// END from loader 693 void RtViewerApp::Handle(const OracleCommandExceptionMessage& message)
801 694 {
802 while (!g_stopApplication) 695 const OracleCommandBase& command = dynamic_cast<const OracleCommandBase&>(message.GetOrigin());
803 { 696
804 //compositor.Refresh(scene); 697 printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), command.GetType());
805 698
806 //////// from loader 699 switch (command.GetType())
807 //// END from loader 700 {
808 701 case IOracleCommand::Type_GetOrthancWebViewerJpeg:
809 SDL_Event event; 702 printf("URI: [%s]\n", dynamic_cast<const GetOrthancWebViewerJpegCommand&>(command).GetUri().c_str());
810 while (!g_stopApplication && SDL_PollEvent(&event)) 703 break;
811 { 704
812 if (event.type == SDL_QUIT) 705 default:
813 { 706 break;
814 g_stopApplication = true; 707 }
815 break; 708 }
816 } 709 #endif
817 else if (event.type == SDL_WINDOWEVENT && 710
818 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) 711
819 { 712 void RtViewerApp::HandleGeometryReady(const DicomVolumeImage::GeometryReadyMessage& message)
820 DisableTracker(); // was: tracker.reset(NULL); 713 {
821 } 714 RetrieveGeometry();
822 else if (event.type == SDL_KEYDOWN && 715 }
823 event.key.repeat == 0 /* Ignore key bounce */) 716
824 { 717 void RtViewerApp::HandleCTLoaded(const OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality& message)
825 switch (event.key.keysym.sym) 718 {
826 { 719 UpdateLayers();
827 case SDLK_f: 720 }
828 // TODO: implement GetWindow!!! 721
829 // viewport_->GetContext()->GetWindow().ToggleMaximize(); 722 void RtViewerApp::HandleCTContentUpdated(const DicomVolumeImage::ContentUpdatedMessage& message)
830 ORTHANC_ASSERT(false, "Please implement GetWindow()"); 723 {
831 break; 724 UpdateLayers();
832 725 }
833 case SDLK_r: 726
834 break; 727 void RtViewerApp::HandleDoseLoaded(const DicomVolumeImage::ContentUpdatedMessage& message)
835 728 {
836 case SDLK_s: 729 //TODO: compute dose extent, with outlier rejection
837 FitContent(); 730 UpdateLayers();
838 break; 731 }
839 732
840 case SDLK_q: 733 void RtViewerApp::HandleStructuresReady(const DicomStructureSetLoader::StructuresReady& message)
841 g_stopApplication = true; 734 {
842 break; 735 UpdateLayers();
843 default: 736 }
844 break; 737
845 } 738 void RtViewerApp::HandleStructuresUpdated(const DicomStructureSetLoader::StructuresUpdated& message)
846 } 739 {
847 HandleApplicationEvent(event); 740 UpdateLayers();
848 } 741 }
849 SDL_Delay(1); 742
850 } 743 void RtViewerApp::SetCtVolumeSlicer(int depth,
851 744 const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume,
852 //// from loader 745 OrthancStone::ILayerStyleConfigurator* style)
853 746 {
854 //Orthanc::SystemToolbox::ServerBarrier(); 747 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
855 748 ViewportController& controller = lock->GetController();
856 /** 749 Scene2D& scene = controller.GetScene();
857 * WARNING => The oracle must be stopped BEFORE the objects using 750
858 * it are destroyed!!! This forces to wait for the completion of 751 ctVolumeLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume));
859 * the running callback methods. Otherwise, the callbacks methods 752
860 * might still be running while their parent object is destroyed, 753 if (style != NULL)
861 * resulting in crashes. This is very visible if adding a sleep(), 754 {
862 * as in (*). 755 ctVolumeLayerSource_->SetConfigurator(style);
863 **/ 756 }
864 757 }
865 oracle_.Stop(); 758
866 //// END from loader 759 void RtViewerApp::SetDoseVolumeSlicer(int depth,
867 } 760 const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume,
761 OrthancStone::ILayerStyleConfigurator* style)
762 {
763 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
764 ViewportController& controller = lock->GetController();
765 Scene2D& scene = controller.GetScene();
766
767 doseVolumeLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume));
768
769 if (style != NULL)
770 {
771 doseVolumeLayerSource_->SetConfigurator(style);
772 }
773 }
774
775 void RtViewerApp::SetStructureSet(int depth,
776 const boost::shared_ptr<OrthancStone::DicomStructureSetLoader>& volume)
777 {
778 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
779 ViewportController& controller = lock->GetController();
780 Scene2D& scene = controller.GetScene();
781
782 structLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume));
783 }
784
868 785
869 void RtViewerApp::SetInfoDisplayMessage( 786 void RtViewerApp::SetInfoDisplayMessage(
870 std::string key, std::string value) 787 std::string key, std::string value)
871 { 788 {
872 if (value == "") 789 if (value == "")
898 int main(int argc, char* argv[]) 815 int main(int argc, char* argv[])
899 { 816 {
900 using namespace OrthancStone; 817 using namespace OrthancStone;
901 818
902 StoneInitialize(); 819 StoneInitialize();
903 Orthanc::Logging::EnableInfoLevel(true);
904 //Orthanc::Logging::EnableTraceLevel(true);
905 820
906 try 821 try
907 { 822 {
908 boost::shared_ptr<RtViewerApp> app = RtViewerApp::Create(); 823 boost::shared_ptr<RtViewerApp> app = RtViewerApp::Create();
909 g_app = app; 824 g_app = app;
910 //app->PrepareScene(); 825 app->RunSdl(argc,argv);
911 app->Run();
912 } 826 }
913 catch (Orthanc::OrthancException& e) 827 catch (Orthanc::OrthancException& e)
914 { 828 {
915 LOG(ERROR) << "EXCEPTION: " << e.What(); 829 LOG(ERROR) << "EXCEPTION: " << e.What();
916 } 830 }