source: Sophya/trunk/SophyaProg/Tests/sph2lm.cc@ 4064

Last change on this file since 4064 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 18.1 KB
Line 
1#include "sopnamsp.h"
2#include "tarray.h"
3#include "cimage.h"
4#include "skymap.h"
5#include "mapoperation.h"
6#include "sambainit.h"
7#include "fftwserver.h"
8
9#include <typeinfo>
10
11
12//--------------------------------------------------------------------------
13// Classe pour projeter localement (dans un tableau indexe i,j)
14// des coordonnees spheriques
15
16class MtxLM {
17public:
18 MtxLM(double latdeg, double longdeg,
19 double deltheta_min, double delphi_min,
20 int_4 npixtheta, int_4 npixphi);
21 MtxLM(TMatrix<r_8> & mtx, bool uselat=true);
22
23 virtual ~MtxLM();
24
25 void Init(double latdeg, double longdeg,
26 double deltheta_min, double delphi_min,
27 int_4 npixtheta, int_4 npixphi);
28
29 // Conversion d'index de pixel (ip,jt) (ip: Phi/X/Column, jt: Theta/Y/Row )
30 // en Theta,Phi
31 void ip_jt2tp(int_4 ip, int_4 jt, double& theta, double& phi);
32 // Conversion de (Theta,Phi) en index de pixel (ip,jt)
33 // (ip: Phi/X/Column, jt: Theta/Y/Row )
34 void tp2ipjt(double theta, double phi, int_4& ip, int_4& jt);
35
36 double _latdeg, _longdeg;
37 double _deltheta_min, _delphi_min;
38 int_4 _npixtheta, _npixphi;
39 double _theta0, _phi0;
40 double _thetaC, _phiC;
41 double _deltatheta, _deltaphi;
42 static double _deuxpi;
43};
44
45double MtxLM::_deuxpi = 2.*M_PI;
46
47MtxLM::MtxLM(double latdeg, double longdeg,
48 double deltheta_min, double delphi_min,
49 int_4 npixtheta, int_4 npixphi)
50{
51 Init(latdeg, longdeg, deltheta_min, delphi_min, npixtheta, npixphi );
52}
53
54//--------------------------------------------------------------------------
55
56MtxLM::MtxLM(TMatrix<r_8> & mtx, bool uselat)
57{
58 double latdeg = (uselat) ? (double)mtx.Info()["Latitude_C"] : 0.;
59 double longdeg = mtx.Info()["Longitude_C"];
60 double deltheta_min = mtx.Info()["LatPixSize"];
61 double delphi_min = mtx.Info()["LongPixSize"];
62 int_4 npixtheta = mtx.NRows();
63 int_4 npixphi = mtx.NCols();
64 Init(latdeg, longdeg, deltheta_min, delphi_min, npixtheta, npixphi);
65}
66
67MtxLM::~MtxLM()
68{
69}
70
71void MtxLM::Init(double latdeg, double longdeg,
72 double deltheta_min, double delphi_min,
73 int_4 npixtheta, int_4 npixphi)
74{
75 _latdeg = latdeg;
76 _longdeg = longdeg;
77 _deltheta_min = deltheta_min;
78 _delphi_min = delphi_min;
79 _npixtheta = npixtheta;
80 _npixphi = npixphi;
81 _thetaC = (90.-latdeg)*M_PI/180.;
82 _phiC = longdeg*M_PI/180.;
83 _deltatheta = deltheta_min*M_PI/(180.*60.);
84 _deltaphi = delphi_min*M_PI/(180.*60.)/sin(_thetaC);
85 _theta0 = _thetaC-0.5*(double)_npixtheta*_deltatheta;
86 if ((_thetaC + 0.5*(double)_npixtheta*_deltatheta) > M_PI-1.e-6)
87 throw RangeCheckError("MtxLM::Init() ThetaMax out of range (> M_PI-1.e-6)");
88 if ((_thetaC - 0.5*(double)_npixtheta*_deltatheta) < 1.e-6)
89 throw RangeCheckError("MtxLM::Init() ThetaMin out of range (< 1.e-6)");
90
91 double deltaphitot = delphi_min*M_PI/(180.*60.)/sin(_thetaC + 0.5*(double)_npixtheta*_deltatheta);
92 if (deltaphitot*_npixphi > _deuxpi)
93 throw RangeCheckError("MtxLM::Init() Wrapping will occur for Phi at ThetaMax ! ");
94 deltaphitot = delphi_min*M_PI/(180.*60.)/sin(_thetaC - 0.5*(double)_npixtheta*_deltatheta);
95 if (deltaphitot*_npixphi > _deuxpi)
96 throw RangeCheckError("MtxLM::Init() Wrapping will occur for Phi at ThetaMin ! ");
97
98 _phi0 = _phiC-0.5*(double)_npixphi*_deltaphi;
99 return;
100}
101
102void MtxLM::ip_jt2tp(int_4 ip, int_4 jt, double& theta, double& phi)
103{
104 theta = jt*_deltatheta+_theta0;
105 if ( (theta<0.) || (theta > M_PI) )
106 throw RangeCheckError(" MtxLM::ip_jt2tp - Theta out of range !");
107 double delphi = _delphi_min*M_PI/(180.*60.)/sin(theta);
108 double phi0 = _phiC-0.5*(double)_npixphi*delphi;
109 // phi = ip*_deltaphi+_phi0;
110 phi = ip*delphi+phi0;
111
112 while (phi < 0.) phi += _deuxpi;
113 while (phi >=_deuxpi ) phi -= _deuxpi;
114
115 if ( (phi<0.) || (phi > _deuxpi) )
116 throw RangeCheckError(" MtxLM::ip_jt2tp - Phi out of range !");
117 return;
118}
119
120void MtxLM::tp2ipjt(double theta, double phi, int_4& ip, int_4& jt)
121{
122 if ( (theta<0.) || (theta > M_PI) )
123 throw RangeCheckError(" MtxLM::tp2ipjt - Theta out of range !");
124 if ( (phi<0.) || (phi > _deuxpi) )
125 throw RangeCheckError(" MtxLM::tp2ipjt - Phi out of range !");
126
127 jt = (theta-_theta0)/_deltatheta;
128 double delphi = _delphi_min*M_PI/(180.*60.)/sin(theta);
129 double phi0 = _phiC-0.5*(double)_npixphi*delphi;
130 if (phi0 < 0.) phi0 += 2*M_PI;
131 // ip = (phi-_phi0)/_deltaphi;
132 ip = (phi-phi0)/delphi;
133 if ((ip < 0) || (ip >= _npixphi) )
134 throw RangeCheckError(" MtxLM::ip_jt2tp - ip out of range !");
135 if ((jt < 0) || (jt >= _npixtheta) )
136 throw RangeCheckError(" MtxLM::ip_jt2tp - jt out of range !");
137 return;
138}
139
140//--------------------------------------------------------------------------
141// Fonction de filtrage de carte de type Matrix
142//--------------------------------------------------------------------------
143template <class T>
144void FilterMtxMap(TMatrix<T> & mtx, TMatrix<T> & mxout, int filw=1)
145{
146 if (filw < 1) return;
147 mxout = mtx;
148 sa_size_t r,c;
149 sa_size_t fw = 2*filw+1;
150 // Filtering
151 // Filling holes in Matrix
152 for(r=filw; r<mtx.NRows()-filw; r++)
153 for(c=filw; c<mtx.NCols()-filw; c++)
154 mxout(r,c) = mtx(Range(r-filw, 0, fw), Range(c-filw, 0, fw)).Sum()/fw*fw;
155
156 return;
157}
158
159//--------------------------------------------------------------------------
160// Projection depuis une carte spherique dans un local map
161//--------------------------------------------------------------------------
162
163template <class T>
164void Sph2LocalMap(SphericalMap<T> & in, LocalMap<T> & out)
165{
166 out.SetPixels(0);
167 int kout;
168 double teta,phi;
169
170 // Projecting to localMap
171 for(kout=0; kout<out.NbPixels(); kout++) {
172 out.PixThetaPhi(kout, teta, phi);
173 int pixel = in.PixIndexSph(teta,phi);
174 out(kout) = in.PixVal(pixel);
175 }
176
177 return;
178}
179
180//--------------------------------------------------------------------------
181// Projection depuis une matrice ds carte spherique
182//--------------------------------------------------------------------------
183template <class T>
184void ProjectMatrix2Sph(TMatrix<T> & mtx, SphericalMap<T> & out, bool userot=false)
185{
186 if (userot) {
187 double phi = (double)mtx.Info()["Longitude_C"]+90.;
188 double psi = -((double)mtx.Info()["Latitude_C"])*M_PI/180.;
189 while (phi >= 360.) phi -= 360.;
190 phi *= (M_PI/180.);
191 Vector3d omega(M_PI/2., phi);
192 ProjMatrix2RotateSph(mtx, out, omega, psi, false);
193 }
194 else ProjMatrix2Sph(mtx, out);
195 return;
196}
197
198//--------------------------------------------------------------------------
199// Projection depuis une matrice ds carte spherique sans rotation explicite
200//--------------------------------------------------------------------------
201template <class T>
202void ProjMatrix2Sph(TMatrix<T> & mtx, SphericalMap<T> & out)
203{
204 int kout;
205 double teta,phi;
206
207 // Projecting to Matrix
208 sa_size_t i,j,r,c;
209 MtxLM mtxlm(mtx);
210 for(r=0; r<mtx.NRows(); r++)
211 for(c=0; c<mtx.NCols(); c++) {
212 mtxlm.ip_jt2tp(c, r, teta, phi);
213 out(teta, phi) = mtx(r,c);
214 }
215 return;
216}
217
218//--------------------------------------------------------------------------
219// Projection depuis une matrice ds carte spherique avec rotation explicite
220//--------------------------------------------------------------------------
221template <class T>
222void ProjMatrix2RotateSph(TMatrix<T> & mtx, SphericalMap<T> & out,
223 Vector3d& omega, double phirot, bool uselat=true)
224{
225 double teta,phi;
226
227 // Projecting to Matrix
228 sa_size_t r,c;
229 MtxLM mtxlm(mtx, uselat);
230 for(r=0; r<mtx.NRows(); r++)
231 for(c=0; c<mtx.NCols(); c++) {
232 mtxlm.ip_jt2tp(c, r, teta, phi);
233 Vector3d vv1(teta, phi);
234 Vector3d vv2 = vv1.Rotate(omega, phirot);
235 out(vv2.Theta(), vv2.Phi()) = mtx(r,c);
236 }
237 return;
238}
239//--------------------------------------------------------------------------
240// Projection depuis carte spherique ds une matrice
241//--------------------------------------------------------------------------
242template <class T>
243void Sphere2Matrix(SphericalMap<T> & in, TMatrix<T> & mtx, bool userot=false)
244{
245 if (userot) {
246 double phi = (double)mtx.Info()["Longitude_C"]+90.;
247 double psi = -((double)mtx.Info()["Latitude_C"])*M_PI/180.;
248 while (phi >= 360.) phi -= 360.;
249 phi *= (M_PI/180.);
250 Vector3d omega(M_PI/2., phi);
251 RotateSph2Matrix(in, mtx, omega, psi, false);
252 }
253 else Sph2Matrix(in, mtx);
254 return;
255
256}
257
258//--------------------------------------------------------------------------
259// Projection depuis carte spherique ds une matrice sans rotation explicite
260//--------------------------------------------------------------------------
261template <class T>
262void Sph2Matrix(SphericalMap<T> & in, TMatrix<T> & mtx)
263{
264 int kout;
265 double teta,phi;
266
267 // Projecting to Matrix
268 sa_size_t i,j,r,c;
269 MtxLM mtxlm(mtx);
270 for(r=0; r<mtx.NRows(); r++)
271 for(c=0; c<mtx.NCols(); c++) {
272 mtxlm.ip_jt2tp(c, r, teta, phi);
273 mtx(r, c) = in.PixVal(in.PixIndexSph(teta,phi));
274 }
275
276 // Filling holes in Matrix
277 int_4 nholes = 0;
278 for(r=2; r<mtx.NRows()-2; r++)
279 for(c=2; c<mtx.NCols()-2; c++) {
280 if (fabs(mtx(r,c)) < 1.e-31) {
281 nholes++;
282 mtx(r,c) = mtx(Range(r-2, 0, 5), Range(c-2, 0, 5)).Sum()/24.;
283 }
284 }
285 cout << " Sph2Matrix()/Info: NbHoles= " << nholes << " filled " << endl;
286 return;
287}
288
289//--------------------------------------------------------------------------
290// Projection depuis carte spherique ds une matrice, avec une rotation
291// d'angle phi autour du vecteur omega
292//--------------------------------------------------------------------------
293template <class T>
294void RotateSph2Matrix(SphericalMap<T> & in, TMatrix<T> & mtx,
295 Vector3d& omega,double phirot, bool uselat=true)
296{
297 double teta,phi;
298
299 // Projecting to Matrix
300 sa_size_t r,c;
301 MtxLM mtxlm(mtx,uselat);
302 for(r=0; r<mtx.NRows(); r++)
303 for(c=0; c<mtx.NCols(); c++) {
304 mtxlm.ip_jt2tp(c, r, teta, phi);
305 Vector3d vv1(teta, phi);
306 Vector3d vv2 = vv1.Rotate(omega, phirot);
307 mtx(r, c) = in.PixVal(in.PixIndexSph(vv2.Theta(), vv2.Phi()));
308 }
309
310 // Filling holes in Matrix
311 int_4 nholes = 0;
312 for(r=2; r<mtx.NRows()-2; r++)
313 for(c=2; c<mtx.NCols()-2; c++) {
314 if (fabs(mtx(r,c)) < 1.e-31) {
315 nholes++;
316 mtx(r,c) = mtx(Range(r-2, 0, 5), Range(c-2, 0, 5)).Sum()/24.;
317 }
318 }
319 cout << " RotateSph2Matrix()/Info: NbHoles= " << nholes << " filled " << endl;
320 return;
321}
322
323
324//--------------------------------------------------------------------------
325//--------------------------------------------------------------------------
326
327template <class T>
328void CheckRotatedProjection(SphericalMap<T> & in);
329
330//--------------------------------------------------------------------------
331// ************** Le main *****************
332//--------------------------------------------------------------------------
333
334int main(int narg, char* arg[])
335{
336 #define NLM 9
337 // Tableau des theta,phi des cartes partielles
338 // latitude_map : Latitude en degre
339 // longitude_map : longitude en degre
340 // nx_map : Nb de pixels selon la longitude (Phi)
341 // ny_map : Nb de pixels selon la latitude (Theta)
342 // resolx_map : Resolution cartes selon la longitude (phi)
343 // resoly_map : Resolution cartes selon la latitue (theta)
344 // double latitude_map[NLM] = {0., -15., -15., 65., 65., 65., 65.};
345 double latitude_map[NLM] = {0., -15., -15., -28., 50., 60., 50., 75., 75.};
346 // double thetadeg_map[NLM] = {90., 105., 105., 25., 25., 25., 25.};
347 // double thetadeg_map[NLM] = {90., 105., 105., 115., 40., 30., 40., 15., 15.};
348 double thetadeg_map[NLM]; // = 90.-latitude_map[lnm]
349 double longitude_map[NLM] = {95., 100., 120., 130., 82., 90., 200., 140., 200.};
350 int nx_map[NLM] = {512, 512, 512, 512, 512, 512, 512, 512, 512};
351 int ny_map[NLM] = {512, 512, 512, 512, 512, 512, 512, 512, 512};
352 double resolx_map[NLM] = {2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5};
353 double resoly_map[NLM] = {2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5};
354
355
356 if ( (narg > 1) && (strcmp(arg[1], "-h") == 0) ) {
357 cout << " Usage: sph2lm InHealPixPPFName OutPPFName [-userot/-tstrot] [Filter1/2W = 0] "
358 << endl;
359 exit(0);
360 }
361 if (narg < 3) {
362 cout << " sph2lm/Erreur argument - sph2lm -h for usage" << endl;
363 exit(0);
364 }
365
366 bool userot = false;
367 bool tstrot = false;
368 if (narg > 3) {
369 if (strcmp(arg[3],"-userot") == 0) {
370 userot = true;
371 cout << " sph2lm: Explicit rotation will be used -> userot=true " << endl;
372 }
373 if (strcmp(arg[3],"-tstrot") == 0) {
374 userot = true;
375 cout << " sph2lm: Test rotated projection -> tstrot=true / CheckRotatedProjection() " << endl;
376 }
377 }
378 int filw = 0;
379 if (narg > 4) filw = atoi(arg[4]);
380
381 cout << "\n >>>> Starting sph2lm: arg[1]= " << arg[1]
382 << " arg[2]= " << arg[2] << " FW=" << filw << endl;
383
384 // We handle exception at the high level
385 try {
386 // This macro initialize the library
387 // static objects handle this - However, not all loader call
388 // the constructor for static objects
389 SophyaInit();
390
391 cout << " --- Reading input SphericalMap from file " << arg[1] << endl;
392 PInPersist inppf(arg[1]);
393 PPersist * pps = inppf.ReadObject();
394 AnyDataObj * obj = pps->DataObj();
395 cout << " Object type read from input PPF file : "
396 << typeid(*obj).name() << endl;
397 SphereHEALPix<r_8> * ps8 = dynamic_cast< SphereHEALPix<r_8>* > (obj);
398 SphereHEALPix<r_8> sphin;
399 if (ps8 != NULL) sphin.Share(*ps8);
400 else {
401 SphereHEALPix<r_4> * ps4 = dynamic_cast< SphereHEALPix<r_4>* > (obj);
402 if (ps4 != NULL) {
403 cout << " -- Converting SphereHEALPix<r_4> to SphereHEALPix<r_8> " << endl;
404 sphin.Resize(ps4->SizeIndex());
405 for(int kp=0; kp<sphin.NbPixels(); kp++) sphin(kp) = (*ps4)(kp);
406 }
407 else {
408 cout << " sph2lm/Error : Unsupported input object ! " << endl;
409 throw TypeMismatchExc("sph2lm/Error wrong input object type ");
410 }
411 }
412
413 // inppf.GetObject(sphin);
414 cout << " Sphere read: SizeIndex()= " << sphin.SizeIndex()
415 << " NbPixels()= " << sphin.NbPixels() << endl;
416
417 if (tstrot) {
418 CheckRotatedProjection(sphin);
419 cout << " sph2lm: CheckRotatedProjection() done --> exit() " << endl;
420 return(0);
421 }
422 cout << " --- Opening output PPF file " << arg[1] << endl;
423 POutPersist outppf(arg[2]);
424
425 FFTWServer FFTServ;
426 SphereHEALPix<r_8> sphck(128);
427 SphereHEALPix<r_8> sphckmtx(128);
428
429 int nlm;
430 for(nlm=0; nlm<NLM; nlm++) {
431 thetadeg_map[nlm] = 90.-latitude_map[nlm];
432 cout << "\n ------ LocalMap No " << nlm+1 << " Latitude=" << latitude_map[nlm]
433 << " Longitude= " << longitude_map[nlm] << endl;
434
435 LocalMap<r_8> lm(nx_map[nlm], ny_map[nlm],
436 nx_map[nlm]*resolx_map[nlm]/60.,
437 ny_map[nlm]*resoly_map[nlm]/60.,
438 thetadeg_map[nlm], longitude_map[nlm],
439 nx_map[nlm]/2, ny_map[nlm]/2);
440 TMatrix<r_8> mtx(nx_map[nlm], ny_map[nlm]);
441
442 // lm.SetOrigin(thetadeg_map[nlm], longitude_map[nlm]);
443 // lm.SetSize(nx_map[nlm]*resolx_map[nlm]/60.,
444 // ny_map[nlm]*resoly_map[nlm]/60.);
445
446 lm.SetPixels((nlm+1)*100.);
447 mtx.Info()["Latitude_C"] = latitude_map[nlm];
448 mtx.Info()["Longitude_C"] = longitude_map[nlm];
449 mtx.Info()["LatPixSize"] = resoly_map[nlm];
450 mtx.Info()["LongPixSize"] = resolx_map[nlm];
451 mtx = (nlm+1)*100.;
452
453 cout << " Doing lm.Project(sphck) ... " << endl;
454 lm.ProjectionToSphere(sphck);
455 cout << " Doing mtx.Project(sphck) ... " << endl;
456 ProjectMatrix2Sph(mtx, sphckmtx, userot);
457
458 cout << " Doing Sph2LocalMap(sphin, lm) ... " << endl;
459 Sph2LocalMap(sphin, lm);
460 cout << " Doing Sphere2Matrix(sphin, lm) ... " << endl;
461 Sphere2Matrix(sphin, mtx, userot);
462 MuTyV num = nlm+1;
463 string name = "lm" + (string)num;
464 cout << " Writing local map and mtx to OutPPF " << endl;
465 outppf.PutObject(lm, name);
466 name = "mtx" + (string)num;
467 outppf.PutObject(mtx, name);
468
469 cout << " Calling FFTServ.FFTForward(mtx, fftmtx) " << endl;
470 TMatrix< complex<r_8> > fftmtx;
471 FFTServ.FFTForward(mtx, fftmtx);
472
473 name = "fftmtx" + (string)num;
474 cout << " Writing fftmtx to OutPPF " << endl;
475 outppf.PutObject(fftmtx, name);
476
477 if (filw < 1) continue;
478 TMatrix<r_8> fmtx;
479 cout << " Filtering mtx FilterW= " << filw << endl;
480 FilterMtxMap(mtx, fmtx, filw);
481 cout << " Calling FFTServ.FFTForward(fmtx, fftfmtx) " << endl;
482 TMatrix< complex<r_8> > fftfmtx;
483 FFTServ.FFTForward(fmtx, fftfmtx);
484
485 cout << " Writing fmtx and fftfmtx to OutPPF " << endl;
486 name = "fmtx" + (string)num;
487 outppf.PutObject(fmtx, name);
488 name = "fftfmtx" + (string)num;
489 outppf.PutObject(fftfmtx, name);
490 }
491
492 // cout << " Doing Sph2Sph(sphin, lm) ... " << endl;
493 // Sph2Sph(sphin, lm);
494 cout << "\n --- Writing sphck and sphckmtxsphericalmap to OutPPF " << endl;
495 outppf.PutObject(sphck, "sphck");
496 outppf.PutObject(sphckmtx, "sphckmtx");
497
498 }
499 catch (PThrowable & exc) {
500 cerr << " Catched Exception " << (string)typeid(exc).name()
501 << " - Msg= " << exc.Msg() << endl;
502 }
503 catch (...) {
504 cerr << " some other exception was caught ! " << endl;
505 }
506
507 cout << " >>>> End of sph2lm <<<< " << endl;
508}
509
510//--------------------------------------------------------------------------
511// Fonction pour la verification des projection avec rotation
512//--------------------------------------------------------------------------
513
514template <class T>
515void CheckRotatedProjection(SphericalMap<T> & in)
516{
517
518 cout << " >>> CheckRotatedProjection() : Testing rotated projection with matrices " << endl;
519 SphereHEALPix<r_8> sphckrot(128);
520 double latdeg = 0.;
521 double longdeg = 90.;
522 int nr = 512;
523 int nc = 512;
524 double resol = 2.5;
525
526 TMatrix<r_8> mtx(nr, nc);
527 TMatrix<r_8> mtxA, mtxB, mtxC;
528
529 mtx.Info()["Latitude_C"] = latdeg;
530 mtx.Info()["Longitude_C"] = longdeg;
531 mtx.Info()["LatPixSize"] = resol;
532 mtx.Info()["LongPixSize"] = resol;
533
534 mtx = 100.;
535 ProjMatrix2Sph(mtx, sphckrot);
536 Sph2Matrix(in, mtx);
537 mtxA = mtx;
538 Vector3d omega(M_PI/2., M_PI);
539 mtx = 200.;
540 ProjMatrix2RotateSph(mtx, sphckrot, omega, -M_PI/2.);
541 RotateSph2Matrix(in, mtx, omega, -M_PI/2.);
542 mtxB = mtx;
543 mtx = 300.;
544 ProjMatrix2RotateSph(mtx, sphckrot, omega, -M_PI/4.);
545 RotateSph2Matrix(in, mtx, omega, -M_PI/4.);
546 mtxC = mtx;
547
548 string ppfname = "rotproj.ppf";
549 cout << " -- Writing mtxA,B,C & sphckrot to OutPPF " << ppfname << endl;
550 POutPersist outppf(ppfname);
551
552 outppf.PutObject(mtxA, "mtxA");
553 outppf.PutObject(mtxB, "mtxB");
554 outppf.PutObject(mtxC, "mtxC");
555
556 outppf.PutObject(sphckrot, "sphckrot");
557
558 cout << " >>> End of CheckRotatedProjection() " << endl;
559
560 return;
561}
Note: See TracBrowser for help on using the repository browser.