MoveGeometryTool.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/MoveGeometryTool.cpp
22 
23  \brief This class implements a concrete tool to move geometries.
24 */
25 
26 // TerraLib
27 #include "../../../common/STLUtils.h"
28 #include "../../../dataaccess/dataset/ObjectId.h"
29 #include "../../../dataaccess/dataset/ObjectIdSet.h"
30 #include "../../../dataaccess/utils/Utils.h"
31 #include "../../../geometry/GeometryProperty.h"
32 #include "../../../qt/widgets/canvas/MapDisplay.h"
33 #include "../../../qt/widgets/Utils.h"
34 #include "../../Feature.h"
35 #include "../../RepositoryManager.h"
36 #include "../../Utils.h"
37 #include "../Renderer.h"
38 #include "../Utils.h"
39 #include "MoveGeometryTool.h"
40 
41 // Qt
42 #include <QMessageBox>
43 #include <QMouseEvent>
44 #include <QPainter>
45 #include <QPixmap>
46 #include <QDebug>
47 
48 // STL
49 #include <cassert>
50 #include <memory>
51 
53  : GeometriesUpdateTool(display, layer.get(), parent),
54  m_moveStarted(false),
55  m_vecFeatures(0),
56  m_stack(UndoStackManager::getInstance())
57 {
58  updateCursor();
59 
60  draw();
61 }
62 
64 {
66  m_vecFeatures.clear();
67 }
68 
70 {
71  if (e->button() != Qt::LeftButton)
72  return false;
73 
74  bool selected = false;
75 
76  if (m_layer->getSelected())
77  {
78  if (m_layer->getSelected()->size())
79  {
80  std::unique_ptr<te::da::DataSet> ds(m_layer->getData(m_layer->getSelected()));
81  std::size_t gpos = te::da::GetFirstSpatialPropertyPos(ds.get());
82 
83  std::vector<std::string> oidPropertyNames;
84  te::da::GetOIDPropertyNames(m_layer->getSchema().get(), oidPropertyNames);
85 
86  if (!m_vecFeatures.size())
87  {
88  ds->moveBeforeFirst();
89  while (ds->moveNext())
90  {
91  std::unique_ptr<te::gm::Geometry> g(ds->getGeometry(gpos));
92  m_feature = new Feature(te::da::GenerateOID(ds.get(), oidPropertyNames), g.release());
93  if (m_feature)
94  {
95  m_feature->setOperationTypeId(UPDATE);
96  m_vecFeatures.push_back(m_feature->clone());
97  selected = true;
98  }
99  delete m_feature;
100  m_feature = nullptr;
101  }
102  }
103  }
104  }
105 
106  if (!selected)
108 
109  if (m_vecFeatures.size())
110  m_moveStarted = true;
111 
113 
114  m_delta *= 0;
115 
116  return true;
117 }
118 
120 {
121  if(!m_moveStarted)
122  return false;
123 
124  QPointF currentPosition = m_display->transform(GetPosition(e));
125 
126  // Calculates the delta value
127  m_delta = currentPosition - m_origin;
128 
129  // Move geometry using the current delta
130  if (m_vecFeatures.size())
131  {
132  for (std::size_t i = 0; i < m_vecFeatures.size(); ++i)
133  MoveGeometry(m_vecFeatures[i]->getGeometry(), m_delta.x(), m_delta.y());
134  }
135 
136  draw();
137 
138  m_origin = currentPosition;
139 
140  return true;
141 }
142 
144 {
145  if (e->button() == Qt::RightButton)
146  {
147  emit geometriesEdited();
148  return false;
149  }
150 
151  m_moveStarted = false;
152 
153  if (m_delta == QPointF(0., 0.))
154  return false;
155 
156  storeFeature();
157 
159 
160  draw();
161 
162  return true;
163 }
164 
166 {
167  delete m_feature;
168 
170  m_vecFeatures.clear();
171 
172  m_moveStarted = false;
173 
174  m_origin *= 0;
175  m_delta *= 0;
176 }
177 
179 {
180  reset();
181 
182  te::gm::Envelope env = buildEnvelope(pos);
183 
184  try
185  {
187  if (m_feature)
188  m_vecFeatures.push_back(m_feature->clone());
189 
190  draw();
191  }
192  catch(std::exception& e)
193  {
194  QMessageBox::critical(m_display, tr("Error"), QString(tr("The geometry cannot be selected from the layer. Details:") + " %1.").arg(e.what()));
195  }
196 }
197 
199 {
200  QPointF pixelOffset(4.0, 4.0);
201 
202  QRectF rect(pos - pixelOffset, pos + pixelOffset);
203 
204  // Converts rect boundary to world coordinates
205  QPointF ll(rect.left(), rect.bottom());
206  QPointF ur(rect.right(), rect.top());
207  ll = m_display->transform(ll);
208  ur = m_display->transform(ur);
209 
210  te::gm::Envelope env(ll.x(), ll.y(), ur.x(), ur.y());
211 
212  return env;
213 }
214 
216 {
217  const te::gm::Envelope& env = m_display->getExtent();
218  if(!env.isValid())
219  return;
220 
221  // Clear!
222  QPixmap* draft = m_display->getDraftPixmap();
223  draft->fill(Qt::transparent);
224 
225  // Initialize the renderer
226  Renderer& renderer = Renderer::getInstance();
227  renderer.begin(draft, env, m_display->getSRID());
228 
229  // Draw the layer edited geometries
230  renderer.drawRepository(m_layer->getId(), env, m_display->getSRID());
231 
232  if (!m_vecFeatures.size() || m_stack.m_currentIndex < 0)
233  {
234  renderer.end();
235  m_display->repaint();
236  return;
237  }
238 
239  if (m_delta == QPointF(0., 0.))
240  {
241  renderer.end();
242  m_display->repaint();
243  return;
244  }
245 
246  for (std::size_t i = 0; i < m_vecFeatures.size(); ++i)
247  {
248  // Draw the vertexes
249  if (RepositoryManager::getInstance().hasIdentify(m_layer->getId(), m_vecFeatures[i]->getId()) == false)
250  renderer.draw(m_vecFeatures[i]->getGeometry(), true);
251  else
252  {
253  switch (m_vecFeatures[i]->getGeometry()->getGeomTypeId())
254  {
255  case te::gm::PointType:
257  renderer.draw(m_vecFeatures[i]->getGeometry());
258  break;
259 
260  default:
261  renderer.drawVertexes(m_vecFeatures[i]->getGeometry());
262  }
263  }
264  }
265 
266  renderer.end();
267 
268  m_display->repaint();
269 }
270 
272 {
273  // Get the geometry type of layer
274  std::unique_ptr<te::da::DataSetType> dt = m_layer->getSchema();
276 
277  switch (geomProp->getGeometryType())
278  {
280  case te::gm::PointType:
281  setCursor(Qt::ArrowCursor);
282  break;
283 
284  default:
285  setCursor(Qt::OpenHandCursor);
286  }
287 }
288 
290 {
291  if (!m_vecFeatures.size())
292  return;
293 
294  for (std::size_t i = 0; i < m_vecFeatures.size(); ++i)
295  RepositoryManager::getInstance().addFeature(m_layer->getId(), m_vecFeatures[i]->clone());
296 }
297 
299 {
300  if (!m_vecFeatures.size())
301  return;
302 
303  for (std::size_t i = 0; i < m_vecFeatures.size(); ++i)
304  {
305  m_stack.addWatch(m_vecFeatures[i]->clone());
306 
307  QUndoCommand* command = new AddCommand(m_display, m_layer, m_vecFeatures[i]->clone()->getId());
308  m_stack.addUndoStack(command);
309  }
310 }
311 
313 {
314  m_feature = nullptr;
315 
317  m_vecFeatures.clear();
318 }
virtual const std::string & getId() const
It returns the layer id.
Geometric property.
Undo/Redo for add one components.
Definition: AddCommand.h:52
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
UndoStackManager & m_stack
Feature * clone() const
Definition: Feature.cpp:182
void addWatch(Feature *feature)
A widget to control the display of a set of layers.
static te::dt::Date ds(2010, 01, 01)
std::vector< te::edit::Feature * > m_vecFeatures
This class implements a concrete tool to move geometries.
void addUndoStack(QUndoCommand *command)
Method that insert command Undo/Redo of type AddCommand in the Undo/Redo stack.
virtual QPointF transform(const QPointF &p)
Transforms the given point, in screen coordinates, to a point in world coordinates.
TEDATAACCESSEXPORT std::size_t GetFirstSpatialPropertyPos(const te::da::DataSet *dataset)
It returns the first dataset spatial property or NULL if none is found.
void setOperationTypeId(const te::edit::OperationType &currentOperationType)
Definition: Feature.cpp:124
static T & getInstance()
It returns a reference to the singleton instance.
Definition: Singleton.h:126
An Envelope defines a 2D rectangular region.
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
std::size_t size() const
It returns the object id set size.
virtual std::unique_ptr< LayerSchema > getSchema() const =0
It returns the layer schema.
TEEDITEXPORT Feature * PickFeature(const te::map::AbstractLayerPtr &layer, const te::gm::Envelope &env, int srid)
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
static te::dt::TimeDuration dt(20, 30, 50, 11)
TEEDITQTEXPORT QPointF GetPosition(QMouseEvent *e)
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
void draw(te::gm::Geometry *geom, bool showVertexes=false)
Definition: Renderer.cpp:260
bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
TEEDITEXPORT void MoveGeometry(te::gm::Geometry *geom, const double &deltax, const double &deltay)
This is a singleton for rendering geometries and features.
Definition: Renderer.h:70
te::map::AbstractLayer * m_layer
QPointF m_delta
Difference between pressed point and destination point on mouse move.
virtual const te::da::ObjectIdSet * getSelected() const
It returns the selected group of this Layer.
te::gm::Envelope buildEnvelope(const QPointF &pos)
virtual std::unique_ptr< te::da::DataSet > getData(te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess) const =0
It gets the dataset identified by the layer name.
virtual QPixmap * getDraftPixmap() const
It returns the map display draft pixmap.
void drawVertexes(te::gm::Geometry *geom)
Definition: Renderer.cpp:292
bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
void begin(QPaintDevice *device, const te::gm::Envelope &e, int srid)
Definition: Renderer.cpp:59
void drawRepository(const std::string &source, const te::gm::Envelope &e, int srid)
Definition: Renderer.cpp:78
void setCursor(const QCursor &cursor)
It sets the tool cursor.
MapDisplay * m_display
The map display associated with the tool.
Definition: AbstractTool.h:171
TEDATAACCESSEXPORT void GetOIDPropertyNames(const DataSetType *type, std::vector< std::string > &pnames)
MoveGeometryTool(te::qt::widgets::MapDisplay *display, const te::map::AbstractLayerPtr &layer, QObject *parent=0)
It constructs a move geometry tool associated with the given map display.
QPointF m_origin
Origin point on mouse pressed.
bool m_moveStarted
Flag that indicates if move operation was started.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
bool mouseReleaseEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse release events for ...
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
bool isValid() const
It tells if the rectangle is valid or not.
void pickFeature(const QPointF &pos)