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