FFSM++  1.1.0
French Forest Sector Model ++
MapBox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2015 by Laboratoire d'Economie Forestière *
3  * http://ffsm-project.org *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version, given the compliance with the *
9  * exceptions listed in the file COPYING that is distribued together *
10  * with this file. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 #include <iostream>
23 
24 //#include <QtGui> // Qt4
25 #include <QtWidgets> // Qt5
26 #include <math.h>
27 #include "MapBox.h"
28 
29 using namespace std;
30 
31 const double ZoomOutFactor = 0.8;
32 const double ZoomInFactor = 1 / ZoomOutFactor;
33 const int ScrollStep = 20;
34 
35 MapBox::MapBox(QWidget *parent):QWidget(parent) {
36 
37  currentLayerName = "";
38  setCursor(Qt::CrossCursor);
39 
40  // setting source and destination init corners..
41  sx1 = 0;
42  sy1 = 0;
43  sx2 = this->width();
44  sy2 = this->height();
45  dx1 = 0;
46  dy1 = 0;
47  dx2 = this->width();
48  dy2 = this->height();
49 }
50 
51 /**
52 We paint the image pixel by pixel picking up the colors from the map pointed by currentLayer.
53 */
54 void
55 MapBox::paintEvent(QPaintEvent *event) {
56 
57  if (layersVector.size() < 1) return;
58  QPainter painter(this);
59  painter.fillRect(rect(), Qt::lightGray );
60  QPixmap pixmap = QPixmap::fromImage(currentLayer); // It doesn't get autmoatically refreshed if I use a separate function to update the pixmap from the image
61  QRectF source (sx1, sy1, sx2-sx1, sy2-sy1); // the second point is in coordinates origin of the firt point !!!!
62  QRectF destination(dx1, dy1, dx2-dx1, dy2-dy1); // the second point is in coordinates origin of the firt point !!!!
63  /*
64  This is the main function of the widget... the good pointa are:
65  A) It takes into account the low level details of scaling, such interpolation
66  B) If the destination is outside the widgets bounds, it doesn't matter. It make its job on the widget without any error (in this sence it isnot like an array luckily...)
67  */
68  painter.drawPixmap(destination, pixmap, source);
69 
70 }
71 
72 void
73 MapBox::updatePixel(QString layerName_h, int x_h, int y_h, QColor color_h){
74  for (uint i=0;i<layersVector.size();i++){
75  if (layersNameVector.at(i) == layerName_h){
76  layersVector.at(i).setPixel(x_h, y_h, color_h.rgb());
77  if(layerName_h == currentLayerName){
78  currentLayer = layersVector.at(i);
79  update();
80  }
81  return;
82  }
83  }
84 }
85 
86 void
87 MapBox::updateImage(QString layerName_h, const QImage& image_h){
88  static int counter = 0;
89  for (uint i=0;i<layersVector.size();i++){
90  if (layersNameVector.at(i) == layerName_h){
91  layersVector.at(i) = image_h;
92  if(layerName_h == currentLayerName){
93  currentLayer = layersVector.at(i);
94  update();
95  }
96  if (counter == 0) { // that's the first image we got !!
97  fitInWindow();
98  }
99  counter ++;
100  return;
101  }
102  }
103  counter ++;
104  cout << "*** ERROR in MapBox::updateImage(): layerName_h "<< qPrintable(layerName_h) << " not found "<< endl;
105 }
106 
107 void
108 MapBox::switchToLayer(QString layerName_h){
109  if (layerName_h != currentLayerName){
110  for (uint i=0;i<layersVector.size();i++){
111  if (layersNameVector.at(i) == layerName_h){
112  currentLayer = layersVector.at(i);
113  currentLayerName = layerName_h;
114  update();
115  return;
116  }
117  }
118  cout << "*** ERROR in MapBox::switchToLayer(): layerName_h "<< qPrintable(layerName_h) << " not found "<< endl;
119  }
120 }
121 
122 int
123 MapBox::getLayerIndex(QString layerName_h){
124  if( layerName_h == "") layerName_h = currentLayerName;
125  for (uint i=0;i<layersVector.size();i++){
126  if (layersNameVector.at(i) == layerName_h){
127  return i;
128  }
129  }
130  cout << "*** ERROR in MapBox:getLayerIndex(): layerName_h "<< qPrintable(layerName_h) << " not found "<< endl;
131  return -1;
132 }
133 
134 void
135 MapBox::addLayer(QString layerName_h){
136  static int counter = 0;
137  QImage newlayer = QImage(this->width(), this->height(), QImage::Format_RGB32);
138  newlayer.fill(qRgb(255, 255, 255));
139  layersVector.push_back(newlayer);
140  layersNameVector.push_back(layerName_h);
141  if (counter == 0) {
142  currentLayerName = layerName_h;
143  currentLayer = layersVector.at(0);
144  }
145  counter ++;
146 }
147 
148 void
149 MapBox::keyPressEvent(QKeyEvent *event) {
150  switch (event->key()) {
151  case Qt::Key_Plus:
153  break;
154  case Qt::Key_Minus:
156  break;
157  case Qt::Key_Left:
158  scroll(+ScrollStep, 0);
159  break;
160  case Qt::Key_Right:
161  scroll(-ScrollStep, 0);
162  break;
163  case Qt::Key_Down:
164  scroll(0, -ScrollStep);
165  break;
166  case Qt::Key_Up:
167  scroll(0, +ScrollStep);
168  break;
169  default:
170  QWidget::keyPressEvent(event);
171  }
172 }
173 
174 void
175 MapBox::wheelEvent(QWheelEvent *event){
176  int numDegrees = event->delta() / 8;
177  double numSteps = numDegrees / 15.0f;
178  zoom(pow(ZoomInFactor, numSteps));
179 }
180 
181 void
182 MapBox::mousePressEvent(QMouseEvent *event){
183  if (event->button() == Qt::LeftButton){
184  lastDragPos = event->pos();
185  }
186  else if (event->button() == Qt::RightButton){
187  prepareQueryEvent(event->pos());
188  }
189 }
190 
191 void
193  double cx = ((double) click.x()); //clicked x, casted to double
194  double cy = ((double) click.y()); //clicked y, casted to double
195  int mx, my = 0; // outputed x and y
196  int px_ID; // pixel ID
197  int layerIndex = getLayerIndex();
198  // checking it is not out of the destination border range..
199  if (cx>dx2 || cx<dx1 || cy>dy2 || cy<dy1) return;
200  mx = ( (int) (cx-dx1) * (sx2-sx1)/(dx2-dx1) + sx1); // casting to int, not round() !!
201  my = ( (int) (cy-dy1) * (sy2-sy1)/(dy2-dy1) + sy1); // casting to int, not round() !!
202  px_ID = mx+my*(sx2-sx1);
203  emit queryRequestOnPx(px_ID, layerIndex, true);
204 
205 }
206 
207 
208 void
209 MapBox::mouseMoveEvent(QMouseEvent *event) {
210  if (event->buttons() & Qt::LeftButton) {
211  scroll(event->pos().x()-lastDragPos.x(), event->pos().y()-lastDragPos.y());
212  lastDragPos = event->pos();
213  update();
214  }
215 }
216 
218 
219  QPixmap pixmap = QPixmap::fromImage(currentLayer);
220  double tempXScale = ( (double) this->width()) / ((double)pixmap.width());
221  double tempYScale = ( (double) this->height())/ ((double)pixmap.height());
222 
223  sx1 = 0;
224  sy1 = 0;
225  sx2 = pixmap.width();
226  sy2 = pixmap.height();
227  dx1 = 0;
228  dy1 = 0;
229 
230  if ( tempXScale >= tempYScale){
231  dx2 = ((double)pixmap.width())*tempYScale;
232  dy2 = this->height();
233  } else {
234  dx2 = this->width();
235  dy2 = ((double)pixmap.height())*tempXScale;
236  }
237  update();
238 }
239 
240 void
241 MapBox::zoom(double zoomFactor){
242  double dx1new, dx2new, dy1new, dy2new;
243  dx1new = dx2- (dx2-dx1)* ( 1+ (zoomFactor-1)/2 );
244  dx2new = dx1+ (dx2-dx1)* ( 1+ (zoomFactor-1)/2 );
245  dy1new = dy2- (dy2-dy1)* ( 1+ (zoomFactor-1)/2 );
246  dy2new = dy1+ (dy2-dy1)* ( 1+ (zoomFactor-1)/2 );
247  dx1 = dx1new;
248  dy1 = dy1new;
249  dx2 = dx2new;
250  dy2 = dy2new;
251  update();
252 }
253 
254 void
255 MapBox::scroll(int deltaX, int deltaY){
256  dx1 += ((double) deltaX);
257  dx2 += ((double) deltaX);
258  dy1 += ((double) deltaY);
259  dy2 += ((double) deltaY);
260  update();
261 }
262 
int getLayerIndex(QString layerName_h="")
Return the index of the specified layer (null to ask for the current one)
Definition: MapBox.cpp:123
void mouseMoveEvent(QMouseEvent *event)
Definition: MapBox.cpp:209
MapBox(QWidget *parent=0)
Definition: MapBox.cpp:35
QString currentLayerName
Definition: MapBox.h:71
void wheelEvent(QWheelEvent *event)
Definition: MapBox.cpp:175
const double ZoomInFactor
Definition: MapBox.cpp:32
double dy1
Definition: MapBox.h:74
STL namespace.
void switchToLayer(QString layerName_h)
Change the layer that currentLayer and currentLayerName points.
Definition: MapBox.cpp:108
vector< QImage > layersVector
Vector of QImages.
Definition: MapBox.h:68
void addLayer(QString layerName_h)
Definition: MapBox.cpp:135
void keyPressEvent(QKeyEvent *event)
Definition: MapBox.cpp:149
void queryRequestOnPx(int px_ID, int currentLayerIndex, bool newRequest)
void paintEvent(QPaintEvent *event)
Reimplementation of the standard paintEvent method.
Definition: MapBox.cpp:55
QImage currentLayer
Definition: MapBox.h:70
void fitInWindow()
Definition: MapBox.cpp:217
double dx1
Definition: MapBox.h:74
void prepareQueryEvent(QPoint click)
Definition: MapBox.cpp:192
double dy2
coordinates of corner pixels of destination - widget - rectangle
Definition: MapBox.h:74
double sy1
Definition: MapBox.h:73
double sy2
coordinates of corner pixels of source - pixmap - rectangle
Definition: MapBox.h:73
const int ScrollStep
Definition: MapBox.cpp:33
void updatePixel(QString layerName_h, int x_h, int y_h, QColor color_h)
Definition: MapBox.cpp:73
double sx2
Definition: MapBox.h:73
void scroll(int deltaX, int deltaY)
Definition: MapBox.cpp:255
void zoom(double zoomFactor)
Definition: MapBox.cpp:241
void mousePressEvent(QMouseEvent *event)
Definition: MapBox.cpp:182
double sx1
Definition: MapBox.h:73
void updateImage(QString layerName_h, const QImage &image_h)
Definition: MapBox.cpp:87
double dx2
Definition: MapBox.h:74
const double ZoomOutFactor
Definition: MapBox.cpp:31
vector< QString > layersNameVector
Vector of layer names.
Definition: MapBox.h:69
QPoint lastDragPos
Definition: MapBox.h:72