comparison Framework/Scene2DViewport/MeasureToolsToolbox.cpp @ 698:8b6adfb62a2f refactor-viewport-controller

Code is broken -- stashing ongoing work in a branch
author Benjamin Golinvaux <bgo@osimis.io>
date Wed, 15 May 2019 16:56:17 +0200
parents
children c0fcb2757b0a 712ff6ff3c19
comparison
equal deleted inserted replaced
660:cb3b76d16234 698:8b6adfb62a2f
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-2019 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 #include "MeasureToolsToolbox.h"
22
23 #include <Framework/Scene2D/TextSceneLayer.h>
24
25 #include <boost/math/constants/constants.hpp>
26
27 namespace
28 {
29 double g_pi = boost::math::constants::pi<double>();
30 }
31
32 namespace OrthancStone
33 {
34 double RadiansToDegrees(double angleRad)
35 {
36 static const double factor = 180.0 / g_pi;
37 return angleRad * factor;
38 }
39
40 void AddSquare(PolylineSceneLayer::Chain& chain,
41 const Scene2D& scene,
42 const ScenePoint2D& centerS,
43 const double& sideLength)
44 {
45 chain.clear();
46 chain.reserve(4);
47 ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform());
48 //TODO: take DPI into account
49 double handleLX = centerC.GetX() - sideLength / 2;
50 double handleTY = centerC.GetY() - sideLength / 2;
51 double handleRX = centerC.GetX() + sideLength / 2;
52 double handleBY = centerC.GetY() + sideLength / 2;
53 ScenePoint2D LTC(handleLX, handleTY);
54 ScenePoint2D RTC(handleRX, handleTY);
55 ScenePoint2D RBC(handleRX, handleBY);
56 ScenePoint2D LBC(handleLX, handleBY);
57
58 ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform());
59 ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform());
60 ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform());
61 ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform());
62
63 chain.push_back(startLT);
64 chain.push_back(startRT);
65 chain.push_back(startRB);
66 chain.push_back(startLB);
67 }
68 #if 0
69 void AddArc(
70 PolylineSceneLayer::Chain& chain
71 , const Scene2D& scene
72 , const ScenePoint2D& p1
73 , const ScenePoint2D& c
74 , const ScenePoint2D& p2
75 , const double& radiusS
76 , const bool clockwise
77 , const int subdivisionsCount)
78 {
79 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX());
80 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX());
81 AddArc(
82 chain, scene, c, radiusS, p1cAngle, p2cAngle,
83 clockwise, subdivisionsCount);
84 }
85 #endif
86
87 void AddShortestArc(
88 PolylineSceneLayer::Chain& chain
89 , const Scene2D& scene
90 , const ScenePoint2D& p1
91 , const ScenePoint2D& c
92 , const ScenePoint2D& p2
93 , const double& radiusS
94 , const int subdivisionsCount)
95 {
96 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX());
97 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX());
98 AddShortestArc(
99 chain, scene, c, radiusS, p1cAngle, p2cAngle, subdivisionsCount);
100 }
101
102 void GetPositionOnBisectingLine(
103 ScenePoint2D& result
104 , const ScenePoint2D& p1
105 , const ScenePoint2D& c
106 , const ScenePoint2D& p2
107 , const double d)
108 {
109 // TODO: fix correct half-plane
110 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX());
111 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX());
112 double angle = 0.5*(p1cAngle + p2cAngle);
113 double unitVectorX = cos(angle);
114 double unitVectorY = sin(angle);
115 double posX = c.GetX() + d * unitVectorX;
116 double posY = c.GetX() + d * unitVectorY;
117 result = ScenePoint2D(posX, posY);
118 }
119
120 void AddShortestArc(
121 PolylineSceneLayer::Chain& chain
122 , const Scene2D& scene
123 , const ScenePoint2D& centerS
124 , const double& radiusS
125 , const double startAngleRad
126 , const double endAngleRad
127 , const int subdivisionsCount)
128 {
129 // this gives a signed difference between angle which
130 // is the smallest difference (in magnitude) between
131 // the angles
132 double delta = NormalizeAngle(endAngleRad-startAngleRad);
133
134 chain.clear();
135 chain.reserve(subdivisionsCount + 1);
136
137 double angleIncr = delta/static_cast<double>(subdivisionsCount);
138
139 double theta = startAngleRad;
140 for (int i = 0; i < subdivisionsCount + 1; ++i)
141 {
142 double offsetX = radiusS * cos(theta);
143 double offsetY = radiusS * sin(theta);
144 double pointX = centerS.GetX() + offsetX;
145 double pointY = centerS.GetY() + offsetY;
146 chain.push_back(ScenePoint2D(pointX, pointY));
147 theta += angleIncr;
148 }
149 }
150
151 #if 0
152 void AddArc(
153 PolylineSceneLayer::Chain& chain
154 , const Scene2D& scene
155 , const ScenePoint2D& centerS
156 , const double& radiusS
157 , const double startAngleRad
158 , const double endAngleRad
159 , const bool clockwise
160 , const int subdivisionsCount)
161 {
162 double startAngleRadN = NormalizeAngle(startAngleRad);
163 double endAngleRadN = NormalizeAngle(endAngleRad);
164
165 double angle1Rad = std::min(startAngleRadN, endAngleRadN);
166 double angle2Rad = std::max(startAngleRadN, endAngleRadN);
167
168 // now we are sure angle1Rad < angle2Rad
169 // this means that if we draw from 1 to 2, it will be clockwise (
170 // increasing angles).
171 // let's fix this:
172 if (!clockwise)
173 {
174 angle2Rad -= 2 * g_pi;
175 // now we are sure angle2Rad < angle1Rad (since they were normalized)
176 // and, thus, going from 1 to 2 means the angle values will DECREASE,
177 // which is the definition of anticlockwise
178 }
179
180 chain.clear();
181 chain.reserve(subdivisionsCount + 1);
182
183 double angleIncr = (angle2Rad - angle1Rad)
184 / static_cast<double>(subdivisionsCount);
185
186 double theta = angle1Rad;
187 for (int i = 0; i < subdivisionsCount + 1; ++i)
188 {
189 double offsetX = radiusS * cos(theta);
190 double offsetY = radiusS * sin(theta);
191 double pointX = centerS.GetX() + offsetX;
192 double pointY = centerS.GetY() + offsetY;
193 chain.push_back(ScenePoint2D(pointX, pointY));
194 theta += angleIncr;
195 }
196 }
197 #endif
198
199 void AddCircle(PolylineSceneLayer::Chain& chain,
200 const Scene2D& scene,
201 const ScenePoint2D& centerS,
202 const double& radiusS,
203 const int numSubdivisions)
204 {
205 //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform());
206 //TODO: take DPI into account
207
208 // TODO: automatically compute the number for segments for smooth
209 // display based on the radius in pixels.
210
211 chain.clear();
212 chain.reserve(numSubdivisions);
213
214 double angleIncr = (2.0 * g_pi)
215 / static_cast<double>(numSubdivisions);
216
217 double theta = 0;
218 for (int i = 0; i < numSubdivisions; ++i)
219 {
220 double offsetX = radiusS * cos(theta);
221 double offsetY = radiusS * sin(theta);
222 double pointX = centerS.GetX() + offsetX;
223 double pointY = centerS.GetY() + offsetY;
224 chain.push_back(ScenePoint2D(pointX, pointY));
225 theta += angleIncr;
226 }
227 }
228
229 double NormalizeAngle(double angle)
230 {
231 double retAngle = angle;
232 while (retAngle < -1.0*g_pi)
233 retAngle += 2 * g_pi;
234 while (retAngle >= g_pi)
235 retAngle -= 2 * g_pi;
236 return retAngle;
237 }
238
239 double MeasureAngle(const ScenePoint2D& p1, const ScenePoint2D& c, const ScenePoint2D& p2)
240 {
241 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX());
242 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX());
243 double delta = p2cAngle - p1cAngle;
244 return NormalizeAngle(delta);
245 }
246
247
248 #if 0
249 void AddEllipse(PolylineSceneLayer::Chain& chain,
250 const Scene2D& scene,
251 const ScenePoint2D& centerS,
252 const double& halfHAxis,
253 const double& halfVAxis)
254 {
255 chain.clear();
256 chain.reserve(4);
257 ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform());
258 //TODO: take DPI into account
259 double handleLX = centerC.GetX() - sideLength / 2;
260 double handleTY = centerC.GetY() - sideLength / 2;
261 double handleRX = centerC.GetX() + sideLength / 2;
262 double handleBY = centerC.GetY() + sideLength / 2;
263 ScenePoint2D LTC(handleLX, handleTY);
264 ScenePoint2D RTC(handleRX, handleTY);
265 ScenePoint2D RBC(handleRX, handleBY);
266 ScenePoint2D LBC(handleLX, handleBY);
267
268 ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform());
269 ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform());
270 ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform());
271 ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform());
272
273 chain.push_back(startLT);
274 chain.push_back(startRT);
275 chain.push_back(startRB);
276 chain.push_back(startLB);
277 }
278 #endif
279
280
281 namespace
282 {
283 /**
284 Helper function for outlined text rendering
285 */
286 TextSceneLayer* GetOutlineTextLayer(
287 Scene2D& scene, int baseLayerIndex, int index)
288 {
289 assert(scene.HasLayer(baseLayerIndex));
290 assert(index >= 0);
291 assert(index < 5);
292
293 ISceneLayer * layer = &(scene.GetLayer(baseLayerIndex + index));
294 TextSceneLayer * concreteLayer = dynamic_cast<TextSceneLayer*>(layer);
295 assert(concreteLayer != NULL);
296 return concreteLayer;
297 }
298 }
299
300 void SetTextLayerOutlineProperties(
301 Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p)
302 {
303 double xoffsets[5] = { 2, 0, -2, 0, 0 };
304 double yoffsets[5] = { 0, -2, 0, 2, 0 };
305
306 // get the scaling factor
307 const double pixelToScene =
308 scene.GetCanvasToSceneTransform().ComputeZoom();
309
310 for (int i = 0; i < 5; ++i)
311 {
312 TextSceneLayer* textLayer = GetOutlineTextLayer(scene, baseLayerIndex, i);
313 textLayer->SetText(text);
314
315 if (i == 4)
316 textLayer->SetColor(0, 223, 81);
317 else
318 textLayer->SetColor(0, 56, 21);
319
320 ScenePoint2D textAnchor;
321 //GetPositionOnBisectingLine(
322 // textAnchor, side1End_, center_, side2End_, 40.0*pixelToScene);
323 textLayer->SetPosition(
324 p.GetX() + xoffsets[i] * pixelToScene,
325 p.GetY() + yoffsets[i] * pixelToScene);
326 }
327 }
328
329
330
331
332
333
334
335
336 }