comparison Samples/Common/MeasureTools.cpp @ 645:1e9ed656318e

Merge + ongoing measure work
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 13 May 2019 15:12:56 +0200
parents f939f449482c
children 462a5074f914
comparison
equal deleted inserted replaced
644:f939f449482c 645:1e9ed656318e
16 * 16 *
17 * You should have received a copy of the GNU Affero General Public License 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/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/ 19 **/
20 20
21 #include "MeasureTools.h"
22
21 #include <Core/Logging.h> 23 #include <Core/Logging.h>
22 #include "MeasureTools.h" 24
23 #include <boost/math/constants/constants.hpp> 25 #include <boost/math/constants/constants.hpp>
24 26
25 namespace OrthancStone 27 namespace OrthancStone
26 { 28 {
27 void MeasureTool::Enable() 29 void MeasureTool::Enable()
33 void MeasureTool::Disable() 35 void MeasureTool::Disable()
34 { 36 {
35 enabled_ = false; 37 enabled_ = false;
36 RefreshScene(); 38 RefreshScene();
37 } 39 }
38
39 LineMeasureTool::~LineMeasureTool()
40 {
41 // this measuring tool is a RABI for the corresponding visual layers
42 // stored in the 2D scene
43 Disable();
44 RemoveFromScene();
45 }
46
47 void LineMeasureTool::RemoveFromScene()
48 {
49 if (layersCreated)
50 {
51 assert(GetScene().HasLayer(polylineZIndex_));
52 assert(GetScene().HasLayer(textZIndex_));
53 GetScene().DeleteLayer(polylineZIndex_);
54 GetScene().DeleteLayer(textZIndex_);
55 }
56 }
57
58
59 void LineMeasureTool::SetStart(ScenePoint2D start)
60 {
61 start_ = start;
62 RefreshScene();
63 }
64
65 void LineMeasureTool::SetEnd(ScenePoint2D end)
66 {
67 end_ = end;
68 RefreshScene();
69 }
70
71 void LineMeasureTool::Set(ScenePoint2D start, ScenePoint2D end)
72 {
73 start_ = start;
74 end_ = end;
75 RefreshScene();
76 }
77
78 PolylineSceneLayer* LineMeasureTool::GetPolylineLayer()
79 {
80 assert(GetScene().HasLayer(polylineZIndex_));
81 ISceneLayer* layer = &(GetScene().GetLayer(polylineZIndex_));
82 PolylineSceneLayer* concreteLayer = dynamic_cast<PolylineSceneLayer*>(layer);
83 assert(concreteLayer != NULL);
84 return concreteLayer;
85 }
86
87 TextSceneLayer* LineMeasureTool::GetTextLayer()
88 {
89 assert(GetScene().HasLayer(textZIndex_));
90 ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_));
91 TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(layer);
92 assert(concreteLayer != NULL);
93 return concreteLayer;
94 }
95
96 namespace
97 {
98 /**
99 This function will create a square around the center point supplied in
100 scene coordinates, with a side length given in canvas coordinates. The
101 square sides are parallel to the canvas boundaries.
102 */
103 void AddSquare(PolylineSceneLayer::Chain& chain,
104 const Scene2D& scene,
105 const ScenePoint2D& centerS,
106 const double& sideLength)
107 {
108 chain.clear();
109 chain.reserve(4);
110 ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform());
111 //TODO: take DPI into account
112 double handleLX = centerC.GetX() - sideLength / 2;
113 double handleTY = centerC.GetY() - sideLength / 2;
114 double handleRX = centerC.GetX() + sideLength / 2;
115 double handleBY = centerC.GetY() + sideLength / 2;
116 ScenePoint2D LTC(handleLX, handleTY);
117 ScenePoint2D RTC(handleRX, handleTY);
118 ScenePoint2D RBC(handleRX, handleBY);
119 ScenePoint2D LBC(handleLX, handleBY);
120
121 ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform());
122 ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform());
123 ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform());
124 ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform());
125
126 chain.push_back(startLT);
127 chain.push_back(startRT);
128 chain.push_back(startRB);
129 chain.push_back(startLB);
130 }
131
132 void AddCircle(PolylineSceneLayer::Chain& chain,
133 const Scene2D& scene,
134 const ScenePoint2D& centerS,
135 const double& radiusS)
136 {
137 chain.clear();
138 chain.reserve(4);
139 //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform());
140 //TODO: take DPI into account
141
142 // TODO: automatically compute the number for segments for smooth
143 // display based on the radius in pixels.
144 int lineCount = 50;
145
146 double angleIncr = (2.0 * boost::math::constants::pi<double>())
147 / static_cast<double>(lineCount);
148
149 double theta = 0;
150 for (int i = 0; i < lineCount; ++i)
151 {
152 double offsetX = radiusS * cos(theta);
153 double offsetY = radiusS * sin(theta);
154 double pointX = centerS.GetX() + offsetX;
155 double pointY = centerS.GetY() + offsetY;
156 chain.push_back(ScenePoint2D(pointX, pointY));
157 theta += angleIncr;
158 }
159 }
160
161 #if 0
162 void AddEllipse(PolylineSceneLayer::Chain& chain,
163 const Scene2D& scene,
164 const ScenePoint2D& centerS,
165 const double& halfHAxis,
166 const double& halfVAxis)
167 {
168 chain.clear();
169 chain.reserve(4);
170 ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform());
171 //TODO: take DPI into account
172 double handleLX = centerC.GetX() - sideLength / 2;
173 double handleTY = centerC.GetY() - sideLength / 2;
174 double handleRX = centerC.GetX() + sideLength / 2;
175 double handleBY = centerC.GetY() + sideLength / 2;
176 ScenePoint2D LTC(handleLX, handleTY);
177 ScenePoint2D RTC(handleRX, handleTY);
178 ScenePoint2D RBC(handleRX, handleBY);
179 ScenePoint2D LBC(handleLX, handleBY);
180
181 ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform());
182 ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform());
183 ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform());
184 ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform());
185
186 chain.push_back(startLT);
187 chain.push_back(startRT);
188 chain.push_back(startRB);
189 chain.push_back(startLB);
190 }
191 #endif
192
193
194 }
195
196
197 void LineMeasureTool::RefreshScene()
198 {
199 if (IsEnabled())
200 {
201 if (!layersCreated)
202 {
203 // Create the layers if need be
204
205 assert(textZIndex_ == -1);
206 {
207 polylineZIndex_ = GetScene().GetMaxDepth() + 100;
208 //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_;
209 std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer());
210 GetScene().SetLayer(polylineZIndex_, layer.release());
211 }
212 {
213 textZIndex_ = GetScene().GetMaxDepth() + 100;
214 //LOG(INFO) << "set textZIndex_ to: " << textZIndex_;
215 std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer());
216 GetScene().SetLayer(textZIndex_, layer.release());
217 }
218 layersCreated = true;
219 }
220 else
221 {
222 assert(GetScene().HasLayer(polylineZIndex_));
223 assert(GetScene().HasLayer(textZIndex_));
224 }
225 {
226 // Fill the polyline layer with the measurement line
227
228 PolylineSceneLayer* polylineLayer = GetPolylineLayer();
229 polylineLayer->ClearAllChains();
230 polylineLayer->SetColor(0, 223, 21);
231
232 {
233 PolylineSceneLayer::Chain chain;
234 chain.push_back(start_);
235 chain.push_back(end_);
236 polylineLayer->AddChain(chain, false);
237 }
238
239 // handles
240 {
241 //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength)
242
243 {
244 PolylineSceneLayer::Chain chain;
245 AddSquare(chain, GetScene(), start_, 10.0); //TODO: take DPI into account
246 polylineLayer->AddChain(chain, true);
247 }
248
249 {
250 PolylineSceneLayer::Chain chain;
251 AddSquare(chain, GetScene(), end_, 10.0); //TODO: take DPI into account
252 polylineLayer->AddChain(chain, true);
253 }
254
255 //ScenePoint2D startC = start_.Apply(GetScene().GetSceneToCanvasTransform());
256 //double squareSize = 10.0;
257 //double startHandleLX = startC.GetX() - squareSize/2;
258 //double startHandleTY = startC.GetY() - squareSize / 2;
259 //double startHandleRX = startC.GetX() + squareSize / 2;
260 //double startHandleBY = startC.GetY() + squareSize / 2;
261 //ScenePoint2D startLTC(startHandleLX, startHandleTY);
262 //ScenePoint2D startRTC(startHandleRX, startHandleTY);
263 //ScenePoint2D startRBC(startHandleRX, startHandleBY);
264 //ScenePoint2D startLBC(startHandleLX, startHandleBY);
265
266 //ScenePoint2D startLT = startLTC.Apply(GetScene().GetCanvasToSceneTransform());
267 //ScenePoint2D startRT = startRTC.Apply(GetScene().GetCanvasToSceneTransform());
268 //ScenePoint2D startRB = startRBC.Apply(GetScene().GetCanvasToSceneTransform());
269 //ScenePoint2D startLB = startLBC.Apply(GetScene().GetCanvasToSceneTransform());
270
271 //PolylineSceneLayer::Chain chain;
272 //chain.push_back(startLT);
273 //chain.push_back(startRT);
274 //chain.push_back(startRB);
275 //chain.push_back(startLB);
276 //polylineLayer->AddChain(chain, true);
277 }
278
279 }
280 {
281 // Set the text layer proporeties
282
283 TextSceneLayer* textLayer = GetTextLayer();
284 double deltaX = end_.GetX() - start_.GetX();
285 double deltaY = end_.GetY() - start_.GetY();
286 double squareDist = deltaX * deltaX + deltaY * deltaY;
287 double dist = sqrt(squareDist);
288 char buf[64];
289 sprintf(buf, "%0.02f units", dist);
290 textLayer->SetText(buf);
291 textLayer->SetColor(0, 223, 21);
292
293 // TODO: for now we simply position the text overlay at the middle
294 // of the measuring segment
295 double midX = 0.5*(end_.GetX() + start_.GetX());
296 double midY = 0.5*(end_.GetY() + start_.GetY());
297 textLayer->SetPosition(midX, midY);
298 }
299 }
300 else
301 {
302 if (layersCreated)
303 {
304 RemoveFromScene();
305 layersCreated = false;
306 }
307 }
308 }
309 } 40 }
310 41