comparison OrthancStone/Sources/Scene2DViewport/LineMeasureTool.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Scene2DViewport/LineMeasureTool.cpp@30deba7bc8e2
children 85e117739eca
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 #include "LineMeasureTool.h"
22 #include "MeasureToolsToolbox.h"
23 #include "EditLineMeasureTracker.h"
24 #include "LayerHolder.h"
25 #include "../StoneException.h"
26
27 #include <Logging.h>
28
29 #include <boost/make_shared.hpp>
30
31 namespace OrthancStone
32 {
33
34 LineMeasureTool::LineMeasureTool(
35 boost::shared_ptr<IViewport> viewport)
36 : MeasureTool(viewport)
37 #if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1
38 , layerHolder_(boost::shared_ptr<LayerHolder>(new LayerHolder(viewport,1,5)))
39 #else
40 , layerHolder_(boost::shared_ptr<LayerHolder>(new LayerHolder(viewport,1,1)))
41 #endif
42 , lineHighlightArea_(LineHighlightArea_None)
43 {
44
45 }
46
47 boost::shared_ptr<LineMeasureTool> LineMeasureTool::Create(boost::shared_ptr<IViewport> viewport)
48 {
49 boost::shared_ptr<LineMeasureTool> obj(new LineMeasureTool(viewport));
50 obj->MeasureTool::PostConstructor();
51 obj->RefreshScene();
52 return obj;
53 }
54
55 LineMeasureTool::~LineMeasureTool()
56 {
57 // this measuring tool is a RABI for the corresponding visual layers
58 // stored in the 2D scene
59 Disable();
60 RemoveFromScene();
61 }
62
63 void LineMeasureTool::RemoveFromScene()
64 {
65 if (layerHolder_->AreLayersCreated() && IsSceneAlive())
66 {
67 layerHolder_->DeleteLayers();
68 }
69 }
70
71 void LineMeasureTool::SetStart(ScenePoint2D start)
72 {
73 start_ = start;
74 RefreshScene();
75 }
76
77 void LineMeasureTool::SetEnd(ScenePoint2D end)
78 {
79 end_ = end;
80 RefreshScene();
81 }
82
83 void LineMeasureTool::Set(ScenePoint2D start, ScenePoint2D end)
84 {
85 start_ = start;
86 end_ = end;
87 RefreshScene();
88 }
89
90 void LineMeasureTool::SetLineHighlightArea(LineHighlightArea area)
91 {
92 if (lineHighlightArea_ != area)
93 {
94 lineHighlightArea_ = area;
95 RefreshScene();
96 }
97 }
98
99 std::string LineMeasureTool::GetDescription()
100 {
101 std::stringstream ss;
102 ss << "LineMeasureTool. Start = " << start_ << " End = " << end_;
103 return ss.str();
104 }
105
106 void LineMeasureTool::ResetHighlightState()
107 {
108 SetLineHighlightArea(LineHighlightArea_None);
109 }
110
111 void LineMeasureTool::Highlight(ScenePoint2D p)
112 {
113 LineHighlightArea lineHighlightArea = LineHitTest(p);
114 SetLineHighlightArea(lineHighlightArea);
115 }
116
117 LineMeasureTool::LineHighlightArea LineMeasureTool::LineHitTest(ScenePoint2D p)
118 {
119 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
120 ViewportController& controller = lock->GetController();
121 Scene2D& scene = controller.GetScene();
122
123 const double pixelToScene = scene.GetCanvasToSceneTransform().ComputeZoom();
124 const double SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD =
125 pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD *
126 pixelToScene * HIT_TEST_MAX_DISTANCE_CANVAS_COORD;
127
128 const double sqDistanceFromStart =
129 ScenePoint2D::SquaredDistancePtPt(p, start_);
130
131 if (sqDistanceFromStart <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
132 return LineHighlightArea_Start;
133
134 const double sqDistanceFromEnd = ScenePoint2D::SquaredDistancePtPt(p, end_);
135
136 if (sqDistanceFromEnd <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
137 return LineHighlightArea_End;
138
139 const double sqDistanceFromPtSegment =
140 ScenePoint2D::SquaredDistancePtSegment(start_, end_, p);
141
142 if (sqDistanceFromPtSegment <= SQUARED_HIT_TEST_MAX_DISTANCE_SCENE_COORD)
143 return LineHighlightArea_Segment;
144
145 return LineHighlightArea_None;
146 }
147
148 bool LineMeasureTool::HitTest(ScenePoint2D p)
149 {
150 return LineHitTest(p) != LineHighlightArea_None;
151 }
152
153 boost::shared_ptr<IFlexiblePointerTracker> LineMeasureTool::CreateEditionTracker(const PointerEvent& e)
154 {
155 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
156 ViewportController& controller = lock->GetController();
157 Scene2D& scene = controller.GetScene();
158
159 ScenePoint2D scenePos = e.GetMainPosition().Apply(
160 scene.GetCanvasToSceneTransform());
161
162 if (!HitTest(scenePos))
163 return boost::shared_ptr<IFlexiblePointerTracker>();
164
165 boost::shared_ptr<EditLineMeasureTracker> editLineMeasureTracker(
166 new EditLineMeasureTracker(shared_from_this(), viewport_, e));
167 return editLineMeasureTracker;
168 }
169
170 boost::shared_ptr<MeasureToolMemento> LineMeasureTool::GetMemento() const
171 {
172 boost::shared_ptr<LineMeasureToolMemento> memento(new LineMeasureToolMemento());
173 memento->start_ = start_;
174 memento->end_ = end_;
175 return memento;
176 }
177
178 void LineMeasureTool::SetMemento(
179 boost::shared_ptr<MeasureToolMemento> mementoBase)
180 {
181 boost::shared_ptr<LineMeasureToolMemento> memento =
182 boost::dynamic_pointer_cast<LineMeasureToolMemento>(mementoBase);
183
184 ORTHANC_ASSERT(memento.get() != NULL, "Internal error: wrong (or bad) memento");
185
186 start_ = memento->start_;
187 end_ = memento->end_;
188 RefreshScene();
189 }
190
191 void LineMeasureTool::RefreshScene()
192 {
193 if (IsSceneAlive())
194 {
195 if (IsEnabled())
196 {
197
198 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
199 ViewportController& controller = lock->GetController();
200 Scene2D& scene = controller.GetScene();
201
202 layerHolder_->CreateLayersIfNeeded();
203 {
204 // Fill the polyline layer with the measurement line
205
206 PolylineSceneLayer* polylineLayer = layerHolder_->GetPolylineLayer(0);
207 if (polylineLayer)
208 {
209 polylineLayer->ClearAllChains();
210
211 const Color color(TOOL_LINES_COLOR_RED,
212 TOOL_LINES_COLOR_GREEN,
213 TOOL_LINES_COLOR_BLUE);
214
215 const Color highlightColor(TOOL_LINES_HL_COLOR_RED,
216 TOOL_LINES_HL_COLOR_GREEN,
217 TOOL_LINES_HL_COLOR_BLUE);
218
219 {
220 PolylineSceneLayer::Chain chain;
221 chain.push_back(start_);
222 chain.push_back(end_);
223 if(lineHighlightArea_ == LineHighlightArea_Segment)
224 polylineLayer->AddChain(chain, false, highlightColor);
225 else
226 polylineLayer->AddChain(chain, false, color);
227 }
228
229 // handles
230 {
231 {
232 PolylineSceneLayer::Chain chain;
233
234 //TODO: take DPI into account
235 AddSquare(chain, controller.GetScene(), start_,
236 controller.GetHandleSideLengthS());
237
238 if (lineHighlightArea_ == LineHighlightArea_Start)
239 polylineLayer->AddChain(chain, true, highlightColor);
240 else
241 polylineLayer->AddChain(chain, true, color);
242 }
243
244 {
245 PolylineSceneLayer::Chain chain;
246
247 //TODO: take DPI into account
248 AddSquare(chain, controller.GetScene(), end_,
249 controller.GetHandleSideLengthS());
250
251 if (lineHighlightArea_ == LineHighlightArea_End)
252 polylineLayer->AddChain(chain, true, highlightColor);
253 else
254 polylineLayer->AddChain(chain, true, color);
255 }
256 }
257 }
258 }
259 {
260 // Set the text layer propreties
261 double deltaX = end_.GetX() - start_.GetX();
262 double deltaY = end_.GetY() - start_.GetY();
263 double squareDist = deltaX * deltaX + deltaY * deltaY;
264 double dist = sqrt(squareDist);
265 char buf[64];
266 sprintf(buf, "%0.02f mm", dist);
267
268 // TODO: for now we simply position the text overlay at the middle
269 // of the measuring segment
270 double midX = 0.5 * (end_.GetX() + start_.GetX());
271 double midY = 0.5 * (end_.GetY() + start_.GetY());
272
273 {
274
275 #if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1
276 SetTextLayerOutlineProperties(
277 scene, layerHolder_, buf, ScenePoint2D(midX, midY), 0);
278 #else
279 SetTextLayerProperties(
280 scene, layerHolder_, buf, ScenePoint2D(midX, midY), 0);
281 #endif
282 lock->Invalidate();
283 }
284 }
285 lock->Invalidate();
286 }
287 else
288 {
289 RemoveFromScene();
290 }
291 }
292 }
293 }