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