Mercurial > hg > orthanc-stone
comparison OrthancStone/Samples/Common/RtViewerApp.cpp @ 1512:244ad1e4e76a
reorganization of folders
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 07 Jul 2020 16:21:02 +0200 |
parents | Samples/Common/RtViewerApp.cpp@15173a383a00 |
children | fa30f275cd80 |
comparison
equal
deleted
inserted
replaced
1511:9dfeee74c1e6 | 1512:244ad1e4e76a |
---|---|
1 /** | |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
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/>. | |
19 **/ | |
20 | |
21 // Sample app | |
22 #include "RtViewerApp.h" | |
23 #include "RtViewerView.h" | |
24 #include "SampleHelpers.h" | |
25 | |
26 // Stone of Orthanc | |
27 #include "../../Sources/StoneInitialization.h" | |
28 #include "../../Sources/Scene2D/CairoCompositor.h" | |
29 #include "../../Sources/Scene2D/ColorTextureSceneLayer.h" | |
30 #include "../../Sources/Scene2D/OpenGLCompositor.h" | |
31 #include "../../Sources/Scene2D/PanSceneTracker.h" | |
32 #include "../../Sources/Scene2D/ZoomSceneTracker.h" | |
33 #include "../../Sources/Scene2D/RotateSceneTracker.h" | |
34 #include "../../Sources/Scene2DViewport/UndoStack.h" | |
35 #include "../../Sources/Scene2DViewport/CreateLineMeasureTracker.h" | |
36 #include "../../Sources/Scene2DViewport/CreateAngleMeasureTracker.h" | |
37 #include "../../Sources/Scene2DViewport/IFlexiblePointerTracker.h" | |
38 #include "../../Sources/Scene2DViewport/MeasureTool.h" | |
39 #include "../../Sources/Scene2DViewport/PredeclaredTypes.h" | |
40 #include "../../Sources/Volumes/VolumeSceneLayerSource.h" | |
41 #include "../../Sources/Oracle/GetOrthancWebViewerJpegCommand.h" | |
42 #include "../../Sources/Scene2D/GrayscaleStyleConfigurator.h" | |
43 #include "../../Sources/Scene2D/LookupTableStyleConfigurator.h" | |
44 #include "../../Sources/Volumes/DicomVolumeImageMPRSlicer.h" | |
45 #include "../../Sources/StoneException.h" | |
46 | |
47 // Orthanc | |
48 #include <Logging.h> | |
49 #include <OrthancException.h> | |
50 | |
51 // System | |
52 #include <boost/shared_ptr.hpp> | |
53 #include <boost/weak_ptr.hpp> | |
54 #include <boost/make_shared.hpp> | |
55 | |
56 #include <stdio.h> | |
57 | |
58 | |
59 namespace OrthancStone | |
60 { | |
61 void RtViewerApp::InvalidateAllViewports() | |
62 { | |
63 for (size_t i = 0; i < views_.size(); ++i) | |
64 { | |
65 views_[i]->Invalidate(); | |
66 } | |
67 } | |
68 | |
69 const VolumeImageGeometry& RtViewerApp::GetMainGeometry() | |
70 { | |
71 ORTHANC_ASSERT(geometryProvider_.get() != NULL); | |
72 ORTHANC_ASSERT(geometryProvider_->HasGeometry()); | |
73 const VolumeImageGeometry& geometry = geometryProvider_->GetImageGeometry(); | |
74 return geometry; | |
75 } | |
76 | |
77 RtViewerApp::RtViewerApp() | |
78 : undoStack_(new UndoStack) | |
79 { | |
80 // Create the volumes that will be filled later on | |
81 ctVolume_ = boost::make_shared<DicomVolumeImage>(); | |
82 doseVolume_ = boost::make_shared<DicomVolumeImage>(); | |
83 } | |
84 | |
85 boost::shared_ptr<RtViewerApp> RtViewerApp::Create() | |
86 { | |
87 boost::shared_ptr<RtViewerApp> thisOne(new RtViewerApp()); | |
88 return thisOne; | |
89 } | |
90 | |
91 void RtViewerApp::DisableTracker() | |
92 { | |
93 if (activeTracker_) | |
94 { | |
95 activeTracker_->Cancel(); | |
96 activeTracker_.reset(); | |
97 } | |
98 } | |
99 | |
100 void RtViewerApp::CreateView(const std::string& canvasId, VolumeProjection projection) | |
101 { | |
102 boost::shared_ptr<RtViewerView> | |
103 view(new RtViewerView(shared_from_this(), canvasId, projection)); | |
104 | |
105 view->RegisterMessages(); | |
106 | |
107 view->CreateLayers(ctLoader_, doseLoader_, doseVolume_, rtstructLoader_); | |
108 | |
109 views_.push_back(view); | |
110 } | |
111 | |
112 void RtViewerApp::CreateLoaders() | |
113 { | |
114 // the viewport hosts the scene | |
115 { | |
116 // "true" means use progressive quality (jpeg 50 --> jpeg 90 --> 16-bit raw) | |
117 // "false" means only using hi quality | |
118 // TODO: add flag for quality | |
119 ctLoader_ = OrthancSeriesVolumeProgressiveLoader::Create(*loadersContext_, ctVolume_, true); | |
120 | |
121 // better priority for CT vs dose and struct | |
122 ctLoader_->SetSchedulingPriority(-100); | |
123 | |
124 | |
125 // we need to store the CT loader to ask from geometry details later on when geometry is loaded | |
126 geometryProvider_ = ctLoader_; | |
127 | |
128 doseLoader_ = OrthancMultiframeVolumeLoader::Create(*loadersContext_, doseVolume_); | |
129 rtstructLoader_ = DicomStructureSetLoader::Create(*loadersContext_); | |
130 } | |
131 | |
132 /** | |
133 Register for notifications issued by the loaders | |
134 */ | |
135 | |
136 Register<DicomVolumeImage::GeometryReadyMessage> | |
137 (*ctLoader_, &RtViewerApp::HandleGeometryReady); | |
138 | |
139 Register<OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality> | |
140 (*ctLoader_, &RtViewerApp::HandleCTLoaded); | |
141 | |
142 Register<DicomVolumeImage::ContentUpdatedMessage> | |
143 (*ctLoader_, &RtViewerApp::HandleCTContentUpdated); | |
144 | |
145 Register<DicomVolumeImage::ContentUpdatedMessage> | |
146 (*doseLoader_, &RtViewerApp::HandleDoseLoaded); | |
147 | |
148 Register<DicomStructureSetLoader::StructuresReady> | |
149 (*rtstructLoader_, &RtViewerApp::HandleStructuresReady); | |
150 | |
151 Register<DicomStructureSetLoader::StructuresUpdated> | |
152 (*rtstructLoader_, &RtViewerApp::HandleStructuresUpdated); | |
153 } | |
154 | |
155 void RtViewerApp::StartLoaders() | |
156 { | |
157 ORTHANC_ASSERT(HasArgument("ctseries") && HasArgument("rtdose") && HasArgument("rtstruct")); | |
158 | |
159 LOG(INFO) << "About to load:"; | |
160 LOG(INFO) << " CT : " << GetArgument("ctseries"); | |
161 LOG(INFO) << " RTDOSE : " << GetArgument("rtdose"); | |
162 LOG(INFO) << " RTSTRUCT : " << GetArgument("rtstruct"); | |
163 ctLoader_->LoadSeries(GetArgument("ctseries")); | |
164 doseLoader_->LoadInstance(GetArgument("rtdose")); | |
165 rtstructLoader_->LoadInstanceFullVisibility(GetArgument("rtstruct")); | |
166 } | |
167 | |
168 void RtViewerApp::HandleGeometryReady(const DicomVolumeImage::GeometryReadyMessage& message) | |
169 { | |
170 for (size_t i = 0; i < views_.size(); ++i) | |
171 { | |
172 views_[i]->RetrieveGeometry(); | |
173 } | |
174 FitContent(); | |
175 UpdateLayersInAllViews(); | |
176 } | |
177 | |
178 void RtViewerApp::FitContent() | |
179 { | |
180 for (size_t i = 0; i < views_.size(); ++i) | |
181 { | |
182 views_[i]->FitContent(); | |
183 } | |
184 } | |
185 | |
186 void RtViewerApp::UpdateLayersInAllViews() | |
187 { | |
188 for (size_t i = 0; i < views_.size(); ++i) | |
189 { | |
190 views_[i]->UpdateLayers(); | |
191 } | |
192 } | |
193 | |
194 void RtViewerApp::HandleCTLoaded(const OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality& message) | |
195 { | |
196 for (size_t i = 0; i < views_.size(); ++i) | |
197 { | |
198 views_[i]->RetrieveGeometry(); | |
199 } | |
200 UpdateLayersInAllViews(); | |
201 } | |
202 | |
203 void RtViewerApp::HandleCTContentUpdated(const DicomVolumeImage::ContentUpdatedMessage& message) | |
204 { | |
205 UpdateLayersInAllViews(); | |
206 } | |
207 | |
208 void RtViewerApp::HandleDoseLoaded(const DicomVolumeImage::ContentUpdatedMessage& message) | |
209 { | |
210 //TODO: compute dose extent, with outlier rejection | |
211 UpdateLayersInAllViews(); | |
212 } | |
213 | |
214 void RtViewerApp::HandleStructuresReady(const DicomStructureSetLoader::StructuresReady& message) | |
215 { | |
216 UpdateLayersInAllViews(); | |
217 } | |
218 | |
219 void RtViewerApp::HandleStructuresUpdated(const DicomStructureSetLoader::StructuresUpdated& message) | |
220 { | |
221 UpdateLayersInAllViews(); | |
222 } | |
223 | |
224 void RtViewerApp::SetArgument(const std::string& key, const std::string& value) | |
225 { | |
226 if (key == "loglevel") | |
227 OrthancStoneHelpers::SetLogLevel(value); | |
228 else | |
229 arguments_[key] = value; | |
230 } | |
231 | |
232 std::string RtViewerApp::GetArgument(const std::string& key) const | |
233 { | |
234 std::map<std::string, std::string>::const_iterator found = arguments_.find(key); | |
235 if (found == arguments_.end()) | |
236 { | |
237 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
238 } | |
239 else | |
240 { | |
241 return found->second; | |
242 } | |
243 } | |
244 | |
245 bool RtViewerApp::HasArgument(const std::string& key) const | |
246 { | |
247 return (arguments_.find(key) != arguments_.end()); | |
248 } | |
249 } | |
250 |