Mercurial > hg > orthanc-stone
comparison Samples/Common/MeasureToolsToolbox.cpp @ 645:1e9ed656318e
Merge + ongoing measure work
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Mon, 13 May 2019 15:12:56 +0200 |
parents | |
children | 62f6ff016085 |
comparison
equal
deleted
inserted
replaced
644:f939f449482c | 645:1e9ed656318e |
---|---|
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 <boost/math/constants/constants.hpp> | |
24 | |
25 namespace | |
26 { | |
27 double g_pi = boost::math::constants::pi<double>(); | |
28 } | |
29 | |
30 namespace OrthancStone | |
31 { | |
32 | |
33 void AddSquare(PolylineSceneLayer::Chain& chain, | |
34 const Scene2D& scene, | |
35 const ScenePoint2D& centerS, | |
36 const double& sideLength) | |
37 { | |
38 chain.clear(); | |
39 chain.reserve(4); | |
40 ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); | |
41 //TODO: take DPI into account | |
42 double handleLX = centerC.GetX() - sideLength / 2; | |
43 double handleTY = centerC.GetY() - sideLength / 2; | |
44 double handleRX = centerC.GetX() + sideLength / 2; | |
45 double handleBY = centerC.GetY() + sideLength / 2; | |
46 ScenePoint2D LTC(handleLX, handleTY); | |
47 ScenePoint2D RTC(handleRX, handleTY); | |
48 ScenePoint2D RBC(handleRX, handleBY); | |
49 ScenePoint2D LBC(handleLX, handleBY); | |
50 | |
51 ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); | |
52 ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); | |
53 ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); | |
54 ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); | |
55 | |
56 chain.push_back(startLT); | |
57 chain.push_back(startRT); | |
58 chain.push_back(startRB); | |
59 chain.push_back(startLB); | |
60 } | |
61 | |
62 void AddArc( | |
63 PolylineSceneLayer::Chain& chain | |
64 , const Scene2D& scene | |
65 , const ScenePoint2D& p1 | |
66 , const ScenePoint2D& c | |
67 , const ScenePoint2D& p2 | |
68 , const double& radiusS | |
69 , const bool clockwise | |
70 , const int subdivisionsCount) | |
71 { | |
72 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); | |
73 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); | |
74 AddArc( | |
75 chain, scene, c, radiusS, p1cAngle, p2cAngle, | |
76 clockwise, subdivisionsCount); | |
77 } | |
78 | |
79 double RadiansToDegrees(double angleRad) | |
80 { | |
81 static const double factor = 180.0 / g_pi; | |
82 return angleRad * factor; | |
83 } | |
84 | |
85 void GetPositionOnBisectingLine( | |
86 ScenePoint2D& result | |
87 , const ScenePoint2D& p1 | |
88 , const ScenePoint2D& c | |
89 , const ScenePoint2D& p2 | |
90 , const double d) | |
91 { | |
92 // TODO: fix correct half-plane | |
93 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); | |
94 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); | |
95 double angle = 0.5*(p1cAngle + p2cAngle); | |
96 double unitVectorX = cos(angle); | |
97 double unitVectorY = sin(angle); | |
98 double posX = c.GetX() + d * unitVectorX; | |
99 double posY = c.GetX() + d * unitVectorY; | |
100 result = ScenePoint2D(posX, posY); | |
101 } | |
102 | |
103 void AddArc( | |
104 PolylineSceneLayer::Chain& chain | |
105 , const Scene2D& scene | |
106 , const ScenePoint2D& centerS | |
107 , const double& radiusS | |
108 , const double startAngleRad | |
109 , const double endAngleRad | |
110 , const bool clockwise | |
111 , const int subdivisionsCount) | |
112 { | |
113 double startAngleRadN = NormalizeAngle(startAngleRad); | |
114 double endAngleRadN = NormalizeAngle(endAngleRad); | |
115 | |
116 double angle1Rad = std::min(startAngleRadN, endAngleRadN); | |
117 double angle2Rad = std::max(startAngleRadN, endAngleRadN); | |
118 | |
119 // now we are sure angle1Rad < angle2Rad | |
120 // this means that if we draw from 1 to 2, it will be clockwise ( | |
121 // increasing angles). | |
122 // let's fix this: | |
123 if (!clockwise) | |
124 { | |
125 angle2Rad -= 2 * g_pi; | |
126 // now we are sure angle2Rad < angle1Rad (since they were normalized) | |
127 // and, thus, going from 1 to 2 means the angle values will DECREASE, | |
128 // which is the definition of anticlockwise | |
129 } | |
130 | |
131 chain.clear(); | |
132 chain.reserve(subdivisionsCount + 1); | |
133 | |
134 double angleIncr = (angle2Rad - angle1Rad) | |
135 / static_cast<double>(subdivisionsCount); | |
136 | |
137 double theta = angle1Rad; | |
138 for (int i = 0; i < subdivisionsCount + 1; ++i) | |
139 { | |
140 double offsetX = radiusS * cos(theta); | |
141 double offsetY = radiusS * sin(theta); | |
142 double pointX = centerS.GetX() + offsetX; | |
143 double pointY = centerS.GetY() + offsetY; | |
144 chain.push_back(ScenePoint2D(pointX, pointY)); | |
145 theta += angleIncr; | |
146 } | |
147 } | |
148 | |
149 void AddCircle(PolylineSceneLayer::Chain& chain, | |
150 const Scene2D& scene, | |
151 const ScenePoint2D& centerS, | |
152 const double& radiusS, | |
153 const int numSubdivisions) | |
154 { | |
155 //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); | |
156 //TODO: take DPI into account | |
157 | |
158 // TODO: automatically compute the number for segments for smooth | |
159 // display based on the radius in pixels. | |
160 | |
161 chain.clear(); | |
162 chain.reserve(numSubdivisions); | |
163 | |
164 double angleIncr = (2.0 * g_pi) | |
165 / static_cast<double>(numSubdivisions); | |
166 | |
167 double theta = 0; | |
168 for (int i = 0; i < numSubdivisions; ++i) | |
169 { | |
170 double offsetX = radiusS * cos(theta); | |
171 double offsetY = radiusS * sin(theta); | |
172 double pointX = centerS.GetX() + offsetX; | |
173 double pointY = centerS.GetY() + offsetY; | |
174 chain.push_back(ScenePoint2D(pointX, pointY)); | |
175 theta += angleIncr; | |
176 } | |
177 } | |
178 | |
179 double NormalizeAngle(double angle) | |
180 { | |
181 double retAngle = angle; | |
182 while (retAngle < 0) | |
183 retAngle += 2 * g_pi; | |
184 while (retAngle >= 2 * g_pi) | |
185 retAngle -= 2 * g_pi; | |
186 return retAngle; | |
187 } | |
188 | |
189 double MeasureAngle(const ScenePoint2D& p1, const ScenePoint2D& c, const ScenePoint2D& p2) | |
190 { | |
191 double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); | |
192 double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); | |
193 double delta = p2cAngle - p1cAngle; | |
194 return NormalizeAngle(delta); | |
195 } | |
196 | |
197 | |
198 #if 0 | |
199 void AddEllipse(PolylineSceneLayer::Chain& chain, | |
200 const Scene2D& scene, | |
201 const ScenePoint2D& centerS, | |
202 const double& halfHAxis, | |
203 const double& halfVAxis) | |
204 { | |
205 chain.clear(); | |
206 chain.reserve(4); | |
207 ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); | |
208 //TODO: take DPI into account | |
209 double handleLX = centerC.GetX() - sideLength / 2; | |
210 double handleTY = centerC.GetY() - sideLength / 2; | |
211 double handleRX = centerC.GetX() + sideLength / 2; | |
212 double handleBY = centerC.GetY() + sideLength / 2; | |
213 ScenePoint2D LTC(handleLX, handleTY); | |
214 ScenePoint2D RTC(handleRX, handleTY); | |
215 ScenePoint2D RBC(handleRX, handleBY); | |
216 ScenePoint2D LBC(handleLX, handleBY); | |
217 | |
218 ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); | |
219 ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); | |
220 ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); | |
221 ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); | |
222 | |
223 chain.push_back(startLT); | |
224 chain.push_back(startRT); | |
225 chain.push_back(startRB); | |
226 chain.push_back(startLB); | |
227 } | |
228 #endif | |
229 } |