Selection.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/qt/widgets/tools/Selection.cpp
22 
23  \brief This class implements a concrete tool to select layer features using an extent.
24 */
25 
26 // TerraLib
27 #include "../../../common/STLUtils.h"
28 #include "../../../dataaccess/dataset/DataSet.h"
29 #include "../../../dataaccess/dataset/DataSetType.h"
30 #include "../../../dataaccess/dataset/ObjectIdSet.h"
31 #include "../../../dataaccess/utils/Utils.h"
32 #include "../../../geometry/Coord2D.h"
33 #include "../../../geometry/Geometry.h"
34 #include "../../../geometry/GeometryProperty.h"
35 #include "../../../geometry/Point.h"
36 #include "../../../geometry/Utils.h"
37 #include "../../../srs/Config.h"
38 #include "../canvas/MapDisplay.h"
39 #include "../utils/ScopedCursor.h"
40 #include "Selection.h"
41 
42 // Qt
43 #include <QtCore/QString>
44 #include <QKeyEvent>
45 #include <QMessageBox>
46 #include <QMouseEvent>
47 
48 // STL
49 #include <cassert>
50 #include <exception>
51 #include <memory>
52 
53 te::qt::widgets::Selection::Selection(te::qt::widgets::MapDisplay* display, const QCursor& cursor, const std::list<te::map::AbstractLayerPtr>& layers, QObject* parent)
54  : RubberBand(display, parent),
55  m_layers(layers),
56  m_selectionStarted(false),
57  m_keepPreviousSelection(false),
58  m_selectionByPointing(false)
59 {
60  setCursor(cursor);
61 
62  // Setups the rubber band style
63  m_pen.setStyle(Qt::DashLine);
64  m_pen.setColor(QColor(255, 255, 100));
65  m_pen.setWidth(2);
66  m_brush = QColor(255, 255, 100, 80);
67 }
68 
70 
72 {
73  if(e->button() != Qt::LeftButton)
74  return false;
75 
76  m_selectionStarted = true;
77  m_rect = QRectF();
78 
80 }
81 
83 {
85  return false;
86 
88 }
89 
91 {
92  ScopedCursor cursor(Qt::WaitCursor);
93 
94  m_selectionStarted = false;
95 
96  if(e->button() != Qt::LeftButton)
97  return false;
98 
100 
101  m_keepPreviousSelection = false;
102 
103  Qt::KeyboardModifiers keys = e->modifiers();
104 
105  if(keys & Qt::ControlModifier || keys & Qt::ShiftModifier)
107 
108  m_selectionByPointing = false;
109 
110  if(m_rect.isNull())
111  {
112  m_selectionByPointing = true;
113  QPointF pixelOffset(4.0, 4.0);
114 #if QT_VERSION >= 0x050000
115  m_rect = QRectF(e->localPos() - pixelOffset, e->localPos() + pixelOffset);
116 #else
117  m_rect = QRectF(e->posF() - pixelOffset, e->posF() + pixelOffset);
118 #endif
119  }
120 
121  // Converts rect boundary to world coordinates
122  QPointF ll(m_rect.left(), m_rect.bottom());
123  QPointF ur(m_rect.right(), m_rect.top());
124  ll = m_display->transform(ll);
125  ur = m_display->transform(ur);
126 
127  te::gm::Envelope envelope(ll.x(), ll.y(), ur.x(), ur.y());
128 
129  // Select the layers
130  std::list<te::map::AbstractLayerPtr>::iterator it;
131  for(it = m_layers.begin(); it != m_layers.end(); ++it)
132  executeSelection(*it, envelope);
133 
134  return true;
135 }
136 
137 void te::qt::widgets::Selection::setLayers(const std::list<te::map::AbstractLayerPtr>& layers)
138 {
139  m_layers = layers;
140 }
141 
143 {
144  if(layer->getVisibility() != te::map::VISIBLE || !layer->isValid() || layer->getType() == "FOLDERLAYER")
145  return;
146 
147  std::unique_ptr<te::da::DataSetType> dsType = layer->getSchema();
148 
149  if(!dsType->hasGeom())
150  return;
151 
152  te::gm::Envelope reprojectedEnvelope(e);
153 
154  if((layer->getSRID() != TE_UNKNOWN_SRS) && (m_display->getSRID() != TE_UNKNOWN_SRS) && (layer->getSRID() != m_display->getSRID()))
155  reprojectedEnvelope.transform(m_display->getSRID(), layer->getSRID());
156 
157  // Clear previous selection?
159  {
160  layer->clearSelected();
161  emit layerSelectedObjectsChanged(layer);
162  }
163 
164  if(!reprojectedEnvelope.intersects(layer->getExtent()))
165  return;
166 
167  try
168  {
169  // Gets the layer schema
170  std::unique_ptr<const te::map::LayerSchema> schema(layer->getSchema());
171  if(!schema->hasGeom())
172  return;
173 
175 
176  // Gets the dataset
177  std::unique_ptr<te::da::DataSet> dataset = layer->getData(gp->getName(), &reprojectedEnvelope, te::gm::INTERSECTS);
178  assert(dataset.get());
179 
180  // Let's generate the oids
181  te::da::ObjectIdSet* oids = nullptr;
182  te::da::GetEmptyOIDSet(schema.get(), oids);
183  assert(oids);
184 
185  std::vector<std::string> pnames;
186  te::da::GetOIDPropertyNames(schema.get(), pnames);
187 
188  // Generates a geometry from the given extent. It will be used to refine the results
189  std::unique_ptr<te::gm::Geometry> geometryFromEnvelope(te::gm::GetGeomFromEnvelope(&reprojectedEnvelope, layer->getSRID()));
190 
191  if(m_selectionByPointing == false)
192  {
193  while(dataset->moveNext())
194  {
195  std::unique_ptr<te::gm::Geometry> g(dataset->getGeometry(gp->getName()));
196 
197  if(g.get() == nullptr)
198  continue;
199 
200  if(g->getSRID() == TE_UNKNOWN_SRS)
201  g->setSRID(layer->getSRID());
202 
203  if(!g->intersects(geometryFromEnvelope.get()))
204  continue;
205 
206  // Feature found!
207  oids->add(te::da::GenerateOID(dataset.get(), pnames));
208  }
209 
210  oids->setExpressionByIntersection(gp->getName(), reprojectedEnvelope, layer->getSRID());
211  }
212  else
213  {
214  // The restriction point. It will be used to refine the results
215  te::gm::Coord2D center = reprojectedEnvelope.getCenter();
216  te::gm::Point point(center.x, center.y, layer->getSRID());
217 
218  while(dataset->moveNext())
219  {
220  std::unique_ptr<te::gm::Geometry> g(dataset->getGeometry(gp->getName()));
221 
222  if(g.get() == nullptr)
223  continue;
224 
225  if(g->getSRID() == TE_UNKNOWN_SRS)
226  g->setSRID(layer->getSRID());
227 
228  if(g->contains(&point) || g->crosses(geometryFromEnvelope.get()) || geometryFromEnvelope->contains(g.get()))
229  {
230  // Feature found!
231  oids->add(te::da::GenerateOID(dataset.get(), pnames));
232  }
233  }
234 
235  oids->setExpressionByInClause();
236  }
237 
238  assert(oids);
239 
240  // Adjusts the layer selection
241 
242  const te::da::ObjectIdSet* currentOids = layer->getSelected();
243  if(currentOids == nullptr || !m_keepPreviousSelection)
244  {
245  layer->select(oids);
246  emit layerSelectedObjectsChanged(layer);
247  return;
248  }
249 
250  te::da::ObjectIdSet* finalSelected = currentOids->clone();
251  finalSelected->symDifference(oids);
252 
253  delete oids;
254 
255  layer->clearSelected();
256 
257  layer->select(finalSelected);
258 
259  emit layerSelectedObjectsChanged(layer);
260  }
261  catch(std::exception& e)
262  {
263  QMessageBox::critical(m_display, tr("Error"), QString(tr("The selection cannot be retrieved from the layer. Details:") + " %1.").arg(e.what()));
264  // TODO: catch the exceptions...
265  }
266 }
virtual bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
Definition: RubberBand.cpp:53
Geometric property.
TEDATAACCESSEXPORT void GetEmptyOIDSet(const DataSetType *type, ObjectIdSet *&set)
Returns an empty ObjectIdSet, with the definitions of fields that compose it.
double y
y-coordinate.
Definition: Coord2D.h:114
bool m_selectionByPointing
Flag that indicates if the selection is by pointing.
Definition: Selection.h:124
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
virtual bool mouseReleaseEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse release events for ...
Definition: RubberBand.cpp:70
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
double x
x-coordinate.
Definition: Coord2D.h:113
void layerSelectedObjectsChanged(const te::map::AbstractLayerPtr &layer)
virtual bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
Definition: RubberBand.cpp:47
QPen m_pen
The pen used to draw the rubber band shape.
Definition: RubberBand.h:94
A widget to control the display of a set of layers.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
bool mouseReleaseEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse release events for ...
Definition: Selection.cpp:90
void setLayers(const std::list< te::map::AbstractLayerPtr > &layers)
Definition: Selection.cpp:137
QBrush m_brush
The brush used to draw the rubber band shape.
Definition: RubberBand.h:95
QRectF m_rect
The boundary rectangle managed by the rubber band.
Definition: RubberBand.h:93
Coord2D getCenter() const
It returns the rectangle&#39;s center coordinate.
bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
Definition: Selection.cpp:82
virtual QPointF transform(const QPointF &p)
Transforms the given point, in screen coordinates, to a point in world coordinates.
A point with x and y coordinate values.
Definition: Point.h:50
An Envelope defines a 2D rectangular region.
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
bool m_selectionStarted
Flag that indicates if selection operation was started.
Definition: Selection.h:122
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
bool m_keepPreviousSelection
Flag that indicates if the tool must keep the previous selection.
Definition: Selection.h:123
virtual void setCursor(const QCursor &cursor)
It sets the tool cursor.
Selection(MapDisplay *display, const QCursor &cursor, const std::list< te::map::AbstractLayerPtr > &layers, QObject *parent=0)
It constructs a selection tool associated with the given map display.
Definition: Selection.cpp:53
void symDifference(const ObjectIdSet *rhs)
It performs the symmetric difference operation between this ObjectIdSet and the given ObjectIdSet...
This class provides a rectangle that can indicate a boundary.
Definition: RubberBand.h:52
std::list< te::map::AbstractLayerPtr > m_layers
The layer list that will be selected.
Definition: Selection.h:121
void executeSelection(const te::map::AbstractLayerPtr &layer, const te::gm::Envelope &e)
Definition: Selection.cpp:142
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)
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
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.
ObjectIdSet * clone() const
This class implements a concrete tool to select layer features using an extent.
TEGEOMEXPORT Geometry * GetGeomFromEnvelope(const Envelope *const e, int srid)
It creates a Geometry (a polygon) from the given envelope.
An object that when created shows a cursor during its scope.
Definition: ScopedCursor.h:48
bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
Definition: Selection.cpp:71
const std::string & getName() const
It returns the property name.
Definition: Property.h:127