comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1809:79a5838739a6

starting the integration of AnnotationsSceneLayer into Stone Web viewer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 May 2021 18:52:02 +0200
parents 39673d351ef2
children fdc6a8089eb9
comparison
equal deleted inserted replaced
1808:797633f48a9c 1809:79a5838739a6
68 #include <Loaders/SeriesMetadataLoader.h> 68 #include <Loaders/SeriesMetadataLoader.h>
69 #include <Loaders/SeriesThumbnailsLoader.h> 69 #include <Loaders/SeriesThumbnailsLoader.h>
70 #include <Messages/ObserverBase.h> 70 #include <Messages/ObserverBase.h>
71 #include <Oracle/ParseDicomFromWadoCommand.h> 71 #include <Oracle/ParseDicomFromWadoCommand.h>
72 #include <Oracle/ParseDicomSuccessMessage.h> 72 #include <Oracle/ParseDicomSuccessMessage.h>
73 #include <Scene2D/AnnotationsSceneLayer.h>
73 #include <Scene2D/ArrowSceneLayer.h> 74 #include <Scene2D/ArrowSceneLayer.h>
74 #include <Scene2D/ColorTextureSceneLayer.h> 75 #include <Scene2D/ColorTextureSceneLayer.h>
75 #include <Scene2D/FloatTextureSceneLayer.h> 76 #include <Scene2D/FloatTextureSceneLayer.h>
76 #include <Scene2D/MacroSceneLayer.h> 77 #include <Scene2D/MacroSceneLayer.h>
77 #include <Scene2D/OsiriXLayerFactory.h> 78 #include <Scene2D/OsiriXLayerFactory.h>
131 { 132 {
132 WebViewerAction_Windowing, 133 WebViewerAction_Windowing,
133 WebViewerAction_Zoom, 134 WebViewerAction_Zoom,
134 WebViewerAction_Pan, 135 WebViewerAction_Pan,
135 WebViewerAction_Rotate, 136 WebViewerAction_Rotate,
136 WebViewerAction_Crosshair 137 WebViewerAction_Crosshair,
138
139 WebViewerAction_CreateAngle,
140 WebViewerAction_CreateCircle,
141 WebViewerAction_CreateSegment,
142 WebViewerAction_DeleteMeasure
137 }; 143 };
138 144
139 145
140 146
141 static OrthancStone::MouseAction ConvertWebViewerAction(int action) 147 static OrthancStone::MouseAction ConvertWebViewerAction(int action)
153 159
154 case WebViewerAction_Rotate: 160 case WebViewerAction_Rotate:
155 return OrthancStone::MouseAction_Rotate; 161 return OrthancStone::MouseAction_Rotate;
156 162
157 case WebViewerAction_Crosshair: 163 case WebViewerAction_Crosshair:
164 case WebViewerAction_CreateAngle:
165 case WebViewerAction_CreateCircle:
166 case WebViewerAction_CreateSegment:
167 case WebViewerAction_DeleteMeasure:
158 return OrthancStone::MouseAction_None; 168 return OrthancStone::MouseAction_None;
159 169
160 default: 170 default:
161 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 171 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
162 } 172 }
1193 }; 1203 };
1194 1204
1195 private: 1205 private:
1196 static const int LAYER_TEXTURE = 0; 1206 static const int LAYER_TEXTURE = 0;
1197 static const int LAYER_REFERENCE_LINES = 1; 1207 static const int LAYER_REFERENCE_LINES = 1;
1198 static const int LAYER_ANNOTATIONS = 2; 1208 static const int LAYER_ANNOTATIONS_OSIRIX = 2;
1209 static const int LAYER_ANNOTATIONS_STONE = 3;
1199 1210
1200 1211
1201 class ICommand : public Orthanc::IDynamicObject 1212 class ICommand : public Orthanc::IDynamicObject
1202 { 1213 {
1203 private: 1214 private:
1566 bool hasFocusOnInstance_; 1577 bool hasFocusOnInstance_;
1567 std::string focusSopInstanceUid_; 1578 std::string focusSopInstanceUid_;
1568 size_t focusFrameNumber_; 1579 size_t focusFrameNumber_;
1569 1580
1570 boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations_; 1581 boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations_;
1582 boost::shared_ptr<OrthancStone::AnnotationsSceneLayer> annotationsStone_;
1571 1583
1572 void ScheduleNextPrefetch() 1584 void ScheduleNextPrefetch()
1573 { 1585 {
1574 while (!prefetchQueue_.empty()) 1586 while (!prefetchQueue_.empty())
1575 { 1587 {
1739 else 1751 else
1740 { 1752 {
1741 layer->SetPixelSpacing(pixelSpacingX, pixelSpacingY); 1753 layer->SetPixelSpacing(pixelSpacingX, pixelSpacingY);
1742 } 1754 }
1743 1755
1744 std::unique_ptr<OrthancStone::MacroSceneLayer> annotationsLayer; 1756 std::unique_ptr<OrthancStone::MacroSceneLayer> annotationsOsiriX;
1745 1757
1746 if (annotations_) 1758 if (annotations_)
1747 { 1759 {
1748 std::set<size_t> a; 1760 std::set<size_t> a;
1749 annotations_->LookupSopInstanceUid(a, instance.GetSopInstanceUid()); 1761 annotations_->LookupSopInstanceUid(a, instance.GetSopInstanceUid());
1750 if (plane.IsValid() && 1762 if (plane.IsValid() &&
1751 !a.empty()) 1763 !a.empty())
1752 { 1764 {
1753 annotationsLayer.reset(new OrthancStone::MacroSceneLayer); 1765 annotationsOsiriX.reset(new OrthancStone::MacroSceneLayer);
1754 // annotationsLayer->Reserve(a.size()); 1766 // annotationsOsiriX->Reserve(a.size());
1755 1767
1756 OrthancStone::OsiriXLayerFactory factory; 1768 OrthancStone::OsiriXLayerFactory factory;
1757 factory.SetColor(0, 255, 0); 1769 factory.SetColor(0, 255, 0);
1758 1770
1759 for (std::set<size_t>::const_iterator it = a.begin(); it != a.end(); ++it) 1771 for (std::set<size_t>::const_iterator it = a.begin(); it != a.end(); ++it)
1760 { 1772 {
1761 const OrthancStone::OsiriX::Annotation& annotation = annotations_->GetAnnotation(*it); 1773 const OrthancStone::OsiriX::Annotation& annotation = annotations_->GetAnnotation(*it);
1762 annotationsLayer->AddLayer(factory.Create(annotation, plane)); 1774 annotationsOsiriX->AddLayer(factory.Create(annotation, plane));
1763 } 1775 }
1764 } 1776 }
1765 } 1777 }
1766 1778
1767 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); 1779 {
1768 1780 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
1769 OrthancStone::Scene2D& scene = lock->GetController().GetScene(); 1781
1770 1782 OrthancStone::Scene2D& scene = lock->GetController().GetScene();
1771 scene.SetLayer(LAYER_TEXTURE, layer.release()); 1783
1772 1784 scene.SetLayer(LAYER_TEXTURE, layer.release());
1773 if (annotationsLayer.get() != NULL) 1785
1774 { 1786 if (annotationsOsiriX.get() != NULL)
1775 scene.SetLayer(LAYER_ANNOTATIONS, annotationsLayer.release()); 1787 {
1776 } 1788 scene.SetLayer(LAYER_ANNOTATIONS_OSIRIX, annotationsOsiriX.release());
1777 else 1789 }
1778 { 1790 else
1779 scene.DeleteLayer(LAYER_ANNOTATIONS); 1791 {
1780 } 1792 scene.DeleteLayer(LAYER_ANNOTATIONS_OSIRIX);
1781 1793 }
1782 if (fitNextContent_) 1794
1783 { 1795 if (fitNextContent_)
1784 lock->RefreshCanvasSize(); 1796 {
1785 lock->GetCompositor().FitContent(scene); 1797 lock->RefreshCanvasSize();
1786 fitNextContent_ = false; 1798 lock->GetCompositor().FitContent(scene);
1787 } 1799 fitNextContent_ = false;
1800 }
1801
1802 annotationsStone_->Render(scene);
1788 1803
1789 //lock->GetCompositor().Refresh(scene); 1804 //lock->GetCompositor().Refresh(scene);
1790 lock->Invalidate(); 1805 lock->Invalidate();
1806 }
1791 } 1807 }
1792 1808
1793 1809
1794 void RenderCurrentSceneFromCommand(const Orthanc::ImageAccessor& frame, 1810 void RenderCurrentSceneFromCommand(const Orthanc::ImageAccessor& frame,
1795 const std::string& loadedSopInstanceUid, 1811 const std::string& loadedSopInstanceUid,
2008 2024
2009 { 2025 {
2010 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); 2026 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
2011 std::string ttf; 2027 std::string ttf;
2012 Orthanc::EmbeddedResources::GetFileResource(ttf, Orthanc::EmbeddedResources::UBUNTU_FONT); 2028 Orthanc::EmbeddedResources::GetFileResource(ttf, Orthanc::EmbeddedResources::UBUNTU_FONT);
2013 lock->GetCompositor().SetFont(0, ttf, 24 /* font size */, Orthanc::Encoding_Latin1); 2029 lock->GetCompositor().SetFont(0, ttf, 16 /* font size */, Orthanc::Encoding_Latin1);
2014 } 2030 }
2015 2031
2016 emscripten_set_wheel_callback(viewport_->GetCanvasCssSelector().c_str(), this, true, OnWheel); 2032 emscripten_set_wheel_callback(viewport_->GetCanvasCssSelector().c_str(), this, true, OnWheel);
2017 2033
2018 SetWindowingPreset(); 2034 SetWindowingPreset();
2035
2036 {
2037 annotationsStone_.reset(new OrthancStone::AnnotationsSceneLayer(LAYER_ANNOTATIONS_STONE));
2038 annotationsStone_->AddSegmentAnnotation(OrthancStone::ScenePoint2D(0, 0),
2039 OrthancStone::ScenePoint2D(100, 100));
2040 annotationsStone_->AddAngleAnnotation(OrthancStone::ScenePoint2D(100, 50),
2041 OrthancStone::ScenePoint2D(150, 40),
2042 OrthancStone::ScenePoint2D(200, 50));
2043 annotationsStone_->AddCircleAnnotation(OrthancStone::ScenePoint2D(50, 200),
2044 OrthancStone::ScenePoint2D(100, 250));
2045 annotationsStone_->SetActiveTool(OrthancStone::AnnotationsSceneLayer::Tool_Edit);
2046 }
2019 } 2047 }
2020 2048
2021 2049
2022 void Handle(const OrthancStone::ViewportController::GrayscaleWindowingChanged& message) 2050 void Handle(const OrthancStone::ViewportController::GrayscaleWindowingChanged& message)
2023 { 2051 {
2093 void Handle(const OrthancStone::ParseDicomSuccessMessage& message) 2121 void Handle(const OrthancStone::ParseDicomSuccessMessage& message)
2094 { 2122 {
2095 dynamic_cast<const ICommand&>(message.GetOrigin().GetPayload()).Handle(message); 2123 dynamic_cast<const ICommand&>(message.GetOrigin().GetPayload()).Handle(message);
2096 } 2124 }
2097 2125
2126
2127 void RefreshAnnotations()
2128 {
2129 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
2130 annotationsStone_->Render(lock->GetController().GetScene());
2131 lock->Invalidate();
2132 }
2133
2134 void Handle(const OrthancStone::ViewportController::SceneTransformChanged& message)
2135 {
2136 RefreshAnnotations();
2137 }
2138
2139 void Handle(const OrthancStone::AnnotationsSceneLayer::AnnotationChangedMessage& message)
2140 {
2141 RefreshAnnotations();
2142 }
2143
2144 void Handle(const OrthancStone::AnnotationsSceneLayer::AnnotationAddedMessage& message)
2145 {
2146 RefreshAnnotations();
2147 LOG(WARNING) << "annotation added";
2148 }
2149
2150 void Handle(const OrthancStone::AnnotationsSceneLayer::AnnotationRemovedMessage& message)
2151 {
2152 RefreshAnnotations();
2153 LOG(WARNING) << "annotation removed";
2154 }
2155
2098 public: 2156 public:
2099 virtual ~ViewerViewport() 2157 virtual ~ViewerViewport()
2100 { 2158 {
2101 // Unregister the callbacks to avoid any call with a "void*" that 2159 // Unregister the callbacks to avoid any call with a "void*" that
2102 // has been destroyed. "WebAssemblyViewport::CreateObjectCookie()" 2160 // has been destroyed. "WebAssemblyViewport::CreateObjectCookie()"
2123 viewport->Register<OrthancStone::HttpCommand::SuccessMessage>( 2181 viewport->Register<OrthancStone::HttpCommand::SuccessMessage>(
2124 lock->GetOracleObservable(), &ViewerViewport::Handle); 2182 lock->GetOracleObservable(), &ViewerViewport::Handle);
2125 2183
2126 viewport->Register<OrthancStone::ParseDicomSuccessMessage>( 2184 viewport->Register<OrthancStone::ParseDicomSuccessMessage>(
2127 lock->GetOracleObservable(), &ViewerViewport::Handle); 2185 lock->GetOracleObservable(), &ViewerViewport::Handle);
2186
2187 viewport->Register<OrthancStone::AnnotationsSceneLayer::AnnotationChangedMessage>(
2188 *viewport->annotationsStone_, &ViewerViewport::Handle);
2189
2190 viewport->Register<OrthancStone::AnnotationsSceneLayer::AnnotationAddedMessage>(
2191 *viewport->annotationsStone_, &ViewerViewport::Handle);
2192
2193 viewport->Register<OrthancStone::AnnotationsSceneLayer::AnnotationRemovedMessage>(
2194 *viewport->annotationsStone_, &ViewerViewport::Handle);
2128 } 2195 }
2129 2196
2130 { 2197 {
2131 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->viewport_->Lock()); 2198 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->viewport_->Lock());
2132 viewport->Register<OrthancStone::ViewportController::GrayscaleWindowingChanged>(lock->GetController(), &ViewerViewport::Handle); 2199 viewport->Register<OrthancStone::ViewportController::GrayscaleWindowingChanged>(lock->GetController(), &ViewerViewport::Handle);
2200 viewport->Register<OrthancStone::ViewportController::SceneTransformChanged>(lock->GetController(), &ViewerViewport::Handle);
2133 } 2201 }
2134 2202
2135 return viewport; 2203 return viewport;
2136 } 2204 }
2137 2205
2221 if (fitContent) 2289 if (fitContent)
2222 { 2290 {
2223 lock->GetCompositor().FitContent(lock->GetController().GetScene()); 2291 lock->GetCompositor().FitContent(lock->GetController().GetScene());
2224 } 2292 }
2225 2293
2294 annotationsStone_->Render(lock->GetController().GetScene());
2295
2226 lock->Invalidate(); 2296 lock->Invalidate();
2227 } 2297 }
2228 2298
2229 void AcquireObserver(IObserver* observer) 2299 void AcquireObserver(IObserver* observer)
2230 { 2300 {
2557 2627
2558 return NULL; // No need for a tracker, this is just a click 2628 return NULL; // No need for a tracker, this is just a click
2559 } 2629 }
2560 else 2630 else
2561 { 2631 {
2632 {
2633 std::unique_ptr<OrthancStone::IViewport::ILock> lock2(lock1->Lock());
2634
2635 std::unique_ptr<OrthancStone::IFlexiblePointerTracker> t;
2636 t.reset(viewer_.annotationsStone_->CreateTracker(event.GetMainPosition(), lock2->GetController().GetScene()));
2637
2638 if (t.get() != NULL)
2639 {
2640 return t.release();
2641 }
2642 }
2643
2562 return DefaultViewportInteractor::CreateTracker( 2644 return DefaultViewportInteractor::CreateTracker(
2563 viewport, event, viewportWidth, viewportHeight); 2645 viewport, event, viewportWidth, viewportHeight);
2564 } 2646 }
2565 } 2647 }
2566 }; 2648 };