Mercurial > hg > orthanc-stone
comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1603:595c0952ef7e
focusing on osirix annotations in Stone Web viewer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 28 Oct 2020 18:49:01 +0100 |
parents | b253b79906fa |
children | 2df998314507 |
comparison
equal
deleted
inserted
replaced
1602:b2941196cabf | 1603:595c0952ef7e |
---|---|
1308 std::list<PrefetchItem> prefetchQueue_; | 1308 std::list<PrefetchItem> prefetchQueue_; |
1309 | 1309 |
1310 | 1310 |
1311 bool hasFocusOnInstance_; | 1311 bool hasFocusOnInstance_; |
1312 std::string focusSopInstanceUid_; | 1312 std::string focusSopInstanceUid_; |
1313 size_t focusFrameNumber_; | |
1313 | 1314 |
1314 boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations_; | 1315 boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations_; |
1315 | 1316 |
1316 void ScheduleNextPrefetch() | 1317 void ScheduleNextPrefetch() |
1317 { | 1318 { |
1576 | 1577 |
1577 case Annotation::Type_Text: | 1578 case Annotation::Type_Text: |
1578 { | 1579 { |
1579 const TextAnnotation& text = dynamic_cast<const TextAnnotation&>(annotation); | 1580 const TextAnnotation& text = dynamic_cast<const TextAnnotation&>(annotation); |
1580 double x, y; | 1581 double x, y; |
1581 OrthancStone::LinearAlgebra::Print(text.GetCenter()); | |
1582 if (GetCurrentFrameGeometry().ProjectPoint(x, y, text.GetCenter())) | 1582 if (GetCurrentFrameGeometry().ProjectPoint(x, y, text.GetCenter())) |
1583 { | 1583 { |
1584 std::unique_ptr<OrthancStone::TextSceneLayer> layer2(new OrthancStone::TextSceneLayer()); | 1584 std::unique_ptr<OrthancStone::TextSceneLayer> layer2(new OrthancStone::TextSceneLayer()); |
1585 layer2->SetPosition(x, y); | 1585 layer2->SetPosition(x, y); |
1586 layer2->SetText(text.GetText()); | 1586 layer2->SetText(text.GetText()); |
1749 cache_(cache), | 1749 cache_(cache), |
1750 fitNextContent_(true), | 1750 fitNextContent_(true), |
1751 isCtrlDown_(false), | 1751 isCtrlDown_(false), |
1752 flipX_(false), | 1752 flipX_(false), |
1753 flipY_(false), | 1753 flipY_(false), |
1754 hasFocusOnInstance_(false) | 1754 hasFocusOnInstance_(false), |
1755 focusFrameNumber_(0) | |
1755 { | 1756 { |
1756 if (!cache_) | 1757 if (!cache_) |
1757 { | 1758 { |
1758 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | 1759 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); |
1759 } | 1760 } |
1855 void Handle(const OrthancStone::ParseDicomSuccessMessage& message) | 1856 void Handle(const OrthancStone::ParseDicomSuccessMessage& message) |
1856 { | 1857 { |
1857 dynamic_cast<const ICommand&>(message.GetOrigin().GetPayload()).Handle(message); | 1858 dynamic_cast<const ICommand&>(message.GetOrigin().GetPayload()).Handle(message); |
1858 } | 1859 } |
1859 | 1860 |
1860 void ApplyScheduledFocus() | |
1861 { | |
1862 size_t instanceIndex; | |
1863 | |
1864 if (hasFocusOnInstance_ && | |
1865 frames_.get() != NULL && | |
1866 frames_->LookupSopInstanceUid(instanceIndex, focusSopInstanceUid_)) | |
1867 { | |
1868 // TODO | |
1869 | |
1870 hasFocusOnInstance_ = false; | |
1871 } | |
1872 } | |
1873 | |
1874 public: | 1861 public: |
1875 static boost::shared_ptr<ViewerViewport> Create(OrthancStone::ILoadersContext::ILock& lock, | 1862 static boost::shared_ptr<ViewerViewport> Create(OrthancStone::ILoadersContext::ILock& lock, |
1876 const OrthancStone::DicomSource& source, | 1863 const OrthancStone::DicomSource& source, |
1877 const std::string& canvas, | 1864 const std::string& canvas, |
1878 boost::shared_ptr<FramesCache> cache, | 1865 boost::shared_ptr<FramesCache> cache, |
1934 loader_->ScheduleGetDicomWeb( | 1921 loader_->ScheduleGetDicomWeb( |
1935 boost::make_shared<OrthancStone::LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID), | 1922 boost::make_shared<OrthancStone::LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID), |
1936 0, source_, uri, new SetDefaultWindowingCommand(GetSharedObserver())); | 1923 0, source_, uri, new SetDefaultWindowingCommand(GetSharedObserver())); |
1937 } | 1924 } |
1938 } | 1925 } |
1939 } | 1926 |
1940 | 1927 ApplyScheduledFocus(); |
1941 | 1928 } |
1942 void UpdateCurrentFrame() | 1929 |
1930 | |
1931 void Redraw() | |
1943 { | 1932 { |
1944 if (cursor_.get() != NULL) | 1933 if (cursor_.get() != NULL) |
1945 { | 1934 { |
1946 unsigned int quality; | 1935 unsigned int quality; |
1947 DisplayFrame(quality, cursor_->GetCurrentIndex()); | 1936 DisplayFrame(quality, cursor_->GetCurrentIndex()); |
2173 void SetAnnotations(boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations) | 2162 void SetAnnotations(boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations) |
2174 { | 2163 { |
2175 annotations_ = annotations; | 2164 annotations_ = annotations; |
2176 } | 2165 } |
2177 | 2166 |
2167 void ScheduleFrameFocus(const std::string& sopInstanceUid, | |
2168 unsigned int frameNumber) | |
2169 { | |
2170 hasFocusOnInstance_ = true; | |
2171 focusSopInstanceUid_ = sopInstanceUid; | |
2172 focusFrameNumber_ = frameNumber; | |
2173 | |
2174 ApplyScheduledFocus(); | |
2175 } | |
2176 | |
2177 void ApplyScheduledFocus() | |
2178 { | |
2179 size_t frameIndex; | |
2180 | |
2181 if (hasFocusOnInstance_ && | |
2182 cursor_.get() != NULL && | |
2183 frames_.get() != NULL && | |
2184 frames_->LookupFrame(frameIndex, focusSopInstanceUid_, focusFrameNumber_)) | |
2185 { | |
2186 size_t current = cursor_->GetCurrentIndex(); | |
2187 | |
2188 if (current != frameIndex) | |
2189 { | |
2190 cursor_->SetCurrentIndex(frameIndex); | |
2191 DisplayCurrentFrame(); | |
2192 } | |
2193 | |
2194 hasFocusOnInstance_ = false; | |
2195 } | |
2196 } | |
2178 }; | 2197 }; |
2179 | 2198 |
2180 | 2199 |
2181 | 2200 |
2182 | 2201 |
2249 "seriesInstanceUid" : UTF8ToString($1) }); | 2268 "seriesInstanceUid" : UTF8ToString($1) }); |
2250 window.dispatchEvent(customEvent); | 2269 window.dispatchEvent(customEvent); |
2251 }, | 2270 }, |
2252 studyInstanceUid.c_str(), | 2271 studyInstanceUid.c_str(), |
2253 seriesInstanceUid.c_str()); | 2272 seriesInstanceUid.c_str()); |
2273 | |
2274 for (Viewports::const_iterator it = allViewports_.begin(); it != allViewports_.end(); ++it) | |
2275 { | |
2276 assert(it->second != NULL); | |
2277 it->second->ApplyScheduledFocus(); | |
2278 } | |
2254 } | 2279 } |
2255 | 2280 |
2256 virtual void SignalFrameUpdated(const ViewerViewport& viewport, | 2281 virtual void SignalFrameUpdated(const ViewerViewport& viewport, |
2257 size_t currentFrame, | 2282 size_t currentFrame, |
2258 size_t countFrames, | 2283 size_t countFrames, |
2721 } | 2746 } |
2722 EXTERN_CATCH_EXCEPTIONS; | 2747 EXTERN_CATCH_EXCEPTIONS; |
2723 } | 2748 } |
2724 | 2749 |
2725 | 2750 |
2751 // Side-effect: "GetStringBuffer()" is filled with the "Series | |
2752 // Instance UID" of the first loaded annotation | |
2726 EMSCRIPTEN_KEEPALIVE | 2753 EMSCRIPTEN_KEEPALIVE |
2727 int LoadOsiriXAnnotations(const char* xml, | 2754 int LoadOsiriXAnnotations(const char* xml, |
2728 int clearPreviousAnnotations) | 2755 int clearPreviousAnnotations) |
2729 { | 2756 { |
2730 try | 2757 try |
2733 { | 2760 { |
2734 annotations_->Clear(); | 2761 annotations_->Clear(); |
2735 } | 2762 } |
2736 | 2763 |
2737 annotations_->LoadXml(xml); | 2764 annotations_->LoadXml(xml); |
2738 | 2765 |
2766 // Force redraw, as the annotations might have changed | |
2739 for (Viewports::iterator it = allViewports_.begin(); it != allViewports_.end(); ++it) | 2767 for (Viewports::iterator it = allViewports_.begin(); it != allViewports_.end(); ++it) |
2740 { | 2768 { |
2741 // TODO - Check if the viewport contains one of the SOP | |
2742 // Instance UID from the loaded annotations => focus on this | |
2743 // instance | |
2744 | |
2745 // TODO - If no viewport contains the instance => monitor the | |
2746 // "ResourcesLoader" as new series get loaded | |
2747 | |
2748 assert(it->second != NULL); | 2769 assert(it->second != NULL); |
2749 it->second->UpdateCurrentFrame(); | 2770 it->second->Redraw(); |
2771 } | |
2772 | |
2773 if (annotations_->GetSize() == 0) | |
2774 { | |
2775 stringBuffer_.clear(); | |
2776 } | |
2777 else | |
2778 { | |
2779 stringBuffer_ = annotations_->GetAnnotation(0).GetSeriesInstanceUid(); | |
2750 } | 2780 } |
2751 | 2781 |
2752 LOG(WARNING) << "Loaded " << annotations_->GetSize() << " annotations from OsiriX"; | 2782 LOG(WARNING) << "Loaded " << annotations_->GetSize() << " annotations from OsiriX"; |
2753 return 1; | 2783 return 1; |
2754 } | 2784 } |
2755 EXTERN_CATCH_EXCEPTIONS; | 2785 EXTERN_CATCH_EXCEPTIONS; |
2756 return 0; | 2786 return 0; |
2757 } | 2787 } |
2788 | |
2789 | |
2790 EMSCRIPTEN_KEEPALIVE | |
2791 void FocusFirstOsiriXAnnotation(const char* canvas) | |
2792 { | |
2793 try | |
2794 { | |
2795 if (annotations_->GetSize() != 0) | |
2796 { | |
2797 const OrthancStone::OsiriX::Annotation& annotation = annotations_->GetAnnotation(0); | |
2798 | |
2799 boost::shared_ptr<ViewerViewport> viewport = GetViewport(canvas); | |
2800 viewport->ScheduleFrameFocus(annotation.GetSopInstanceUid(), 0 /* focus on first frame */); | |
2801 | |
2802 // Force redraw, as the annotations might already have changed | |
2803 viewport->Redraw(); | |
2804 } | |
2805 } | |
2806 EXTERN_CATCH_EXCEPTIONS; | |
2807 } | |
2758 } | 2808 } |