face.cpp

Go to the documentation of this file.
00001 /* ============================================================================
00002 'face.cpp' defines a Face class.
00003 
00004 Written by Nicholas Phillips.
00005 QT4 adaption by Michael R. Greason, ADNET, 27 August 2007
00006 ============================================================================ */
00007 /*
00008                         Fetch header files.
00009 */
00010 #include "face.h"
00011 #include "debug.h"
00012 #include "boundary.h"
00013 #include "heal.h"
00014 #include "map_exception.h"
00015 
00016 using namespace std;
00017 /* ----------------------------------------------------------------------------
00018 'zero' performs a zero check on a floating point value.
00019 
00020 Arguments:
00021         x - The value to test.
00022 
00023 Returned:
00024         res - The result.
00025 
00026 Written by Nicholas Phillips.
00027 ---------------------------------------------------------------------------- */
00028 inline float zero(float x)
00029 {
00030         return fabs(x) < 1e-8 ? 0 : x;
00031 }
00032 /* ----------------------------------------------------------------------------
00033 'min' returns the minimum of two values.
00034 
00035 Arguments:
00036         a,b - The two values.
00037 
00038 Returned:
00039         res - The result.
00040 
00041 Written by Nicholas Phillips.
00042 ---------------------------------------------------------------------------- */
00043 inline unsigned int min(const uint a, const uint b)
00044 {
00045         return a < b ? a : b;
00046 }
00047 /* ----------------------------------------------------------------------------
00048 'setRigging_NP' computes the cosine thetas (rigging) for a north-pole face.
00049 
00050 Arguments:
00051         nside     - The size of the map.
00052         costhetas - The cosine thetas.
00053         rad       - The radius of the projection.  Defaults to 1.
00054 
00055 Returned:
00056         Nothing.
00057 
00058 Written by Nicholas Phillips.
00059 ---------------------------------------------------------------------------- */
00060 void Face::setRigging_NP(const int nside, vector<double> &costhetas, double rad)
00061 {
00062         double ds = 1./nside;
00063         double s = 0, t = 0;
00064         Boundary lower;
00065         Boundary boundry0;
00066         Boundary boundry1;
00067 
00068         quadList.resize(nside);
00069         GLVertVI qli = quadList.begin();
00070         lower.set_eq( 0, 0.5*M_PI*(face+0.5), 1);
00071         for(int i = 0; i < nside; i++) {
00072                 t = 0;
00073                 qli->resize(2*(nside+1));
00074                 GLVertI pti = qli->begin();
00075                 bool boundry0_reset = false;
00076                 bool boundry1_reset = false;
00077                 boundry0.set_eq(costhetas[i],   lower(costhetas[i]),   -1);
00078                 boundry1.set_eq(costhetas[i+1], lower(costhetas[i+1]), -1);
00079                 for(int j = i; j <= i+nside; j++) {
00080                         pti->setVertS(acos(costhetas[j]),boundry0(costhetas[j]),rad);
00081                         pti->setTex(s,t);
00082                         ++pti;
00083 
00084                         pti->setVertS(acos(costhetas[j+1]),boundry1(costhetas[j+1]),rad);
00085                         pti->setTex(s+ds,t);
00086                         ++pti;
00087 
00088                         if( (costhetas[j] >= 2./3.) && ! boundry0_reset) {
00089                                 boundry0.set_np(costhetas[j],boundry0(costhetas[j]),face);
00090                                 boundry0_reset = true;
00091                         }
00092 
00093                         if( (costhetas[j+1 ]>= 2./3.) && ! boundry1_reset) {
00094                                 boundry1.set_np(costhetas[j+1],boundry1(costhetas[j+1]),face);
00095                                 boundry1_reset = true;
00096                         }
00097 
00098                         t += ds;
00099                 }
00100                 s += ds;
00101                 ++qli;
00102         }
00103         return;
00104 }
00105 /* ----------------------------------------------------------------------------
00106 'setRigging_SP' computes the cosine thetas (rigging) for a south-pole face.
00107 
00108 Arguments:
00109         nside     - The size of the map.
00110         costhetas - The cosine thetas.
00111         rad       - The radius of the projection.  Defaults to 1.
00112 
00113 Returned:
00114         Nothing.
00115 
00116 Written by Nicholas Phillips.
00117 ---------------------------------------------------------------------------- */
00118 void Face::setRigging_SP(const int nside, vector<double> &costhetas, double rad)
00119 {
00120         double ds = 1./nside;
00121         double s = 0, t = 0;
00122         double phi_boundry = 0.5*M_PI*(face-7);
00123         Boundary boundry0;
00124         Boundary boundry1;
00125 
00126         quadList.resize(nside);
00127         GLVertVI qli = quadList.begin();
00128         for(int i = 0; i < nside; i++) {
00129                 t = 0;
00130                 qli->resize(2*(nside+1));
00131                 GLVertI pti = qli->begin();
00132                 bool boundry0_reset = false;
00133                 bool boundry1_reset = false;
00134                 boundry0.set_sp(costhetas[i],   phi_boundry, face);
00135                 boundry1.set_sp(costhetas[i+1], phi_boundry, face);
00136                 for(int j = i; j <= i+nside; j++) {
00137                         pti->setVertS(acos(costhetas[j]),boundry0(costhetas[j]),rad);
00138                         pti->setTex(s,t);
00139                         ++pti;
00140 
00141                         pti->setVertS(acos(costhetas[j+1]),boundry1(costhetas[j+1]),rad);
00142                         pti->setTex(s+ds,t);
00143                         ++pti;
00144 
00145                         if( (costhetas[j] > (-2./3. - 0.001)) && ! boundry0_reset) {
00146                                 boundry0.set_eq(costhetas[j],boundry0(costhetas[j]),-1);
00147                                 boundry0_reset = true;
00148                         }
00149                         if( (costhetas[j+1] > (-2./3. - 0.001)) && ! boundry1_reset) {
00150                                 boundry1.set_eq(costhetas[j+1],boundry1(costhetas[j+1]),-1);
00151                                 boundry1_reset = true;
00152                         }
00153 
00154                         t += ds;
00155                 }
00156                 s += ds;
00157                 ++qli;
00158         }
00159         return;
00160 }
00161 /* ----------------------------------------------------------------------------
00162 'setRigging_EQ' computes the cosine thetas (rigging) for an equatorial face.
00163 
00164 Arguments:
00165         nside     - The size of the map.
00166         costhetas - The cosine thetas.
00167         rad       - The radius of the projection.  Defaults to 1.
00168 
00169 Returned:
00170         Nothing.
00171 
00172 Written by Nicholas Phillips.
00173 ---------------------------------------------------------------------------- */
00174 void Face::setRigging_EQ(const int nside, vector<double> &costhetas, double rad)
00175 {
00176         double ds = 1./nside;
00177         double s = 0, t = 0;
00178         Boundary lower;
00179         lower.set_eq(-2./3., 0.5*M_PI*(face-4), 1);
00180         Boundary boundry0;
00181         Boundary boundry1;
00182 
00183         quadList.resize(nside);
00184         GLVertVI qli = quadList.begin();
00185         for(int i = 0; i < nside; i++) {
00186                 t = 0;
00187                 qli->resize(2*(nside+1));
00188                 GLVertI pti = qli->begin();
00189                 boundry0.set_eq(costhetas[i],   lower(costhetas[i]),   -1);
00190                 boundry1.set_eq(costhetas[i+1], lower(costhetas[i+1]), -1);
00191                 for(int j = i; j <= i+nside; j++) {
00192                         pti->setVertS(acos(costhetas[j]),boundry0(costhetas[j]),rad);
00193                         pti->setTex(s,t);
00194                         ++pti;
00195 
00196                         pti->setVertS(acos(costhetas[j+1]),boundry1(costhetas[j+1]),rad);
00197                         pti->setTex(s+ds,t);
00198                         ++pti;
00199 
00200                         t += ds;
00201                 }
00202                 s += ds;
00203                 ++qli;
00204         }
00205         return;
00206 }
00207 /* ----------------------------------------------------------------------------
00208 'setRigging' computes the cosine thetas (rigging) for a face.
00209 
00210 Arguments:
00211         nside     - The size of the map.
00212         costhetas - The cosine thetas.
00213         viewmoll  - Projection to use:  true=mollweide, false=3D sphere.
00214         rad       - The radius of the projection.  Defaults to 1.
00215 
00216 Returned:
00217         Nothing.
00218 
00219 Written by Nicholas Phillips.
00220 ---------------------------------------------------------------------------- */
00221 void Face::setRigging(const int nside, vector<double> &costhetas,
00222         bool viewmoll, double rad)
00223 {
00224         double radius = viewmoll ? 1. : rad;
00225         if( face < 4)
00226                 setRigging_NP(nside,costhetas,radius);
00227         else if( face > 7)
00228                 setRigging_SP(nside,costhetas,radius);
00229         else
00230                 setRigging_EQ(nside,costhetas,radius);
00231         rigging_set = true;
00232 
00233         GLVertVI qli = quadList.begin();
00234         for(int i = 0; i < nside; i++) {
00235                 GLVertI pti = qli->begin();
00236                 GLVertI pti_end = qli->end();
00237                 for(; pti != pti_end; ++pti) {
00238                         pti->s = 0.25*pti->s + 0.25*(face % 4);
00239                         pti->t = 0.25*pti->t + 0.25*(face / 4);
00240                 }
00241                 ++qli;
00242         }
00243 
00244         if (viewmoll || showmoll) toMollweide(rad);
00245         
00246         return;
00247 }
00248 /* ----------------------------------------------------------------------------
00249 'draw' paints the face.
00250 
00251 Arguments:
00252         None.
00253 
00254 Returned:
00255         Nothing.
00256 
00257 Written by Nicholas Phillips.
00258 ---------------------------------------------------------------------------- */
00259 void Face::draw()
00260 {
00261         if (! rigging_set) {
00262                 throw (MapException(MapException::Other, 0,
00263                         "Face::draw:Rigging not set, face = "));;
00264         }
00265         
00266         if( showface6 && face != 6 ) return;
00267         
00268         QColor color;
00269         GLVertVI qli = quadList.begin();
00270         GLVertVI qli_end = quadList.end();
00271         GLVertI pti;
00272         GLVertI pti_end;
00273         
00274         unsigned int list = 0;
00275         for(; qli !=  qli_end; ++qli) {
00276                 pti_end = qli->end();
00277                 
00278                 if( true || (list==(quadList.size()/2)) ) {
00279                         
00280                         if( showrigging ) {
00281                                 glColor3f(1.0, 1.0, 1.0);
00282                                 glLineWidth(1.0);
00283                                 glBegin(GL_LINE_STRIP);
00284                                 for(pti = qli->begin(); pti != pti_end; ++pti) {
00285                                         pti->glSet();
00286                                 }
00287                                 
00288                                 glEnd();
00289                         }
00290                         if( showrigging ) {
00291                                 glLineWidth(3.0);
00292                                 glBegin(GL_LINE_STRIP);
00293                         }
00294                         else
00295                                 glBegin(GL_QUAD_STRIP);
00296                         
00297                         int pixel = 0;
00298                         for(pti = qli->begin(); pti != pti_end; ++pti) {
00299                                 
00300                                 if( showrigging ) {
00301                                         color.setHsv((int)(360*pixel/(qli->size()-1.)), 255, 255);
00302                                         glColor3f(color.red()/255.,color.green()/255.,color.blue()/255.);
00303                                 }
00304                                 pti->glSet();
00305                                 pixel++;
00306                         }
00307                         glEnd();
00308                         
00309                 }
00310                 list++;
00311         }
00312         return;
00313 }
00314 /* ----------------------------------------------------------------------------
00315 'toMollweide' computes the vertices assuming a Molleweide projection.  If
00316 the supplied radius is <1 then push the projection out of the screen so that
00317 it lies behind a projection with radius 1, when viewed from x < 0.
00318 
00319 Arguments:
00320         rad - The radius of the projection.  Defaults to 1.
00321 
00322 Returned:
00323         Nothing.
00324 
00325 Written by Nicholas Phillips.
00326 ---------------------------------------------------------------------------- */
00327 void Face::toMollweide(double rad)
00328 {
00329         double r = 1/sqrt(2.);
00330         double phi;
00331         double lambda;
00332         double x,y;
00333         
00334         int i = 0;
00335         for(GLVertVI qli = quadList.begin(); qli !=  quadList.end(); ++qli) {
00336                 int j = 0;
00337                 for(GLVertI pti = qli->begin(); pti != qli->end(); ++pti) {
00338                         phi = asin(pti->z);
00339                         lambda = atan2(pti->y,pti->x);
00340 			::toMollweide(phi, lambda, x, y);
00341                         if( (face == 2 || face == 10) && x > 0) x *= -1;
00342                         pti->y = r*x;
00343                         pti->z = r*y;
00344                         pti->x = (rad < 1.) ? -(rad - 1.) : 0;
00345                         j++;
00346                 }
00347                 i++;
00348         }
00349         if( face == 6 )
00350                 toMollweideBackfaceSplit();
00351 
00352         return;
00353 }
00354 /* ----------------------------------------------------------------------------
00355 'toMollweideBackfaceSplit' computes the vertices assuming a Molleweide
00356 projection in the face that needs to be split.
00357 
00358 Arguments:
00359         None.
00360 
00361 Returned:
00362         Nothing.
00363 
00364 Written by Nicholas Phillips.
00365 ---------------------------------------------------------------------------- */
00366 void Face::toMollweideBackfaceSplit(void)
00367 {
00368         if( face != 6 )
00369                 return;
00370         
00371         // copy the current list to temp storage
00372         GLVertVec oldquads;
00373         oldquads.resize(quadList.size());
00374         GLVertVI srcqli = quadList.begin();
00375         GLVertVI destqli = oldquads.begin();
00376         for(uint i = 0; i < quadList.size(); i++) {
00377                 destqli->resize(srcqli->size());
00378                 GLVertI srcpti = srcqli->begin();
00379                 GLVertI destpti = destqli->begin();
00380                 for( uint j = 0; j < srcqli->size(); j++)
00381                         *destpti++ = *srcpti++;
00382                 srcqli++;
00383                 destqli++;
00384         }
00385         
00386         // Now refill it, making the break along the back as needed
00387         srcqli = oldquads.begin();
00388         GLVertVI qli;
00389         quadList.resize(0);
00390         uint i = 0;
00391         for(srcqli = oldquads.begin(); srcqli != oldquads.end(); ++srcqli) {
00392                 i++;
00393                 
00394                 bool patch = true;      // need to patch the end of the left and start of the right sides
00395                 bool leftside = true;   // true while building the left side quadlist
00396                 
00397                 GLVertices newverts1;
00398                 GLVertices newverts2;
00399                 
00400                 uint jbreak = srcqli->size(); // vertex number of switch between left and right side
00401                 jbreak = 2*i-2;
00402                 for(uint j = 0; j < srcqli->size(); j++ ){
00403                         
00404                         GLPoint p = (*srcqli)[j];
00405                         if( leftside ) {
00406                                 p.y = -fabs(p.y);
00407                                 newverts1.push_back(p);
00408                                 leftside = j < jbreak;
00409                         }
00410                         else if( patch ) {
00411                                 
00412                                 p.y = -fabs(p.y);
00413                                 newverts1.push_back(p);
00414                                 
00415                                 GLPoint p2;
00416                                 GLVertVI qli = srcqli;
00417                                 qli++;
00418                                 if( qli != oldquads.end() ) {
00419                                         p2 = (*qli)[j+1];
00420                                         p2.y = -fabs(p2.y);
00421                                 }
00422                                 else {
00423                                         p2.y = -1.66597;
00424                                         p2.z =  0.553293;
00425                                         p2.s = 0.75;
00426                                         p2.t = 0.5;
00427                                 }
00428                                 newverts1.push_back(p2);
00429                                 newverts1.push_back(p);
00430                                 
00431                                 
00432                                 // Patch the beginning of the right side of the split face
00433                                 p = (*srcqli)[j+1];
00434                                 p.y = fabs(p.y);
00435                                 if( srcqli != oldquads.begin() ) {
00436                                         qli = srcqli;
00437                                         qli--;
00438                                         p2 = (*qli)[j];
00439                                         p2.y = fabs(p2.y);
00440                                 }
00441                                 else {
00442                                         p2.y =  1.66597;
00443                                         p2.z = -0.553293;
00444                                         p2.s = 0.5;
00445                                         p2.t = 0.25;
00446                                 }
00447                                 newverts2.push_back(p);
00448                                 newverts2.push_back(p2);
00449                                 
00450                                 patch = false;
00451                         }
00452                         else {
00453                                 p.y = fabs(p.y);
00454                                 newverts2.push_back(p);
00455                         }
00456                         
00457                 }
00458                 quadList.push_back(newverts1);
00459                 quadList.push_back(newverts2);
00460         }
00461         return;
00462 }

Generated on Fri Feb 6 15:32:42 2009 for Skyviewer by  doxygen 1.4.7