All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
MixtureModelDialog.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/rp/widgets/se/MixtureModelDialog.cpp
22 
23  \brief A dialog used to execute mixture model decomposition.
24 */
25 
26 // TerraLib
27 #include "../canvas/Canvas.h"
28 #include "../canvas/MapDisplay.h"
29 #include "../../../common/StringUtils.h"
30 #include "../../../geometry/Coord2D.h"
31 #include "../../../geometry/Envelope.h"
32 #include "../../../geometry/Point.h"
33 #include "../../../maptools/Utils.h"
34 #include "../../../raster/Grid.h"
35 #include "../../../rp/MixtureModel.h"
36 #include "../../../rp/MixtureModelLinearStrategy.h"
37 #include "../../../rp/MixtureModelPCAStrategy.h"
38 #include "../../../rp/Functions.h"
39 #include "../../widgets/tools/CoordTracking.h"
40 #include "../../widgets/tools/Pan.h"
41 #include "../../widgets/tools/ZoomWheel.h"
42 
43 // GUI
44 #include "MixtureModelDialog.h"
45 #include <ui_MixtureModelForm.h>
46 
47 // QT
48 #include <QCheckBox>
49 #include <QComboBox>
50 #include <QGridLayout>
51 #include <QImage>
52 #include <QKeyEvent>
53 #include <QLineEdit>
54 #include <QMessageBox>
55 
56 // defines
57 #define PATTERN_W 11
58 
60  : QObject(parent), m_mDisplay(parent)
61 {
62 }
63 
65 {
66 }
67 
69 {
70  if(event->type() == QEvent::Enter)
71  m_mDisplay->grabKeyboard();
72  else if(event->type() == QEvent::Leave)
73  m_mDisplay->releaseKeyboard();
74  else if(event->type() == QEvent::KeyPress)
75  {
76  if(m_mDisplay->underMouse())
77  emit(keyPressedOverMapDisplay(((QKeyEvent*)event)->key()));
78  }
79 
80  return false;
81 }
82 
83 te::qt::widgets::MixtureModelDialog::MixtureModelDialog(const te::map::DataSetLayerPtr& inputLayerPtr, const std::string& outpuRasterDSType,
84  const std::map<std::string, std::string>& outpuRasterInfo, QWidget* parent, Qt::WindowFlags f)
85  : QDialog(parent, f),
86  m_inputRasterPtr(te::map::GetRaster(inputLayerPtr.get())),
87  m_outpuRasterDSType(outpuRasterDSType),
88  m_outpuRasterInfo(outpuRasterInfo),
89  m_maxComponentsInserted(0)
90 {
91  m_uiPtr = new Ui::MixtureModelForm;
92 
93  m_uiPtr->setupUi(this);
94 
95 // insert image in frame
96  QGridLayout* rasterGridLayout = new QGridLayout(m_uiPtr->m_rasterFrame);
97  m_mapDisplay = new te::qt::widgets::MapDisplay(m_uiPtr->m_rasterFrame->size(), m_uiPtr->m_rasterFrame);
98  m_mapDisplay->setMouseTracking(true);
99  rasterGridLayout->addWidget(m_mapDisplay);
101  std::list<te::map::AbstractLayerPtr> layerList;
102  layerList.push_back(inputLayerPtr);
103  m_mapDisplay->setLayerList(layerList);
105  te::gm::Envelope displayExtent(*(m_inputRasterPtr->getExtent()));
106  m_mapDisplay->setExtent(displayExtent);
107 
108 // image frame events
109  m_panClickEvent = new te::qt::widgets::Pan(m_mapDisplay, Qt::OpenHandCursor, Qt::ClosedHandCursor);
113 
114  m_mapDisplay->installEventFilter(m_coordTracking);
115  m_mapDisplay->installEventFilter(m_keyboardPressTracking);
116  m_mapDisplay->installEventFilter(m_panClickEvent);
117  m_mapDisplay->installEventFilter(m_zoomScroolEvent);
118 
119 // signals & slots
120  connect(m_uiPtr->m_okPushButton, SIGNAL(clicked()), SLOT(on_okPushButton_clicked()));
121  connect(m_coordTracking, SIGNAL(coordTracked(QPointF&)), this, SLOT(on_coordTracked_changed(QPointF&)));
122  connect(m_keyboardPressTracking, SIGNAL(keyPressedOverMapDisplay(int)), this, SLOT(on_keyPressedOverMapDisplay(int)));
123  connect(m_mapDisplay, SIGNAL(extentChanged()), this, SLOT(on_mapDisplay_extentChanged()));
124 
125 // define sensor information
126  QStringList sensorsDescriptions;
127  std::vector<std::string> bandNames = te::rp::GetBandNames();
128  for(unsigned int i = 0; i < bandNames.size(); i++)
129  sensorsDescriptions.append(bandNames[i].c_str());
130 
131 // initializing the list of bands
132  QGridLayout *bandsListLayout = new QGridLayout();
133  for(unsigned b = 0 ; b < m_inputRasterPtr->getNumberOfBands(); b++)
134  {
135  std::string bname = "Band " + te::common::Convert2String(b);
136  QCheckBox* bandCheckBox = new QCheckBox(tr(bname.c_str()));
137 
138  QComboBox* sensorDescriptionComboBox = new QComboBox();
139  sensorDescriptionComboBox->addItems(sensorsDescriptions);
140 
141  bandsListLayout->addWidget(bandCheckBox, b, 0);
142  bandsListLayout->addWidget(sensorDescriptionComboBox, b, 1);
143  }
144  m_uiPtr->m_bandsListGroupBox->setLayout(bandsListLayout);
145 
146 // initializing the list of components
147  QGridLayout *componentsListLayout = new QGridLayout();
148  m_uiPtr->m_componentsListGroupBox->setLayout(componentsListLayout);
149 
150 // creating "x" pattern to plot on map
152 
153  for(unsigned int line = 0; line < PATTERN_W; line++)
154  {
156 
157  for(unsigned int col = 0; col < PATTERN_W; col++)
158  {
159  if((line == col) || (line == (PATTERN_W - col - 1)))
160  m_selectedPointPattern[line][col].setColor(255, 0, 0, TE_OPAQUE);
161  else
162  m_selectedPointPattern[line][col].setColor(0, 0, 0, TE_TRANSPARENT);
163  }
164  }
165 }
166 
168 {
169 // delete "x" patterns
170  for(unsigned int line = 0; line < PATTERN_W; line++)
171  delete[] m_selectedPointPattern[line];
172 
173  delete[] m_selectedPointPattern;
174 
175 // delete interface
176  delete m_uiPtr;
177 }
178 
179 bool te::qt::widgets::MixtureModelDialog::getOutputRaster(boost::shared_ptr<te::rst::Raster>& outputRasterPtr)
180 {
181  if(m_outputRasterPtr.get())
182  {
183  outputRasterPtr = m_outputRasterPtr;
184 
185  return true;
186  }
187 
188  return false;
189 }
190 
192 {
193  m_outputRasterPtr.reset();
194 
195  if (!m_inputRasterPtr)
196  {
197  QMessageBox::critical(this, "", tr("Invalid input raster"));
198 
199  return;
200  }
201 
202 // define classification parameters
203 
204 // input parameters
205  te::rp::MixtureModel::InputParameters algoInputParameters;
206  algoInputParameters.m_strategyName = (m_uiPtr->m_mmTypeComboBox->currentText() == "Linear" ? "linear" : "pca");
207  algoInputParameters.m_inputRasterPtr = m_inputRasterPtr;
208 
209  unsigned selectedBands = 0;
210  std::vector<bool> selectedBandsVector;
211  for (int i = 0; i < (m_uiPtr->m_bandsListGroupBox->layout()->count() - 1); i += 2)
212  {
213  QCheckBox* bandCheckBox = (QCheckBox*) m_uiPtr->m_bandsListGroupBox->layout()->itemAt(i)->widget();
214 
215  if (bandCheckBox->isChecked())
216  {
217  selectedBandsVector.push_back(true);
218  selectedBands++;
219 
220 // insert band number
221  algoInputParameters.m_inputRasterBands.push_back(i / 2);
222 
223 // insert sensor description of band
224  QComboBox *sensorComboBox = (QComboBox*) m_uiPtr->m_bandsListGroupBox->layout()->itemAt(i + 1)->widget();
225 #if (QT_VERSION >= 0x050000)
226  algoInputParameters.m_inputSensorBands.push_back(std::string(sensorComboBox->currentText().toLatin1()));
227 #else
228  algoInputParameters.m_inputSensorBands.push_back(std::string(sensorComboBox->currentText().toAscii()));
229 #endif
230  }
231  else
232  selectedBandsVector.push_back(false);
233  }
234 
235 // insert mixture components
236  std::map<std::string, std::vector<double> >::const_iterator cit = m_components.begin();
237  std::vector<double> components;
238  while (cit != m_components.end())
239  {
240  components.clear();
241 
242  for (unsigned int i = 0; i < selectedBandsVector.size(); i++)
243  if (selectedBandsVector[i])
244  components.push_back(cit->second[i]);
245 
246  algoInputParameters.m_components[cit->first] = components;
247 
248  ++cit;
249  }
250 
251 // link specific parameters with chosen implementation
252  if (m_uiPtr->m_mmTypeComboBox->currentText() == "Linear")
253  {
255  algoInputParameters.setMixtureModelStrategyParams(specificParameters);
256  }
257  else // "pca"
258  {
260  algoInputParameters.setMixtureModelStrategyParams(specificParameters);
261  }
262 
263 // output parameters
264  te::rp::MixtureModel::OutputParameters algoOutputParameters;
265  algoOutputParameters.m_rInfo = m_outpuRasterInfo;
266  algoOutputParameters.m_rType = m_outpuRasterDSType;
267  algoOutputParameters.m_normalizeOutput = m_uiPtr->m_normalizeOutputCheckBox->isChecked();
268  algoOutputParameters.m_createErrorRaster = m_uiPtr->m_createErrorRasterCheckBox->isChecked();
269 
270 // execute the algorithm
271  te::rp::MixtureModel MixtureModelinstance;
272 
273  if(!MixtureModelinstance.initialize(algoInputParameters))
274  {
275  QMessageBox::critical(this, "", tr("MixtureModel initialization error"));
276 
277  return;
278  }
279 
280  if(!MixtureModelinstance.execute(algoOutputParameters))
281  {
282  QMessageBox::critical(this, "", tr("MixtureModel execution error"));
283 
284  return;
285  }
286 
287  QMessageBox::information(this, "", tr("Mixture model decomposition ended sucessfully"));
288 }
289 
291 {
292 // find the selected pixel location for component
293  te::gm::Coord2D pixelLocation = m_inputRasterPtr->getGrid()->geoToGrid((double) coordinate.rx(), (double)coordinate.ry());
294  currentColumn = pixelLocation.x;
295  currentRow = pixelLocation.y;
296 }
297 
299 {
300 // check range
301  if (currentColumn < 0 || currentColumn >= (int) m_inputRasterPtr->getNumberOfColumns())
302  return;
303  if (currentRow < 0 || currentRow >= (int) m_inputRasterPtr->getNumberOfRows())
304  return;
305 
306  std::vector<double> componentsVector;
307 
308  QString* className = new QString("Change name " + QString::number(m_maxComponentsInserted++));
309 
310  double value;
311  for(unsigned b = 0 ; b < m_inputRasterPtr->getNumberOfBands(); b++)
312  {
313  m_inputRasterPtr->getValue(currentColumn, currentRow, value, b);
314 
315  componentsVector.push_back(value);
316  }
317 
318  m_components[className->toStdString()] = componentsVector;
319 
320  te::gm::Coord2D coordinate(currentColumn, currentRow);
321  m_coordinates[className->toStdString()] = coordinate;
322 
323  updateComponentsGrid();
324 }
325 
327 {
328  QPushButton* sender = (QPushButton*) QObject::sender();
329 
330 // retrieve component class name
331  std::string className = sender->statusTip().toStdString();
332 
333  m_components.erase(className);
334  m_coordinates.erase(className);
335 
336  updateComponentsGrid();
337 }
338 
340 {
341 // get canvas to draw the "x" on selected points
342  const te::gm::Envelope& mapDisplayExtent = m_mapDisplay->getExtent();
343 
344  m_mapDisplay->getDraftPixmap()->fill(QColor(0, 0, 0, 0));
345 
346  te::qt::widgets::Canvas canvasInstance(m_mapDisplay->getDraftPixmap());
347  canvasInstance.setWindow(mapDisplayExtent.m_llx, mapDisplayExtent.m_lly,
348  mapDisplayExtent.m_urx, mapDisplayExtent.m_ury);
349 
350  canvasInstance.setPointPattern(m_selectedPointPattern, PATTERN_W, PATTERN_W);
351 
352  te::gm::Point auxPoint;
353  te::gm::Coord2D auxCoord2D;
354 
355  std::map<std::string, te::gm::Coord2D>::const_iterator cpit = m_coordinates.begin();
356  while (cpit != m_coordinates.end())
357  {
358 // draw "x"
359  m_inputRasterPtr->getGrid()->gridToGeo(cpit->second.x, cpit->second.y,
360  auxCoord2D.x, auxCoord2D.y);
361 
362  auxPoint.setX(auxCoord2D.x);
363  auxPoint.setY(auxCoord2D.y);
364 
365  canvasInstance.draw(&auxPoint);
366 
367  ++cpit;
368  }
369 }
370 
372 {
373  QGridLayout* componentsListLayout = (QGridLayout*) m_uiPtr->m_componentsListGroupBox->layout();
374 
375 // update class names
376  for (int i = 0; i < (componentsListLayout->count() / 5); i++)
377  {
378  std::string className = ((QLineEdit*) componentsListLayout->itemAtPosition(i, 1)->widget())->text().toStdString();
379  std::string originalClassName = ((QLineEdit*) componentsListLayout->itemAtPosition(i, 1)->widget())->toolTip().toStdString();
380 
381 // check if className is already in m_components
382  if (className != originalClassName)
383  {
384  m_components[className] = m_components[originalClassName];
385  m_coordinates[className] = m_coordinates[originalClassName];
386 
387  m_components.erase(originalClassName);
388  m_coordinates.erase(originalClassName);
389  }
390 
391  }
392 
393 // clear layout
394  QLayoutItem* child;
395  while ((child = componentsListLayout->takeAt(0)) != 0)
396  {
397  delete child->widget();
398  delete child;
399  }
400 
401 // clear map display to redraw "x" points
402  te::gm::Envelope auxEnvelope(m_mapDisplay->getExtent());
403  m_mapDisplay->setExtent(auxEnvelope);
404 
405 // add lines
406  std::map<std::string, std::vector<double> >::const_iterator cit = m_components.begin();
407  unsigned int totalComponents = 0;
408  while (cit != m_components.end())
409  {
410 // define remove button and line edits
411  QPushButton* removeButton = new QPushButton("x");
412 
413  removeButton->setStatusTip(cit->first.c_str());
414  removeButton->setMaximumSize(20, 20);
415  connect(removeButton, SIGNAL(clicked()), SLOT(on_removeButton_clicked()));
416 
417  componentsListLayout->addWidget(removeButton, totalComponents, 0);
418 
419  QLineEdit* className = new QLineEdit(cit->first.c_str());
420  className->setToolTip(cit->first.c_str());
421  componentsListLayout->addWidget(className, totalComponents, 1);
422 
423  std::vector<double> components = cit->second;
424  for (unsigned int i = 0; i < components.size(); i++)
425  {
426  QLineEdit* currentPixel = new QLineEdit(QString::number(components[i]));
427 
428  currentPixel->setMaximumSize(50, currentPixel->maximumHeight());
429 
430  componentsListLayout->addWidget(currentPixel, totalComponents, i + 2);
431  }
432 
433  totalComponents++;
434  ++cit;
435  }
436 }
te::gm::Envelope * getExtent()
Returns the geographic extension of the raster data.
Definition: Raster.cpp:104
double y
y-coordinate.
Definition: Coord2D.h:114
void setColor(const std::string &hexColor)
It sets the color using a two hexadecimal RGB-encoded color.
Definition: RGBAColor.h:329
Raster decomposition using mixture model.
Definition: MixtureModel.h:59
std::string m_rType
Output raster data source type (as described in te::raster::RasterFactory ).
Definition: MixtureModel.h:150
double x
x-coordinate.
Definition: Coord2D.h:113
std::vector< std::string > GetBandNames()
Returns a vector os with band's names.
Definition: Functions.cpp:556
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
te::color::RGBAColor ** m_selectedPointPattern
The display draw pattern used for selected points.
std::vector< std::string > m_inputSensorBands
The names of the sensor/bands.
Definition: MixtureModel.h:110
A widget to control the display of a set of layers.
Definition: MapDisplay.h:66
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
std::string m_strategyName
The mixture model strategy name see each te::rp::MixtureModelStrategyFactory inherited classes docume...
Definition: MixtureModel.h:112
#define PATTERN_W
MixtureModelDialogMDEventFilter(te::qt::widgets::MapDisplay *parent)
const te::rst::Raster * m_inputRasterPtr
Input raster pointer.
std::map< std::string, std::string > m_rInfo
The necessary information to create the raster (as described in te::raster::RasterFactory).
Definition: MixtureModel.h:151
MixtureModel input parameters.
Definition: MixtureModel.h:69
virtual void setLayerList(const std::list< te::map::AbstractLayerPtr > &layers)
It sets the layer list to be showed in the Map Display.
Definition: MapDisplay.cpp:42
void on_coordTracked_changed(QPointF &coordinate)
void setWindow(const double &llx, const double &lly, const double &urx, const double &ury)
It sets the world (or window) coordinates area (supposing a cartesian reference system).
Definition: Canvas.cpp:147
This class implements a concrete tool to geographic pan operation.
Definition: Pan.h:49
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
virtual void setResizePolicy(const ResizePolicy &policy)
Sets the resize policy to this map display.
Definition: MapDisplay.cpp:227
bool m_normalizeOutput
A flag to indicate that output raster will be normalized, by default [0, 255].
Definition: MixtureModel.h:153
A point with x and y coordinate values.
Definition: Point.h:50
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
te::qt::widgets::Pan * m_panClickEvent
Pan click event for map display.
Ui::MixtureModelForm * m_uiPtr
User interface.
A dialog used to execute mixture model decomposition.
#define TE_OPAQUE
For an RGBA color this is the value of the alpha-channel for totally opaque.
Definition: Config.h:39
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
te::qt::widgets::ZoomWheel * m_zoomScroolEvent
Zoom event using mouse scrool for map display.
This class implements a concrete tool to geographic coordinate tracking on mouse move operation...
Definition: CoordTracking.h:52
bool eventFilter(QObject *watched, QEvent *event)
TEMAPEXPORT te::rst::Raster * GetRaster(DataSetLayer *layer)
It gets the raster referenced by the given data set layer.
Definition: Utils.cpp:192
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
A canvas built on top of Qt.
Definition: Canvas.h:54
std::map< std::string, std::vector< double > > m_components
A set of endmembers and its radiances.
Definition: MixtureModel.h:111
CoordTracking * m_coordTracking
Coordinate tracking for map display.
MixtureModel output parameters.
Definition: MixtureModel.h:123
int getSRID() const
Returns the raster spatial reference system identifier.
Definition: Raster.cpp:203
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:143
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
bool execute(AlgorithmOutputParameters &outputParams)
Executes the algorithm using the supplied parameters.
#define TE_TRANSPARENT
For an RGBA color this is the value of the alpha-channel for totally transparent. ...
Definition: Config.h:46
bool getOutputRaster(boost::shared_ptr< te::rst::Raster > &outputRasterPtr)
Returns the output result raster.
This class implements a concrete tool to geographic zoom operation using the mouse wheel...
Definition: ZoomWheel.h:49
boost::intrusive_ptr< DataSetLayer > DataSetLayerPtr
Definition: DataSetLayer.h:171
A helper class for 32-bit RGBA (Red-Green-Blue-Alpha channel) color.
Definition: RGBAColor.h:57
void setMixtureModelStrategyParams(const StrategyParameters &p)
Set specific mixture model strategy parameters.
te::rst::Raster const * m_inputRasterPtr
Input raster.
Definition: MixtureModel.h:108
te::qt::widgets::MapDisplay * m_mapDisplay
The map display to show the input raster.
MixtureModelDialog(const te::map::DataSetLayerPtr &inputLayerPtr, const std::string &outpuRasterDSType, const std::map< std::string, std::string > &outpuRasterInfo, QWidget *parent=0, Qt::WindowFlags f=0)
Constructs a basic dialog which is a child of parent, with widget flags set to f. ...
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:157
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:51
bool m_createErrorRaster
A flag to indicate that output raster will include the error bands.
Definition: MixtureModel.h:154
bool initialize(const AlgorithmInputParameters &inputParams)
Initialize the algorithm instance making it ready for execution.
virtual void setSRID(const int &srid, bool doRefresh=true)
It sets a new Spatial Reference System to be used by the Map Display.
Definition: MapDisplay.cpp:211
virtual void setExtent(te::gm::Envelope &e, bool doRefresh=true)
It sets the world visible area and refreshes the contents in the map display.
Definition: MapDisplay.cpp:150
MixtureModelDialogMDEventFilter * m_keyboardPressTracking
The event filter to detect when user press space bar.
std::vector< unsigned int > m_inputRasterBands
Bands to be processed from the input raster.
Definition: MixtureModel.h:109
A event filter to handle map display events.