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