Mercurial > hg > orthanc-stone
comparison Applications/Samples/Common/RtViewerApp.cpp @ 1538:d1806b4e4839
moving OrthancStone/Samples/ as Applications/Samples/
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 Aug 2020 13:24:38 +0200 |
parents | OrthancStone/Samples/Common/RtViewerApp.cpp@31b0449a163a |
children | 6e0da8370270 |
comparison
equal
deleted
inserted
replaced
1537:de8cf5859e84 | 1538:d1806b4e4839 |
---|---|
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 | |
161 if (GetArgument("ctseries") == "") | |
162 { | |
163 LOG(INFO) << " CT : <unspecified>"; | |
164 } | |
165 else | |
166 { | |
167 LOG(INFO) << " CT : " << GetArgument("ctseries"); | |
168 ctLoader_->LoadSeries(GetArgument("ctseries")); | |
169 } | |
170 | |
171 if (GetArgument("rtdose") == "") | |
172 { | |
173 LOG(INFO) << " RTDOSE : <unspecified>"; | |
174 } | |
175 else | |
176 { | |
177 LOG(INFO) << " RTDOSE : " << GetArgument("rtdose"); | |
178 doseLoader_->LoadInstance(GetArgument("rtdose")); | |
179 } | |
180 | |
181 if (GetArgument("rtstruct") == "") | |
182 { | |
183 LOG(INFO) << " RTSTRUCT : : <unspecified>"; | |
184 } | |
185 else | |
186 { | |
187 LOG(INFO) << " RTSTRUCT : : " << GetArgument("rtstruct"); | |
188 rtstructLoader_->LoadInstanceFullVisibility(GetArgument("rtstruct")); | |
189 } | |
190 } | |
191 | |
192 void RtViewerApp::HandleGeometryReady(const DicomVolumeImage::GeometryReadyMessage& message) | |
193 { | |
194 for (size_t i = 0; i < views_.size(); ++i) | |
195 { | |
196 views_[i]->RetrieveGeometry(); | |
197 } | |
198 FitContent(); | |
199 UpdateLayersInAllViews(); | |
200 } | |
201 | |
202 void RtViewerApp::FitContent() | |
203 { | |
204 for (size_t i = 0; i < views_.size(); ++i) | |
205 { | |
206 views_[i]->FitContent(); | |
207 } | |
208 } | |
209 | |
210 void RtViewerApp::UpdateLayersInAllViews() | |
211 { | |
212 for (size_t i = 0; i < views_.size(); ++i) | |
213 { | |
214 views_[i]->UpdateLayers(); | |
215 } | |
216 } | |
217 | |
218 void RtViewerApp::HandleCTLoaded(const OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality& message) | |
219 { | |
220 for (size_t i = 0; i < views_.size(); ++i) | |
221 { | |
222 views_[i]->RetrieveGeometry(); | |
223 } | |
224 UpdateLayersInAllViews(); | |
225 } | |
226 | |
227 void RtViewerApp::HandleCTContentUpdated(const DicomVolumeImage::ContentUpdatedMessage& message) | |
228 { | |
229 UpdateLayersInAllViews(); | |
230 } | |
231 | |
232 void RtViewerApp::HandleDoseLoaded(const DicomVolumeImage::ContentUpdatedMessage& message) | |
233 { | |
234 //TODO: compute dose extent, with outlier rejection | |
235 UpdateLayersInAllViews(); | |
236 } | |
237 | |
238 void RtViewerApp::HandleStructuresReady(const DicomStructureSetLoader::StructuresReady& message) | |
239 { | |
240 UpdateLayersInAllViews(); | |
241 } | |
242 | |
243 void RtViewerApp::HandleStructuresUpdated(const DicomStructureSetLoader::StructuresUpdated& message) | |
244 { | |
245 UpdateLayersInAllViews(); | |
246 } | |
247 | |
248 void RtViewerApp::SetArgument(const std::string& key, const std::string& value) | |
249 { | |
250 if (key == "loglevel") | |
251 OrthancStoneHelpers::SetLogLevel(value); | |
252 else | |
253 arguments_[key] = value; | |
254 } | |
255 | |
256 std::string RtViewerApp::GetArgument(const std::string& key) const | |
257 { | |
258 std::map<std::string, std::string>::const_iterator found = arguments_.find(key); | |
259 if (found == arguments_.end()) | |
260 { | |
261 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
262 } | |
263 else | |
264 { | |
265 return found->second; | |
266 } | |
267 } | |
268 | |
269 bool RtViewerApp::HasArgument(const std::string& key) const | |
270 { | |
271 return (arguments_.find(key) != arguments_.end()); | |
272 } | |
273 } | |
274 |