SkaterDialog.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/sa/qt/SkaterDialog.cpp
22 
23  \brief A dialog for Spatial 'K'luster Analysis by Tree Edge Removal.
24 */
25 
26 // TerraLib
27 #include "../../common/Logger.h"
28 #include "../../common/progress/ProgressManager.h"
29 #include "../../common/Translator.h"
30 #include "../../common/STLUtils.h"
31 #include "../../dataaccess/datasource/DataSource.h"
32 #include "../../dataaccess/utils/Utils.h"
33 #include "../../geometry/GeometryProperty.h"
34 #include "../../maptools/DataSetLayer.h"
35 #include "../../qt/widgets/datasource/selector/DataSourceSelectorDialog.h"
36 #include "../../qt/widgets/progress/ProgressViewerDialog.h"
37 #include "../core/GPMBuilder.h"
38 #include "../core/GPMConstructorAdjacencyStrategy.h"
39 #include "../core/GPMWeightsNoWeightsStrategy.h"
40 #include "../core/SkaterOperation.h"
41 #include "../core/SkaterParams.h"
42 #include "../core/SpatialWeightsExchanger.h"
43 #include "../core/Utils.h"
44 #include "../Exception.h"
45 #include "SkaterDialog.h"
46 #include "Utils.h"
47 #include "ui_SkaterDialogForm.h"
48 
49 // Qt
50 #include <QFileDialog>
51 #include <QFileInfo>
52 #include <QGridLayout>
53 #include <QMessageBox>
54 #include <QValidator>
55 
56 // STL
57 #include <memory>
58 
59 // Boost
60 #include <boost/filesystem.hpp>
61 
63 
64 te::sa::SkaterDialog::SkaterDialog(QWidget* parent, Qt::WindowFlags f)
65  : QDialog(parent, f),
66  m_ui(new Ui::SkaterDialogForm)
67 {
68 // add controls
69  m_ui->setupUi(this);
70 
71 // add double list widget
73  m_doubleListWidget->setLeftLabel("Layer Attributes");
74  m_doubleListWidget->setRightLabel("Selected Attributes");
75  QGridLayout* layout = new QGridLayout(m_ui->m_widget);
76  layout->addWidget(m_doubleListWidget);
77  layout->setContentsMargins(0, 0, 0, 0);
78 
79 // add icons
80  m_ui->m_imgLabel->setPixmap(QIcon::fromTheme("sa-skater-hint").pixmap(112,48));
81  m_ui->m_targetDatasourceToolButton->setIcon(QIcon::fromTheme("datasource"));
82 
83 // connectors
84  connect(m_ui->m_inputLayerComboBox, SIGNAL(activated(int)), this, SLOT(onInputLayerComboBoxActivated(int)));
85  connect(m_ui->m_okPushButton, SIGNAL(clicked()), this, SLOT(onOkPushButtonClicked()));
86  connect(m_ui->m_targetDatasourceToolButton, SIGNAL(pressed()), this, SLOT(onTargetDatasourceToolButtonPressed()));
87  connect(m_ui->m_targetFileToolButton, SIGNAL(pressed()), this, SLOT(onTargetFileToolButtonPressed()));
88  connect(m_ui->m_gpmToolButton, SIGNAL(clicked()), this, SLOT(onGPMToolButtonClicked()));
89 
90 // help info
91  m_ui->m_helpPushButton->setNameSpace("dpi.inpe.br.plugins");
92  m_ui->m_helpPushButton->setPageReference("plugins/sa/sa_skater.html");
93 }
94 
96 {
97 }
98 
99 void te::sa::SkaterDialog::setLayers(std::list<te::map::AbstractLayerPtr> layers)
100 {
101  std::list<te::map::AbstractLayerPtr>::iterator it = layers.begin();
102 
103  while(it != layers.end())
104  {
106 
107  if(l->isValid())
108  {
109  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
110  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(l.get());
111 
112  if(dsLayer && dsType->hasGeom())
113  m_ui->m_inputLayerComboBox->addItem(it->get()->getTitle().c_str(), QVariant::fromValue(l));
114  }
115 
116  ++it;
117  }
118 
119 // fill attributes combo
120  if(m_ui->m_inputLayerComboBox->count() > 0)
121  onInputLayerComboBoxActivated(0);
122 }
123 
125 {
126  return m_outputLayer;
127 }
128 
130 {
131  QVariant varLayer = m_ui->m_inputLayerComboBox->itemData(index, Qt::UserRole);
132 
134 
135  std::auto_ptr<te::da::DataSetType> dsType = l->getSchema();
136 
137  std::vector<te::dt::Property*> propVec = dsType->getProperties();
138 
139  m_ui->m_popComboBox->clear();
140  m_ui->m_attrLinkComboBox->clear();
141 
142  m_doubleListWidget->clearInputValues();
143  m_doubleListWidget->clearOutputValues();
144 
145  std::vector<std::string> vec;
146 
147  for(std::size_t t = 0; t < propVec.size(); ++t)
148  {
149  int dataType = propVec[t]->getType();
150 
151  if (dataType == te::dt::INT16_TYPE || dataType == te::dt::UINT16_TYPE ||
152  dataType == te::dt::INT32_TYPE || dataType == te::dt::UINT32_TYPE ||
153  dataType == te::dt::INT64_TYPE || dataType == te::dt::UINT64_TYPE ||
154  dataType == te::dt::FLOAT_TYPE || dataType == te::dt::DOUBLE_TYPE)
155  {
156  m_ui->m_popComboBox->addItem(propVec[t]->getName().c_str(), dataType);
157 
158  vec.push_back(propVec[t]->getName());
159  }
160 
161  m_ui->m_attrLinkComboBox->addItem(propVec[t]->getName().c_str(), dataType);
162  }
163 
164  std::sort(vec.begin(), vec.end());
165 
166  m_doubleListWidget->setInputValues(vec);
167 }
168 
170 {
171  // check input parameters
172  if(m_ui->m_repositoryLineEdit->text().isEmpty())
173  {
174  QMessageBox::information(this, tr("Warning"), tr("Define a repository for the result."));
175  return;
176  }
177 
178  if(m_ui->m_newLayerNameLineEdit->text().isEmpty())
179  {
180  QMessageBox::information(this, tr("Warning"), tr("Define a name for the resulting layer."));
181  return;
182  }
183 
184  if(!m_ui->m_clustersCheckBox->isChecked() && !m_ui->m_popCheckBox->isChecked())
185  {
186  QMessageBox::information(this, tr("Warning"), tr("Select the aggregation type."));
187  return;
188  }
189 
190  if(m_ui->m_clustersCheckBox->isChecked())
191  {
192  if(m_ui->m_nClustersLineEdit->text().isEmpty())
193  {
194  QMessageBox::information(this, tr("Warning"), tr("Number of clusters not defined."));
195  return;
196  }
197  }
198 
199  if(m_ui->m_popCheckBox->isChecked())
200  {
201  if(m_ui->m_minPopLineEdit->text().isEmpty())
202  {
203  QMessageBox::information(this, tr("Warning"), tr("Minimum population not defined."));
204  return;
205  }
206  }
207 
208  std::vector<std::string> attrs = m_doubleListWidget->getOutputValues();
209 
210  if(attrs.empty())
211  {
212  QMessageBox::information(this, tr("Warning"), tr("Select the attributes."));
213  return;
214  }
215 
216  //get GPM
217  std::auto_ptr<te::sa::GeneralizedProximityMatrix> gpm;
218 
219  try
220  {
221  gpm = loadGPM();
222  }
223  catch(...)
224  {
225  QMessageBox::warning(this, tr("Warning"), tr("Internal error. GPM not loaded."));
226  return;
227  }
228 
229  if(!gpm.get())
230  return;
231 
232 //get selected layer
233  QVariant varLayer = m_ui->m_inputLayerComboBox->itemData(m_ui->m_inputLayerComboBox->currentIndex(), Qt::UserRole);
235 
236  std::auto_ptr<te::da::DataSetType> dataSetType = l->getSchema();
237  std::auto_ptr<te::da::DataSet> dataSet = l->getData();
238 
239 //create datasource to save the output information
240  std::string dataSetName = m_ui->m_newLayerNameLineEdit->text().toStdString();
241 
242  std::size_t idx = dataSetName.find(".");
243  if (idx != std::string::npos)
244  dataSetName=dataSetName.substr(0,idx);
245 
246  te::da::DataSourcePtr outputDataSource;
247 
248  if(m_toFile)
249  {
250  outputDataSource = te::sa::CreateOGRDataSource(m_ui->m_repositoryLineEdit->text().toStdString());
251  }
252  else
253  {
254  outputDataSource = te::da::GetDataSource(m_outputDatasource->getId());
255  }
256 
257  //run skater
259 
260  inParams->m_ds = dataSet;
261  inParams->m_dsType = dataSetType;
262  inParams->m_gpmAttrLink = gpm->getAttributeName();
263  inParams->m_gpm = gpm;
264 
265 
266  if(m_ui->m_clustersCheckBox->isChecked() && m_ui->m_popCheckBox->isChecked())
267  {
268  inParams->m_aggregType = te::sa::Both;
269  inParams->m_nClusters = (std::size_t)m_ui->m_nClustersLineEdit->text().toInt();
270  inParams->m_minPop = (std::size_t)m_ui->m_minPopLineEdit->text().toInt();
271  inParams->m_attrPop = m_ui->m_popComboBox->currentText().toStdString();
272  }
273  else if(m_ui->m_clustersCheckBox->isChecked())
274  {
275  inParams->m_aggregType = te::sa::Clusters;
276  inParams->m_nClusters = (std::size_t)m_ui->m_nClustersLineEdit->text().toInt();
277  }
278  else if(m_ui->m_popCheckBox->isChecked())
279  {
280  inParams->m_aggregType = te::sa::Population;
281  inParams->m_minPop = (std::size_t)m_ui->m_minPopLineEdit->text().toInt();
282  inParams->m_attrPop = m_ui->m_popComboBox->currentText().toStdString();
283  }
284 
285  inParams->m_attrs = attrs;
286 
288 
289  outParams->m_dataSource = outputDataSource;
290  outParams->m_outputDataSetName = dataSetName;
291 
292  int nClasses;
293 
294  //progress
297 
298  QApplication::setOverrideCursor(Qt::WaitCursor);
299 
300  try
301  {
303 
304  op.setParameters(inParams, outParams);
305 
306  op.execute();
307 
308  nClasses = op.getNumberOfClasses();
309  }
310  catch(const std::exception& e)
311  {
312  QMessageBox::warning(this, tr("Warning"), e.what());
313 
314  QApplication::restoreOverrideCursor();
315 
317 
318  return;
319  }
320  catch(...)
321  {
322  QMessageBox::warning(this, tr("Warning"), tr("Internal Error. Skater not calculated."));
323 
324  QApplication::restoreOverrideCursor();
325 
327 
328  return;
329  }
330 
331  QApplication::restoreOverrideCursor();
332 
334 
335  //create layer
336  m_outputLayer = te::sa::CreateLayer(outputDataSource, dataSetName);
337 
338  //create legend
339  te::sa::CreateSkaterGrouping(m_outputLayer, nClasses);
340 
341  accept();
342 }
343 
345 {
346  m_ui->m_newLayerNameLineEdit->clear();
347  m_ui->m_newLayerNameLineEdit->setEnabled(true);
348 
350  dlg.exec();
351 
352  std::list<te::da::DataSourceInfoPtr> dsPtrList = dlg.getSelecteds();
353 
354  if(dsPtrList.empty())
355  return;
356 
357  std::list<te::da::DataSourceInfoPtr>::iterator it = dsPtrList.begin();
358 
359  m_ui->m_repositoryLineEdit->setText(QString(it->get()->getTitle().c_str()));
360 
361  m_outputDatasource = *it;
362 
363  m_toFile = false;
364 }
365 
367 {
368  m_ui->m_newLayerNameLineEdit->clear();
369  m_ui->m_repositoryLineEdit->clear();
370 
371  QString fileName = QFileDialog::getSaveFileName(this, tr("Save as..."), QString(), tr("Shapefile (*.shp *.SHP);;"),0, QFileDialog::DontConfirmOverwrite);
372 
373  if (fileName.isEmpty())
374  return;
375 
376  boost::filesystem::path outfile(fileName.toStdString());
377 
378  m_ui->m_repositoryLineEdit->setText(outfile.string().c_str());
379 
380  m_ui->m_newLayerNameLineEdit->setText(outfile.leaf().string().c_str());
381 
382  m_ui->m_newLayerNameLineEdit->setEnabled(false);
383 
384  m_toFile = true;
385 }
386 
388 {
389  QString fileName = QFileDialog::getOpenFileName(this, tr("Open Generalized Proximity Matrix File"), "", tr("GAL Files (*.gal *.GAL);; GWT Files (*.gwt *.GWT)"));
390 
391  if(fileName.isEmpty())
392  return;
393 
394  //get selected layer
395  QVariant varLayer = m_ui->m_inputLayerComboBox->itemData(m_ui->m_inputLayerComboBox->currentIndex(), Qt::UserRole);
397  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(l.get());
398 
399  //check if the selected gpm is valid for selected layer
400  std::string path = fileName.toStdString();
401  std::string dataSetName = "";
402  std::string attrName = "";
403 
405 
406  if(dsLayer->getDataSetName() != dataSetName)
407  {
408  QMessageBox::warning(this, tr("Warning"), tr("Invalid GPM file for selected layer."));
409  return;
410  }
411 
412  if(m_ui->m_attrLinkComboBox->currentText().toStdString() != attrName)
413  {
414  QMessageBox::warning(this, tr("Warning"), tr("Invalid GPM file for selected Attr Link."));
415  return;
416  }
417 
418  m_ui->m_gpmLineEdit->setText(fileName);
419 }
420 
421 std::auto_ptr<te::sa::GeneralizedProximityMatrix> te::sa::SkaterDialog::loadGPM()
422 {
423  std::auto_ptr<te::sa::GeneralizedProximityMatrix> gpm;
424 
425  //get selected layer
426  QVariant varLayer = m_ui->m_inputLayerComboBox->itemData(m_ui->m_inputLayerComboBox->currentIndex(), Qt::UserRole);
428 
429  if(!l.get())
430  {
431  QMessageBox::warning(this, tr("Warning"), tr("Invalid selected layer."));
432  return gpm;
433  }
434 
435  te::map::DataSetLayer* dsLayer = dynamic_cast<te::map::DataSetLayer*>(l.get());
436 
437  //get gpm necessary parameters
439 
440  std::string dataSetName = dsLayer->getDataSetName();
441 
442  if(!m_ui->m_gpmGroupBox->isChecked())
443  {
444  //create gpm
445  if(QMessageBox::question(this, tr("Spatial Analysis"), tr("GPM not selected. Create default GPM?"), QMessageBox::No, QMessageBox::Yes) == QMessageBox::No)
446  return gpm;
447 
448  //get attrlink
449  std::auto_ptr<te::da::DataSetType> dsType = dsLayer->getSchema();
450 
451  if(!dsType->getPrimaryKey() || dsType->getPrimaryKey()->getProperties().empty())
452  {
453  QMessageBox::warning(this, tr("Warning"), tr("Invalid Data Set Primary Key."));
454  return gpm;
455  }
456 
457  std::string attrLink = dsType->getPrimaryKey()->getProperties()[0]->getName();
458 
459  //create default gpm
462 
463  te::sa::GPMBuilder builder(constructor, weights);
464 
465  builder.setGPMInfo(ds, dataSetName, attrLink);
466 
467  gpm = builder.build();
468  }
469  else
470  {
471  if(m_ui->m_gpmLineEdit->text().isEmpty())
472  {
473  QMessageBox::warning(this, tr("Warning"), tr("GPM File not selected."));
474  return gpm;
475  }
476 
477  //load gpm
478  QFileInfo file(m_ui->m_gpmLineEdit->text());
479 
480  std::string extension = file.suffix().toStdString();
481 
483 
484  if(extension == "gal" || extension == "GAL")
485  {
486  gpm.reset(swe.importFromGAL(m_ui->m_gpmLineEdit->text().toStdString(), ds.get()));
487  }
488  else if(extension == "gwt" || extension == "GWT")
489  {
490  gpm.reset(swe.importFromGWT(m_ui->m_gpmLineEdit->text().toStdString(), ds.get()));
491  }
492  }
493 
494  return gpm;
495 }
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 execute()
Function to execute the skater operation.
This class defines a an adjacency strategy class for a GPM constructor.
std::size_t m_nClusters
Number of clusters (Aggregation type = Clusters)
Definition: SkaterParams.h:83
void setRightLabel(std::string value)
std::auto_ptr< GeneralizedProximityMatrix > build()
Definition: GPMBuilder.cpp:78
Utility functions for the data access module.
const std::string & getDataSetName() const
SkaterDialog(QWidget *parent=0, Qt::WindowFlags f=0)
te::map::AbstractLayerPtr getOutputLayer()
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
TESAEXPORT te::da::DataSourcePtr CreateOGRDataSource(std::string repository)
Definition: Utils.cpp:63
std::vector< std::string > m_attrs
List of attributes selected to calculate the weight of the edge.
Definition: SkaterParams.h:87
bool setGPMInfo(te::da::DataSourcePtr ds, const std::string &dataSetName, const std::string &attributeName)
Function used to create a empty gpm (using a MEMORY DIRECT graph)
Definition: GPMBuilder.cpp:49
void setLeftLabel(std::string value)
This class defines a class to calculates a weight for a GPM using No Weights strategy.
Class that represents the skater input parameters.
Definition: SkaterParams.h:56
void setLayers(std::list< te::map::AbstractLayerPtr > layers)
Set the layer that can be used.
te::qt::widgets::DoubleListWidget * m_doubleListWidget
Widget used to select attributes.
Definition: SkaterDialog.h:88
te::sa::GeneralizedProximityMatrix * importFromGAL(std::string pathFileName, te::da::DataSource *ds=0)
Function used to import a gpm from a Spatial Weights File GAL Format.
te::sa::GeneralizedProximityMatrix * importFromGWT(std::string pathFileName, te::da::DataSource *ds=0)
Function used to import a gpm from a Spatial Weights File GWT Format.
Class that represents the skater output parameters.
Definition: SkaterParams.h:98
Class used to execute the skater operations.
void onTargetDatasourceToolButtonPressed()
std::size_t m_minPop
Number of minimum population (Aggregation type = Population)
Definition: SkaterParams.h:84
A dialog for Spatial 'K'luster Analysis by Tree Edge Removal.
void removeViewer(int viewerId)
Dettach a progress viewer.
static ProgressManager & getInstance()
It returns a reference to the singleton instance.
const std::string & getDataSourceId() const
void setParameters(te::sa::SkaterInputParams *inParams, te::sa::SkaterOutputParams *outParams)
std::string m_gpmAttrLink
Attribute from dataset that was used to generate the gpm.
Definition: SkaterParams.h:80
te::sa::SkaterAggregationType m_aggregType
Aggregation type.
Definition: SkaterParams.h:82
std::auto_ptr< te::sa::GeneralizedProximityMatrix > m_gpm
Attribute with graph information.
Definition: SkaterParams.h:79
static void getSpatialWeightsFileInfo(std::string pathFileName, std::string &dataSetName, std::string &attrName)
Function used to get information of how a Spatial Weights was generated.
std::string m_outputDataSetName
Attribute that defines the output dataset name.
Definition: SkaterParams.h:117
Q_DECLARE_METATYPE(te::map::AbstractLayerPtr)
std::auto_ptr< te::da::DataSet > m_ds
Attribute with data set.
Definition: SkaterParams.h:78
std::string m_attrPop
Attribute used to represent the population (Aggregation type = Population)
Definition: SkaterParams.h:85
This class defines a an Abstract class for a GPM constructor.
int addViewer(AbstractProgressViewer *apv)
Attach a progress viewer.
This class defines a an Abstract class to calculates a weight for a GPM.
te::da::DataSourcePtr m_dataSource
Pointer to the output data source.
Definition: SkaterParams.h:115
const std::list< te::da::DataSourceInfoPtr > & getSelecteds() const
TESAEXPORT te::map::AbstractLayerPtr CreateLayer(te::da::DataSourcePtr ds, std::string dataSetName)
Definition: Utils.cpp:122
A dialog for selecting a data source.
std::auto_ptr< te::da::DataSetType > m_dsType
Attribute used to access the data set metadata.
Definition: SkaterParams.h:77
std::auto_ptr< Ui::SkaterDialogForm > m_ui
Definition: SkaterDialog.h:86
This class defines functions used to load and save gpm's using GAL and GWT formats, both formats use a ' ' as separator.
A layer with reference to a dataset.
Definition: DataSetLayer.h:47
std::auto_ptr< LayerSchema > getSchema() const
It returns the layer schema.
This class defines the GPM Builder class.
Definition: GPMBuilder.h:54
TESAEXPORT void CreateSkaterGrouping(te::map::AbstractLayerPtr layer, int nClasses)
Definition: Utils.cpp:408
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
std::auto_ptr< te::sa::GeneralizedProximityMatrix > loadGPM()
void onInputLayerComboBoxActivated(int index)
void onTargetFileToolButtonPressed()