MapBox.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006-2008 by Antonello Lobianco                         *
00003  *   http://regmas.org                                                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 3 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include <iostream>
00021 
00022 #include <QtGui>
00023 #include <math.h>
00024 #include "MapBox.h"
00025 
00026 using namespace std;
00027 
00028 const double ZoomOutFactor = 0.8;
00029 const double ZoomInFactor = 1 / ZoomOutFactor;
00030 const int ScrollStep = 20;
00031 
00032 MapBox::MapBox(QWidget *parent):QWidget(parent) {
00033 
00034     currentLayerName = "";
00035     setCursor(Qt::CrossCursor);
00036 
00037     // setting source and destination init corners..
00038     sx1 = 0;
00039     sy1 = 0;
00040     sx2 = this->width();
00041     sy2 = this->height();
00042     dx1 = 0;
00043     dy1 = 0;
00044     dx2 = this->width();
00045     dy2 = this->height();
00046 }
00047 
00051 void
00052 MapBox::paintEvent(QPaintEvent *event) {
00053 
00054     if (layersVector.size() < 1) return;
00055     QPainter painter(this);
00056     painter.fillRect(rect(), Qt::lightGray  );
00057     QPixmap pixmap = QPixmap::fromImage(currentLayer); // It doesn't get autmoatically refreshed if I use a separate function to update the pixmap from the image
00058     QRectF source     (sx1, sy1, sx2-sx1, sy2-sy1); // the second point is in coordinates origin of the firt point !!!!
00059     QRectF destination(dx1, dy1, dx2-dx1, dy2-dy1); // the second point is in coordinates origin of the firt point !!!!
00060     /*
00061     This is the main function of the widget... the good pointa are:
00062     A) It takes into account the low level details of scaling, such interpolation
00063     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...)
00064     */
00065     painter.drawPixmap(destination, pixmap, source);
00066 
00067 }
00068 
00069 void
00070 MapBox::updatePixel(QString layerName_h, int x_h, int y_h, QColor color_h){
00071     for (uint i=0;i<layersVector.size();i++){
00072         if (layersNameVector.at(i) == layerName_h){
00073             layersVector.at(i).setPixel(x_h, y_h, color_h.rgb());
00074             if(layerName_h == currentLayerName){
00075                 currentLayer = layersVector.at(i);
00076                 update();
00077             }
00078             return;
00079         }
00080     }
00081 }
00082 
00083 void
00084 MapBox::updateImage(QString layerName_h, const QImage& image_h){
00085     static int counter = 0;
00086     for (uint i=0;i<layersVector.size();i++){
00087         if (layersNameVector.at(i) == layerName_h){
00088             layersVector.at(i) = image_h;
00089             if(layerName_h == currentLayerName){
00090                 currentLayer = layersVector.at(i);
00091                 update();
00092             }
00093             if (counter == 0) { // that's the first image we got !!
00094                 fitInWindow();
00095             }
00096             counter ++;
00097             return;
00098         }
00099     }
00100     counter ++;
00101     cout << "*** ERROR in MapBox::updateImage(): layerName_h "<< qPrintable(layerName_h) << " not found "<< endl;
00102 }
00103 
00104 void
00105 MapBox::switchToLayer(QString layerName_h){
00106     if (layerName_h != currentLayerName){
00107         for (uint i=0;i<layersVector.size();i++){
00108             if (layersNameVector.at(i) == layerName_h){
00109                 currentLayer = layersVector.at(i);
00110                 currentLayerName = layerName_h;
00111                 update();
00112                 return;
00113             }
00114         }
00115         cout << "*** ERROR in MapBox::switchToLayer(): layerName_h "<< qPrintable(layerName_h) << " not found "<< endl;
00116     }
00117 }
00118 
00119 int
00120 MapBox::getLayerIndex(QString layerName_h){
00121     if( layerName_h == "") layerName_h = currentLayerName;
00122     for (uint i=0;i<layersVector.size();i++){
00123         if (layersNameVector.at(i) == layerName_h){
00124             return i;
00125         }
00126     }
00127     cout << "*** ERROR in MapBox:getLayerIndex(): layerName_h "<< qPrintable(layerName_h) << " not found "<< endl;
00128     return -1;
00129 }
00130 
00131 void
00132 MapBox::addLayer(QString layerName_h){
00133     static int counter = 0;
00134     QImage newlayer = QImage(this->width(), this->height(), QImage::Format_RGB32);
00135     newlayer.fill(qRgb(255, 255, 255));
00136     layersVector.push_back(newlayer);
00137     layersNameVector.push_back(layerName_h);
00138     if (counter == 0) {
00139         currentLayerName = layerName_h;
00140         currentLayer = layersVector.at(0);
00141     }
00142     counter ++;
00143 }
00144 
00145 void
00146 MapBox::keyPressEvent(QKeyEvent *event) {
00147     switch (event->key()) {
00148         case Qt::Key_Plus:
00149         zoom(ZoomInFactor);
00150         break;
00151     case Qt::Key_Minus:
00152         zoom(ZoomOutFactor);
00153         break;
00154     case Qt::Key_Left:
00155         scroll(+ScrollStep, 0);
00156         break;
00157     case Qt::Key_Right:
00158         scroll(-ScrollStep, 0);
00159         break;
00160     case Qt::Key_Down:
00161         scroll(0, -ScrollStep);
00162         break;
00163     case Qt::Key_Up:
00164         scroll(0, +ScrollStep);
00165         break;
00166     default:
00167         QWidget::keyPressEvent(event);
00168     }
00169 }
00170 
00171 void
00172 MapBox::wheelEvent(QWheelEvent *event){
00173     int numDegrees = event->delta() / 8;
00174     double numSteps = numDegrees / 15.0f;
00175     zoom(pow(ZoomInFactor, numSteps));
00176 }
00177 
00178 void
00179 MapBox::mousePressEvent(QMouseEvent *event){
00180     if (event->button() == Qt::LeftButton){
00181         lastDragPos = event->pos();
00182     }
00183     else if (event->button() == Qt::RightButton){
00184         prepareQueryEvent(event->pos());
00185     }
00186 }
00187 
00188 void
00189 MapBox::prepareQueryEvent(QPoint click){
00190     double cx = ((double) click.x()); //clicked x, casted to double
00191     double cy = ((double) click.y()); //clicked y, casted to double
00192     int   mx, my = 0; // outputed x and y
00193     int   px_ID;  // pixel ID
00194     int   layerIndex = getLayerIndex();
00195     // checking it is not out of the destination border range..
00196     if (cx>dx2 || cx<dx1 || cy>dy2 || cy<dy1) return;
00197     mx = ( (int) (cx-dx1) * (sx2-sx1)/(dx2-dx1) + sx1); // casting to int, not round() !!
00198     my = ( (int) (cy-dy1) * (sy2-sy1)/(dy2-dy1) + sy1); // casting to int, not round() !!
00199     px_ID = mx+my*(sx2-sx1);
00200     emit queryRequestOnPx(px_ID, layerIndex, true);
00201 
00202 }
00203 
00204 
00205 void
00206 MapBox::mouseMoveEvent(QMouseEvent *event) {
00207     if (event->buttons() & Qt::LeftButton) {
00208         scroll(event->pos().x()-lastDragPos.x(), event->pos().y()-lastDragPos.y());
00209         lastDragPos = event->pos();
00210         update();
00211     }
00212 }
00213 
00214 void MapBox::fitInWindow(){
00215 
00216     QPixmap pixmap = QPixmap::fromImage(currentLayer);
00217     double tempXScale = ( (double) this->width()) / ((double)pixmap.width());
00218     double tempYScale = ( (double) this->height())/ ((double)pixmap.height());
00219 
00220     sx1 = 0;
00221     sy1 = 0;
00222     sx2 = pixmap.width();
00223     sy2 = pixmap.height();
00224     dx1 = 0;
00225     dy1 = 0;
00226 
00227     if ( tempXScale >= tempYScale){
00228         dx2 = ((double)pixmap.width())*tempYScale;
00229         dy2 = this->height();
00230     } else {
00231         dx2 = this->width();
00232         dy2 = ((double)pixmap.height())*tempXScale;
00233     }
00234     update();
00235 }
00236 
00237 void
00238 MapBox::zoom(double zoomFactor){
00239     double dx1new, dx2new, dy1new, dy2new;
00240     dx1new = dx2- (dx2-dx1)* ( 1+ (zoomFactor-1)/2 ); 
00241     dx2new = dx1+ (dx2-dx1)* ( 1+ (zoomFactor-1)/2 );
00242     dy1new = dy2- (dy2-dy1)* ( 1+ (zoomFactor-1)/2 ); 
00243     dy2new = dy1+ (dy2-dy1)* ( 1+ (zoomFactor-1)/2 );
00244     dx1 = dx1new;
00245     dy1 = dy1new;
00246     dx2 = dx2new;
00247     dy2 = dy2new;
00248     update();
00249 }
00250 
00251 void
00252 MapBox::scroll(int deltaX, int deltaY){
00253     dx1 += ((double) deltaX);
00254     dx2 += ((double) deltaX);
00255     dy1 += ((double) deltaY);
00256     dy2 += ((double) deltaY);
00257     update();
00258 }
00259