GeometricOpWizard.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/vp/qt/GeometricOpWizard.cpp
22 
23  \brief A Qt dialog that allows users to run the basic geographic operations defined by VP module.
24 */
25 
26 // TerraLib
27 #include "../Enums.h"
28 #include "../../common/Logger.h"
29 #include "../../common/progress/ProgressManager.h"
30 #include "../../dataaccess/dataset/DataSet.h"
31 #include "../../dataaccess/dataset/DataSetType.h"
32 #include "../../dataaccess/dataset/DataSetTypeConverter.h"
33 #include "../../dataaccess/datasource/DataSourceCapabilities.h"
34 #include "../../dataaccess/datasource/DataSourceInfo.h"
35 #include "../../dataaccess/datasource/DataSourceInfoManager.h"
36 #include "../../dataaccess/datasource/DataSourceFactory.h"
37 #include "../../dataaccess/datasource/DataSourceManager.h"
38 #include "../../dataaccess/utils/Utils.h"
39 
40 #include "../../maptools/AbstractLayer.h"
41 
42 #include "../../qt/widgets/help/HelpPushButton.h"
43 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
44 #include "../../qt/widgets/layer/search/LayerSearchWidget.h"
45 #include "../../qt/widgets/layer/search/LayerSearchWizardPage.h"
46 #include "../../qt/widgets/layer/utils/DataSet2Layer.h"
47 
48 #include "../Config.h"
49 #include "../Exception.h"
50 
51 #include "GeometricOpWizard.h"
52 #include "GeometricOpWizardPage.h"
54 #include "../GeometricOp.h"
55 #include "../GeometricOpMemory.h"
56 #include "../GeometricOpQuery.h"
57 //#include "Utils.h"
58 
59 // STL
60 #include <cassert>
61 
62 // Qt
63 #include <QMessageBox>
64 
65 // Boost
66 #include <boost/filesystem.hpp>
67 #include <boost/uuid/random_generator.hpp>
68 #include <boost/uuid/uuid_io.hpp>
69 
71  : QWizard(parent)
72 {
73  //configure the wizard
74  this->setWizardStyle(QWizard::ModernStyle);
75  this->setWindowTitle(tr("Geometric Operation"));
76 
77  this->setOption(QWizard::HaveHelpButton, true);
78  this->setOption(QWizard::HelpButtonOnRight, false);
79 
81 
82  this->setButton(QWizard::HelpButton, helpButton);
83 
84  helpButton->setPageReference("plugins/vp/vp_geometricOper.html");
85 
86  addPages();
87 }
88 
90 {
91 
92 }
93 
95 {
96  if(currentPage() == m_layerSearchPage.get())
97  {
98  std::list<te::map::AbstractLayerPtr> list = m_layerSearchPage->getSearchWidget()->getSelecteds();
99 
100  if(list.empty() == false)
101  {
102  te::map::AbstractLayerPtr l = *list.begin();
103  m_geomOpPage->setLayer(l);
104  m_inLayer = l;
105 
106  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
107  std::vector<te::dt::Property*> vecProp = dsType->getProperties();
108  std::vector<std::string> vecPropName;
109 
110  for(std::size_t i = 0; i < vecProp.size(); ++i)
111  {
112  if(vecProp[i]->getType() != te::dt::GEOMETRY_TYPE)
113  vecPropName.push_back(vecProp[i]->getName());
114  }
115 
116  m_geomOpOutputPage->setAttributes(vecPropName);
117  }
118 
119  return m_layerSearchPage->isComplete();
120  }
121  else if(currentPage() == m_geomOpOutputPage.get())
122  {
123  if(!m_geomOpOutputPage->getToFile())
124  {
125  if(!m_geomOpOutputPage->getDsInfoPtr())
126  {
127  QMessageBox::information(this,
128  "Basic Geographic Operation",
129  "Set the output data source before execute the operation.");
130  return false;
131  }
132  if(m_geomOpOutputPage->getOutDsName() == "")
133  {
134  QMessageBox::information(this,
135  "Basic Geographic Operation",
136  "Set a Name for the output dataset before execute the operation.");
137  return false;
138  }
139  }
140 
141  return execute();
142  }
143 
144  return true;
145 }
146 
147 void te::vp::GeometricOpWizard::setList(std::list<te::map::AbstractLayerPtr>& layerList)
148 {
149  m_layerSearchPage->getSearchWidget()->setList(layerList);
150  m_layerSearchPage->getSearchWidget()->filterOnlyByGeom();
151 }
152 
154 {
155  removePage(m_layerSearchId);
156  m_geomOpPage->setLayer(layer);
157 }
158 
160 {
161  return m_inLayer;
162 }
163 
164 std::vector<te::map::AbstractLayerPtr> te::vp::GeometricOpWizard::getOutLayer()
165 {
166  return m_outLayer;
167 }
168 
170 {
171  m_layerSearchPage.reset(new te::qt::widgets::LayerSearchWizardPage(this));
172  m_geomOpPage.reset(new te::vp::GeometricOpWizardPage(this));
173  m_geomOpOutputPage.reset(new te::vp::GeometricOpOutputWizardPage(this));
174 
175  m_layerSearchId = addPage(m_layerSearchPage.get());
176  addPage(m_geomOpPage.get());
177  addPage(m_geomOpOutputPage.get());
178 
179  //for contrast only one layer can be selected
180  m_layerSearchPage->getSearchWidget()->enableMultiSelection(false);
181 }
182 
184 {
185  bool result;
186 
187 // progress
190 
191  try
192  {
193  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(m_inLayer.get());
194  te::da::DataSourcePtr inDataSource = te::da::GetDataSource(dsLayer->getDataSourceId(), true);
195 
196  m_ops.clear();
197 
198  //Params
199  if(m_geomOpOutputPage->hasConvexHull())
200  m_ops.push_back(te::vp::CONVEX_HULL);
201 
202  if(m_geomOpOutputPage->hasCentroid())
203  m_ops.push_back(te::vp::CENTROID);
204 
205  if(m_geomOpOutputPage->hasMBR())
206  m_ops.push_back(te::vp::MBR);
207 
208  if(m_geomOpOutputPage->hasArea())
209  m_ops.push_back(te::vp::AREA);
210 
211  if(m_geomOpOutputPage->hasLine())
212  m_ops.push_back(te::vp::LINE);
213 
214  if(m_geomOpOutputPage->hasPerimeter())
215  m_ops.push_back(te::vp::PERIMETER);
216 
217 // get the selected properties of input layer
218  std::vector<std::string> geoProps = m_geomOpPage->getSelectedProps();
219 
220  std::string outputdataset = m_geomOpOutputPage->getOutDsName();
221  std::vector<std::string> outputDSetNames;
222 
223 //get the selected property if the operation is by attribute
224  m_attribute = m_geomOpOutputPage->getAttribute();
225 
226 // Verify output datasource
227  if(m_geomOpOutputPage->getToFile())
228  {
229  boost::filesystem::path uri(m_geomOpOutputPage->getPath());
230 
231  bool ops_selected = false;
232 
233  if(m_geomOpOutputPage->hasConvexHull())
234  {
235  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + "_convex_hull.shp");
236  if (boost::filesystem::exists(uri_file))
237  {
238  QMessageBox::information(this, "Geographic Operation", "The convex hull output file already exists. Remove it or select a new name and try again.");
239  return false;
240  }
241 
242  ops_selected = true;
243  }
244  if(m_geomOpOutputPage->hasCentroid())
245  {
246  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + "_centroid.shp");
247  if (boost::filesystem::exists(uri_file))
248  {
249  QMessageBox::information(this, "Geographic Operation", "The centroid output file already exists. Remove it or select a new name and try again.");
250  return false;
251  }
252 
253  ops_selected = true;
254  }
255  if(m_geomOpOutputPage->hasMBR())
256  {
257  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + "_mbr.shp");
258  if (boost::filesystem::exists(uri_file))
259  {
260  QMessageBox::information(this, "Geographic Operation", "The mbr output file already exists. Remove it or select a new name and try again.");
261  return false;
262  }
263 
264  ops_selected = true;
265  }
266  if(!ops_selected)
267  {
268  boost::filesystem::path uri_file(m_geomOpOutputPage->getPath() + "/" + outputdataset + ".shp");
269  if (boost::filesystem::exists(uri_file))
270  {
271  QMessageBox::information(this, "Geographic Operation", "Output file already exists. Remove it or select a new name and try again.");
272  return false;
273  }
274  }
275 
276  std::size_t idx = outputdataset.find(".");
277 
278  if (idx != std::string::npos)
279  outputdataset=outputdataset.substr(0,idx);
280 
281  std::map<std::string, std::string> dsinfo;
282  dsinfo["URI"] = uri.string();
283  dsinfo["DRIVER"] = "ESRI Shapefile";
284 
285  std::auto_ptr<te::da::DataSource> dsOGR = te::da::DataSourceFactory::make("OGR");
286  dsOGR->setConnectionInfo(dsinfo);
287  dsOGR->open();
288  if (dsOGR->dataSetExists(outputdataset))
289  {
290  QMessageBox::information(this, "Basic Geographic Operation", "There is already a dataset with the requested name in the output data source. Remove it or select a new name and try again.");
291  return false;
292  }
293 
294  std::auto_ptr<te::da::DataSetTypeConverter> converter(new te::da::DataSetTypeConverter(dsLayer->getSchema().get(), dsOGR->getCapabilities(), dsOGR->getEncoding()));
295  te::da::AssociateDataSetTypeConverterSRID(converter.get(), dsLayer->getSRID());
296 
297  this->setCursor(Qt::WaitCursor);
298 
299  // sera feito por algum tipo de factory
300  te::vp::GeometricOp* geomOp = 0;
301 
302  // select a strategy based on the capabilities of the input datasource
303  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
304 
305  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
306  {
307  geomOp = new te::vp::GeometricOpQuery();
308  }
309  else
310  {
311  geomOp = new te::vp::GeometricOpMemory();
312  }
313 
314  geomOp->setInput(inDataSource, dsLayer->getDataSetName(), converter);
315  geomOp->setOutput(dsOGR, outputdataset);
316  geomOp->setParams(geoProps,
317  m_ops,
318  m_geomOpOutputPage->getObjectStrategy(),
319  m_attribute,
320  m_geomOpOutputPage->hasOutputLayer());
321 
322  if (!geomOp->paramsAreValid())
323  result = false;
324  else
325  result = geomOp->run();
326 
327  if (!result)
328  {
329  this->setCursor(Qt::ArrowCursor);
330  QMessageBox::information(this, "Geometric Operation", "Error: could not generate the operation, check the log file.");
331  return false;
332  }
333 
334  outputDSetNames = geomOp->GetOutputDSetNames();
335 
336  delete geomOp;
337 
338  // let's include the new datasource in the managers
339  boost::uuids::basic_random_generator<boost::mt19937> gen;
340  boost::uuids::uuid u = gen();
341  std::string id = boost::uuids::to_string(u);
342 
344  ds->setConnInfo(dsinfo);
345  ds->setTitle(uri.stem().string());
346  ds->setAccessDriver("OGR");
347  ds->setType("OGR");
348  ds->setDescription(uri.string());
349  ds->setId(id);
350 
351  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id, "OGR", ds->getConnInfo());
352  newds->open();
354  m_outputDatasource = ds;
355  }
356  else
357  {
358  m_outputDatasource = m_geomOpOutputPage->getDsInfoPtr();
359  std::auto_ptr<te::da::DataSource> trgDs = te::da::DataSourceFactory::make(m_outputDatasource->getType());
360  trgDs->setConnectionInfo(m_outputDatasource->getConnInfo());
361  trgDs->open();
362 
363  if (!trgDs.get())
364  {
365  QMessageBox::information(this, "Geometric Operation", "The selected output datasource can not be accessed.");
366  return false;
367  }
368 
369  if (trgDs->dataSetExists(outputdataset))
370  {
371  QMessageBox::information(this, "Geometric Operation", "Dataset already exists. Remove it or select a new name and try again.");
372  return false;
373  }
374 
375  std::auto_ptr<te::da::DataSetTypeConverter> converter(new te::da::DataSetTypeConverter(dsLayer->getSchema().get(), trgDs->getCapabilities(), trgDs->getEncoding()));
376  te::da::AssociateDataSetTypeConverterSRID(converter.get(), dsLayer->getSRID());
377 
378  this->setCursor(Qt::WaitCursor);
379 
380  te::vp::GeometricOp* geomOp = 0;
381 
382  // select a strategy based on the capabilities of the input datasource
383  const te::da::DataSourceCapabilities dsCapabilities = inDataSource->getCapabilities();
384 
385  if(dsCapabilities.supportsPreparedQueryAPI() && dsCapabilities.getQueryCapabilities().supportsSpatialSQLDialect())
386  {
387  geomOp = new te::vp::GeometricOpQuery();
388  }
389  else
390  {
391  geomOp = new te::vp::GeometricOpMemory();
392  }
393 
394  geomOp->setInput(inDataSource, dsLayer->getDataSetName(), converter);
395  geomOp->setOutput(trgDs, outputdataset);
396  geomOp->setParams(geoProps,
397  m_ops,
398  m_geomOpOutputPage->getObjectStrategy(),
399  m_attribute,
400  m_geomOpOutputPage->hasOutputLayer());
401 
402  if (!geomOp->paramsAreValid())
403  result = false;
404  else
405  result = geomOp->run();
406 
407  if (!result)
408  {
409  this->setCursor(Qt::ArrowCursor);
410  QMessageBox::information(this, "Geometric Operation", "Error: could not generate the operation.");
411  return false;
412  }
413 
414  outputDSetNames = geomOp->GetOutputDSetNames();
415 
416  delete geomOp;
417  }
418 
419 // creating a layer for the result
420  te::da::DataSourcePtr outDataSource = te::da::GetDataSource(m_outputDatasource->getId());
421  te::qt::widgets::DataSet2Layer converter(m_outputDatasource->getId());
422 
423  for(std::size_t i = 0; i < outputDSetNames.size(); ++i)
424  {
425  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputDSetNames[i]).release());
426  if(dt)
427  m_outLayer.push_back(converter(dt));
428  }
429  }
430  catch(const std::exception& e)
431  {
432  this->setCursor(Qt::ArrowCursor);
433  QMessageBox::information(this, "Greographic Operation", e.what());
434 
435 #ifdef TERRALIB_LOGGER_ENABLED
436  std::string str = "Greographic Operation - ";
437  str += e.what();
438  te::common::Logger::logDebug("vp", str.c_str());
439 #endif
440 
442  return false;
443  }
444 
446  this->setCursor(Qt::ArrowCursor);
447 
448  return true;
449 }
TEDATAACCESSEXPORT DataSourcePtr GetDataSource(const std::string &datasourceId, const bool opened=true)
Search for a data source with the informed id in the DataSourceManager.
Definition: Utils.cpp:262
void setList(std::list< te::map::AbstractLayerPtr > &layerList)
const std::string & getDataSetName() const
std::vector< std::string > GetOutputDSetNames()
Definition: GeometricOp.cpp:91
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
The geographic operation Line.
Definition: Enums.h:106
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
TEDATAACCESSEXPORT void AssociateDataSetTypeConverterSRID(DataSetTypeConverter *converter, const int &inputSRID, const int &outputSRID=TE_UNKNOWN_SRS)
Definition: Utils.cpp:670
The geographic operation Minimum Bounding Rectangle.
Definition: Enums.h:104
void setLayer(te::map::AbstractLayerPtr layer)
void setPageReference(const QString &ref)
Sets the documentation page reference.
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::auto_ptr< te::da::DataSetTypeConverter > converter)
Definition: GeometricOp.cpp:49
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
This class is GUI used to define the basic geometric operator parameters for the VP operation...
const QueryCapabilities & getQueryCapabilities() const
An converter for DataSetType.
The geographic operation Area.
Definition: Enums.h:105
void removeViewer(int viewerId)
Dettach a progress viewer.
static ProgressManager & getInstance()
It returns a reference to the singleton instance.
const std::string & getDataSourceId() const
static std::auto_ptr< DataSource > make(const std::string &dsType)
A Qt dialog that allows users to run the basic geometric operations defined by VP module...
The geographic operation Perimeter.
Definition: Enums.h:107
bool supportsSpatialSQLDialect() const
void setOutput(std::auto_ptr< te::da::DataSource > outDsrc, std::string dsname)
Definition: GeometricOp.cpp:71
The geographic operation Centroid.
Definition: Enums.h:103
std::vector< te::map::AbstractLayerPtr > getOutLayer()
This file defines a class for Basic Geometric Operation Wizard Page.
int addViewer(AbstractProgressViewer *apv)
Attach a progress viewer.
Push button that uses te::qt::widgets::HelpManager on its mouse pressed implementation.
virtual bool paramsAreValid()
Definition: GeometricOp.cpp:77
te::map::AbstractLayerPtr getInLayer()
The geographic operation Convex Hull.
Definition: Enums.h:102
A class that represents a data source component.
virtual int getSRID() const
It returns the Spatial Reference System ID associated to the Layer.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
std::auto_ptr< LayerSchema > getSchema() const
It returns the layer schema.
void setParams(std::vector< std::string > selectedProps, std::vector< te::vp::GeometricOperation > operations, te::vp::GeometricOpObjStrategy objStrategy, std::string attribute, bool outputLayer)
Definition: GeometricOp.cpp:58
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
GeometricOpWizard(QWidget *parent)
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
virtual bool run()=0