All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
VertexTool.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/edit/qt/tools/VertexTool.cpp
22 
23  \brief This class implements a concrete tool for vertex operations (move, add, etc.).
24 */
25 
26 // TerraLib
27 #include "../../../dataaccess/dataset/ObjectId.h"
28 #include "../../../geometry/Coord2D.h"
29 #include "../../../geometry/Geometry.h"
30 #include "../../../geometry/LineString.h"
31 #include "../../../geometry/MultiPolygon.h"
32 #include "../../../geometry/Polygon.h"
33 #include "../../../geometry/Utils.h"
34 #include "../../../qt/widgets/canvas/MapDisplay.h"
35 #include "../../../qt/widgets/Utils.h"
36 #include "../../Feature.h"
37 #include "../../RepositoryManager.h"
38 #include "../../Utils.h"
39 #include "../Renderer.h"
40 #include "../Utils.h"
41 #include "VertexTool.h"
42 
43 // Qt
44 #include <QMessageBox>
45 #include <QMouseEvent>
46 #include <QPainter>
47 #include <QPixmap>
48 
49 // STL
50 #include <cassert>
51 #include <memory>
52 #include <string>
53 
55  : AbstractTool(display, parent),
56  m_layer(layer),
57  m_feature(0),
58  m_currentStage(FEATURE_SELECTION)
59 {
60  assert(m_layer.get());
61 
62  // Signals & slots
63  connect(m_display, SIGNAL(extentChanged()), SLOT(onExtentChanged()));
64 
66 
67  updateCursor();
68 
69  draw();
70 }
71 
73 {
74  delete m_feature;
75 }
76 
78 {
79  Qt::KeyboardModifiers keys = e->modifiers();
80 
81  if(e->button() == Qt::LeftButton && m_currentStage == VERTEX_FOUND)
82  {
83  // Moving...
84  if(keys == Qt::NoModifier)
85  {
86  setStage(VERTEX_MOVING);
87  return true;
88  }
89 
90  // Removing...
91  if(keys == Qt::ShiftModifier)
92  {
93  RemoveVertex(m_lines, m_currentVertexIndex);
94 
95  storeEditedFeature();
96 
97  m_currentVertexIndex.makeInvalid();
98 
99  setStage(VERTEX_SEARCH);
100 
101  updateRTree();
102 
103  draw();
104 
105  return true;
106  }
107  }
108 
109  // This operation will be handled by mouse double click
110  if(m_currentStage == VERTEX_READY_TO_ADD)
111  return false;
112 
113  // Else...
114  setStage(FEATURE_SELECTION);
115 
116  return false;
117 }
118 
120 {
121  switch(m_currentStage)
122  {
123  case VERTEX_SEARCH:
124  case VERTEX_FOUND:
125  case VERTEX_READY_TO_ADD:
126  {
127  if(m_rtree.isEmpty())
128  return false;
129 
130  te::gm::Envelope env = buildEnvelope(GetPosition(e));
131 
132  // Search on rtree
133  std::vector<VertexIndex> report;
134  m_rtree.search(env, report);
135 
136  if(!report.empty()) // Vertex found!
137  {
138  setStage(VERTEX_FOUND);
139 
140  m_currentVertexIndex = report[0];
141 
142  draw();
143 
144  return false;
145  }
146 
147  // Else, try search "virtual vertex" at a segment
148  m_currentVertexIndex.makeInvalid();
149 
150  std::auto_ptr<te::gm::Point> borderPoint(0);
151 
152  if(m_feature != 0)
153  {
154  std::auto_ptr<te::gm::Geometry> geometryFromEnvelope(te::gm::GetGeomFromEnvelope(&env, m_display->getSRID()));
155 
156  if(m_feature->getGeometry()->intersects(geometryFromEnvelope.get()) && !m_feature->getGeometry()->contains(geometryFromEnvelope.get())) // Mouse over a segment?
157  borderPoint.reset(new te::gm::Point(env.getCenter().x, env.getCenter().y));
158  }
159 
160  borderPoint.get() != 0 ? setStage(VERTEX_READY_TO_ADD) : setStage(VERTEX_SEARCH);
161 
162  draw(borderPoint.get());
163 
164  return false;
165  }
166 
167  case VERTEX_MOVING:
168  {
169  QPointF point = GetPosition(e);
170  point = m_display->transform(point);
171 
172  MoveVertex(m_lines, m_currentVertexIndex, point.x(), point.y());
173 
174  storeEditedFeature();
175 
176  draw();
177 
178  return false;
179  }
180 
181  default:
182  return false;
183  }
184 
185  return false;
186 }
187 
189 {
190  switch(m_currentStage)
191  {
192  case FEATURE_SELECTION:
193  {
194  if(e->button() != Qt::LeftButton)
195  return false;
196 
197  pickFeature(m_layer, GetPosition(e));
198 
199  if(m_feature)
200  setStage(VERTEX_SEARCH);
201 
202  return true;
203  }
204 
205  case VERTEX_MOVING:
206  {
207  updateRTree();
208 
209  setStage(VERTEX_SEARCH);
210  }
211 
212  default:
213  return false;
214  }
215 }
216 
218 {
219  if(e->button() == Qt::LeftButton && m_currentStage == VERTEX_READY_TO_ADD)
220  {
221  // Added point
222  QPointF point = GetPosition(e);
223 
224  // Added point extent
225  te::gm::Envelope e = buildEnvelope(point);
226 
227  // Convert to world coordinates
228  point = m_display->transform(point);
229 
230  AddVertex(m_lines, point.x(), point.y(), e, m_display->getSRID());
231 
232  storeEditedFeature();
233 
234  m_currentVertexIndex.makeInvalid();
235 
236  setStage(VERTEX_SEARCH);
237 
238  updateRTree();
239 
240  draw();
241 
242  return true;
243  }
244 
245  return false;
246 }
247 
249 {
250  delete m_feature;
251  m_feature = 0;
252 
253  setStage(FEATURE_SELECTION);
254 
255  m_lines.clear();
256 
257  m_currentVertexIndex.makeInvalid();
258 
259  m_rtree.clear();
260 }
261 
262 void te::edit::VertexTool::pickFeature(const te::map::AbstractLayerPtr& layer, const QPointF& pos)
263 {
264  te::gm::Envelope env = buildEnvelope(pos);
265  pickFeature(m_layer, env);
266 }
267 
269 {
270  reset();
271 
272  try
273  {
274  m_feature = PickFeature(m_layer, env, m_display->getSRID());
275 
276  m_lines.clear();
277 
278  if(m_feature != 0)
279  GetLines(m_feature->getGeometry(), m_lines);
280 
281  updateRTree();
282 
283  draw();
284  }
285  catch(std::exception& e)
286  {
287  QMessageBox::critical(m_display, tr("Error"), QString(tr("The geometry cannot be selected from the layer. Details:") + " %1.").arg(e.what()));
288  }
289 }
290 
292 {
293  const te::gm::Envelope& env = m_display->getExtent();
294  if(!env.isValid())
295  return;
296 
297  // Clear!
298  QPixmap* draft = m_display->getDraftPixmap();
299  draft->fill(Qt::transparent);
300 
301  // Initialize the renderer
302  Renderer& renderer = Renderer::getInstance();
303  renderer.begin(draft, env, m_display->getSRID());
304 
305  // Draw the layer edited geometries
306  renderer.drawRepository(m_layer->getId(), env, m_display->getSRID());
307 
308  if(m_lines.empty())
309  {
310  renderer.end();
311  m_display->repaint();
312  return;
313  }
314 
315  // Draw the vertexes
316  if(RepositoryManager::getInstance().hasIdentify(m_layer->getId(), m_feature->getId()) == false)
317  renderer.draw(m_feature->getGeometry(), true);
318  else
319  renderer.drawVertexes(m_feature->getGeometry());
320 
321  // Draw the current vertex
322  if(m_currentVertexIndex.isValid())
323  {
324  te::gm::LineString* line = m_lines[m_currentVertexIndex.m_line];
325  std::auto_ptr<te::gm::Point> point(line->getPointN(m_currentVertexIndex.m_pos));
326 
327  renderer.setPointStyle("circle", Qt::transparent, Qt::blue, 3, 24);
328  renderer.draw(point.get());
329  }
330 
331  // Draw the virtual vertex
332  if(virtualVertex)
333  {
334  assert(virtualVertex);
335 
336  renderer.setPointStyle("circle", Qt::transparent, Qt::darkGreen, 3, 24);
337  renderer.draw(virtualVertex);
338  }
339 
340  renderer.end();
341 
342  m_display->repaint();
343 }
344 
346 {
347  draw();
348 }
349 
351 {
352  QPointF pixelOffset(4.0, 4.0);
353 
354  QRectF rect(pos - pixelOffset, pos + pixelOffset);
355 
356  // Converts rect boundary to world coordinates
357  QPointF ll(rect.left(), rect.bottom());
358  QPointF ur(rect.right(), rect.top());
359  ll = m_display->transform(ll);
360  ur = m_display->transform(ur);
361 
362  te::gm::Envelope env(ll.x(), ll.y(), ur.x(), ur.y());
363 
364  return env;
365 }
366 
368 {
369  m_rtree.clear();
370 
371  for(std::size_t i = 0; i < m_lines.size(); ++i)
372  {
373  te::gm::LineString* line = m_lines[i];
374 
375  for(std::size_t j = 0; j < line->getNPoints(); ++j)
376  {
377  te::gm::Envelope e(line->getX(j), line->getY(j), line->getX(j), line->getY(j));
378 
379  VertexIndex index;
380  index.setIndex(i, j);
381 
382  m_rtree.insert(e, index);
383  }
384  }
385 }
386 
388 {
389  m_currentStage = stage;
390  updateCursor();
391 }
392 
394 {
395  switch(m_currentStage)
396  {
397  case FEATURE_SELECTION:
398  case VERTEX_SEARCH:
399  m_display->setCursor(Qt::ArrowCursor);
400  break;
401 
402  case VERTEX_FOUND:
403  m_display->setCursor(Qt::OpenHandCursor);
404  break;
405 
406  case VERTEX_MOVING:
407  m_display->setCursor(Qt::ClosedHandCursor);
408  break;
409 
410  default:
411  m_display->setCursor(Qt::ArrowCursor);
412  }
413 }
414 
416 {
417  RepositoryManager::getInstance().addGeometry(m_layer->getId(), m_feature->getId()->clone(), dynamic_cast<te::gm::Geometry*>(m_feature->getGeometry()->clone()));
418 }
void addGeometry(const std::string &source, te::gm::Geometry *geom)
TEEDITEXPORT void MoveVertex(std::vector< te::gm::LineString * > &lines, const VertexIndex &index, const double &x, const double &y)
Definition: Utils.cpp:158
double y
y-coordinate.
Definition: Coord2D.h:114
void setPointStyle(const QString &mark, const QColor &fillColor, const QColor &contourColor, const std::size_t &contourWidth, const std::size_t &size)
Definition: Renderer.cpp:211
StageType
Defines the operation stage to this tool.
Definition: VertexTool.h:81
double x
x-coordinate.
Definition: Coord2D.h:113
This class implements a concrete tool for vertex operations (move, add, etc.).
void setStage(StageType stage)
Definition: VertexTool.cpp:387
Point * getPointN(std::size_t i) const
It returns the specified point in this LineString.
Definition: LineString.cpp:323
bool mouseReleaseEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse release events for ...
Definition: VertexTool.cpp:188
~VertexTool()
Destructor.
Definition: VertexTool.cpp:72
A widget to control the display of a set of layers.
Definition: MapDisplay.h:66
bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
Definition: VertexTool.cpp:77
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
Definition: LineString.cpp:391
Coord2D getCenter() const
It returns the rectangle's center coordinate.
Definition: Envelope.cpp:51
TEEDITEXPORT void RemoveVertex(std::vector< te::gm::LineString * > &lines, const VertexIndex &index)
Definition: Utils.cpp:176
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
static Renderer & getInstance()
It returns a reference to the singleton instance.
A point with x and y coordinate values.
Definition: Point.h:50
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
void setIndex(const std::size_t &line, const std::size_t &pos)
Definition: Utils.h:62
const double & getX(std::size_t i) const
It returns the n-th x coordinate value.
Definition: LineString.cpp:385
te::gm::Envelope buildEnvelope(const QPointF &pos)
Definition: VertexTool.cpp:350
bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
Definition: VertexTool.cpp:119
TEEDITEXPORT Feature * PickFeature(const te::map::AbstractLayerPtr &layer, const te::gm::Envelope &env, int srid)
Definition: Utils.cpp:55
TEEDITQTEXPORT QPointF GetPosition(QMouseEvent *e)
Definition: Utils.cpp:42
void draw(te::gm::Geometry *geom, bool showVertexes=false)
Definition: Renderer.cpp:141
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
VertexIndex m_currentVertexIndex
Definition: VertexTool.h:154
This is a singleton for rendering geometries and features.
Definition: Renderer.h:67
void draw(te::gm::Point *virtualVertex=0)
Definition: VertexTool.cpp:291
TEEDITEXPORT void AddVertex(std::vector< te::gm::LineString * > &lines, const double &x, const double &y, const te::gm::Envelope &env, int srid)
Definition: Utils.cpp:208
VertexTool(te::qt::widgets::MapDisplay *display, const te::map::AbstractLayerPtr &layer, QObject *parent=0)
It constructs a vertex tool associated with the given map display.
Definition: VertexTool.cpp:54
te::map::AbstractLayerPtr m_layer
Definition: VertexTool.h:151
void drawVertexes(te::gm::Geometry *geom)
Definition: Renderer.cpp:157
void begin(QPaintDevice *device, const te::gm::Envelope &e, int srid)
Definition: Renderer.cpp:55
TEEDITEXPORT void GetLines(te::gm::Geometry *geom, std::vector< te::gm::LineString * > &lines)
Definition: Utils.cpp:109
bool mouseDoubleClickEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse double click events...
Definition: VertexTool.cpp:217
void drawRepository(const std::string &source, const te::gm::Envelope &e, int srid)
Definition: Renderer.cpp:73
MapDisplay * m_display
The map display associated with the tool.
Definition: AbstractTool.h:160
void makeInvalid()
Definition: Utils.h:68
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
bool isValid() const
It tells if the rectangle is valid or not.
Definition: Envelope.h:438
TEGEOMEXPORT Geometry * GetGeomFromEnvelope(const Envelope *const e, int srid)
It creates a Geometry (a polygon) from the given envelope.
Definition: Utils.cpp:38
void pickFeature(const te::map::AbstractLayerPtr &layer, const QPointF &pos)
Definition: VertexTool.cpp:262