00001 /*************************************************************************** 00002 glorbitalview.cpp - description 00003 ------------------- 00004 begin : Thu Nov 4 2004 00005 copyright : (C) 2004-2006 by Ben Swerts 00006 email : bswerts@users.sourceforge.net 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00019 00027 00028 00029 00031 00032 // C++ header files 00033 #include <cfloat> 00034 #include <cmath> 00035 00036 // Qt header files 00037 #include <qapplication.h> 00038 #include <qcolor.h> 00039 #include <qfiledialog.h> 00040 #include <qimage.h> 00041 #include <qmessagebox.h> 00042 #include <qprogressdialog.h> 00043 #include <qstringlist.h> 00044 #include <qtimer.h> 00045 00046 // Xbrabo header files 00047 #include "glorbitalview.h" 00048 #include <point3d.h> 00049 #include <quaternion.h> 00050 00054 00056 GLOrbitalView::GLOrbitalView(QWidget* parent, const char* name) : GLView(parent, name), 00057 colorPositive(QColor(0, 0, 255)), 00058 colorNegative(QColor(255, 0, 0)), 00059 maximumRadius(1.0f), 00060 scaleFactor(1.0f) 00062 { 00063 00064 } 00065 00067 GLOrbitalView::~GLOrbitalView() 00069 { 00070 00071 } 00072 00074 void GLOrbitalView::updateColors(QColor pos, QColor neg) 00076 { 00077 colorPositive = pos; 00078 colorNegative = neg; 00079 } 00080 00082 std::vector<Point3D<float> >* GLOrbitalView::getCoordinates() 00084 { 00085 return &coords; 00086 } 00087 00089 QMutex* GLOrbitalView::getMutex() 00091 { 00092 return &mutex; 00093 } 00094 00096 void GLOrbitalView::setMaximumRadius(const double radius) 00101 { 00102 maximumRadius = radius; 00103 scaleFactor = 10.0f/maximumRadius; // scale the radius of the bounding sphere to 10.0f 00104 zoomFit(false); // doesn't work correctly if called with (true), possibly calls updateGL() of base class 00105 updateGL(); 00106 } 00107 00108 /*//// updateValues //////////////////////////////////////////////////////////// 00109 void GLOrbitalView::updateValues(int atom, int n, int l, int m, QColor pos, QColor neg, int type, int resolution, float probability, int dots) 00110 { 00112 00113 //qDebug("updating GLorbitalView with atom = %d, n = %d, l = %d, m = %d, type = %d, res = %d, prob = %f, dots = %d", atom, n, l, m, type, resolution, probability, dots); 00114 atomNumber = static_cast<unsigned int>(atom); 00115 qnPrincipal = static_cast<unsigned int>(n); 00116 qnOrbital = static_cast<unsigned int>(l); 00117 qnMomentum = static_cast<int>(m); 00118 ASSERT(qnOrbital - abs(qnMomentum) >= 0); 00119 ASSERT(qnPrincipal > qnOrbital); 00120 00121 colorPositive = pos; 00122 colorNegative = neg; 00123 00124 ASSERT(probability > 0.0f); 00125 ASSERT(type >= 0 && type < 5); 00126 00128 unsigned int neededPrecision = PRECISION_UNKNOWN; 00129 if(type != 4) 00130 { 00132 // check whether the largest possible number ((4n)^n) can be represented by a float 00133 if(largestResult<float>(qnPrincipal, qnOrbital, qnMomentum, atomNumber) != HUGE_VAL) 00134 //if(powf(static_cast<float>(4 * atomNumber * qnPrincipal), qnPrincipal) != HUGE_VALF) 00135 neededPrecision = PRECISION_FLOAT; 00136 // by a double 00137 else if(pow(static_cast<double>(4 * atomNumber * qnPrincipal), qnPrincipal) != HUGE_VAL) 00138 neededPrecision = PRECISION_DOUBLE; 00139 // or by a long double 00140 else if(powl(static_cast<long double>(4 * atomNumber * qnPrincipal), qnPrincipal) != HUGE_VAL) 00141 neededPrecision = PRECISION_LONG_DOUBLE; 00142 } 00143 else 00144 { 00146 // check whether the largest possible number ((2l)!) can be represented by a float 00147 if(factorial<float>(2*qnOrbital) != HUGE_VAL) 00148 neededPrecision = PRECISION_FLOAT; 00149 // by a double 00150 else if(factorial<float>(2*qnOrbital) != HUGE_VAL) 00151 neededPrecision = PRECISION_DOUBLE; 00152 // or by a long double 00153 else if(factorial<float>(2*l) != HUGE_VAL) 00154 neededPrecision = PRECISION_LONG_DOUBLE; 00155 } 00156 qDebug("required precision = %d", neededPrecision); 00157 if(neededPrecision == PRECISION_UNKNOWN) 00158 { 00159 // QMessageBox 00160 qDebug("exceeded long double limits"); 00161 return; 00162 } 00163 if(neededPrecision != PRECISION_FLOAT) 00164 { 00165 qDebug("precision higher than float not implemented yet"); 00166 return; 00167 } 00168 00169 allowedToQuit = false; 00170 cancelRequested = false; 00171 qDebug("starting calc"); 00172 00173 switch(type) 00174 { 00175 case 0: getIsoProbability(static_cast<float>(resolution), probability); 00176 break; 00177 case 1: getAccumulatedProbability(static_cast<float>(resolution), probability); 00178 break; 00179 case 2: getRandomDots(static_cast<unsigned int>(dots)); 00180 break; 00181 case 3: getRadialPart(static_cast<float>(resolution)); 00182 break; 00183 case 4: getAngularPart(static_cast<float>(resolution)); 00184 } 00185 allowedToQuit = true; 00186 qDebug("maximum radius = %f (= %f n^2)", maximumRadius, maximumRadius/(n*n)); 00187 if(maximumRadius < 0.1f) maximumRadius = 0.1f; 00188 scaleFactor = 10.0f/maximumRadius; // scale the radius of the bounding sphere to 10.0f 00189 zoomFit(false); // doesn't work correctly if called with (true), possibly calls updateGL() of base class 00190 updateGL(); 00191 } 00192 */ 00193 00194 00198 00200 void GLOrbitalView::drawScene() 00203 { 00204 // scale if the boundaries exceed 100.0f (the far z-value) 00205 glScalef(scaleFactor, scaleFactor, scaleFactor); 00206 00207 //* 00209 glDisable(GL_LIGHTING); 00210 00211 glBegin(GL_POINTS); 00212 mutex.lock(); 00213 std::vector<Point3D<float> >::iterator it = coords.begin(); 00214 while(it != coords.end()) 00215 { 00216 if(it->id() == 1) 00217 qglColor(colorPositive); 00218 else 00219 qglColor(colorNegative); 00220 glVertex3f(it->x(), it->y(), it->z()); 00221 it++; 00222 } 00223 mutex.unlock(); 00224 glEnd(); 00225 // no use in making a display list as the coordinates might be updated at any time 00226 00227 /*// lines 00228 glBegin(GL_LINE_LOOP); 00229 00230 // loop over the indices 00231 const unsigned int maxPoints = qnOrbital == 0 ? 2*qnPrincipal -1 : 2*(qnPrincipal - qnOrbital); 00232 const unsigned int resolution = 20; 00233 00234 for(unsigned int i = 1; i <= maxPoints; i++) 00235 { 00236 // get 360/resolution phi's and draw a looped lines around them 00237 std::vector<float>::iterator itX = coordsX.begin(); 00238 std::vector<float>::iterator itY = coordsY.begin(); 00239 std::vector<float>::iterator itZ = coordsZ.begin(); 00240 std::vector<bool>::iterator itP = phase.begin(); 00241 std::vector<unsigned int>::iterator itI = index.begin(); 00242 00243 while(itX != coordsX.end()) 00244 { 00245 glBegin(GL_LINE_LOOP); 00246 unsigned int numPoints = 0; 00247 while(numPoints < resolution && itX != coordsX.end()) 00248 { 00249 if(*itI == i) 00250 { 00251 numPoints++; 00252 if(*itP) 00253 qglColor(QColor(255, 255, 0)); 00254 else 00255 qglColor(QColor(0, 255, 255)); 00256 glVertex3f(*itX, *itY, *itZ); 00257 } 00258 itX++; 00259 itY++; 00260 itZ++; 00261 itP++; 00262 itI++; 00263 } 00264 glEnd(); 00265 } 00266 } 00267 // other lines (180/resolution theta) 00268 for(unsigned int i = 1; i <= maxPoints; i++) 00269 { 00270 // fill some vectors with the data for the current point 00271 std::vector<float> lcoordsX, lcoordsY, lcoordsZ; 00272 std::vector<bool> lphase; 00273 00274 std::vector<float>::iterator itX = coordsX.begin(); 00275 std::vector<float>::iterator itY = coordsY.begin(); 00276 std::vector<float>::iterator itZ = coordsZ.begin(); 00277 std::vector<bool>::iterator itP = phase.begin(); 00278 std::vector<unsigned int>::iterator itI = index.begin(); 00279 while(itI != index.end()) 00280 { 00281 if(*itI == i) 00282 { 00283 lcoordsX.push_back(*itX); 00284 lcoordsY.push_back(*itY); 00285 lcoordsZ.push_back(*itZ); 00286 lphase.push_back(*itP); 00287 } 00288 itX++; 00289 itY++; 00290 itZ++; 00291 itP++; 00292 itI++; 00293 } 00294 00295 std::vector<float>::iterator itlX = lcoordsX.begin(); 00296 std::vector<float>::iterator itlY = lcoordsY.begin(); 00297 std::vector<float>::iterator itlZ = lcoordsZ.begin(); 00298 std::vector<bool>::iterator itlP = lphase.begin(); 00299 00300 for(unsigned int startPoint = 0; startPoint < resolution; startPoint++) 00301 { 00302 // start at each point and draw the line 00303 std::vector<float>::iterator itlX2 = itlX; 00304 std::vector<float>::iterator itlY2 = itlY; 00305 std::vector<float>::iterator itlZ2 = itlZ; 00306 std::vector<bool>::iterator itlP2 = itlP; 00307 unsigned int numPoints = 0; 00308 glBegin(GL_LINE_LOOP); 00309 while(itlX2 != lcoordsX.end()) 00310 { 00311 numPoints++; 00312 if(numPoints%resolution == 0) 00313 { 00314 if(*itlP2) 00315 qglColor(QColor(255, 255, 0)); 00316 else 00317 qglColor(QColor(0, 255, 255)); 00318 00319 glVertex3f(*itlX2, *itlY2, *itlZ2); 00320 } 00321 itlX2++; 00322 itlY2++; 00323 itlZ2++; 00324 itlP2++; 00325 } 00326 glEnd(); 00327 itlX++; 00328 itlY++; 00329 itlZ++; 00330 itlP++; 00331 if(itlX == lcoordsX.end()) break; 00332 } 00333 } 00334 */ 00335 } 00336 00338 float GLOrbitalView::boundingSphereRadius() 00340 { 00341 return static_cast<float>(maximumRadius*scaleFactor); 00342 } 00343