RasterToVectorDialog.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/attributefill/RasterToVectorDialog.cpp
22 
23  \brief Raster to vector attributefill dialog.
24 */
25 
26 // TerraLib
27 #include "../../BuildConfig.h"
28 #include "../../common/Logger.h"
29 #include "../../common/progress/ProgressManager.h"
30 #include "../../common/Translator.h"
31 #include "../../common/STLUtils.h"
32 #include "../../dataaccess/dataset/DataSetType.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 #include "../../datatype/Enums.h"
40 #include "../../datatype/Property.h"
41 #include "../../maptools/AbstractLayer.h"
42 #include "../../qt/af/Utils.h"
43 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
44 #include "../../qt/widgets/layer/utils/DataSet2Layer.h"
45 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
46 #include "../../qt/widgets/Utils.h"
47 #include "../../raster/RasterProperty.h"
48 #include "../../statistics/core/Utils.h"
49 #include "../Config.h"
50 #include "../Exception.h"
51 #include "RasterToVectorDialog.h"
52 #include "../RasterToVector.h"
53 #include "ui_RasterToVectorDialogForm.h"
54 
55 // Qt
56 #include <QFileDialog>
57 #include <QList>
58 #include <QListWidget>
59 #include <QListWidgetItem>
60 #include <QMessageBox>
61 
62 // Boost
63 #include <boost/algorithm/string.hpp>
64 #include <boost/filesystem.hpp>
65 #include <boost/lexical_cast.hpp>
66 #include <boost/uuid/random_generator.hpp>
67 #include <boost/uuid/uuid_io.hpp>
68 
70  : QDialog(parent, f),
71  m_ui(new Ui::RasterToVectorDialogForm),
72  m_layers(std::list<te::map::AbstractLayerPtr>())
73 {
74  // add controls
75  m_ui->setupUi(this);
76 
77  // add icons
78  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("raster-vector-hint").pixmap(112,48));
79  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
80 
81  connect(m_ui->m_inRasterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onRasterComboBoxChanged(int)));
82  connect(m_ui->m_inVectorComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onVectorComboBoxChanged(int)));
83 
84  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
85  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
86 
87  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
88  connect(m_ui->m_cancelPushButton, SIGNAL(clicked()), this, SLOT(onCancelPushButtonClicked()));
89 
90  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
91  m_ui->m_helpPushButton->setPageReference("plugins/attributefill/attrfill_raster_to_vector.html");
92 
93 }
94 
96 {
97 }
98 
99 void te::attributefill::RasterToVectorDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
100 {
101  m_layers = layers;
102 
103  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
104 
105  while(it != m_layers.end())
106  {
107  std::auto_ptr<te::da::DataSetType> dsType = it->get()->getSchema();
108  if(dsType->hasRaster())
109  m_ui->m_inRasterComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
110  if(dsType->hasGeom())
111  m_ui->m_inVectorComboBox->addItem(QString(it->get()->getTitle().c_str()), QVariant(it->get()->getId().c_str()));
112  ++it;
113  }
114 }
115 
117 {
118  return m_outLayer;
119 }
120 
122 {
123  std::vector<unsigned int> vecBands;
124 
125  for(int i = 0; i < m_ui->m_bandsListWidget->count(); ++i)
126  {
127  if(m_ui->m_bandsListWidget->isItemSelected(m_ui->m_bandsListWidget->item(i)))
128  {
129  vecBands.push_back(i);
130  }
131  }
132  return vecBands;
133 }
134 
135 std::vector<te::stat::StatisticalSummary> te::attributefill::RasterToVectorDialog::getSelectedStatistics()
136 {
137  std::vector<te::stat::StatisticalSummary> vecStatistics;
138 
139  for(int i = 0; i < m_ui->m_statisticsListWidget->count(); ++i)
140  {
141  if(m_ui->m_statisticsListWidget->isItemSelected(m_ui->m_statisticsListWidget->item(i)))
142  {
143  switch(i)
144  {
145  case 0:
146  vecStatistics.push_back(te::stat::MIN_VALUE);
147  break;
148  case 1:
149  vecStatistics.push_back(te::stat::MAX_VALUE);
150  break;
151  case 2:
152  vecStatistics.push_back(te::stat::MEAN);
153  break;
154  case 3:
155  vecStatistics.push_back(te::stat::SUM);
156  break;
157  case 4:
158  vecStatistics.push_back(te::stat::COUNT);
159  break;
160  case 5:
161  vecStatistics.push_back(te::stat::VALID_COUNT);
162  break;
163  case 6:
164  vecStatistics.push_back(te::stat::STANDARD_DEVIATION);
165  break;
166  case 7:
167  vecStatistics.push_back(te::stat::VARIANCE);
168  break;
169  case 8:
170  vecStatistics.push_back(te::stat::SKEWNESS);
171  break;
172  case 9:
173  vecStatistics.push_back(te::stat::KURTOSIS);
174  break;
175  case 10:
176  vecStatistics.push_back(te::stat::AMPLITUDE);
177  break;
178  case 11:
179  vecStatistics.push_back(te::stat::MEDIAN);
180  break;
181  case 12:
182  vecStatistics.push_back(te::stat::VAR_COEFF);
183  break;
184  case 13:
185  vecStatistics.push_back(te::stat::MODE);
186  break;
187  case 14:
188  vecStatistics.push_back(te::stat::PERCENT_EACH_CLASS_BY_AREA);
189  break;
190  default:
191  continue;
192  }
193  }
194  }
195  return vecStatistics;
196 }
197 
199 {
200  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
201 
202  std::string layerID = m_ui->m_inRasterComboBox->itemData(index, Qt::UserRole).toString().toStdString();
203 
204  while(it != m_layers.end())
205  {
206  if(layerID == it->get()->getId().c_str())
207  m_rasterLayer = it->get();
208 
209  ++it;
210  }
211 
212  m_ui->m_bandsListWidget->clear();
213 
214  std::auto_ptr<te::da::DataSetType> dsType = m_rasterLayer->getSchema();
215  te::rst::RasterProperty* rasterProp = te::da::GetFirstRasterProperty(dsType.get());
216  std::auto_ptr<te::da::DataSet> dsRaster = m_rasterLayer->getData();
217  std::auto_ptr<te::rst::Raster> raster = dsRaster->getRaster(rasterProp->getName());
218  std::size_t n_bands = raster->getNumberOfBands();
219 
220  for(std::size_t b = 0; b < n_bands; ++b)
221  m_ui->m_bandsListWidget->addItem(boost::lexical_cast<std::string>(b).c_str());
222 
223 
224  m_ui->m_statisticsListWidget->clear();
225 
226  m_ui->m_statisticsListWidget->addItem("Minimum value");
227  m_ui->m_statisticsListWidget->addItem("Maximum value");
228  m_ui->m_statisticsListWidget->addItem("Mean");
229  m_ui->m_statisticsListWidget->addItem("Sum of values");
230  m_ui->m_statisticsListWidget->addItem("Total number of values");
231  m_ui->m_statisticsListWidget->addItem("Total not null values");
232  m_ui->m_statisticsListWidget->addItem("Standard deviation");
233  m_ui->m_statisticsListWidget->addItem("Variance");
234  m_ui->m_statisticsListWidget->addItem("Skewness");
235  m_ui->m_statisticsListWidget->addItem("Kurtosis");
236  m_ui->m_statisticsListWidget->addItem("Amplitude");
237  m_ui->m_statisticsListWidget->addItem("Median");
238  m_ui->m_statisticsListWidget->addItem("Coefficient variation");
239  m_ui->m_statisticsListWidget->addItem("Mode");
240  m_ui->m_statisticsListWidget->addItem("Percent of each class by area");
241 
242 }
243 
245 {
246  std::list<te::map::AbstractLayerPtr>::iterator it = m_layers.begin();
247 
248  std::string layerID = m_ui->m_inVectorComboBox->itemData(index, Qt::UserRole).toString().toStdString();
249 
250  while(it != m_layers.end())
251  {
252  if(layerID == it->get()->getId().c_str())
253  m_vectorLayer = it->get();
254 
255  ++it;
256  }
257 }
258 
260 {
261  m_ui->m_newLayerNameLineEdit->clear();
262  m_ui->m_newLayerNameLineEdit->setEnabled(true);
264  dlg.exec();
265 
266  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
267 
268  if(dsPtrList.empty())
269  return;
270 
271  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
272 
273  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
274 
275  m_outputDatasource = *it;
276 
277  m_toFile = false;
278 }
279 
281 {
282  m_ui->m_newLayerNameLineEdit->clear();
283  m_ui->m_repositoryLineEdit->clear();
284 
285  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."),
286  QString(), tr("Shapefile (*.shp *.SHP);;"),0, QFileDialog::DontConfirmOverwrite);
287 
288  if (fileName.isEmpty())
289  return;
290 
291  boost::filesystem::path outfile(fileName.toStdString());
292  std::string aux = outfile.leaf().string();
293  m_ui->m_newLayerNameLineEdit->setText(aux.c_str());
294  aux = outfile.string();
295  m_ui->m_repositoryLineEdit->setText(aux.c_str());
296 
297  m_toFile = true;
298  m_ui->m_newLayerNameLineEdit->setEnabled(false);
299 }
300 
302 {
303  if(m_ui->m_inRasterComboBox->count() == 0)
304  {
305  QMessageBox::information(this, "Fill", "Select an input raster layer.");
306  return;
307  }
308 
309  if(m_ui->m_inVectorComboBox->count() == 0)
310  {
311  QMessageBox::information(this, "Fill", "Select an input vector layer.");
312  return;
313  }
314 
315 
316  te::map::DataSetLayer* dsRasterLayer = dynamic_cast<te::map::DataSetLayer*>(m_rasterLayer.get());
317 
318  if(!dsRasterLayer)
319  {
320  QMessageBox::information(this, "Fill", "Can not execute this operation on this type of layer.");
321  return;
322  }
323 
324  te::map::DataSetLayer* dsVectorLayer = dynamic_cast<te::map::DataSetLayer*>(m_vectorLayer.get());
325 
326  if(!dsVectorLayer)
327  {
328  QMessageBox::information(this, "Fill", "Can not execute this operation on this type of layer.");
329  return;
330  }
331 
332  te::da::DataSourcePtr inRasterDataSource = te::da::GetDataSource(dsRasterLayer->getDataSourceId(), true);
333  if (!inRasterDataSource.get())
334  {
335  QMessageBox::information(this, "Fill", "The selected raster data source can not be accessed.");
336  return;
337  }
338 
339  te::da::DataSourcePtr inVectorDataSource = te::da::GetDataSource(dsVectorLayer->getDataSourceId(), true);
340  if (!inVectorDataSource.get())
341  {
342  QMessageBox::information(this, "Fill", "The selected vector data source can not be accessed.");
343  return;
344  }
345 
346  std::vector<unsigned int> vecBands = getSelectedBands();
347  if(vecBands.empty())
348  {
349  QMessageBox::information(this, "Fill", "Select at least one band.");
350  return;
351  }
352 
353 
354  std::vector<te::stat::StatisticalSummary> vecStatistics = getSelectedStatistics();
355  m_texture = m_ui->m_textureCheckBox->isChecked();
356 
357  if(vecStatistics.empty() && m_texture == false)
358  {
359  QMessageBox::information(this, "Fill", "Select at least one statistic operation or select the texture checkbox.");
360  return;
361  }
362 
363  if(m_ui->m_repositoryLineEdit->text().isEmpty())
364  {
365  QMessageBox::information(this, "Fill", "Define a repository for the result.");
366  return;
367  }
368 
369  if(m_ui->m_newLayerNameLineEdit->text().isEmpty())
370  {
371  QMessageBox::information(this, "Fill", "Define a name for the resulting layer.");
372  return;
373  }
374 
375  std::string outputdataset = m_ui->m_newLayerNameLineEdit->text().toStdString();
376 
377  //progress
380 
381  try
382  {
383  bool res;
384 
385  if(m_toFile)
386  {
387  boost::filesystem::path uri(m_ui->m_repositoryLineEdit->text().toStdString());
388 
389  if (boost::filesystem::exists(uri))
390  {
391  QMessageBox::information(this, "Fill", "Output file already exists. Remove it or select a new name and try again.");
392  return;
393  }
394 
395  std::size_t idx = outputdataset.find(".");
396  if (idx != std::string::npos)
397  outputdataset=outputdataset.substr(0,idx);
398 
399  std::map<std::string, std::string> dsinfo;
400  dsinfo["URI"] = uri.string();
401 
403  dsOGR->setConnectionInfo(dsinfo);
404  dsOGR->open();
405  if (dsOGR->dataSetExists(outputdataset))
406  {
407  QMessageBox::information(this, "Fill", "There is already a dataset with the requested name in the output data source. Remove it or select a new name and try again.");
408  return;
409  }
410 
411  this->setCursor(Qt::WaitCursor);
412 
414  rst2vec->setInput(inRasterDataSource,
415  dsRasterLayer->getDataSetName(),
416  dsRasterLayer->getSchema(),
417  inVectorDataSource,
418  dsVectorLayer->getDataSetName(),
419  dsVectorLayer->getSchema());
420 
421  rst2vec->setParams(vecBands, vecStatistics, m_texture);
422 
423  rst2vec->setOutput(dsOGR, outputdataset);
424 
425  if (!rst2vec->paramsAreValid())
426  res = false;
427  else
428  res = rst2vec->run();
429 
430  if (!res)
431  {
432  this->setCursor(Qt::ArrowCursor);
433  dsOGR->close();
434  QMessageBox::information(this, "Fill", "Error: could not generate the operation.");
435  reject();
436  }
437  dsOGR->close();
438 
439  delete rst2vec;
440 
441  // let's include the new datasource in the managers
442  boost::uuids::basic_random_generator<boost::mt19937> gen;
443  boost::uuids::uuid u = gen();
444  std::string id_ds = boost::uuids::to_string(u);
445 
447  ds->setConnInfo(dsinfo);
448  ds->setTitle(uri.stem().string());
449  ds->setAccessDriver("OGR");
450  ds->setType("OGR");
451  ds->setDescription(uri.string());
452  ds->setId(id_ds);
453 
454  te::da::DataSourcePtr newds = te::da::DataSourceManager::getInstance().get(id_ds, "OGR", ds->getConnInfo());
455  newds->open();
457  m_outputDatasource = ds;
458  }
459  else
460  {
461  te::da::DataSourcePtr aux = te::da::GetDataSource(m_outputDatasource->getId());
462  if (!aux)
463  {
464  QMessageBox::information(this, "Fill", "The selected output datasource can not be accessed.");
465  return;
466  }
467 
468  if (aux->dataSetExists(outputdataset))
469  {
470  QMessageBox::information(this, "Fill", "Dataset already exists. Remove it or select a new name and try again.");
471  return;
472  }
473  this->setCursor(Qt::WaitCursor);
474 
476 
477  rst2vec->setInput(inRasterDataSource,
478  dsRasterLayer->getDataSetName(),
479  dsRasterLayer->getSchema(),
480  inVectorDataSource,
481  dsVectorLayer->getDataSetName(),
482  dsVectorLayer->getSchema());
483 
484  rst2vec->setParams(vecBands, vecStatistics, m_texture);
485 
486  rst2vec->setOutput(aux, outputdataset);
487 
488  if (!rst2vec->paramsAreValid())
489  res = false;
490  else
491  res = rst2vec->run();
492 
493  delete rst2vec;
494 
495  if (!res)
496  {
497  this->setCursor(Qt::ArrowCursor);
498  QMessageBox::information(this, "Fill", "Error: could not generate the operation.");
500 
501  reject();
502  }
503  }
504 
505  // creating a layer for the result
506  te::da::DataSourcePtr outDataSource = te::da::GetDataSource(m_outputDatasource->getId());
507 
508  te::qt::widgets::DataSet2Layer converter(m_outputDatasource->getId());
509 
510  te::da::DataSetTypePtr dt(outDataSource->getDataSetType(outputdataset).release());
511  m_outLayer = converter(dt);
512  }
513  catch(const std::exception& e)
514  {
515  this->setCursor(Qt::ArrowCursor);
516 
517  QMessageBox::information(this, "Fill", e.what());
518 
519 #ifdef TERRALIB_LOGGER_ENABLED
520  te::common::Logger::logDebug("attributefill", e.what());
521 #endif // TERRALIB_LOGGER_ENABLED
522 
524 
525  return;
526  }
527 
529  this->setCursor(Qt::ArrowCursor);
530  accept();
531 }
532 
534 {
535  reject();
536 }
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
Raster to vector attributefill dialog.
Mean.
Definition: Enums.h:43
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
Definition: Utils.cpp:571
std::vector< unsigned int > getSelectedBands()
Get the selected bands based on selected QListWidgetItem.
const std::string & getDataSetName() const
boost::shared_ptr< DataSetType > DataSetTypePtr
Definition: DataSetType.h:653
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
Skewness.
Definition: Enums.h:49
Total not null values.
Definition: Enums.h:46
Total number of values.
Definition: Enums.h:45
void setOutput(te::da::DataSourcePtr outDsrc, std::string dsName)
void setParams(std::vector< unsigned int > bands, std::vector< te::stat::StatisticalSummary > statSum, bool texture)
Percente of each class by area.
Definition: Enums.h:55
Raster property.
Minimum value.
Definition: Enums.h:41
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
void removeViewer(int viewerId)
Dettach a progress viewer.
static ProgressManager & getInstance()
It returns a reference to the singleton instance.
std::auto_ptr< Ui::RasterToVectorDialogForm > m_ui
User interface.
const std::string & getDataSourceId() const
Median.
Definition: Enums.h:52
static std::auto_ptr< DataSource > make(const std::string &dsType)
URI C++ Library.
Kurtosis.
Definition: Enums.h:50
Standard deviation.
Definition: Enums.h:47
Sum of values.
Definition: Enums.h:44
te::map::AbstractLayerPtr getLayer()
Get the generated layer.
void setInput(te::da::DataSourcePtr inRasterDsrc, std::string inRasterName, std::auto_ptr< te::da::DataSetType > inRasterDsType, te::da::DataSourcePtr inVectorDsrc, std::string inVectorName, std::auto_ptr< te::da::DataSetType > inVectorDsType)
Coefficient variation.
Definition: Enums.h:53
int addViewer(AbstractProgressViewer *apv)
Attach a progress viewer.
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
Mode.
Definition: Enums.h:54
A dialog for selecting a data source.
A class that represents a data source component.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
std::auto_ptr< LayerSchema > getSchema() const
It returns the layer schema.
std::vector< te::stat::StatisticalSummary > getSelectedStatistics()
Get the selected statistics based on selected QListWidgetItem.
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
Variance.
Definition: Enums.h:48
Maximum value.
Definition: Enums.h:42
boost::shared_ptr< DataSourceInfo > DataSourceInfoPtr
Amplitude.
Definition: Enums.h:51
RasterToVectorDialog(QWidget *parent=0, Qt::WindowFlags f=0)
const std::string & getName() const
It returns the property name.
Definition: Property.h:127