FFSM++ 1.1.0
French Forest Sector Model ++
Loading...
Searching...
No Matches
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
29using namespace std;
30
31const double ZoomOutFactor = 0.8;
32const double ZoomInFactor = 1 / ZoomOutFactor;
33const int ScrollStep = 20;
34
35MapBox::MapBox(QWidget *parent):QWidget(parent) {
36
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/**
52We paint the image pixel by pixel picking up the colors from the map pointed by currentLayer.
53*/
54void
55MapBox::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
72void
73MapBox::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){
79 update();
80 }
81 return;
82 }
83 }
84}
85
86void
87MapBox::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){
94 update();
95 }
96 if (counter == 0) { // that's the first image we got !!
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
107void
108MapBox::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){
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
122int
123MapBox::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
134void
135MapBox::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;
144 }
145 counter ++;
146}
147
148void
149MapBox::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
174void
175MapBox::wheelEvent(QWheelEvent *event){
176 int numDegrees = event->delta() / 8;
177 double numSteps = numDegrees / 15.0f;
178 zoom(pow(ZoomInFactor, numSteps));
179}
180
181void
182MapBox::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
191void
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
208void
209MapBox::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
240void
241MapBox::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
254void
255MapBox::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
const double ZoomInFactor
Definition MapBox.cpp:32
const int ScrollStep
Definition MapBox.cpp:33
const double ZoomOutFactor
Definition MapBox.cpp:31
double dy2
coordinates of corner pixels of destination - widget - rectangle
Definition MapBox.h:74
QPoint lastDragPos
Definition MapBox.h:72
vector< QImage > layersVector
Vector of QImages.
Definition MapBox.h:68
vector< QString > layersNameVector
Vector of layer names.
Definition MapBox.h:69
void queryRequestOnPx(int px_ID, int currentLayerIndex, bool newRequest)
double sx1
Definition MapBox.h:73
double sy2
coordinates of corner pixels of source - pixmap - rectangle
Definition MapBox.h:73
double dx2
Definition MapBox.h:74
QImage currentLayer
Definition MapBox.h:70
double dy1
Definition MapBox.h:74
MapBox(QWidget *parent=0)
Definition MapBox.cpp:35
void scroll(int deltaX, int deltaY)
Definition MapBox.cpp:255
void addLayer(QString layerName_h)
Definition MapBox.cpp:135
double sy1
Definition MapBox.h:73
double sx2
Definition MapBox.h:73
int getLayerIndex(QString layerName_h="")
Return the index of the specified layer (null to ask for the current one)
Definition MapBox.cpp:123
void fitInWindow()
Definition MapBox.cpp:217
void zoom(double zoomFactor)
Definition MapBox.cpp:241
double dx1
Definition MapBox.h:74
void prepareQueryEvent(QPoint click)
Definition MapBox.cpp:192
void updateImage(QString layerName_h, const QImage &image_h)
Definition MapBox.cpp:87
void wheelEvent(QWheelEvent *event)
Definition MapBox.cpp:175
void paintEvent(QPaintEvent *event)
Reimplementation of the standard paintEvent method.
Definition MapBox.cpp:55
void mousePressEvent(QMouseEvent *event)
Definition MapBox.cpp:182
void switchToLayer(QString layerName_h)
Change the layer that currentLayer and currentLayerName points.
Definition MapBox.cpp:108
void updatePixel(QString layerName_h, int x_h, int y_h, QColor color_h)
Definition MapBox.cpp:73
void keyPressEvent(QKeyEvent *event)
Definition MapBox.cpp:149
void mouseMoveEvent(QMouseEvent *event)
Definition MapBox.cpp:209
QString currentLayerName
Definition MapBox.h:71