SplitPolygonTool.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/SplitPolygonTool.cpp
22 
23  \brief This class implements a concrete tool to split polygons.
24 */
25 
26 // TerraLib
27 #include "../../../common/STLUtils.h"
28 #include "../../../geometry/Envelope.h"
29 #include "../../../dataaccess/utils/Utils.h"
30 #include "../../../qt/widgets/canvas/MapDisplay.h"
31 #include "../../../qt/widgets/Utils.h"
32 #include "../../Feature.h"
33 #include "../../Repository.h"
34 #include "../../RepositoryManager.h"
35 #include "../../Utils.h"
36 #include "../Renderer.h"
37 #include "../Utils.h"
38 #include "SplitPolygonTool.h"
39 
40 // Qt
41 #include <QMessageBox>
42 #include <QMouseEvent>
43 #include <QPainter>
44 #include <QPixmap>
45 
46 // STL
47 #include <cassert>
48 #include <memory>
49 
51  : CreateLineTool(display, layer, Qt::ArrowCursor, parent),
52  m_tol(0.000001),
53  m_oidSet(nullptr),
54  m_vecFeatures(0)
55 {
56  setCursor(Qt::ArrowCursor);
57 
58  pickFeatures();
59 
60  draw();
61 }
62 
64 {
66  m_vecFeatures.clear();
67 
68  if (m_oidSet)
69  m_oidSet = nullptr;
70 
72 }
73 
75 {
76  if (e->button() != Qt::LeftButton)
77  return false;
78 
79  if (m_isFinished) // Is Finished?! So, start again...
80  {
82  m_isFinished = false;
83 
84  pickFeatures();
85  }
86 
88 }
89 
91 {
93 }
94 
96 {
97  if (Qt::LeftButton != e->button())
98  return false;
99 
100  editingFinished();
101 
102  return true;
103 }
104 
106 {
107  if (Qt::RightButton != e->button())
108  return false;
109 
110  editingFinished();
111 
112  return true;
113 }
114 
116 {
117  if (m_coords.size() < 2) // Can not stop yet...
118  return;
119 
120  m_isFinished = true;
121 
122  if (m_oidSet == nullptr)
124 
125  for (std::size_t i = 0; i < m_vecFeatures.size(); ++i)
126  {
127  if (RepositoryManager::getInstance().hasIdentify(m_layer->getId(), m_vecFeatures[i]->getId()))
128  {
129  RepositoryManager::getInstance().removeFeature(m_layer->getId(), m_vecFeatures[i]->getId());
130  splitPolygon(i);
131  }
132  }
133 
135 
136  if (!m_oidSet->size())
137  return;
138 
139  emit geometriesEdited();
140 }
141 
143 {
144  setCursor(Qt::WaitCursor);
145 
146  try
147  {
148  int srid = m_display->getSRID();
149  std::vector<te::gm::Polygon*> outPolygons;
150 
151  if (m_layer->getSRID() != m_display->getSRID())
152  m_vecFeatures.at(index)->getGeometry()->transform(srid);
153 
154  std::unique_ptr<te::gm::Geometry> geom_bounds;
155  geom_bounds.reset(m_vecFeatures.at(index)->getGeometry()->getBoundary());
156  geom_bounds->setSRID(srid);
157 
158  std::unique_ptr<te::gm::Geometry> blade_in;
159  blade_in.reset(te::edit::CreateLineTool::buildLine());
160  blade_in->setSRID(srid);
161 
162  std::unique_ptr<te::gm::Geometry> vgeoms;
163  vgeoms.reset(geom_bounds->Union(blade_in.get()));
164  vgeoms->setSRID(srid);
165 
166  te::gm::Polygonizer(vgeoms.get(), outPolygons);
167 
168  std::size_t i = 1;
169  while (i < outPolygons.size())
170  {
171  if (!outPolygons.at(i)->equals(m_vecFeatures.at(index)->getGeometry()) &&
172  outPolygons.at(i)->coveredBy(m_vecFeatures.at(index)->getGeometry()->buffer(m_tol)))
173  {
174  Feature* f = new Feature(GenerateId(), outPolygons.at(i));
175  f->setData(m_vecFeatures.at(index)->clone()->getData());
177 
178  RepositoryManager::getInstance().addFeature(m_layer->getId(), f->clone());
179  m_oidSet->add(f->clone()->getId());
180 
181  delete f;
182  f = nullptr;
183  }
184 
185  i++;
186  }
187 
188  if (m_oidSet->size() &&
189  outPolygons.at(0)->coveredBy(m_vecFeatures.at(index)->getGeometry()->buffer(m_tol)))
190  {
191  m_vecFeatures.at(index)->setGeometry(outPolygons.at(0));
192  RepositoryManager::getInstance().addFeature(m_layer->getId(), m_vecFeatures.at(index)->clone());
193 
194  m_oidSet->add(m_vecFeatures.at(index)->getId());
195  }
196 
197  setCursor(Qt::ArrowCursor);
198  }
199  catch (std::exception& e)
200  {
201  setCursor(Qt::ArrowCursor);
202  QMessageBox::critical(m_display, tr("Error"), QString(tr("Could not split.") + " %1.").arg(e.what()));
203  return;
204  }
205 }
206 
208 {
209  const te::gm::Envelope& env = m_display->getExtent();
210  if (!env.isValid())
211  return;
212 
213  // Clear!
214  QPixmap* draft = m_display->getDraftPixmap();
215  draft->fill(Qt::transparent);
216 
217  // Initialize the renderer
218  Renderer& renderer = Renderer::getInstance();
219  renderer.begin(draft, env, m_display->getSRID());
220 
221  // Draw the layer edited geometries
222  renderer.drawRepository(m_layer->getId(), env, m_display->getSRID());
223 
224  renderer.end();
225 
226  m_display->repaint();
227 }
228 
230 {
232 
233  if (m_oidSet)
234  {
235  std::set<te::da::ObjectId*, te::common::LessCmp<te::da::ObjectId*> >::const_iterator it;
236  for (it = m_oidSet->begin(); it != m_oidSet->end(); ++it)
237  {
238  if (repo->hasIdentifier(*it))
239  repo->remove((*it));
240  }
241  }
242 
244  m_isFinished = true;
245  m_oidSet = nullptr;
246 }
247 
249 {
250  std::map<std::size_t, te::dt::AbstractData*> mapFields;
251 
252  try
253  {
254  if(m_layer->getSelected() == nullptr || m_layer->getSelected()->size() == 0)
255  {
256  QMessageBox::information(m_display,
257  tr("TerraAmazon"),
258  tr("To use this tool, you must select at least one geometry."));
259  return;
260  }
261 
262  std::unique_ptr<te::da::DataSet> ds(m_layer->getData(m_layer->getSelected()));
263  std::size_t gpos = te::da::GetFirstSpatialPropertyPos(ds.get());
264 
265  std::vector<std::string> oidPropertyNames;
266  te::da::GetOIDPropertyNames(m_layer->getSchema().get(), oidPropertyNames);
267 
268  m_vecFeatures.clear();
269 
270  ds->moveBeforeFirst();
271  while (ds->moveNext())
272  {
273  std::unique_ptr<te::gm::Geometry> g(ds->getGeometry(gpos));
274 
275  Feature* f = new Feature(te::da::GenerateOID(ds.get(), oidPropertyNames), g.release());
276  for (std::size_t i = 0; i < ds->getNumProperties(); ++i)
277  {
278  std::size_t pos = te::da::GetPropertyPos(m_layer->getSchema().get(), ds->getPropertyName(i));
279  if (!ds->isNull(pos) && ds->getPropertyDataType(pos) != te::dt::GEOMETRY_TYPE)
280  {
281  std::unique_ptr<te::dt::AbstractData> data(ds->getValue(pos));
282  mapFields[pos] = data.release();
283  }
284  }
285 
286  f->setData(mapFields);
287  f->setOperationTypeId(UPDATE);
288 
289  m_vecFeatures.push_back(f->clone());
290  RepositoryManager::getInstance().addFeature(m_layer->getId(), f->clone());
291 
292  delete f;
293  f = nullptr;
294  }
295 
296  }
297  catch (std::exception& e)
298  {
299  QMessageBox::critical(m_display, tr("Error"), QString(tr("The geometry cannot be selected from the layer. Details:") + " %1.").arg(e.what()));
300  }
301 }
virtual const std::string & getId() const
It returns the layer id.
bool mouseReleaseEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse release events for ...
bool m_isFinished
A flag that indicates if the operations was finished.
void splitPolygon(std::size_t index)
std::vector< te::edit::Feature * > m_vecFeatures
TEEDITEXPORT te::da::ObjectId * GenerateId()
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
te::da::ObjectId * getId() const
Definition: Feature.cpp:134
This class implements a concrete tool to create lines.
TEDATAACCESSEXPORT std::size_t GetPropertyPos(const DataSet *dataset, const std::string &name)
Feature * clone() const
Definition: Feature.cpp:182
A widget to control the display of a set of layers.
static te::dt::Date ds(2010, 01, 01)
bool hasIdentifier(te::da::ObjectId *id)
Definition: Repository.cpp:167
te::da::ObjectIdSet * m_oidSet
bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
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 RepositoryManager & getInstance()
It returns a reference to the singleton instance.
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
void remove(te::da::ObjectId *id)
Definition: Repository.cpp:136
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.
std::vector< te::gm::Coord2D > m_coords
The coord list managed by this tool.
virtual std::unique_ptr< LayerSchema > getSchema() const =0
It returns the layer schema.
bool mouseMoveEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse move events for the...
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
virtual void clearSelected()
It clears the selected group of this Layer.
void setData(const std::map< std::size_t, te::dt::AbstractData * > &data)
Definition: Feature.cpp:103
bool mousePressEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse press events for th...
SplitPolygonTool(te::qt::widgets::MapDisplay *display, const te::map::AbstractLayerPtr &layer, QObject *parent=0)
It constructs a split polygon tool associated with the given map display.
TEGEOMEXPORT void Polygonizer(te::gm::Geometry *g, std::vector< te::gm::Polygon * > &pols)
It will get a list of polygons formed by the polygonization.
This is a singleton for rendering geometries and features.
Definition: Renderer.h:70
This class implements a concrete tool to split polygons.
te::map::AbstractLayer * m_layer
bool mouseDoubleClickEvent(QMouseEvent *e)
This event handler can be reimplemented in a concrete tool class to receive mouse double click events...
virtual const te::da::ObjectIdSet * getSelected() const
It returns the selected group of this Layer.
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.
std::set< ObjectId *, te::common::LessCmp< ObjectId * > >::const_iterator end() const
Returns an iterator for the object ids in container.
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)
void add(ObjectId *oid)
It adds an object id to this object id set.
Definition: ObjectIdSet.cpp:83
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
This class represents a repository of geometries and features.
Definition: Repository.h:63
te::gm::Geometry * buildLine()
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
std::set< ObjectId *, te::common::LessCmp< ObjectId * > >::const_iterator begin() const
Returns an iterator for the object ids in container.
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.