DeleteGeometryByAreaTool.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 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/DeleteGeometryTool.cpp
22 
23  \brief This class implements a concrete tool to remove geometries by drawing an area (polygon).
24 */
25 
26 // TerraLib
27 #include "../../../geometry/GeometryProperty.h"
28 #include "../../../geometry/MultiPolygon.h"
29 #include "../../../dataaccess/dataset/ObjectIdSet.h"
30 #include "../../../dataaccess/utils/Utils.h"
31 #include "../../../datatype/SimpleData.h"
32 #include "../../../qt/widgets/canvas/MapDisplay.h"
33 #include "../../../qt/widgets/utils/ScopedCursor.h"
34 #include "../../../qt/widgets/Utils.h"
35 #include "../../Feature.h"
36 #include "../../RepositoryManager.h"
37 #include "../../Utils.h"
38 #include "../Renderer.h"
39 #include "../Utils.h"
41 
42 // Qt
43 #include <QMessageBox>
44 #include <QMouseEvent>
45 
46 // STL
47 #include <cassert>
48 #include <memory>
49 
51  : GeometriesUpdateTool(display, layer.get(), parent),
52  m_selectionStarted(false),
53  m_keepPreviousSelection(false),
54  m_selectionByPointing(false),
55  m_area(nullptr)
56 {
57  updateCursor();
58 }
59 
61 
63 {
64  if (e->button() != Qt::LeftButton)
65  return false;
66 
67  m_selectionStarted = true;
68 
69  QPointF pw = m_display->transform(te::edit::GetPosition(e));
70 
71  te::gm::Coord2D coord = te::gm::Coord2D(pw.x(), pw.y());
72 
74 
75  m_coords.push_back(coord);
76 
77  return true;
78 }
79 
81 {
82  if (m_coords.size() < 1 || !m_selectionStarted)
83  return false;
84 
85  QPointF pos = te::edit::GetPosition(e);
86  pos += QPointF(0.0001, 0.0001); // To avoid collinear points on polygon
87 
88  QPointF pw = m_display->transform(pos);
89 
90  te::gm::Coord2D coord = te::gm::Coord2D(pw.x(), pw.y());
91 
93 
94  m_coords.push_back(coord);
95 
96  m_lastPos = te::gm::Coord2D(coord.x, coord.y);
97 
98  draw();
99 
100  return false;
101 }
102 
104 {
105  if (e->button() == Qt::MiddleButton)
106  return false;
107 
108  te::qt::widgets::ScopedCursor cursor(Qt::WaitCursor);
109 
110  m_selectionStarted = false;
111 
112  m_coords.clear();
113 
114  m_keepPreviousSelection = false;
115 
116  Qt::KeyboardModifiers keys = e->modifiers();
117 
118  if (keys & Qt::ControlModifier)
120 
121  m_selectionByPointing = false;
122 
123  te::gm::Envelope env;
124  if (m_area == nullptr)
125  {
126  m_selectionByPointing = true;
128  }
129  else
130  {
131  env = *m_area->getMBR();
132  }
133 
134  // Select the draft layer
135  executeSelection(env);
136 
137  emit geometriesEdited();
138 
139  delete m_area;
140  m_area = nullptr;
141 
142  return true;
143 }
144 
146 {
148  !m_layer->isValid() || m_layer->getType() == "FOLDERLAYER")
149  return;
150 
151  te::gm::Envelope reprojectedEnvelope(e);
152 
154  reprojectedEnvelope.transform(m_display->getSRID(), m_layer->getSRID());
155 
156  if (!reprojectedEnvelope.intersects(m_layer->getExtent()))
157  return;
158 
159  std::unique_ptr<te::da::DataSetType> schema = m_layer->getSchema();
160 
161  if (!schema->hasGeom())
162  return;
163 
164  // Clear previous selection?
167 
168  try
169  {
170  // Gets the layer schema
171  std::unique_ptr<const te::map::LayerSchema> schema(m_layer->getSchema());
172  if (!schema->hasGeom())
173  return;
174 
176 
177  // Gets the dataset
178  std::unique_ptr<te::da::DataSet> dataset = m_layer->getData(gp->getName(), &reprojectedEnvelope, te::gm::INTERSECTS);
179  assert(dataset.get());
180 
181  std::vector<std::string> pnames;
182  te::da::GetOIDPropertyNames(schema.get(), pnames);
183 
184  if (m_selectionByPointing == false)
185  {
186  while (dataset->moveNext())
187  {
188  std::unique_ptr<te::gm::Geometry> g(dataset->getGeometry(gp->getName()));
189 
190  if (g.get() == nullptr)
191  continue;
192 
193  if (g->getSRID() == TE_UNKNOWN_SRS)
194  g->setSRID(m_layer->getSRID());
195 
196  if (!g->intersects(m_area))
197  continue;
198 
200 
201  if (RepositoryManager::getInstance().hasIdentify(m_layer->getId(), te::da::GenerateOID(dataset.get(), pnames)))
202  {
203  m_feature = RepositoryManager::getInstance().getFeature(m_layer->getId(), te::da::GenerateOID(dataset.get(), pnames));
204  m_feature->getOperationTypeId() == UPDATE ? oType = DELETE : oType = UPDATE;
205  }
206 
207  // Feature found!
208  m_feature = new Feature(te::da::GenerateOID(dataset.get(), pnames), g.release());
210 
211  storeFeature();
212 
213  delete m_feature;
214  m_feature = nullptr;
215  }
216  }
217  else
218  {
219  while (dataset->moveNext())
220  {
221  std::unique_ptr<te::gm::Geometry> g(dataset->getGeometry(gp->getName()));
222 
223  if (g.get() == nullptr)
224  continue;
225 
226  if (g->getSRID() == TE_UNKNOWN_SRS)
227  g->setSRID(m_layer->getSRID());
228 
230 
231  if (RepositoryManager::getInstance().hasIdentify(m_layer->getId(), te::da::GenerateOID(dataset.get(), pnames)))
232  m_feature->getOperationTypeId() == UPDATE ? oType = DELETE : oType = UPDATE;
233 
234  m_feature = new Feature(te::da::GenerateOID(dataset.get(), pnames), g.release());
236 
237  storeFeature();
238 
239  delete m_feature;
240  m_feature = nullptr;
241  }
242 
243  }
244  }
245  catch (std::exception& e)
246  {
247  QMessageBox::critical(m_display, tr("Error"), QString(tr("The selection cannot be retrieved from the layer. Details:") + " %1.").arg(e.what()));
248  // TODO: catch the exceptions...
249  }
250 }
251 
253 {
254  const te::gm::Envelope& env = m_display->getExtent();
255  if (!env.isValid())
256  return;
257 
258  // Clear!
259  QPixmap* display = m_display->getDraftPixmap();
260  display->fill(Qt::transparent);
261 
262  // Initialize the renderer
264  renderer.begin(display, env, m_display->getSRID());
265 
266  // Draw the layer edited geometries
268 
269  renderer.setPolygonStyle(QColor(255, 255, 255, 0), QColor(255, 0, 0), 1);
270  if (!m_coords.empty())
271  {
272  // Draw the geometry being created
273  if (m_coords.size() > 2)
274  drawPolygon();
275  }
276 
277  renderer.end();
278 
279  m_display->repaint();
280 }
281 
283 {
284  // Build the geometry
285  m_area= buildPolygon();
286 
287  // Draw the current geometry and the vertexes
289  renderer.draw(m_area);
290 
291 }
292 
294 {
295  // Build the geometry
297  for (std::size_t i = 0; i < m_coords.size(); ++i)
298  ring->setPoint(i, m_coords[i].x, m_coords[i].y);
299  ring->setPoint(m_coords.size(), m_coords[0].x, m_coords[0].y); // Closing...
300 
302  polygon->setRingN(0, ring);
303 
304  polygon->setSRID(m_display->getSRID());
305 
306  if (polygon->getSRID() == m_layer->getSRID())
307  return polygon;
308 
309  // else, need conversion...
310  polygon->transform(m_layer->getSRID());
311 
312  return polygon;
313 }
314 
316 {
317  QPointF pixelOffset(4.0, 4.0);
318 
319  QRectF rect(pos - pixelOffset, pos + pixelOffset);
320 
321  // Converts rect boundary to world coordinates
322  QPointF ll(rect.left(), rect.bottom());
323  QPointF ur(rect.right(), rect.top());
324  ll = m_display->transform(ll);
325  ur = m_display->transform(ur);
326 
327  te::gm::Envelope env(ll.x(), ll.y(), ur.x(), ur.y());
328 
329  return env;
330 }
331 
333 {
334  setCursor(Qt::ArrowCursor);
335 }
336 
338 {
340 }
virtual const std::string & getId() const
It returns the layer id.
Geometric property.
bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
double y
y-coordinate.
Definition: Coord2D.h:114
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
void transform(int srid)
It converts the coordinate values of the geometry to the new spatial reference system.
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
virtual const te::gm::Envelope & getExtent() const
It returns the Layer extent (or minimum bounding box).
void setSRID(int srid)
It sets the Spatial Reference System ID of the geometry and all its parts if it is a GeometryCollecti...
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
virtual const std::string & getType() const =0
It returns the layer type.
double x
x-coordinate.
Definition: Coord2D.h:113
Feature * clone() const
Definition: Feature.cpp:182
virtual Visibility getVisibility() const
It returns the layer visibility.
A widget to control the display of a set of layers.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
te::edit::OperationType getOperationTypeId() const
Definition: Feature.cpp:159
te::gm::Envelope buildEnvelope(const QPointF &pos)
virtual bool isValid() const =0
It returns true if the layer can be used for instance to draw, otherwise, it returns false...
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
te::gm::Coord2D m_lastPos
The last position captured on mouse move event.
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
void executeSelection(const te::gm::Envelope &e)
virtual QPointF transform(const QPointF &p)
Transforms the given point, in screen coordinates, to a point in world coordinates.
void setOperationTypeId(const te::edit::OperationType &currentOperationType)
Definition: Feature.cpp:124
static RepositoryManager & getInstance()
It returns a reference to the singleton instance.
const Envelope * getMBR() const _NOEXCEPT_OP(true)
It returns the minimum bounding rectangle for the geometry in an internal representation.
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
An Envelope defines a 2D rectangular region.
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
bool m_selectionByPointing
Flag that indicates if the selection is by pointing.
virtual std::unique_ptr< LayerSchema > getSchema() const =0
It returns the layer schema.
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
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
This is a singleton for rendering geometries and features.
Definition: Renderer.h:70
te::map::AbstractLayer * m_layer
bool mouseReleaseEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse release events for ...
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
TEEDITEXPORT void TrySnap(te::gm::Coord2D &coord, int srid)
bool m_selectionStarted
Flag that indicates if selection operation was started.
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 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)
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
bool m_keepPreviousSelection
Flag that indicates if the tool must keep the previous selection.
DeleteGeometryByAreaTool(te::qt::widgets::MapDisplay *display, const te::map::AbstractLayerPtr &layer, QObject *parent=0)
It constructs a remove geometries tool associated with the given map display.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
void setPolygonStyle(const QColor &fillColor, const QColor &contourColor, const std::size_t &contourWidth)
Definition: Renderer.cpp:351
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
std::vector< te::gm::Coord2D > m_coords
The coord list managed by this tool.
This class implements a concrete tool to remove geometries by drawing an area (polygon).
bool isValid() const
It tells if the rectangle is valid or not.
An object that when created shows a cursor during its scope.
Definition: ScopedCursor.h:48
void setRingN(std::size_t i, Curve *r)
It sets the informed position ring to the new one.
const std::string & getName() const
It returns the property name.
Definition: Property.h:127