#include "spherethetaphi.h" #include "nbmath.h" #include #include "piocmplx.h" #include #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template SphereThetaPhi #pragma define_template SphereThetaPhi #pragma define_template SphereThetaPhi< complex > #pragma define_template SphereThetaPhi< complex > #pragma define_template FIO_SphereThetaPhi #pragma define_template FIO_SphereThetaPhi #pragma define_template FIO_SphereThetaPhi< complex > #pragma define_template FIO_SphereThetaPhi< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class SphereThetaPhi; template class SphereThetaPhi; template class SphereThetaPhi< complex >; template class SphereThetaPhi< complex >; template class FIO_SphereThetaPhi; template class FIO_SphereThetaPhi; template class FIO_SphereThetaPhi< complex >; template class FIO_SphereThetaPhi< complex >; #endif //*************************************************************** //++ // Class SphereThetaPhi // // // include spherethetaphi.h nbmath.h // // Découpage de la sphère selon theta et phi, chaque // hémisphère étant découpé en (m-1) parallèles (l'équateur compte pour du // beurre), chacune des m bandes de theta ainsi définies étant découpée par // des méridiens équirepartis, ce découpage étant fait de sorte que tous // les pixels aient la même surface et soient le plus carré possible. // On commence par découper l'hémisphère de z positif en partant du pôle et // en allant vers l'équateur. Le premier pixel est la calotte polaire, // il est circulaire et centré sur theta=0. //-- //++ // // Links Parents // // SphericalMap //-- //++ // // Links Descendants // // //-- /* --Methode-- */ //++ // Titre Constructeurs //-- //++ template SphereThetaPhi::SphereThetaPhi() //-- { InitNul(); } /* --Methode-- */ //++ template SphereThetaPhi::SphereThetaPhi(char* flnm) // Constructeur : charge une image à partir d'un fichier //-- { InitNul(); cout << " ShereThetaPhi:: constructeur lecture sur fichier A FAIRE " << endl; //PInPersist s(flnm); //Read(s); } /* --Methode-- */ //++ template SphereThetaPhi::SphereThetaPhi(int_4 m) // Constructeur : m est le nombre de bandes en theta sur un hémisphère // (la calotte constituant la premiere bande). // pet est le nombre de pixels (pétales) de la bande en contact avec la // calotte polaire. Pour l'instant pet est inopérant! //-- { InitNul(); Pixelize(m); } template SphereThetaPhi::SphereThetaPhi(const SphereThetaPhi& s) { if(s.mInfo_) mInfo_= new DVList(*s.mInfo_); NTheta_= s.NTheta_; NPix_ = s.NPix_; NPhi_ = new int_4[NTheta_]; Theta_ = new r_4[NTheta_+1]; TNphi_ = new int_4[NTheta_+1]; for(int k = 0; k < NTheta_; k++) { NPhi_[k] = s.NPhi_[k]; Theta_[k]= s.Theta_[k]; TNphi_[k]= s.TNphi_[k]; } Theta_[NTheta_]= s.Theta_[NTheta_]; TNphi_[NTheta_]= s.TNphi_[NTheta_]; Omega_ = s.Omega_; pixels_= s.pixels_; } //++ // Titre Destructeur //-- //++ template SphereThetaPhi::~SphereThetaPhi() //-- { Clear(); } //++ // Titre Méthodes //-- template void SphereThetaPhi::InitNul() // // initialise à zéro les variables de classe pointeurs { NTheta_= 0; NPix_ = 0; Theta_ = NULL; NPhi_ = NULL; TNphi_ = NULL; pixels_.Reset(); } /* --Methode-- */ template void SphereThetaPhi::Clear() { if(Theta_) delete[] Theta_; if(NPhi_ ) delete[] NPhi_; if(TNphi_) delete[] TNphi_; InitNul(); } //++ template void SphereThetaPhi::Resize(int_4 m) // re-pixelize the sphere //-- { Clear(); Pixelize(m); } /* --Methode-- */ //++ template int_4 SphereThetaPhi::NbPixels() const // Retourne le nombre de pixels du découpage //-- { return(NPix_); } /* --Methode-- */ //++ template T& SphereThetaPhi::PixVal(int_4 k) // Retourne la valeur du contenu du pixel d'indice k //-- { if((k < 0) || (k >= NPix_)) { // THROW(out_of_range("SphereThetaPhi::PIxVal Pixel index out of range")); cout << " SphereThetaPhi::PIxVal : exceptions a mettre en place" < T const& SphereThetaPhi::PixVal(int_4 k) const // Retourne la valeur du contenu du pixel d'indice k //-- { if((k < 0) || (k >= NPix_)) { cout << " SphereThetaPhi::PIxVal : exceptions a mettre en place" < int_4 SphereThetaPhi::PixIndexSph(r_4 theta, r_4 phi) const // Retourne l'indice du pixel vers lequel pointe une direction définie par // ses coordonnées sphériques //-- { r_4 dphi; int_4 i,j,k; bool fgzn = false; if( (theta > (r_4)Pi) || (theta < 0. ) ) return(-1); if( (phi < 0.) || (phi > DeuxPi) ) return(-1); if( theta > (r_4)Pi*0.5) { fgzn = true; theta = Pi-theta; } // La bande d'indice kt est limitée par les valeurs de theta contenues dans // Theta_[kt] et Theta_[kt+1] for( i=1; i< NTheta_; i++ ) if( theta < Theta_[i] ) break; dphi= (r_4)DeuxPi/(r_4)NPhi_[i-1]; if (fgzn) k= NPix_-TNphi_[i]+(int_4)(phi/dphi); else k= TNphi_[i-1]+(int_4)(phi/dphi); return(k); } /* --Methode-- */ //++ template void SphereThetaPhi::PixThetaPhi(int_4 k, r_4& theta, r_4& phi) const // Retourne les coordonnées (theta,phi) du milieu du pixel d'indice k //-- { int_4 i; bool fgzn = false; if( (k < 0) || (k >= NPix_) ) {theta = -99999.; phi = -99999.; return; } if( k >= NPix_/2) {fgzn = true; k = NPix_-1-k; } // recupère l'indice i de la tranche qui contient le pixel k for( i=0; i< NTheta_; i++ ) if( k < TNphi_[i+1] ) break; // angle theta theta= 0.5*(Theta_[i]+Theta_[i+1]); if (fgzn) theta= Pi-theta; // angle phi k -= TNphi_[i]; phi= (r_4)DeuxPi/(r_4)NPhi_[i]*(r_4)(k+.5); if (fgzn) phi= DeuxPi-phi; } //++ template r_8 SphereThetaPhi::PixSolAngle(int_4 dummy) const // Pixel Solid angle (steradians) // All the pixels have the same solid angle. The dummy argument is // for compatibility with eventual pixelizations which would not // fulfil this requirement. //-- { return Omega_; } /* --Methode-- */ //++ template void SphereThetaPhi::Limits(int_4 k, r_4& tetMin, r_4& tetMax, r_4& phiMin, r_4& phiMax) // Retourne les valeurs de theta et phi limitant le pixel d'indice k //-- { int_4 j; r_4 dphi; bool fgzn= false; if( (k< 0) || (k >= NPix_) ) { tetMin= -99999.; phiMin= -99999.; tetMax= -99999.; phiMax= -99999.; return; } // si on se trouve dans l'hémisphère Sud if( k >= NPix_/2 ) { fgzn= true; k= NPix_-1-k; } // on recupere l'indice i de la tranche qui contient le pixel k int i; for( i=0; i< NTheta_; i++ ) if( k< TNphi_[i+1] ) break; // valeurs limites de theta dans l'hemisphere Nord tetMin= Theta_[i]; tetMax= Theta_[i+1]; // valeurs limites de theta dans l'hemisphere Sud if (fgzn) { tetMin= Pi-Theta_[i+1]; tetMax= Pi-Theta_[i]; } // pixel correspondant dans l'hemisphere Nord if (fgzn) k= TNphi_[i+1]-k+TNphi_[i]-1; // indice j de discretisation ( phi= j*dphi ) j= k-TNphi_[i]; dphi= (r_4)DeuxPi/(r_4)NPhi_[i]; // valeurs limites de phi phiMin= dphi*(r_4)(j); phiMax= dphi*(r_4)(j+1); return; } /* --Methode-- */ //++ template int_4 SphereThetaPhi::NbThetaSlices() const // Retourne le nombre de tranches en theta sur la sphere //-- { int_4 nbslices; nbslices= 2*NTheta_; return(nbslices); } /* --Methode-- */ //++ template int_4 SphereThetaPhi::NPhi(int_4 kt) const // Retourne le nombre de pixels en phi de la tranche kt //-- { int_4 nbpix; // verification if( (kt< 0) || (kt>= 2*NTheta_) ) return(-1); // si on se trouve dans l'hemisphere Sud if( kt >= NTheta_ ) { kt= 2*NTheta_-1-kt; } // nombre de pixels nbpix= NPhi_[kt]; return(nbpix); } /* --Methode-- */ //++ template void SphereThetaPhi::Theta(int_4 kt,r_4& tetMin,r_4& tetMax) // Retourne les valeurs de theta limitant la tranche kt //-- { bool fgzn= false; // verification if( (kt< 0) || (kt>= 2*NTheta_) ) { tetMin= -99999.; tetMax= -99999.; return; } // si on se trouve dans l'hemisphere Sud if( kt >= NTheta_ ) { fgzn= true; kt= 2*NTheta_-1-kt; } // valeurs limites de theta dans l'hemisphere Nord tetMin= Theta_[kt]; tetMax= Theta_[kt+1]; // valeurs limites de theta dans l'hemisphere Sud if (fgzn) { tetMin= Pi-Theta_[kt+1]; tetMax= Pi-Theta_[kt]; } } /* --Methode-- */ //++ template void SphereThetaPhi::Phi(int_4 kt,int_4 jp,r_4& phiMin,r_4& phiMax) // Retourne les valeurs de phi limitant le pixel jp de la tranche kt //-- { // verification if( (kt< 0) || (kt>= 2*NTheta_) ) { phiMin= -99999.; phiMax= -99999.; return; } // si on se trouve dans l'hemisphere Sud if( kt >= NTheta_ ) kt= 2*NTheta_-1-kt; // verifie si la tranche kt contient au moins jp pixels if( (jp< 0) || (jp >= NPhi_[kt]) ) { phiMin= -88888.; phiMax= -88888.; return; } r_4 dphi= (r_4)DeuxPi/(r_4)NPhi_[kt]; phiMin= dphi*(r_4)(jp); phiMax= dphi*(r_4)(jp+1); return; } /* --Methode-- */ //++ template int_4 SphereThetaPhi::Index(int_4 kt,int_4 jp) const // Retourne l'indice du pixel d'indice jp dans la tranche kt //-- { int_4 k; bool fgzn= false; // si on se trouve dans l'hemisphere Sud if( kt >= NTheta_ ) { fgzn= true; kt= 2*NTheta_-1-kt; } // si la tranche kt contient au moins i pixels if( (jp>=0) && (jp void SphereThetaPhi::ThetaPhiIndex(int_4 k,int_4& kt,int_4& jp) // Retourne les indices kt et jp du pixel d'indice k //-- { bool fgzn= false; // si on se trouve dans l'hemisphere Sud if( k >= NPix_/2 ) { fgzn= true; k= NPix_-1-k; } // on recupere l'indice kt de la tranche qui contient le pixel k int i; for( i=0; i< NTheta_; i++ ) if( k< TNphi_[i+1] ) break; // indice kt de tranche if (fgzn) kt= 2*NTheta_-1-i; else kt= i; // indice jp de pixel if (fgzn) jp= TNphi_[i+1]-k-1; else jp= k-TNphi_[i]; } //++ template void SphereThetaPhi::Pixelize( int_4 m) // effectue le découpage en pixels (m et pet ont la même signification // que pour le constructeur) // // Chaque bande de theta sera découpée en partant de phi=0 ... // L'autre hémisphère est parcourue dans le même sens en phi et de // l'équateur vers le pôle (le pixel qui suit le dernier de la bande la plus // proche de l'équateur a z>0 est celui de plus petit phi de la bande la // plus proche de l'equateur a z<0). //-- { int_4 ntotpix,i,j; // Decodage et controle des arguments d'appel : // au moins 2 et au plus 16384 bandes d'un hemisphere en theta if (m < 2) m = 2; if (m > 16384) m = 16384; // On memorise les arguments d'appel NTheta_ = m; // On commence par decouper l'hemisphere z>0. // Creation des vecteurs contenant : // Les valeurs limites de theta (une valeur de plus que le nombre de bandes...) Theta_= new r_4[m+1]; // Le nombre de pixels en phi de chacune des bandes en theta NPhi_ = new int_4[m]; // Le nombre/Deuxpi total des pixels contenus dans les bandes de z superieur a une // bande donnee (mTPphi[m] contient le nombre de pixels total de l'hemisphere) TNphi_= new int_4[m+1]; // Calcul du nombre total de pixels dans chaque bande pour optimiser // le rapport largeur/hauteur des pixels //calotte polaire TNphi_[0]= 0; NPhi_[0] = 1; //bandes jusqu'a l'equateur for(j = 1; j < m; j++) { TNphi_[j]= TNphi_[j-1]+NPhi_[j-1]; NPhi_[j] = (int_4)(.5+4.*(double)(m-.5)*sin(Pi*(double)j/(double)(2.*m-1.))) ; } // Nombre total de pixels sur l'hemisphere ntotpix = TNphi_[m-1]+NPhi_[m-1]; TNphi_[m]= ntotpix; // et sur la sphere entiere NPix_= 2*ntotpix; // Creation et initialisation du vecteur des contenus des pixels pixels_.ReSize(NPix_); pixels_.Reset(); // Determination des limites des bandes en theta : // omeg est l'angle solide couvert par chaque pixel, // une bande donnee kt couvre un angle solide NPhi_[kt]*omeg // egal a 2* Pi*(cos Theta_[kt]-cos Theta_[kt+1]). De meme, l'angle solide //de la // calotte allant du pole a la limite haute de la bande kt vaut // 2* Pi*(1.-cos Theta_[kt+1])= TNphi_[kt]*omeg... double omeg2pi= 1./(double)ntotpix; Omega_ = omeg2pi*DeuxPi; for(j=0; j <= m; j++) { Theta_[j]= acos(1.-(double)TNphi_[j]*omeg2pi); } } //++ template void SphereThetaPhi::GetThetaSlice(int_4 index, r_4& theta, TVector& phi, TVector& value) const // Retourne, pour la tranche en theta d'indice 'index' le theta // correspondant, un vecteur (Peida) contenant les phi des pixels de // la tranche, un vecteur (Peida) contenant les valeurs de pixel // correspondantes //-- { cout << "entree GetThetaSlice, couche no " << index << endl; if(index < 0 || index > NbThetaSlices()) { // THROW(out_of_range("SphereThetaPhi::PIxVal Pixel index out of range")); cout << " SphereThetaPhi::GetThetaSlice : exceptions a mettre en place" <NPhi(index); int lring = bid; cout << " iring= " << iring << " lring= " << lring << endl; phi.ReSize(lring); value.ReSize(lring); float Te= 0.; float Fi= 0.; for(int kk = 0; kk < lring; kk++) { PixThetaPhi(kk+iring,Te,Fi); phi(kk)= Fi; value(kk)= PixVal(kk+iring); } theta= Te; } template void SphereThetaPhi::setmNPhi(int_4* array, int_4 m) //remplit le tableau contenant le nombre de pixels en phi de chacune des bandes en theta //-- { NPhi_= new int_4[m]; for(int k = 0; k < m; k++) NPhi_[k]= array[k]; } template void SphereThetaPhi::setmTNphi(int_4* array, int_4 m) //remplit le tableau contenant le nombre/Deuxpi total des pixels contenus dans les bandes //-- { TNphi_= new int_4[m]; for(int k = 0; k < m; k++) TNphi_[k]= array[k]; } template void SphereThetaPhi::setmTheta(r_4* array, int_4 m) //remplit le tableau contenant les valeurs limites de theta //-- { Theta_= new r_4[m]; for(int k = 0; k < m; k++) Theta_[k]= array[k]; } template void SphereThetaPhi::setDataBlock(T* data, int_4 m) // remplit le vecteur des contenus des pixels { pixels_.FillFrom(m,data); } template void SphereThetaPhi::print(ostream& os) const { if(mInfo_) os << " DVList Info= " << *mInfo_ << endl; // os << " NTheta_= " << NTheta_ << endl; os << " NPix_ = " << NPix_ << endl; os << " Omega_ = " << Omega_ << endl; os << " contenu de NPhi_ : "; for(int i=0; i < NTheta_; i++) { if(i%5 == 0) os << endl; os << NPhi_[i] <<", "; } os << endl; os << " contenu de Theta_ : "; for(int i=0; i < NTheta_+1; i++) { if(i%5 == 0) os << endl; os << Theta_[i] <<", "; } os << endl; os << " contenu de TNphi_ : "; for(int i=0; i < NTheta_+1; i++) { if(i%5 == 0) os << endl; os << TNphi_[i] <<", "; } os << endl; os << " contenu de pixels : "; for(int i=0; i < NPix_; i++) { if(i%5 == 0) os << endl; os << pixels_(i) <<", "; } os << endl; } /////////////////////////////////////////////////////////// // -------------------------------------------------------- // Les objets delegues pour la gestion de persistance // -------------------------------------------------------- ////////////////////////////////////////////////////////// template FIO_SphereThetaPhi::FIO_SphereThetaPhi() { dobj= new SphereThetaPhi; ownobj= true; } template FIO_SphereThetaPhi::FIO_SphereThetaPhi(string const& filename) { dobj= new SphereThetaPhi; ownobj= true; Read(filename); } template FIO_SphereThetaPhi::FIO_SphereThetaPhi(const SphereThetaPhi& obj) { dobj= new SphereThetaPhi(obj); ownobj= true; } template FIO_SphereThetaPhi::FIO_SphereThetaPhi(SphereThetaPhi* obj) { dobj= obj; ownobj= false; } template FIO_SphereThetaPhi::~FIO_SphereThetaPhi() { if (ownobj && dobj) delete dobj; } template AnyDataObj* FIO_SphereThetaPhi::DataObj() { return(dobj); } template void FIO_SphereThetaPhi::ReadSelf(PInPersist& is) { cout << " FIO_SphereThetaPhi:: ReadSelf " << endl; if(dobj == NULL) { dobj= new SphereThetaPhi; } // Pour savoir s'il y avait un DVList Info associe char strg[256]; is.GetLine(strg, 255); bool hadinfo= false; if(strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0) hadinfo= true; if(hadinfo) { // Lecture eventuelle du DVList Info is >> dobj->Info(); } int_4 mNTheta; is.GetI4(mNTheta); dobj->setSizeIndex(mNTheta); int_4 mNPix; is.GetI4(mNPix); dobj->setNbPixels(mNPix); r_8 mOmeg; is.GetR8(mOmeg); dobj->setPixSolAngle(mOmeg); int_4* mNphi= new int_4[mNTheta]; is.GetI4s(mNphi, mNTheta); dobj->setmNPhi(mNphi, mNTheta); delete [] mNphi; int_4* mTNphi= new int_4[mNTheta+1]; is.GetI4s(mTNphi, mNTheta+1); dobj->setmTNphi(mTNphi, mNTheta+1); delete [] mTNphi; r_4* mTheta= new r_4[mNTheta+1]; is.GetR4s(mTheta, mNTheta+1); dobj->setmTheta(mTheta, mNTheta+1); delete [] mTheta; T* mPixels= new T[mNPix]; //is.Get(mPixels, mNPix); PIOSReadArray(is, mPixels, mNPix); dobj->setDataBlock(mPixels, mNPix); delete [] mPixels; } template void FIO_SphereThetaPhi::WriteSelf(POutPersist& os) const { cout << " FIO_SphereThetaPhi:: WriteSelf " << endl; if(dobj == NULL) { cout << " WriteSelf:: dobj= null " << endl; return; } char strg[256]; int_4 mNTheta= dobj->SizeIndex(); int_4 mNPix = dobj->NbPixels(); if(dobj->ptrInfo()) { sprintf(strg,"SphereThetaPhi: NSlices=%6d NPix=%9d HasInfo",mNTheta,mNPix); os.PutLine(strg); os << dobj->Info(); } else { sprintf(strg,"SphereThetaPhi: NSlices=%6d NPix=%9d ",mNTheta,mNPix); os.PutLine(strg); } os.PutI4(mNTheta); os.PutI4(mNPix); os.PutR8(dobj->PixSolAngle(0)); os.PutI4s(dobj->getmNPhi() , mNTheta); os.PutI4s(dobj->getmTNphi(), mNTheta+1); os.PutR4s(dobj->getmTheta(), mNTheta+1); //os.Put((dobj->getDataBlock())->Data(), mNPix); PIOSWriteArray(os,(dobj->getDataBlock())->Data(), mNPix); }