00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00019 
00028 
00029 
00030 
00032 
00033 
00034 #include <map>
00035 
00036 
00037 #include <cmath>
00038 
00039 
00040 #include <qapplication.h>
00041 #include <qcheckbox.h>
00042 #include <qcolor.h>
00043 #include <qcombobox.h>
00044 #include <qcursor.h>
00045 #include <qfile.h>
00046 #include <qfiledialog.h>
00047 #include <qfileinfo.h>
00048 #include <qimage.h>
00049 #include <qlabel.h>
00050 #include <qlayout.h>
00051 #include <qlineedit.h>
00052 #include <qmessagebox.h>
00053 #include <qnamespace.h>
00054 #include <qpainter.h>
00055 #include <qpoint.h>
00056 #include <qprogressdialog.h>
00057 #include <qpushbutton.h>
00058 #include <qspinbox.h>
00059 #include <qstring.h>
00060 #include <qstringlist.h>
00061 #include <qtextstream.h>
00062 
00063 
00064 #include "colorbutton.h"
00065 #include "plotmapbase.h"
00066 #include "plotmapextensionwidget.h"
00067 #include "plotmaplabel.h"
00068 #include "version.h"
00069 
00073 
00075 PlotMapBase::PlotMapBase(QWidget* parent, const char* name, bool modal, WFlags fl) : PlotMapWidget(parent, name, modal, fl),
00076   loadInProgress(false),
00077   maxValue(1.0),
00078   minValue(-1.0)
00080 {
00081   options = new PlotMapExtensionWidget(this);
00082   options->hide();
00083   PlotMapWidgetLayout->addWidget(options);
00085   options->setFixedHeight(options->height());
00086   options->setMaximumHeight(options->height());
00087   
00089   plotLabel = new PlotMapLabel(this, 0, Qt::WNoAutoErase);
00090   plotLabel->setBackgroundMode(Qt::NoBackground);
00091   plotLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00092   plotLabel->setFrameShape(QFrame::StyledPanel);
00093   plotLabel->setFrameShadow(QFrame::Sunken); 
00094   plotLabel->setLineWidth(1);
00095   plotLabel->setMouseTracking(true);
00096   PixmapLayout->addWidget(plotLabel);
00097 
00099   makeConnections();
00100   init();
00101 }
00102 
00104 PlotMapBase::~PlotMapBase()
00106 {
00107 
00108 }
00109 
00111 bool PlotMapBase::loadMapFile(const QString filename, const bool noerrors)
00114 {
00116   QFile mapFile(filename);
00117   if(!mapFile.exists())
00118   {
00119     if(!noerrors)
00120       QMessageBox::warning(this, "Loading map file", "The map file does not exist");
00121     return false;
00122   }
00123   if(!mapFile.open(IO_ReadOnly))
00124   {
00125     if(!noerrors)
00126       QMessageBox::warning(this, "Loading map file", "The map file could not ne opened");
00127     return false;
00128   }
00129 
00131   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
00132   loadInProgress = true;
00133   QTextStream stream(&mapFile);
00134 
00135   
00136   stream.readLine(); 
00137   QString line = stream.readLine();
00138   numPoints.setValues(line.mid(0, 5).toUInt(), line.mid(75, 5).toUInt(), 0);
00139   origin.setValues(line.mid(5,10).toDouble() * AUTOANG, line.mid(65,10).toDouble() * AUTOANG, 0.0);
00140   delta.setValues(line.mid(15,10).toDouble() * AUTOANG, line.mid(55,10).toDouble() * AUTOANG, 0.0);
00141   QProgressDialog progress(tr("Loading the data..."), tr("Cancel"), numPoints.y() + numPoints.y()/20, this, 0, true);
00142   if(isVisible())
00143     progress.setCancelButton(0); 
00144       
00145   
00146   points.clear();
00147   for(unsigned int j = 0; j < numPoints.y(); j++) 
00148   {
00149     progress.setProgress(j);
00150     qApp->processEvents();
00151     if(progress.wasCancelled())
00152     {
00153       points.clear();
00154       coords.clear();
00155       numPoints.setValues(0, 0, 0);
00156       numAtoms = 0;
00157       loadInProgress = false;
00158      QApplication::restoreOverrideCursor();  
00159      return false;
00160     }
00161     double tempvar;
00162     vector<double> tempvector;
00163     for(unsigned int i = 0; i < numPoints.x(); i++) 
00164     {
00165       stream >> tempvar;
00166       tempvector.push_back(tempvar);
00167     }
00168     points.push_back(tempvector);
00169   }
00171 
00172   loadInProgress = false;
00173   if(stream.atEnd())
00174   {
00175     QApplication::restoreOverrideCursor(); 
00176     QMessageBox::warning(this, tr("Loading map file"), tr("Premature end of file encountered"));
00177     return false; 
00178   }
00179 
00180   
00181   stream >> numAtoms;
00182   coords.clear();
00183   coords.reserve(numAtoms);
00184   Point3D<double> atom;
00185   for(unsigned int i = 0; i < numAtoms; i ++)
00186   {
00187     line = stream.readLine();
00188     atom.setValues(line.left(10).toDouble() * AUTOANG, line.mid(10,10).toDouble() * AUTOANG, line.mid(20,10).toDouble() * AUTOANG);
00189     coords.push_back(atom);
00190   }
00191   
00192   mapFile.close();
00193   plotLabel->setGrid(numPoints, delta);
00194   resize(width(), numPoints.y() + 6); 
00195   
00196 
00198   maxValue = 0.0;
00199   minValue = 0.0;
00200   for(unsigned int j = 0; j < numPoints.y(); j++)
00201   {
00202     progress.setProgress(numPoints.y() + j/20);
00203     for(unsigned int i = 0; i < numPoints.x(); i++)
00204     {
00205       if(points[j][i] > maxValue)
00206         maxValue = points[j][i];
00207       else if(points[j][i] < minValue)
00208         minValue = points[j][i];
00209     }
00210   }
00211  
00212   progress.setProgress(progress.totalSteps());
00213   
00215   setCaption(Version::appName + " - " + tr("Visualizing density map") + " (" + mapFile.name() + ")");
00216 
00218   
00219   TextLabelGridSizeX->setText(QString::number(numPoints.x()));  
00220   TextLabelGridSizeY->setText(QString::number(numPoints.y()));
00221   TextLabelMaxPos->setText(QString::number(maxValue));
00222   TextLabelMaxNeg->setText(QString::number(minValue));
00223 
00225   options->LineEditMaxPos->setText(QString::number(maxValue));
00226   options->LineEditMaxNeg->setText(QString::number(minValue));
00227   
00229   TextLabelCurrentCoordinate->setText("(" + QString::number(numPoints.x()) + ", " + QString::number(numPoints.y()) + ")"); 
00230   TextLabelCurrentCoordinate->setFixedWidth(TextLabelCurrentCoordinate->width());
00231   
00233   TextLabelCurrentCoordinate->setText("none");
00234   TextLabelCurrentValue->setText("none");
00235   TextLabelCurrentCartesian->setText("none");
00236   
00238   resize(width() - plotLabel->contentsRect().width() + numPoints.x(), height() - plotLabel->contentsRect().height() + numPoints.y());
00239 
00241   updateImage();
00242 
00243   QApplication::restoreOverrideCursor();  
00244   return true;
00245 }
00246 
00247 
00251 
00253 bool PlotMapBase::loadMapFile()
00255 {
00256   QString filename = QFileDialog::getOpenFileName(QString::null, "*.map.1", this, 0, tr("Choose a map file to open"));
00257 
00258   if(filename.isEmpty())
00259     return false;  
00260 
00261   return loadMapFile(filename);
00262 }
00263 
00264 
00268 
00270 void PlotMapBase::mousePressEvent(QMouseEvent* e)
00272 {
00273   mousePosition = e->pos();
00274   if(onPixmap(mousePosition))
00275     plotLabel->startDrag(mousePosition - plotLabel->pos());
00276 }
00277 
00279 void PlotMapBase::mouseReleaseEvent(QMouseEvent* e)
00282 {
00283   QPoint mouseEndPosition = e->pos();
00284 
00285   if(onPixmap(mousePosition) && onPixmap(mouseEndPosition))
00286   {
00287     QPoint point1 = mapToImage(mousePosition);
00288     QPoint point2 = mapToImage(mouseEndPosition);
00289     int minX = point1.x() > point2.x() ? point2.x() : point1.x();
00290     int maxX = point1.x() > point2.x() ? point1.x() : point2.x();
00291     int minY = point1.y() > point2.y() ? point2.y() : point1.y();
00292     int maxY = point1.y() > point2.y() ? point1.y() : point2.y();
00293      
00295     double localMaxPosValue = 0.0;
00296     double localMinPosValue = maxValue;
00297     double localMaxNegValue = 0.0;
00298     double localMinNegValue = minValue;
00299     for(int j = minY; j <= maxY; j++)
00300     {
00301       for(int i = minX; i <= maxX; i++)
00302       {
00303         double value = points[j][i];
00304         if(value > 0.0)
00305         {
00306           if(value > localMaxPosValue)
00307             localMaxPosValue = value;
00308           if(value < localMinPosValue)
00309             localMinPosValue = value;
00310         }
00311         else if(value < 0.0)
00312         {
00313           if(value < localMaxNegValue)
00314             localMaxNegValue = value;
00315           if(value > localMinNegValue)
00316             localMinNegValue = value;
00317         }
00318         else
00319           localMinPosValue = localMinNegValue = 0.0; 
00320       }
00321     }  
00322     QString value1, value2, value3, value4;
00323     value1.setNum(localMaxPosValue,'f',5);
00324     value2.setNum(localMinPosValue,'f',5);
00325     value3.setNum(localMaxNegValue,'f',5);
00326     value4.setNum(localMinNegValue,'f',5);
00327     if(localMaxPosValue == localMaxNegValue)
00328     {
00330       value2 = "0.00000";
00331       value4 = "0.00000";
00332     }
00333     else if((localMaxPosValue == 0.0) && (localMinNegValue != 0.0))
00334     {
00336       value1 = tr("none");
00337       value2 = tr("none");
00338     }  
00339     else if((localMaxNegValue == 0.0) && (localMinPosValue != 0.0))
00340     {
00342       value3 = tr("none");
00343       value4 = tr("none");
00344     }  
00345       
00347     QString stats = tr("The selected area has the following statistics:")+"\n";
00348     stats += tr("Maximum positive value: ") + value1 + "\n";
00349     stats += tr("Minimum positive value: ") + value2 + "\n";
00350     stats += tr("Maximum negative value: ") + value3 + "\n";
00351     stats += tr("Minimum negative value: ") + value4;
00352     QMessageBox::information(this, tr("Statistics from selection"), stats);
00353 
00354   }
00355   plotLabel->endDrag();
00356   mousePosition.setX(0);
00357   mousePosition.setY(0);
00358   mouseEndPosition.setX(0);
00359   mouseEndPosition.setY(0);
00360 }
00361 
00362 
00364 void PlotMapBase::mouseMoveEvent(QMouseEvent* e)
00367 {
00368   if(loadInProgress)
00369     return; 
00370 
00372   if(mousePosition.x() && mousePosition.y())
00373     plotLabel->moveDrag(e->pos() - plotLabel->pos());
00374 
00376   if(onPixmap(e->pos()))
00377   {
00379     QPoint position = mapToImage(e->pos());
00380     TextLabelCurrentCoordinate->setText("(" + QString::number(position.x() + 1) + ", " + QString::number(position.y() + 1) + ")");
00381 
00383     QString value0;
00384     value0.setNum(points[position.y()][position.x()],'f', 5);
00385     TextLabelCurrentValue->setText(value0);
00387     position = e->pos() - plotLabel->pos();
00388     
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399     QRect rect = plotLabel->contentsRect(); 
00400     double cx = origin.x() + delta.x()*double(numPoints.x())*double(position.x())/double(rect.width());
00401     double cy = origin.y() + delta.y()*double(numPoints.y())*(1.0 - double(position.y())/double(rect.height()));
00402 
00403     QString value1, value2;
00404     value1.setNum(cx,'f',4);
00405     value2.setNum(cy,'f',4);
00406     TextLabelCurrentCartesian->setText("(" + value1 + ", " + value2 + ")");
00407   }
00408   else
00409   {
00410     TextLabelCurrentCoordinate->setText("none");
00411     TextLabelCurrentValue->setText("none");
00412     TextLabelCurrentCartesian->setText("none");
00413   }
00414 }
00415 
00419 
00421 void PlotMapBase::saveImage()
00423 {
00425   QStringList saveFormats = QImage::outputFormatList();
00426   QStringList::Iterator it = saveFormats.begin();
00427   while(it != saveFormats.end())
00428   {
00429     if((*it) == "JPEG")
00430       *it = "JPEG (*.jpg)";
00431     else  
00432       *it += " (*."+(*it).lower()+")";  
00433     
00434     it++;
00435   }
00436 
00438   QFileDialog saveDialog("", QString::null, this, 0, true);  
00439   saveDialog.setFilters(saveFormats);
00440   saveDialog.setSelectedFilter("PNG (*.png)");
00441   saveDialog.setCaption(tr("Choose a filename and format"));
00442   saveDialog.setMode(QFileDialog::AnyFile);
00443   if(saveDialog.exec() != QDialog::Accepted)
00444     return;
00445   
00447   QString filename = saveDialog.selectedFile();
00448   if(filename.isEmpty())
00449     return;
00450 
00451   QString extension = saveDialog.selectedFilter();
00452   extension = extension.mid(extension.find("."));
00453   extension = extension.remove(")");
00454   
00455 
00456   if(filename.contains(extension) == 0)
00457     filename += extension;
00458 
00459   QString format = saveDialog.selectedFilter();
00460   format = format.left(format.find(" "));
00461   
00462   QPixmap pm = QPixmap::grabWidget(plotLabel);
00463   QImage image = pm.convertToImage();
00464   if(!image.save(filename, format))
00465     QMessageBox::warning(this, tr("Save image"), tr("An error occured. Image is not saved")); 
00466 }
00467 
00469 void PlotMapBase::showOptions()
00471 {
00472   if(options->isVisible())
00473   {
00474     int newHeight = plotLabel->height() + 2*plotLabel->pos().y();
00475     QSize oldsize(width(), newHeight); 
00476     options->hide();
00477     qApp->processEvents();
00478     resize(oldsize);
00479     PushButtonOptions->setText(tr(">>> Show Options"));
00480   }
00481   else
00482   {
00483     int newHeight = plotLabel->height() + 2*plotLabel->pos().y();
00484     options->show();
00485     newHeight += options->height() + 6; 
00486     resize(width(), newHeight); 
00487     PushButtonOptions->setText(tr("<<< Hide Options"));
00488    }
00489 }
00490 
00492 void PlotMapBase::applyOptions()
00494 {
00495   updateImage();
00496 }
00497 
00499 void PlotMapBase::autoApply(bool state)
00501 {
00502   if(state)
00503   {
00504     connect(this, SIGNAL(optionsChanged()), this, SLOT(applyOptions()));
00505     applyOptions();
00506   }  
00507   else
00508     disconnect(this, SIGNAL(optionsChanged()), this, SLOT(applyOptions()));
00509 }
00510 
00512 void PlotMapBase::resetOptions()
00514 {
00515   options->LineEditMaxPos->setText(QString::number(maxValue));
00516   options->ColorButtonPos->setColor(QColor(0, 0, 255));
00517   options->SpinBoxPos->setValue(10);
00518 
00519   options->LineEditMaxNeg->setText(QString::number(minValue));
00520   options->ColorButtonNeg->setColor(QColor(255, 0, 0));
00521   options->SpinBoxNeg->setValue(10);
00522   
00523   options->CheckBoxAtoms->setChecked(true);
00524   options->LineEditAtoms->setText("0.1");
00525   options->ColorButtonAtoms->setColor(QColor(0, 0, 0));
00526 
00527   options->ColorButtonZero->setColor(QColor(255, 255, 255));
00528 
00529   options->ComboBoxStyle->setCurrentItem(2); 
00530   options->ComboBoxInterpolation->setCurrentItem(0); 
00531 
00532   updateImage();
00533 }
00534 
00535 
00539 
00541 void PlotMapBase::makeConnections()
00543 {
00545   connect(PushButtonLoadMap, SIGNAL(clicked()), this, SLOT(loadMapFile()));
00546   connect(PushButtonSaveImage, SIGNAL(clicked()), this, SLOT(saveImage()));
00547   connect(PushButtonOptions, SIGNAL(clicked()), this, SLOT(showOptions()));
00548   connect(PushButtonClose, SIGNAL(clicked()), this, SLOT(close())); 
00549 
00551   connect(options->PushButtonApply, SIGNAL(clicked()), this, SLOT(applyOptions()));
00552   connect(options->CheckBoxApply, SIGNAL(toggled(bool)), this, SLOT(autoApply(bool)));
00553   connect(options->PushButtonDefaults, SIGNAL(clicked()), this, SLOT(resetOptions()));
00554   
00555 
00557   connect(options->LineEditMaxPos, SIGNAL(textChanged(const QString&)), this, SIGNAL(optionsChanged()));
00558   connect(options->ColorButtonPos, SIGNAL(newColor(QColor*)), this, SIGNAL(optionsChanged()));
00559   
00560   connect(options->SpinBoxPos, SIGNAL(valueChanged(int)), this, SIGNAL(optionsChanged()));
00561   connect(options->LineEditMaxNeg, SIGNAL(textChanged(const QString&)), this, SIGNAL(optionsChanged()));
00562   connect(options->ColorButtonNeg, SIGNAL(newColor(QColor*)), this, SIGNAL(optionsChanged()));
00563   
00564   connect(options->SpinBoxNeg, SIGNAL(valueChanged(int)), this, SIGNAL(optionsChanged()));
00565   connect(options->CheckBoxAtoms, SIGNAL(toggled(bool)), this, SIGNAL(optionsChanged()));
00566   connect(options->LineEditAtoms, SIGNAL(textChanged(const QString&)), this, SIGNAL(optionsChanged()));
00567   connect(options->ColorButtonAtoms, SIGNAL(newColor(QColor*)), this, SIGNAL(optionsChanged()));
00568   connect(options->ColorButtonZero, SIGNAL(newColor(QColor*)), this, SIGNAL(optionsChanged()));  
00569 }
00570 
00572 void PlotMapBase::init()
00574 {
00575   mousePosition.setX(0);
00576   mousePosition.setY(0);
00577   resetOptions(); 
00578 }
00579 
00581 void PlotMapBase::updateImage()
00583 {
00584   if((numPoints.x() == 0) || (numPoints.y() == 0))
00585     return;
00586 
00587   if(options->ComboBoxStyle->currentItem() == 0)
00588     updatePixmap();
00589   else
00590     updateIsoLines();
00591   if(options->CheckBoxAtoms->isChecked())
00592     updateCrosses();
00593 
00594   plotLabel->setDrawStyle(options->ComboBoxStyle->currentItem(), options->ComboBoxInterpolation->currentItem() == 1); 
00595   plotLabel->setColors(options->ColorButtonZero->color(), options->ColorButtonAtoms->color());
00596   plotLabel->update();
00597 }
00598 
00600 void PlotMapBase::updatePixmap()
00602 {
00603   QPixmap showPixmap(numPoints.x(), numPoints.y());
00604   QPainter painter(&showPixmap);
00605 
00606   const double maxPlotValue = fabs(options->LineEditMaxPos->text().toDouble());
00607   const QColor positiveColor = options->ColorButtonPos->color();
00608   const bool useLevelsPos = options->SpinBoxPos->value() != 255;
00609   const int numLevelsPos = options->SpinBoxPos->value();  
00610   const double minPlotValue = - fabs(options->LineEditMaxNeg->text().toDouble());
00611   const QColor negativeColor = options->ColorButtonNeg->color();
00612   const bool useLevelsNeg = options->SpinBoxNeg->value() != 255;
00613   const int numLevelsNeg = options->SpinBoxNeg->value();    
00614   const QColor backgroundColor = options->ColorButtonZero->color();
00615       
00616   for(unsigned int j = 0; j < numPoints.y(); j++)
00617   {
00618     for(unsigned int i = 0; i < numPoints.x(); i++)
00619     {
00621       QColor pixelColor;
00622       if(points[j][i] > 0.0)
00623       {
00625         double intensity = 1.0;
00626         if(!useLevelsPos)
00627           intensity = points[j][i]/maxPlotValue;
00628         else
00629           intensity = floor(points[j][i]*double(numLevelsPos)/maxPlotValue + 0.5)/double(numLevelsPos);
00631         pixelColor = plotColor(positiveColor, backgroundColor, intensity);        
00632       }
00633       else
00634       {
00635         double intensity = 1.0;
00636         if(!useLevelsNeg)
00637           intensity = points[j][i]/minPlotValue;
00638         else
00639           intensity = floor(points[j][i]*double(numLevelsNeg)/minPlotValue + 0.5)/double(numLevelsNeg);  
00640         pixelColor = plotColor(negativeColor, backgroundColor, intensity);        
00641       }
00642       
00643       painter.setPen(pixelColor);
00644       painter.drawPoint(i, j);
00645     }
00646   }
00647   plotLabel->setDensityPixmap(showPixmap);
00648 }
00649 
00651 void PlotMapBase::updateCrosses()
00653 {
00654   const double showAtomsLimit = options->LineEditAtoms->text().toDouble();
00655       
00656   vector<Point3D<double> > showCoords;
00657   showCoords.reserve(numAtoms);
00658   Point3D<double>newCoord;
00659   if(options->CheckBoxAtoms->isChecked())
00660   {
00661     for(unsigned int i = 0; i < numAtoms; i++)
00662     {
00663       if(fabs(coords[i].z()) > showAtomsLimit)
00664         continue; 
00665 
00666       
00667       newCoord.setValues(coords[i].x() - origin.x(), coords[i].y() - origin.y(), 0.0);
00668       showCoords.push_back(newCoord);
00669     }
00670   }
00671   
00672   plotLabel->setCrosses(showCoords);
00673 }
00674 
00676 void PlotMapBase::updateIsoLines()
00682 {
00683   const double maxPlotValue = fabs(options->LineEditMaxPos->text().toDouble());
00684   const QColor positiveColor = options->ColorButtonPos->color();
00685   const int numLevelsPos = options->SpinBoxPos->value();  
00686   const double minPlotValue = - fabs(options->LineEditMaxNeg->text().toDouble());
00687   const QColor negativeColor = options->ColorButtonNeg->color();
00688   const int numLevelsNeg = options->SpinBoxNeg->value();    
00689   const QColor backgroundColor = options->ColorButtonZero->color();
00690 
00692   
00693   vector<double> isoLevels;
00694   isoLevels.reserve(numLevelsPos+numLevelsNeg);
00695   for(int i = 1; i <= numLevelsPos; i++) 
00696     isoLevels.push_back(static_cast<double>(i)/numLevelsPos * maxPlotValue);
00697   for(int i = 1; i <= numLevelsNeg; i++) 
00698     isoLevels.push_back(static_cast<double>(i)/numLevelsNeg * minPlotValue);
00699   
00700   vector<QColor> isoColors;
00701   isoColors.reserve(numLevelsPos+numLevelsNeg);
00702   for(int i = 0; i < numLevelsPos; i++)
00703     isoColors.push_back(plotColor(positiveColor, backgroundColor, isoLevels[i]/maxPlotValue));
00704   for(int i = numLevelsPos; i < numLevelsPos+numLevelsNeg; i++)
00705     isoColors.push_back(plotColor(negativeColor, backgroundColor, isoLevels[i]/minPlotValue));
00706   
00707   vector<QColor> lineColors;
00708   lineColors.reserve(numLevelsPos+numLevelsNeg);
00709   for(int i = 0; i < numLevelsPos; i++)
00710     lineColors.push_back(positiveColor);
00711   for(int i = numLevelsPos; i < numLevelsPos+numLevelsNeg; i++)
00712     lineColors.push_back(negativeColor);
00713 
00715   for(unsigned int i = 0; i < isoCurves.size(); i++)
00716     delete isoCurves[i];
00717   isoCurves.clear();
00718 
00720   
00721   vector< vector<Point3D<double> >* > segments;
00722   segments.reserve(isoLevels.size());
00723   
00724   vector<map<unsigned int, unsigned int>* > segmentMaps;
00725   segmentMaps.reserve(isoLevels.size());
00726   for(unsigned int i = 0; i < isoLevels.size(); i++)
00727   {
00728     vector<Point3D<double> >* newSegment = new vector<Point3D<double> >();
00729     segments.push_back(newSegment);
00730     map<unsigned int, unsigned int>* newMap = new map<unsigned int, unsigned int>();
00731     segmentMaps.push_back(newMap);
00732   }
00733 
00735   for(unsigned int y = 0; y < numPoints.y(); y++)
00736   {
00737     unsigned int currentSegment = y * (2*numPoints.x()-1);
00738     for(unsigned int x = 0; x < numPoints.x() - 1; x++)
00739     {
00742       for(unsigned int level = 0; level < isoLevels.size(); level++)
00743       {
00744         if( (points[y][x] <= isoLevels[level] && points[y][x+1] > isoLevels[level]) ||
00745             (points[y][x] > isoLevels[level] && points[y][x+1] <= isoLevels[level]) )
00746         {
00748           Point3D<double> point1(static_cast<double>(x), static_cast<double>(y), 0.0);
00749           Point3D<double> point2(static_cast<double>(x+1), static_cast<double>(y), 0.0);
00750           Point3D<double> result = interpolate2D(point1, point2, points[y][x], points[y][x+1], isoLevels[level]);
00751           result.setID(currentSegment);
00752           segments[level]->push_back(result);
00754           segmentMaps[level]->operator[](currentSegment) = segments[level]->size() - 1;
00755         }
00756       }
00757       currentSegment++;
00758     }
00759   }
00761   for(unsigned int y = 0; y < numPoints.y() - 1; y++)
00762   {
00763     unsigned int currentSegment = (2*y + 1)*numPoints.x() - y - 1; 
00764     for(unsigned int x = 0; x < numPoints.x(); x++)
00765     {
00768       for(unsigned int level = 0; level < isoLevels.size(); level++)
00769       {
00770         if( (points[y][x] <= isoLevels[level] && points[y+1][x] > isoLevels[level]) ||
00771             (points[y][x] > isoLevels[level] && points[y+1][x] <= isoLevels[level]))
00772         {
00774           Point3D<double> point1(static_cast<double>(x), static_cast<double>(y), 0.0);
00775           Point3D<double> point2(static_cast<double>(x), static_cast<double>(y+1), 0.0);
00776           Point3D<double> result = interpolate2D(point1, point2, points[y][x], points[y+1][x], isoLevels[level]);
00777           result.setID(currentSegment);
00778           segments[level]->push_back(result);
00780           segmentMaps[level]->operator[](currentSegment) = segments[level]->size() - 1;
00781         }
00782       }
00783       currentSegment++;
00784     }
00785   }
00786 
00788   const unsigned int totalSegments = (numPoints.x() - 1)*numPoints.y() + numPoints.x()*(numPoints.y() - 1);
00789   
00790   vector<QColor> lineCurveColors;
00791   vector< vector<Point3D<double> > > isoPolygons; 
00792   isoPolygons.reserve(numLevelsPos+numLevelsNeg); 
00793   for(unsigned int level = 0; level < isoLevels.size(); level++)
00794   {
00796     vector<bool> segmentVisited;
00797     segmentVisited.reserve(totalSegments);
00798     for(unsigned int i = 0; i < totalSegments; i++)
00799       segmentVisited.push_back(false);
00800 
00801     const unsigned int firstCurve = isoCurves.size(); 
00802     
00803     for(unsigned int segment = 0; segment < numPoints.x() - 1; segment++)
00804     {
00805       
00806       if(!segmentVisited[segment] && hasPoint(segment, level, segmentMaps))
00807       {
00808         startSearch(segment, level, false, segmentMaps, segmentVisited, segments);
00809         
00810         lineCurveColors.push_back(lineColors[level]);
00811       }
00812     }
00813     
00814     for(unsigned int segment = 2*(numPoints.x() - 1); segment < totalSegments; segment += 2*numPoints.x() - 1)
00815     {
00816       if(!segmentVisited[segment] && hasPoint(segment, level, segmentMaps))
00817       {
00818         startSearch(segment, level, false, segmentMaps, segmentVisited, segments);
00819         
00820         lineCurveColors.push_back(lineColors[level]);
00821      }
00822     }
00823     
00824     for(unsigned int segment = totalSegments - (numPoints.x() - 1); segment < totalSegments; segment++)
00825     {
00826       if(!segmentVisited[segment] && hasPoint(segment, level, segmentMaps))
00827       {
00828         startSearch(segment, level, false, segmentMaps, segmentVisited, segments);
00829         
00830         lineCurveColors.push_back(lineColors[level]);
00831       }
00832     }
00833     
00834     for(unsigned int segment = numPoints.x() - 1; segment < totalSegments; segment += 2*numPoints.x() - 1)
00835     {
00836       if(!segmentVisited[segment] && hasPoint(segment, level, segmentMaps))
00837       {
00838         startSearch(segment, level, false, segmentMaps, segmentVisited, segments);
00839         
00840         lineCurveColors.push_back(lineColors[level]);
00841      }
00842     }
00843 
00844     const unsigned int firstCircularCurve = isoCurves.size(); 
00845     
00846     for(unsigned int segment = 0; segment < totalSegments; segment++)
00847     {
00848       if(!segmentVisited[segment] && hasPoint(segment, level, segmentMaps))
00849       {
00850         startSearch(segment, level, true, segmentMaps, segmentVisited, segments);
00851         
00852         lineCurveColors.push_back(lineColors[level]);
00853       }        
00854     }
00855     const unsigned int lastCurve = isoCurves.size(); 
00856     
00857     vector<Point3D<double> > isoPolygon;
00858     Point3D<double> zeroPoint(0.0, 0.0, 0.0);
00859     
00860     
00861     if(firstCurve != firstCircularCurve)
00862     {
00863       
00864       
00865       
00866       vector<bool> curveAdded;
00867       curveAdded.reserve(firstCircularCurve - firstCurve);
00868       for(unsigned int i = firstCurve; i < firstCircularCurve; i++)
00869         curveAdded.push_back(false);
00870       
00871       isoPolygon.push_back(zeroPoint);
00872       
00873       isoPolygon.reserve(isoPolygon.size() + isoCurves[firstCurve]->size());
00874       isoPolygon.insert(isoPolygon.end(),isoCurves[firstCurve]->begin(), isoCurves[firstCurve]->end());
00875       curveAdded[0] = true;
00876       
00877       continuePolygon(firstCurve, firstCircularCurve, firstCurve, isoPolygon, curveAdded, isoCurves[firstCurve]->operator[](0), false, isoLevels[level]);
00878     }
00879     
00880     for(unsigned int i = firstCircularCurve; i < lastCurve; i++)
00881     {
00882       
00883       isoPolygon.push_back(zeroPoint);
00884       
00885       isoPolygon.reserve(isoPolygon.size() + isoCurves[i]->size());
00886       isoPolygon.insert(isoPolygon.end(),isoCurves[i]->begin(), isoCurves[i]->end());
00887     }
00888     
00889       
00890       isoPolygon.push_back(zeroPoint);
00891 
00892     
00893     isoPolygons.push_back(isoPolygon);
00894   }
00895 
00896   
00897   plotLabel->setIsoCurves(isoCurves, lineCurveColors);
00898   plotLabel->setPolygons(isoPolygons, isoColors);
00899 }
00900 
00902 QColor PlotMapBase::plotColor(const QColor foregroundColor, const QColor backgroundColor, const double opaqueness)
00905 {
00906   double intensity = opaqueness;
00907   limitRange(0.0, intensity, 1.0);
00908     
00909   int newRed = 1000, newGreen = 1000, newBlue = 1000;
00910 
00911   if(backgroundColor.red() == foregroundColor.red())
00912     newRed = backgroundColor.red();
00913   else if(backgroundColor.red() < foregroundColor.red())
00914     newRed = backgroundColor.red() + int(double(foregroundColor.red() - backgroundColor.red())*intensity);
00915   else
00916     newRed = foregroundColor.red() + int(double(backgroundColor.red() - foregroundColor.red())*(1.0 - intensity));
00917 
00918   if(backgroundColor.green() == foregroundColor.green())
00919     newGreen = backgroundColor.green();
00920   else if(backgroundColor.green() < foregroundColor.green())
00921     newGreen = backgroundColor.green() + int(double(foregroundColor.green() - backgroundColor.green())*intensity);
00922   else
00923     newGreen = foregroundColor.green() + int(double(backgroundColor.green() - foregroundColor.green())*(1.0 - intensity));
00924 
00925   if(backgroundColor.blue() == foregroundColor.blue())
00926     newBlue = backgroundColor.blue();
00927   else if(backgroundColor.blue() < foregroundColor.blue())
00928     newBlue = backgroundColor.blue() + int(double(foregroundColor.blue() - backgroundColor.blue())*intensity);
00929   else
00930     newBlue = foregroundColor.blue() + int(double(backgroundColor.blue() - foregroundColor.blue())*(1.0 - intensity));
00931 
00932   
00933     
00934   limitRange(0, newRed, 255);
00935   limitRange(0, newGreen, 255);
00936   limitRange(0, newBlue, 255);
00937       
00938   return QColor(newRed, newGreen, newBlue);
00939 }
00940 
00942 bool PlotMapBase::onPixmap(const QPoint position)
00944 {
00945   
00946 
00947 
00948 
00949 
00950 
00951 
00952 
00953   QRect rect = labelRect();
00954 
00955 
00956   return rect.contains(position);
00957 }
00958 
00960 QPoint PlotMapBase::mapToImage(const QPoint position)
00963 {
00964   QRect rect = labelRect();
00965   QPoint intermediate = position - rect.topLeft();
00966 
00967   return QPoint( intermediate.x()*numPoints.x()/rect.width(), 
00968                  intermediate.y()*numPoints.y()/rect.height() );
00969 
00970   
00971   
00972   
00973   
00974 }
00975 
00977 Point3D<double> PlotMapBase::interpolate2D(const Point3D<double>& point1, const Point3D<double>& point2, const double density1, const double density2, const double isoLevel)
00981 {
00982   Point3D<double> lowPoint, highPoint;
00983   double lowDensity, highDensity, mu;
00984   if(density1 < density2)
00985   {
00986     lowPoint = point1;
00987     highPoint = point2;
00988     lowDensity = density1;
00989     highDensity = density2;
00990   }
00991   else 
00992   {
00993     lowPoint = point2;
00994     highPoint = point1;
00995     lowDensity = density2;
00996     highDensity = density1;
00997   }
00998 
00999   if(highDensity == lowDensity)
01000     mu = 0.5;
01001   else
01002     mu = (isoLevel - lowDensity)/(highDensity - lowDensity);
01003   const double x = lowPoint.x() + mu*(highPoint.x() - lowPoint.x());
01004   const double y = lowPoint.y() + mu*(highPoint.y() - lowPoint.y());
01005 
01006   return Point3D<double>(x, y, 0.0);
01007 }
01008 
01010 bool PlotMapBase::hasPoint(const unsigned int segment, const unsigned int level, const vector<map<unsigned int, unsigned int>* >& segmentMaps)
01012 {
01013   
01014   return segmentMaps[level]->find(segment) != segmentMaps[level]->end();
01015 
01016 }
01017 
01019 Point3D<double> PlotMapBase::getPoint(const unsigned int segment, const unsigned int level, const vector<map<unsigned int, unsigned int>* >& segmentMaps, const vector< vector<Point3D<double> >* >& segments)
01021 {
01022   map<unsigned int, unsigned int>::iterator it = segmentMaps[level]->find(segment);
01023   if(it != segmentMaps[level]->end())
01024   {
01025     
01026     if(segment != segments[level]->at(it->second).id())
01027     {
01028       qDebug("asked for point corresponding to segment %d", segment);
01029       qDebug("returned point with ID %d", segments[level]->at(it->second).id());
01030     }
01031 
01032     return segments[level]->at(it->second);
01033   }
01034   else
01035     return Point3D<double>();
01036 }
01037 
01039 void PlotMapBase::startSearch(const unsigned int segment, const unsigned int level, const bool circular, const vector<map<unsigned int, unsigned int>* >& segmentMaps, vector<bool>& segmentVisited, const vector< vector<Point3D<double> >* >& segments)
01041 {
01043   vector<Point3D<double> >* newCurve = new vector<Point3D<double> >();
01044   isoCurves.push_back(newCurve);
01046   Point3D<double> firstPoint = getPoint(segment, level, segmentMaps, segments);
01047   newCurve->push_back(firstPoint);
01049   if(!circular)
01050     newCurve->push_back(firstPoint);
01052   segmentVisited[segment] = true;
01053   unsigned int oldSegment = segment;
01054   unsigned int newSegment = segment;
01055   if(circular)
01056   {
01057     
01058     
01059     
01060     oldSegment--;
01061   }
01062 
01063   
01064   
01065   
01066 
01067   
01068 
01069   Point3D<double> newPoint = firstPoint;
01070   unsigned int segment1, segment2, segment3;
01071   while(true)
01072   {
01075     if(!getNeighbours(newSegment, oldSegment, segment1, segment2, segment3))
01076     {
01077       if(circular)
01078         qDebug("end of curve reached although a circular curve is searched");
01079       
01080       
01081       
01082       newCurve->push_back(newPoint);
01083       
01084       return;           
01085     }
01086     else
01087     {
01088       
01089       bool segment1HasPoint = hasPoint(segment1, level, segmentMaps) && !segmentVisited[segment1];
01090       bool segment2HasPoint = hasPoint(segment2, level, segmentMaps) && !segmentVisited[segment2];
01091       bool segment3HasPoint = hasPoint(segment3, level, segmentMaps) && !segmentVisited[segment3];
01092 
01093       
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 
01107 
01108 
01109 
01110 
01111 
01112 
01113       if(segment1HasPoint && segment2HasPoint && segment3HasPoint)
01114       {
01115         
01116         
01117         
01118         
01119         oldSegment = newSegment;
01120         newSegment = segment1;
01121         newPoint = getPoint(newSegment, level, segmentMaps, segments);
01122         newCurve->push_back(newPoint);
01123         segmentVisited[newSegment] = true;
01124         
01125       }
01126       else if(!segment1HasPoint && !segment2HasPoint && !segment3HasPoint)
01127       {
01128         
01129         if(circular)
01130         {
01131           
01132           newCurve->push_back(firstPoint);
01133           
01134           return;
01135         }
01136         else
01137         {
01138           
01139           newCurve->push_back(newPoint);
01140           
01141           qDebug(" double last point : point %d: (%f, %f)", static_cast<int>(newCurve->size() - 1), newPoint.x(), newPoint.y());
01142           qDebug("end of non-circular curve reached in the middle of the field");
01143           qDebug(" current segment = %d, possibly next segments: %d, %d and %d", newSegment, segment1, segment2, segment3);
01144           qDebug(" point of current segment: (%f, %f)",newPoint.x(), newPoint.y());
01145           if(isHorizontal(newSegment))
01146             qDebug(" current segment is horizontal");
01147           else
01148             qDebug(" current segment is vertical");
01149           if(hasPoint(segment1, level, segmentMaps))
01150             qDebug(" segment1 has a point but is already visited");
01151           if(hasPoint(segment2, level, segmentMaps))
01152             qDebug(" segment2 has a point but is already visited");
01153           if(hasPoint(segment3, level, segmentMaps))
01154             qDebug(" segment3 has a point but is already visited");
01155           
01156           return;
01157         }
01158       }
01159       else
01160       {
01161         
01162         oldSegment = newSegment;
01163         if(segment1HasPoint)
01164           newSegment = segment1;
01165         else if(segment2HasPoint)
01166           newSegment = segment2;
01167         else
01168           newSegment = segment3;
01169         newPoint = getPoint(newSegment, level, segmentMaps, segments);
01170         newCurve->push_back(newPoint);
01171         segmentVisited[newSegment] = true;
01172         
01173 
01174       }      
01175     }
01176   }
01177 }
01178 
01180 bool PlotMapBase::getNeighbours(const unsigned int currentSegment, const unsigned int previousSegment, unsigned int& segment1, unsigned int& segment2, unsigned int& segment3)
01182 {
01184   if(currentSegment == previousSegment)
01185   {
01186     
01187     if(isHorizontal(currentSegment))
01188     {
01189       
01190       if(currentSegment < numPoints.x() - 1)
01191       {
01192         
01193         segment1 = currentSegment + numPoints.x() - 1;
01194         segment2 = currentSegment + 2*numPoints.x() - 1;
01195         segment3 = currentSegment + numPoints.x();
01196         return true;
01197       }
01198       else
01199       {
01200         
01201         segment1 = currentSegment - numPoints.x();
01202         segment2 = currentSegment + 1 - 2*numPoints.x();
01203         segment3 = currentSegment + 1 - numPoints.x();
01204         return true;
01205       }
01206     }
01207     else
01208     {
01209       
01210       if((currentSegment + 1 - numPoints.x()) % numPoints.x() == 0)
01211       {
01212         
01213         segment1 = currentSegment + 1 - numPoints.x();
01214         segment2 = currentSegment + 1;
01215         segment3 = currentSegment + numPoints.x();
01216         return true;
01217       }
01218       else
01219       {
01220         
01221         segment1 = currentSegment - numPoints.x();
01222         segment2 = currentSegment - 1;
01223         segment3 = currentSegment + numPoints.x() - 1;
01224       }
01225     }
01226   }
01227   else
01228   {
01229     
01230     
01231     if(isHorizontal(currentSegment))
01232     {
01233       if(previousSegment < currentSegment)
01234       {
01235         
01236         
01237         if(currentSegment >= (2*numPoints.x() - 1)*(numPoints.y() - 1))
01238           return false;
01239         else
01240         {
01241           segment1 = currentSegment + numPoints.x() - 1;
01242           segment2 = currentSegment + 2*numPoints.x() - 1;
01243           segment3 = currentSegment + numPoints.x();
01244           return true;
01245         }
01246       }
01247       else
01248       {
01249         
01250         if(currentSegment < numPoints.x())
01251           return false;
01252         else
01253         {
01254           segment1 = currentSegment - numPoints.x();
01255           segment2 = currentSegment + 1 - 2*numPoints.x();
01256           segment3 = currentSegment + 1 - numPoints.x();
01257           return true;
01258         }
01259       }
01260     }
01261     else
01262     {
01263       
01264       if(previousSegment == currentSegment - 1 || previousSegment == currentSegment - numPoints.x() || previousSegment == currentSegment + numPoints.x() - 1)
01265       {
01266         
01267         if((currentSegment - 2*(numPoints.x() - 1)) % (2*numPoints.x() - 1) == 0)
01268           return false;
01269         else
01270         {
01271           segment1 = currentSegment + 1 - numPoints.x();
01272           segment2 = currentSegment + 1;
01273           segment3 = currentSegment + numPoints.x();
01274           return true;
01275         }
01276       }
01277       else
01278       {
01279         
01280         if((currentSegment - (numPoints.x() - 1)) % (2*numPoints.x() - 1) == 0)
01281           return false;
01282         else
01283         {
01284           segment1 = currentSegment - numPoints.x();
01285           segment2 = currentSegment - 1;
01286           segment3 = currentSegment + numPoints.x() - 1;
01287           return true;
01288         }
01289       }
01290     }
01291   }
01292   return true;
01293 }
01294 
01296 bool PlotMapBase::isHorizontal(const unsigned int segment)
01298 {
01299   unsigned int currentSegment = 0;
01300   for(unsigned int y = 0; y < numPoints.y(); y++)
01301   {
01302     if(segment >= currentSegment && segment < currentSegment + numPoints.x() - 1)
01303       return true;
01304     currentSegment += 2*numPoints.x() - 1;
01305   }
01306   return false;
01307 }
01308 
01310 void PlotMapBase::continuePolygon(const unsigned int startCurve, const unsigned int endCurve, unsigned int currentCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const bool fromStart, const double isoLevel)
01312 {  
01314   
01315   Point3D<double> checkPoint;
01316   if(fromStart)
01317     checkPoint = isoCurves[currentCurve]->operator[](0);
01318   else
01319     checkPoint = isoCurves[currentCurve]->operator[](isoCurves[currentCurve]->size() - 1);
01320   
01321   
01322   
01323   
01324   
01325   if(static_cast<int>(checkPoint.y()) == 0)
01326   {
01327     
01328     if(fabs(points[0][static_cast<int>(checkPoint.x())]) > fabs(isoLevel))
01329     {
01330       
01331       
01332       nextPolygonCCWT(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01333     }
01334     else
01335     {
01336       
01337       
01338       nextPolygonCWT(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01339     }
01340   }
01341   else if(static_cast<unsigned int>(checkPoint.x()) == numPoints.x() - 1)
01342   {
01343     
01344     if(fabs(points[static_cast<int>(checkPoint.y())][numPoints.x() - 1]) > fabs(isoLevel))
01345     {
01346       
01347       
01348       nextPolygonCCWR(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01349     }
01350     else
01351     {
01352       
01353       
01354       nextPolygonCWR(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01355     }
01356   }
01357   else if(static_cast<unsigned int>(checkPoint.y()) == numPoints.y() - 1)
01358   {
01359     
01360 
01361 
01362 
01363 
01364 
01365     
01366     if(fabs(points[numPoints.y() - 1][static_cast<int>(checkPoint.x())]) > fabs(isoLevel))
01367     {
01368       
01369       
01370       nextPolygonCWB(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01371     }
01372     else
01373     {
01374       
01375       
01376       nextPolygonCCWB(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01377     }
01378   }
01379   else if(static_cast<int>(checkPoint.x()) == 0)
01380   {
01381     
01382     if(fabs(points[static_cast<int>(checkPoint.y())][0]) > fabs(isoLevel))
01383     {
01384       
01385       
01386       nextPolygonCWL(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01387     }
01388     else
01389     {
01390       
01391       
01392       nextPolygonCCWL(startCurve, endCurve, isoPolygon, curveAdded, startPoint, checkPoint, isoLevel);
01393     }
01394   }
01395 }
01396 
01398 void PlotMapBase::nextPolygonCCWT(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01400 {
01401   
01402   unsigned int nearestCurve = endCurve;
01403   Point3D<double> nearestPoint;
01404   bool nearestStart = false;
01405   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01406   {
01407     if(!curveAdded[curve - startCurve])
01408     {
01409       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01410       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01411       if(static_cast<int>(firstPoint.y()) == 0 && firstPoint.x() < refPoint.x())
01412       {
01413         
01414         if(nearestCurve == endCurve || firstPoint.x() > nearestPoint.x())
01415         {
01416           
01417           nearestCurve = curve;
01418           nearestPoint = firstPoint;
01419           nearestStart = true;
01420         }
01421       }
01422       else if(static_cast<int>(lastPoint.y()) == 0 && lastPoint.x() < refPoint.x())
01423       {
01424         if(nearestCurve == endCurve || lastPoint.x() > nearestPoint.x())
01425         {
01426           nearestCurve = curve;
01427           nearestPoint = lastPoint;
01428           nearestStart = false;
01429         }
01430       }
01431     }
01432   }
01433   
01434   if(nearestCurve == endCurve)
01435   {
01436     
01437     bool allVisited = true;
01438     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01439     {
01440       if(!curveAdded[i])
01441       {
01442         allVisited = false;
01443         break;
01444       }
01445     }
01446     if(allVisited)
01447     {
01448       
01449       if(static_cast<int>(startPoint.y()) == 0)
01450       {
01451         isoPolygon.push_back(startPoint);
01452         return;
01453       }
01454     }
01455     
01456     Point3D<double> zeroPoint(0.0, 0.0, 0.0);
01457     isoPolygon.push_back(zeroPoint);
01458     nextPolygonCCWL(startCurve, endCurve, isoPolygon, curveAdded, startPoint, zeroPoint, isoLevel);
01459   }
01460   else
01461   {
01462     
01463     curveAdded[nearestCurve - startCurve] = true;
01464     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01465     if(nearestStart)
01466     {
01467       
01468       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01469     }
01470     else
01471     {
01472       
01473       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01474     }
01475     
01476     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01477   }
01478 }
01479 
01481 void PlotMapBase::nextPolygonCWT(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01483 {  
01484   
01485   unsigned int nearestCurve = endCurve;
01486   Point3D<double> nearestPoint;
01487   bool nearestStart = false;
01488   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01489   {
01490     if(!curveAdded[curve - startCurve])
01491     {
01492       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01493       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01494       if(static_cast<int>(firstPoint.y()) == 0 && firstPoint.x() > refPoint.x())
01495       {
01496         
01497         if(nearestCurve == endCurve || firstPoint.x() < nearestPoint.x())
01498         {
01499           
01500           nearestCurve = curve;
01501           nearestPoint = firstPoint;
01502           nearestStart = true;
01503         }
01504       }
01505       else if(static_cast<int>(lastPoint.y()) == 0 && lastPoint.x() > refPoint.x())
01506       {
01507         if(nearestCurve == endCurve || lastPoint.x() < nearestPoint.x())
01508         {
01509           nearestCurve = curve;
01510           nearestPoint = lastPoint;
01511           nearestStart = false;
01512         }
01513       }
01514     }
01515   }
01516   
01517   if(nearestCurve == endCurve)
01518   {
01519     
01520     bool allVisited = true;
01521     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01522     {
01523       if(!curveAdded[i])
01524       {
01525         allVisited = false;
01526         break;
01527       }
01528     }
01529     if(allVisited)
01530     {
01531       
01532       if(static_cast<int>(startPoint.y()) == 0)
01533       {
01534         isoPolygon.push_back(startPoint);
01535         return;
01536       }
01537     }
01538     
01539     Point3D<double> cornerPoint(static_cast<double>(numPoints.x() - 1), 0.0, 0.0);
01540     isoPolygon.push_back(cornerPoint);
01541     nextPolygonCWR(startCurve, endCurve, isoPolygon, curveAdded, startPoint, cornerPoint, isoLevel);
01542   }
01543   else
01544   {
01545     
01546     curveAdded[nearestCurve - startCurve] = true;
01547     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01548     if(nearestStart)
01549     {
01550       
01551       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01552     }
01553     else
01554     {
01555       
01556       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01557     }
01558     
01559     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01560   }
01561 }
01562 
01564 void PlotMapBase::nextPolygonCCWR(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01566 {  
01567   
01568   unsigned int nearestCurve = endCurve;
01569   Point3D<double> nearestPoint;
01570   bool nearestStart = false;
01571   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01572   {
01573     if(!curveAdded[curve - startCurve])
01574     {
01575       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01576       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01577       if(static_cast<unsigned int>(firstPoint.x()) == numPoints.x() - 1 && firstPoint.y() < refPoint.y())
01578       {
01579         
01580         if(nearestCurve == endCurve || firstPoint.y() > nearestPoint.y())
01581         {
01582           
01583           nearestCurve = curve;
01584           nearestPoint = firstPoint;
01585           nearestStart = true;
01586         }
01587       }
01588       else if(static_cast<unsigned int>(lastPoint.x()) == numPoints.x() - 1 && lastPoint.y() < refPoint.y())
01589       {
01590         if(nearestCurve == endCurve || lastPoint.y() > nearestPoint.y())
01591         {
01592           nearestCurve = curve;
01593           nearestPoint = lastPoint;
01594           nearestStart = false;
01595         }
01596       }
01597     }
01598   }
01599   
01600   if(nearestCurve == endCurve)
01601   {
01602     
01603     
01604     bool allVisited = true;
01605     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01606     {
01607       if(!curveAdded[i])
01608       {
01609         allVisited = false;
01610         break;
01611       }
01612     }
01613     if(allVisited)
01614     {
01615       
01616       if(static_cast<unsigned int>(startPoint.x()) == numPoints.x() - 1)
01617       {
01618         isoPolygon.push_back(startPoint);
01619         return;
01620       }
01621     }
01622     
01623     
01624     Point3D<double> cornerPoint(static_cast<double>(numPoints.x() - 1), 0.0, 0.0);
01625     isoPolygon.push_back(cornerPoint);
01626     nextPolygonCCWT(startCurve, endCurve, isoPolygon, curveAdded, startPoint, cornerPoint, isoLevel);
01627   }
01628   else
01629   {
01630     
01631     
01632     curveAdded[nearestCurve - startCurve] = true;
01633     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01634     if(nearestStart)
01635     {
01636       
01637       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01638     }
01639     else
01640     {
01641       
01642       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01643     }
01644     
01645     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01646   }
01647 }
01648 
01650 void PlotMapBase::nextPolygonCWR(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01652 {  
01653   
01654   unsigned int nearestCurve = endCurve;
01655   Point3D<double> nearestPoint;
01656   bool nearestStart = false;
01657   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01658   {
01659     if(!curveAdded[curve - startCurve])
01660     {
01661       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01662       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01663       if(static_cast<unsigned int>(firstPoint.x()) == numPoints.x() - 1 && firstPoint.y() > refPoint.y())
01664       {
01665         
01666         if(nearestCurve == endCurve || firstPoint.y() < nearestPoint.y())
01667         {
01668           
01669           nearestCurve = curve;
01670           nearestPoint = firstPoint;
01671           nearestStart = true;
01672         }
01673       }
01674       else if(static_cast<unsigned int>(lastPoint.x()) == numPoints.x() - 1 && lastPoint.y() > refPoint.y())
01675       {
01676         if(nearestCurve == endCurve || lastPoint.y() < nearestPoint.y())
01677         {
01678           nearestCurve = curve;
01679           nearestPoint = lastPoint;
01680           nearestStart = false;
01681         }
01682       }
01683     }
01684   }
01685   
01686   if(nearestCurve == endCurve)
01687   {
01688     
01689     bool allVisited = true;
01690     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01691     {
01692       if(!curveAdded[i])
01693       {
01694         allVisited = false;
01695         break;
01696       }
01697     }
01698     if(allVisited)
01699     {
01700       
01701       if(static_cast<unsigned int>(startPoint.x()) == numPoints.x() - 1)
01702       {
01703         isoPolygon.push_back(startPoint);
01704         return;
01705       }
01706     }
01707     
01708     Point3D<double> cornerPoint(static_cast<double>(numPoints.x() - 1), static_cast<double>(numPoints.y() - 1), 0.0);
01709     isoPolygon.push_back(cornerPoint);
01710     nextPolygonCWB(startCurve, endCurve, isoPolygon, curveAdded, startPoint, cornerPoint, isoLevel);
01711   }
01712   else
01713   {
01714     
01715     curveAdded[nearestCurve - startCurve] = true;
01716     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01717     if(nearestStart)
01718     {
01719       
01720       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01721     }
01722     else
01723     {
01724       
01725       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01726     }
01727     
01728     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01729   }
01730 }
01731 
01733 void PlotMapBase::nextPolygonCCWB(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01735 {  
01736   
01737   unsigned int nearestCurve = endCurve;
01738   Point3D<double> nearestPoint;
01739   bool nearestStart = false;
01740   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01741   {
01742     if(!curveAdded[curve - startCurve])
01743     {
01744       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01745       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01746       if(static_cast<unsigned int>(firstPoint.y()) == numPoints.y() - 1 && firstPoint.x() > refPoint.x())
01747       {
01748         
01749         if(nearestCurve == endCurve || firstPoint.x() < nearestPoint.x())
01750         {
01751           
01752           nearestCurve = curve;
01753           nearestPoint = firstPoint;
01754           nearestStart = true;
01755         }
01756       }
01757       else if(static_cast<unsigned int>(lastPoint.y()) == numPoints.y() - 1 && lastPoint.x() > refPoint.x())
01758       {
01759         if(nearestCurve == endCurve || lastPoint.x() > nearestPoint.x())
01760         {
01761           nearestCurve = curve;
01762           nearestPoint = lastPoint;
01763           nearestStart = false;
01764         }
01765       }
01766     }
01767   }
01768   
01769   if(nearestCurve == endCurve)
01770   {
01771     
01772     bool allVisited = true;
01773     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01774     {
01775       if(!curveAdded[i])
01776       {
01777         allVisited = false;
01778         break;
01779       }
01780     }
01781     if(allVisited)
01782     {
01783       
01784       if(static_cast<unsigned int>(startPoint.y()) == numPoints.y() - 1)
01785       {
01786         isoPolygon.push_back(startPoint);
01787         return;
01788       }
01789     }
01790     
01791     Point3D<double> zeroPoint(static_cast<double>(numPoints.x() - 1), static_cast<double>(numPoints.y() - 1), 0.0);
01792     isoPolygon.push_back(zeroPoint);
01793     nextPolygonCCWR(startCurve, endCurve, isoPolygon, curveAdded, startPoint, zeroPoint, isoLevel);
01794   }
01795   else
01796   {
01797     
01798     curveAdded[nearestCurve - startCurve] = true;
01799     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01800     if(nearestStart)
01801     {
01802       
01803       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01804     }
01805     else
01806     {
01807       
01808       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01809     }
01810     
01811     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01812   }
01813 }
01814 
01816 void PlotMapBase::nextPolygonCWB(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01818 {  
01819   
01820   unsigned int nearestCurve = endCurve;
01821   Point3D<double> nearestPoint;
01822   bool nearestStart = false;
01823   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01824   {
01825     if(!curveAdded[curve - startCurve])
01826     {
01827       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01828       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01829       if(static_cast<unsigned int>(firstPoint.y()) == numPoints.y() - 1 && firstPoint.x() < refPoint.x())
01830       {
01831         
01832         if(nearestCurve == endCurve || firstPoint.x() > nearestPoint.x())
01833         {
01834           
01835           nearestCurve = curve;
01836           nearestPoint = firstPoint;
01837           nearestStart = true;
01838         }
01839       }
01840       else if(static_cast<unsigned int>(lastPoint.y()) == numPoints.y() - 1 && lastPoint.x() < refPoint.x())
01841       {
01842         if(nearestCurve == endCurve || lastPoint.x() > nearestPoint.x())
01843         {
01844           nearestCurve = curve;
01845           nearestPoint = lastPoint;
01846           nearestStart = false;
01847         }
01848       }
01849     }
01850   }
01851   
01852   if(nearestCurve == endCurve)
01853   {
01854     
01855     bool allVisited = true;
01856     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01857     {
01858       if(!curveAdded[i])
01859       {
01860         allVisited = false;
01861         break;
01862       }
01863     }
01864     if(allVisited)
01865     {
01866       
01867       if(static_cast<unsigned int>(startPoint.y()) == numPoints.y() - 1)
01868       {
01869         isoPolygon.push_back(startPoint);
01870         return;
01871       }
01872     }
01873     
01874     Point3D<double> cornerPoint(0.0, static_cast<double>(numPoints.y() - 1), 0.0);
01875     isoPolygon.push_back(cornerPoint);
01876     nextPolygonCWL(startCurve, endCurve, isoPolygon, curveAdded, startPoint, cornerPoint, isoLevel);
01877   }
01878   else
01879   {
01880     
01881     curveAdded[nearestCurve - startCurve] = true;
01882     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01883     if(nearestStart)
01884     {
01885       
01886       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01887     }
01888     else
01889     {
01890       
01891       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01892     }
01893     
01894     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01895   }
01896 }
01897 
01899 void PlotMapBase::nextPolygonCCWL(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01901 {  
01902   
01903   unsigned int nearestCurve = endCurve;
01904   Point3D<double> nearestPoint;
01905   bool nearestStart = false;
01906   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01907   {
01908     if(!curveAdded[curve - startCurve])
01909     {
01910       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01911       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
01912       if(static_cast<int>(firstPoint.x()) == 0 && firstPoint.y() > refPoint.y())
01913       {
01914         
01915         if(nearestCurve == endCurve || firstPoint.y() < nearestPoint.y())
01916         {
01917           
01918           nearestCurve = curve;
01919           nearestPoint = firstPoint;
01920           nearestStart = true;
01921         }
01922       }
01923       else if(static_cast<int>(lastPoint.x()) == 0 && lastPoint.y() > refPoint.y())
01924       {
01925         if(nearestCurve == endCurve || lastPoint.y() < nearestPoint.y())
01926         {
01927           nearestCurve = curve;
01928           nearestPoint = lastPoint;
01929           nearestStart = false;
01930         }
01931       }
01932     }
01933   }
01934   
01935   if(nearestCurve == endCurve)
01936   {
01937     
01938     bool allVisited = true;
01939     for(unsigned int i = 0; i < endCurve - startCurve; i++)
01940     {
01941       if(!curveAdded[i])
01942       {
01943         allVisited = false;
01944         break;
01945       }
01946     }
01947     if(allVisited)
01948     {
01949       
01950       if(static_cast<int>(startPoint.x()) == 0)
01951       {
01952         isoPolygon.push_back(startPoint);
01953         return;
01954       }
01955     }
01956     
01957     Point3D<double> cornerPoint(0.0, static_cast<double>(numPoints.y() - 1), 0.0);
01958     isoPolygon.push_back(cornerPoint);
01959     nextPolygonCCWB(startCurve, endCurve, isoPolygon, curveAdded, startPoint, cornerPoint, isoLevel);
01960   }
01961   else
01962   {
01963     
01964     
01965     
01966     
01967     curveAdded[nearestCurve - startCurve] = true;
01968     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
01969     if(nearestStart)
01970     {
01971       
01972       
01973       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
01974     }
01975     else
01976     {
01977       
01978       
01979       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
01980     }
01981     
01982     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
01983   }
01984 }
01985 
01987 void PlotMapBase::nextPolygonCWL(const unsigned int startCurve, const unsigned int endCurve, vector<Point3D<double> >& isoPolygon, vector<bool>& curveAdded, const Point3D<double>& startPoint, const Point3D<double>& refPoint, const double isoLevel)
01989 {  
01990   
01991   unsigned int nearestCurve = endCurve;
01992   Point3D<double> nearestPoint;
01993   bool nearestStart = false;
01994   for(unsigned int curve = startCurve; curve < endCurve; curve++)
01995   {
01996     if(!curveAdded[curve - startCurve])
01997     {
01998       Point3D<double> firstPoint = isoCurves[curve]->operator[](0); 
01999       Point3D<double> lastPoint = isoCurves[curve]->operator[](isoCurves[curve]->size() - 1); 
02000       if(static_cast<int>(firstPoint.x()) == 0 && firstPoint.y() < refPoint.y())
02001       {
02002         
02003         if(nearestCurve == endCurve || firstPoint.y() > nearestPoint.y())
02004         {
02005           
02006           nearestCurve = curve;
02007           nearestPoint = firstPoint;
02008           nearestStart = true;
02009         }
02010       }
02011       else if(static_cast<int>(lastPoint.x()) == 0 && lastPoint.y() < refPoint.y())
02012       {
02013         if(nearestCurve == endCurve || lastPoint.y() > nearestPoint.y())
02014         {
02015           nearestCurve = curve;
02016           nearestPoint = lastPoint;
02017           nearestStart = false;
02018         }
02019       }
02020     }
02021   }
02022   
02023   if(nearestCurve == endCurve)
02024   {
02025     
02026     bool allVisited = true;
02027     for(unsigned int i = 0; i < endCurve - startCurve; i++)
02028     {
02029       if(!curveAdded[i])
02030       {
02031         allVisited = false;
02032         break;
02033       }
02034     }
02035     if(allVisited)
02036     {
02037       
02038       if(static_cast<int>(startPoint.x()) == 0)
02039       {
02040         isoPolygon.push_back(startPoint);
02041         return;
02042       }
02043     }
02044     
02045     Point3D<double> cornerPoint(0.0, 0.0, 0.0);
02046     isoPolygon.push_back(cornerPoint);
02047     nextPolygonCWT(startCurve, endCurve, isoPolygon, curveAdded, startPoint, cornerPoint, isoLevel);
02048   }
02049   else
02050   {
02051     
02052     curveAdded[nearestCurve - startCurve] = true;
02053     isoPolygon.reserve(isoPolygon.size() + isoCurves[nearestCurve]->size());
02054     if(nearestStart)
02055     {
02056       
02057       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->begin(), isoCurves[nearestCurve]->end());
02058     }
02059     else
02060     {
02061       
02062       isoPolygon.insert(isoPolygon.end(),isoCurves[nearestCurve]->rbegin(), isoCurves[nearestCurve]->rend());
02063     }
02064     
02065     continuePolygon(startCurve, endCurve, nearestCurve, isoPolygon, curveAdded, startPoint, !nearestStart, isoLevel);
02066   }
02067 }
02068 
02070 QRect PlotMapBase::labelRect() const
02074 {
02075   
02076   QRect rect(plotLabel->geometry().topLeft() + plotLabel->contentsRect().topLeft(), plotLabel->contentsRect().size());
02077   
02078   
02079   const double aspectRatio = static_cast<double>(numPoints.x()) / numPoints.y();
02080   if(aspectRatio > static_cast<double>(rect.width()) / rect.height())
02081     rect.setHeight(static_cast<int>(rect.width() / aspectRatio));
02082   else
02083     rect.setWidth(static_cast<int>(rect.height() * aspectRatio));
02084 
02085   
02086   return rect;
02087 }
02088 
02090 template<typename T> void PlotMapBase::limitRange(const T& min, T& value, const T& max)
02092 {
02093   if(min < max)
02094   {
02095     if(value < min)
02096       value = min;
02097     else if(value > max)
02098       value = max;
02099   }
02100   else
02101   { 
02102     if(value < max)
02103       value = max;
02104     else if(value > min)
02105       value = min;
02106   }
02107 }
02108 
02112 const double PlotMapBase::AUTOANG = 1.0/1.889726342;
02113