GeoDesk  0.1.3
 All Classes Namespaces Files Functions Typedefs Pages
mainboard.hpp
Go to the documentation of this file.
1 #ifndef MAINBOARD_HPP
2 #define MAINBOARD_HPP
3 
4 /**
5  * \file mainboard.hpp
6  * \brief Definitions to create program main board.
7  * \author Le Bars, Yoann
8  * \author Vallaeys, Valentin
9  * \version 1.0
10  * \date 2013/06/19
11  * \date 2013/06/20
12  * \date 2013/16/21
13  * \date 2013/06/24
14  * \date 2013/06/25
15  * \date 2013/06/26
16  * \date 2013/06/27
17  * \date 2013/06/28
18  * \date 2013/07/01
19  * \date 2013/07/02
20  * \date 2013/07/03
21  * \date 2013/07/04
22  * \date 2013/07/05
23  * \date 2013/07/08
24  * \date 2013/07/09
25  * \date 2013/07/10
26  * \date 2013/07/29
27  * \date 2013/07/30
28  * \date 2013/07/31
29  * \date 2013/09/23
30  * \date 2013/10/15
31  * \date 2013/10/18
32  * \date 2013/10/21
33  * \date 2013/10/31
34  * \date 2013/11/06
35  * \date 2013/11/12
36  * \date 2013/11/22
37  */
38 
39 #include <boost/concept_check.hpp>
40 #include <QtGui>
41 #include <QWidget>
42 #include <QLabel>
43 #include <QMenu>
44 #include <QApplication>
45 #include <QString>
46 #include <QAction>
47 #include <QScrollBar>
48 #include <QPoint>
49 #include <utility>
50 #include <vector>
51 #include <list>
52 #include <boost/units/systems/si/length.hpp>
53 #include <boost/units/static_constant.hpp>
54 #include <boost/units/conversion.hpp>
55 
56 #include "ui_mainboard.h"
57 #include "projection.hpp"
58 
59 // /// \brief Namespace for library Boost.
60 // namespace boost{
61 // /// \brief Namespace for units.
62 // namespace units {
63 // /// \brief Namespace for US units system.
64 // namespace us {
65 // /// \brief Base for US foot.
66 // struct foot_base_unit: base_unit<foot_base_unit, length_dimension, 1>{};
67 //
68 // /// \brief Creates US system.
69 // typedef make_system<foot_base_unit>::type us_system;
70 //
71 // /// \brief US dimensionless.
72 // typedef unit<dimensionless_type, us_system> dimensionless;
73 //
74 // /// \brief US foot.
75 // typedef unit<length_dimension, us_system> length;
76 //
77 // /// \brief Foot constant.
78 // BOOST_UNITS_STATIC_CONSTANT(foot, length);
79 // }
80 // }
81 // }
82 
83 /// \brief Namespace for GUI definition.
84 namespace GUI {
85  using namespace Projection;
86  using namespace boost::units;
87  using namespace boost::units::si;
88 
89 // /// \brief Foot unit.
90 // struct foot_base_unit: base_unit<foot_base_unit, length_dimension, 1> {};
91 //
92 // /// \brief Conversion between foot and meter.
93 // BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, meter_base_unit,
94 // double, 0.3048);
95 
96  /// \brief Class for program main window.
97  class MainBoard: public QMainWindow {
98  Q_OBJECT
99 
100  public:
101  /// \brief Default constructor.
102  explicit MainBoard (): QMainWindow () {
103  ui.setupUi(this);
104 
105  /**
106  * \todo Initialising "imageLabel" should be done in file
107  * "mainboard.ui" (using Qt Designer).
108  */
109  imageLabel = new QLabel;
110  imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
111  imageLabel->setScaledContents(true);
112 
113  /**
114  * \todo Initialising "scrollArea" should be done in file
115  * "mainboard.ui" (using Qt Designer).
116  */
117  scrollArea = new QScrollArea;
118  scrollArea->setWidget(imageLabel);
119  setCentralWidget(scrollArea);
120  }
121 
122  /// \brief Destructor.
123  virtual ~MainBoard () {
124  delete imageLabel;
125  delete scrollArea;
126  }
127 
128  protected slots:
129  /// \brief Get the name of the file to be opened.
130  void on_actionOpen_triggered ();
131 
132  /// \brief Load a world file.
133  void on_actionLoadWorldFile_triggered ();
134 
135  /// \brief Load reference points.
136  void on_actionLoadReferencePoints_triggered ();
137 
138  /// \brief Load a data file.
139  void on_actionLoadDataFile_triggered ();
140 
141  /// \brief Zooms in an image.
142  void on_actionZoomIn_triggered ();
143 
144  /// \brief Zooms out an image.
145  void on_actionZoomOut_triggered ();
146 
147  /// \brief Gets the image back to its normal size.
148  void on_actionNormalSize_triggered ();
149 
150  /// \brief Save reference points, used for image geo-referencing.
151  void on_actionSaveReferencePoints_triggered ();
152 
153  /// \brief Save reference points in a new file.
154  void on_actionSaveReferencePointsAs_triggered ();
155 
156  /**
157  * \brief Save a world file associated to an image.
158  *
159  * Information about world file format can be found at:
160  * <http://en.wikipedia.org/wiki/World_file>
161  */
162  void on_actionSaveWorldFile_triggered ();
163 
164  /// \brief Save data which have been set by user.
165  void on_actionSaveDataFile_triggered ();
166 
167  /// \brief Save data in a new file.
168  void on_actionSaveDataFileAs_triggered ();
169 
170  /// \brief Give reference points for image geo-reference.
171  void on_actionGeoreferenceImage_triggered ();
172 
173  /// \brief Enable setting of geo-referenced data.
174  void on_actionSetData_triggered ();
175 
176  /// \brief Sampling an isobath.
177  void on_actionSampleIsobath_triggered ();
178 
179  protected:
180  /**
181  * \brief What to do when mouse is clicked.
182  * \param event The event that indicates mouse button is clicked.
183  */
184  virtual void mousePressEvent (QMouseEvent *event);
185 
186  private:
187  /// \brief Type for a reference point.
188  typedef std::pair<Point2D, Point2D> ReferencePointType;
189 
190  /// \brief Type for list containing reference points.
191  typedef std::list<ReferencePointType> ReferencePointListType;
192 
193  /// \brief String indicating operation complete.
194  const QString done = tr("Done.");
195 
196  /// \brief String indicating geo-referencing is enable.
197  const QString geoOk = tr("Image with geo-reference.");
198 
199  /// \brief String indicating geo-referencing is disable.
200  const QString geoNotOk = tr("Image without geo-reference.");
201 
202  /// \brief String indicating there is no file to be opened.
203  const QString noFile = tr("No file to be opened.");
204 
205  /// \brief String indicating an operation has been aborted.
206  const QString aborted = tr("Operation aborted.");
207 
208  /// \brief String indicating a file is about to be opened.
209  const QString openFile = tr("Open file");
210 
211  /// \brief String for opening text files or any file.
212  const QString textOrAny = tr("Text files (*.txt);;All files (*)");
213 
214  /// \brief Number of reference points required.
215  const size_t requiredReference = 3;
216 
217  /// \brief Matrix to compute referential change.
218  Eigen::Matrix<double, 2, 3> change;
219 
220  /// \brief List of reference points.
221  ReferencePointListType referencePointList;
222 
223  /// \brief Image scale factor.
224  double scaleFactor;
225 
226  /// \brief Value to be set.
227  double value;
228 
229  /// \brief Name of the world file associated to the image.
230  QString worldFileName;
231 
232  /// \brief Name of the file containing geo-referenced data.
233  QString dataFileName;
234 
235  /// \brief Name of the file containing reference points.
236  QString referencePointFileName;
237 
238  /// \brief Data to be stored.
239  QString data;
240 
241  /// \brief Label for image manipulation.
242  QLabel* imageLabel;
243 
244  /// \brief Allows to scroll in the image.
245  QScrollArea* scrollArea;
246 
247  /// \brief Get the GUI description.
248  Ui::MainBoard ui;
249 
250  /// \brief Number of given reference points.
251  size_t numberReferencePoints;
252 
253  /// \brief Whether or not the world file exists.
254  bool worldExists;
255 
256  /// \brief Whether or not being referencing image.
257  bool referencing;
258 
259  /// \brief Whether or not being setting geo-referenced data.
260  bool setting;
261 
262  /// \brief Whether or not being sampling an isobath.
263  bool sampling;
264 
265  /**
266  * \brief Actually load world file.
267  * \param fileName Name of the world file.
268  */
269  void loadWorldFile (const QString &fileName) {
270  /* The world file itself. */
271  QFile worldFile (fileName);
272  if (worldFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
273  /* Stream on the file. */
274  QTextStream worldFileStream (&worldFile);
275  worldFileStream >> change(0, 0) >> change(1, 0) >> change(0, 1)
276  >> change(1, 1) >> change(0, 2) >> change(1, 2);
277  worldFile.close();
278  worldExists = true;
279  ui.statusbar->showMessage(geoOk);
280  ui.actionSaveWorldFile->setEnabled(false);
281  ui.actionSetData->setEnabled(true);
282  ui.actionSampleIsobath->setEnabled(true);
283  }
284  else {
285  QMessageBox::critical(this, tr("Error"),
286  tr("World file cannot be opened."));
287  }
288  }
289 
290  /// \brief Actually save data file.
291  void saveDataFile () {
292  if (!dataFileName.isEmpty()) {
293  /* Data file itself. */
294  QFile dataFile (dataFileName);
295  if (dataFile.open(QIODevice::WriteOnly | QIODevice::Text |
296  QIODevice::Truncate)) {
297  /* Stream on the data file. */
298  QTextStream dataFileStream (&dataFile);
299  dataFileStream << data;
300  dataFile.close();
301  }
302  else {
303  QMessageBox::critical(this, tr("Error"),
304  tr("File named \"%1\" cannot "
305  "be opened.").arg(dataFileName));
306  }
307  ui.statusbar->showMessage(done);
308  }
309  else {
310  ui.statusbar->showMessage(tr("No file name specified."));
311  }
312  }
313 
314  /// \brief Actually save reference points.
315  void saveReferencePointFile () {
316  if (!referencePointFileName.isEmpty()) {
317  /* File containing reference points. */
318  QFile referencePointFile (referencePointFileName);
319  if (referencePointFile.open(QIODevice::WriteOnly | QIODevice::Text
320  | QIODevice::Truncate)) {
321  /* Stream on the file. */
322  QTextStream referencePointFileStream (&referencePointFile);
323 
324  for (ReferencePointListType::iterator point =
325  referencePointList.begin();
326  point != referencePointList.end(); ++point)
327  referencePointFileStream << point->first.x() << ' '
328  << point->first.y() << ' '
329  << point->second.x() << ' '
330  << point->second.y() << '\n';
331 
332  referencePointFile.close();
333  ui.actionSaveReferencePoints->setEnabled(false);
334  ui.actionSaveReferencePointsAs->setEnabled(false);
335  }
336  else {
337  QMessageBox::critical(this, tr("Error"),
338  tr("File named \"%1\" cannot "
339  "be opened.").arg(dataFileName));
340  }
341  ui.statusbar->showMessage(done);
342  }
343  else {
344  ui.statusbar->showMessage(tr("No file name specified"));
345  }
346  }
347 
348  /**
349  * \brief Set scroll bar if needed.
350  * \param scrollBar Scroll bar to be adjusted.
351  * \param factor Factor for adjusting.
352  */
353  void adjustScrollBar (QScrollBar* scrollBar, double factor) {
354  scrollBar->setValue(static_cast<int>(factor * scrollBar->value()
355  + ((factor - 1) * scrollBar->pageStep() / 2)));
356  }
357 
358  /// \brief Change scale of an image.
359  void scaleImage (double factor) {
360  Q_ASSERT(imageLabel->pixmap());
361  scaleFactor *= factor;
362  imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());
363 
364  adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
365  adjustScrollBar(scrollArea->verticalScrollBar(), factor);
366 
367  ui.actionZoomIn->setEnabled(scaleFactor < 3.0);
368  ui.actionZoomOut->setEnabled(scaleFactor > 0.1);
369  }
370 
371  /**
372  * \brief Get mouse pointer position in the image referential.
373  * \param pos Position given by the event.
374  * \return A pair containing abscissa and ordinate of the point being
375  * clicked.
376  */
377  Point2D getMousePosition (const QPoint &pos) {
378  /* Minimum of horizontal scroll bar. */
379  const double horizontalMinimum =
380  static_cast<double>(scrollArea->horizontalScrollBar()->minimum());
381  /* Maximum of horizontal scroll bar. */
382  const double horizontalMaximum =
383  static_cast<double>(scrollArea->horizontalScrollBar()->maximum());
384  /* Minimum of vertical scroll bar. */
385  const double verticalMinimum =
386  static_cast<double>(scrollArea->verticalScrollBar()->minimum());
387  /* Maximum of vertical scroll bar. */
388  const double verticalMaximum =
389  static_cast<double>(scrollArea->verticalScrollBar()->maximum());
390  /* Quantity of pixel not shown according horizontal orientation. */
391  const double horizontalRemaining =
392  std::max((imageLabel->pixmap()->width() * scaleFactor)
393  - imageLabel->width(), 0.);
394  /* Quantity of pixel not shown according vertical orientation. */
395  const double verticalRemaining =
396  std::max((imageLabel->pixmap()->height() * scaleFactor)
397  - imageLabel->height(), 0.);
398  /* How much horizontally scrolled. */
399  const double horizontalPercentage =
400  (horizontalMaximum > horizontalMinimum)?
401  (static_cast<double>(scrollArea->horizontalScrollBar()->value())
402  - horizontalMinimum)
403  / (horizontalMaximum - horizontalMinimum): 0. ;
404  /* How much vertically scrolled. */
405  const double verticalPercentage =
406  (verticalMaximum > verticalMinimum)?
407  (static_cast<double>(scrollArea->verticalScrollBar()->value())
408  - verticalMinimum)
409  / (verticalMaximum - verticalMinimum): 0. ;
410  /* Localisation where clicked in the frame. */
411  const QPoint localisation =
412  pos - imageLabel->pos() - scrollArea->pos();
413  /* Abscissa of the point clicked in the image. */
414  const double x =
415  (static_cast<double>(localisation.x())
416  + (horizontalRemaining * horizontalPercentage))
417  / scaleFactor;
418  /* Ordinate of the point clicked in the image. */
419  const double y =
420  (static_cast<double>(localisation.y())
421  + (verticalRemaining * verticalPercentage))
422  / scaleFactor;
423 
424  return Point2D (x, y);
425  }
426  };
427 }
428 
429 #endif // #ifndef MAINBOARD_HPP
virtual ~MainBoard()
Destructor.
Definition: mainboard.hpp:123
Class for 2D points.
Definition: projection.hpp:23
MainBoard()
Default constructor.
Definition: mainboard.hpp:102
Class for program main window.
Definition: mainboard.hpp:97
Utilities for conversion from coordinates in an image to geographical coordinates.