comparison OrthancStone/Sources/Scene2D/Scene2D.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Scene2D/Scene2D.cpp@30deba7bc8e2
children 4fb8fdf03314
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
22 #include "Scene2D.h"
23
24 #include <OrthancException.h>
25
26
27 namespace OrthancStone
28 {
29 class Scene2D::Item
30 {
31 private:
32 std::unique_ptr<ISceneLayer> layer_;
33 uint64_t identifier_;
34
35 public:
36 Item(ISceneLayer* layer,
37 uint64_t identifier) :
38 layer_(layer),
39 identifier_(identifier)
40 {
41 if (layer == NULL)
42 {
43 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
44 }
45 }
46
47 ISceneLayer& GetLayer() const
48 {
49 if (layer_.get() == NULL)
50 {
51 LOG(ERROR) << "Scene2D::Item::GetLayer(): (layer_.get() == NULL)";
52 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
53 }
54 else
55 {
56 return *layer_;
57 }
58 }
59
60 ISceneLayer* ReleaseLayer()
61 {
62 if (layer_.get() == NULL)
63 {
64 LOG(ERROR) << "Scene2D::Item::ReleaseLayer(): (layer_.get() == NULL)";
65 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
66 }
67 else
68 {
69 return layer_.release();
70 }
71 }
72
73 uint64_t GetIdentifier() const
74 {
75 return identifier_;
76 }
77 };
78
79
80 Scene2D::Scene2D(const Scene2D& other)
81 : sceneToCanvas_(other.sceneToCanvas_)
82 , canvasToScene_(other.canvasToScene_)
83 , layerCounter_(0)
84 {
85 for (Content::const_iterator it = other.content_.begin();
86 it != other.content_.end(); ++it)
87 {
88 content_[it->first] = new Item(it->second->GetLayer().Clone(), layerCounter_++);
89 }
90 }
91
92
93 Scene2D::~Scene2D()
94 {
95 for (Content::iterator it = content_.begin();
96 it != content_.end(); ++it)
97 {
98 assert(it->second != NULL);
99 delete it->second;
100 }
101 }
102
103
104 void Scene2D::SetLayer(int depth,
105 ISceneLayer* layer) // Takes ownership
106 {
107 LOG(TRACE) << "SetLayer(" << depth << ", " << reinterpret_cast<intptr_t>(layer) << ")";
108 std::unique_ptr<Item> item(new Item(layer, layerCounter_++));
109
110 if (layer == NULL)
111 {
112 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
113 }
114
115 Content::iterator found = content_.find(depth);
116
117 if (found == content_.end())
118 {
119 content_[depth] = item.release();
120 }
121 else
122 {
123 assert(found->second != NULL);
124 delete found->second;
125 found->second = item.release();
126 }
127 }
128
129
130 void Scene2D::DeleteLayer(int depth)
131 {
132
133 Content::iterator found = content_.find(depth);
134
135 if (found != content_.end())
136 {
137 LOG(TRACE) << "DeleteLayer --found-- (" << depth << ")";
138 assert(found->second != NULL);
139 delete found->second;
140 content_.erase(found);
141 }
142 }
143
144
145 bool Scene2D::HasLayer(int depth) const
146 {
147 return (content_.find(depth) != content_.end());
148 }
149
150
151 ISceneLayer& Scene2D::GetLayer(int depth) const
152 {
153 Content::const_iterator found = content_.find(depth);
154
155 if (found == content_.end())
156 {
157 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
158 }
159 else
160 {
161 assert(found->second != NULL);
162 return found->second->GetLayer();
163 }
164 }
165
166
167 int Scene2D::GetMinDepth() const
168 {
169 if (content_.size() == 0)
170 return 0;
171 else
172 return content_.begin()->first;
173 }
174
175
176 int Scene2D::GetMaxDepth() const
177 {
178 if (content_.size() == 0)
179 return 0;
180 else
181 return content_.rbegin()->first;
182 }
183
184 ISceneLayer* Scene2D::ReleaseLayer(int depth)
185 {
186 Content::iterator found = content_.find(depth);
187
188 if (found == content_.end())
189 {
190 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
191 }
192 else
193 {
194 assert(found->second != NULL);
195
196 std::unique_ptr<ISceneLayer> layer(found->second->ReleaseLayer());
197 assert(layer.get() != NULL);
198
199 content_.erase(found);
200
201 return layer.release();
202 }
203 }
204
205 void Scene2D::Apply(IVisitor& visitor) const
206 {
207 for (Content::const_iterator it = content_.begin();
208 it != content_.end(); ++it)
209 {
210 assert(it->second != NULL);
211 visitor.Visit(*this, it->second->GetLayer(), it->second->GetIdentifier(), it->first);
212 }
213 }
214
215
216 void Scene2D::SetSceneToCanvasTransform(const AffineTransform2D& transform)
217 {
218 // Make sure the transform is invertible before making any change
219 AffineTransform2D inverse = AffineTransform2D::Invert(transform);
220
221 sceneToCanvas_ = transform;
222 canvasToScene_ = inverse;
223 }
224
225 void Scene2D::GetBoundingBox(Extent2D &target) const
226 {
227 target.Reset();
228
229 for (Content::const_iterator it = content_.begin();
230 it != content_.end(); ++it)
231 {
232 assert(it->second != NULL);
233
234 Extent2D tmp;
235 if (it->second->GetLayer().GetBoundingBox(tmp))
236 {
237 target.Union(tmp);
238 }
239 }
240 }
241
242 void Scene2D::FitContent(unsigned int canvasWidth,
243 unsigned int canvasHeight)
244 {
245 Extent2D extent;
246
247 GetBoundingBox(extent);
248
249 if (!extent.IsEmpty())
250 {
251 double zoomX = static_cast<double>(canvasWidth) / extent.GetWidth();
252 double zoomY = static_cast<double>(canvasHeight) / extent.GetHeight();
253
254 double zoom = std::min(zoomX, zoomY);
255 if (LinearAlgebra::IsCloseToZero(zoom))
256 {
257 zoom = 1;
258 }
259
260 double panX = extent.GetCenterX();
261 double panY = extent.GetCenterY();
262
263 // Bring the center of the scene to (0,0)
264 AffineTransform2D t1 = AffineTransform2D::CreateOffset(-panX, -panY);
265
266 // Scale the scene
267 AffineTransform2D t2 = AffineTransform2D::CreateScaling(zoom, zoom);
268
269 SetSceneToCanvasTransform(AffineTransform2D::Combine(t2, t1));
270 }
271 }
272 }