GammaLib 2.0.0
Loading...
Searching...
No Matches
GWcsSIN.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GWcsSIN.cpp - Orthographic/synthesis (SIN) projection class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2016-2021 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GWcsSIN.cpp
23 * @brief Orthographic/synthesis (SIN) projection class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GException.hpp"
32#include "GMath.hpp"
33#include "GWcsSIN.hpp"
34#include "GWcsRegistry.hpp"
35
36/* __ Method name definitions ____________________________________________ */
37#define G_PRJ_X2S "GWcsSIN::prj_x2s(int, int, int, int, double*, double*,"\
38 " double*, double*, int*)"
39#define G_PRJ_S2X "GWcsSIN::prj_s2x(int, int, int, int, double*, double*,"\
40 " double*, double*, int*)"
41
42/* __ Macros _____________________________________________________________ */
43
44/* __ Coding definitions _________________________________________________ */
45
46/* __ Debug definitions __________________________________________________ */
47
48/* __ Local prototypes ___________________________________________________ */
49
50/* __ Constants __________________________________________________________ */
51
52/* __ Globals ____________________________________________________________ */
54const GWcsRegistry g_wcs_sin_registry(&g_wcs_sin_seed);
55
56
57/*==========================================================================
58 = =
59 = Constructors/destructors =
60 = =
61 ==========================================================================*/
62
63/***********************************************************************//**
64 * @brief Void constructor
65 ***************************************************************************/
67{
68 // Initialise class members
70
71 // Return
72 return;
73}
74
75
76/***********************************************************************//**
77 * @brief Projection constructor
78 *
79 * @param[in] coords Coordinate system.
80 * @param[in] crval1 X value of reference pixel.
81 * @param[in] crval2 Y value of reference pixel.
82 * @param[in] crpix1 X index of reference pixel (starting from 1).
83 * @param[in] crpix2 Y index of reference pixel (starting from 1).
84 * @param[in] cdelt1 Increment in x direction at reference pixel [deg].
85 * @param[in] cdelt2 Increment in y direction at reference pixel [deg].
86 ***************************************************************************/
87GWcsSIN::GWcsSIN(const std::string& coords,
88 const double& crval1, const double& crval2,
89 const double& crpix1, const double& crpix2,
90 const double& cdelt1, const double& cdelt2) :
91 GWcs(coords, crval1, crval2, crpix1, crpix2, cdelt1, cdelt2)
92
93{
94 // Initialise class members
96
97 // Setup WCS derived parameters
98 wcs_set();
99
100 // Return
101 return;
102}
103
104
105/***********************************************************************//**
106 * @brief Copy constructor
107 *
108 * @param[in] wcs World Coordinate System.
109 ***************************************************************************/
110GWcsSIN::GWcsSIN(const GWcsSIN& wcs) : GWcs(wcs)
111{
112 // Initialise class members for clean destruction
113 init_members();
114
115 // Copy members
116 copy_members(wcs);
117
118 // Return
119 return;
120}
121
122
123/***********************************************************************//**
124 * @brief Destructor
125 ***************************************************************************/
127{
128 // Free members
129 free_members();
130
131 // Return
132 return;
133}
134
135
136/*==========================================================================
137 = =
138 = Operators =
139 = =
140 ==========================================================================*/
141
142/***********************************************************************//**
143 * @brief Assignment operator
144 *
145 * @param[in] wcs World Coordinate System.
146 * @return World Coordinate System.
147 ***************************************************************************/
149{
150 // Execute only if object is not identical
151 if (this != &wcs) {
152
153 // Copy base class members
154 this->GWcs::operator=(wcs);
155
156 // Free members
157 free_members();
158
159 // Initialise private members for clean destruction
160 init_members();
161
162 // Copy members
163 copy_members(wcs);
164
165 } // endif: object was not identical
166
167 // Return this object
168 return *this;
169}
170
171
172/*==========================================================================
173 = =
174 = Public methods =
175 = =
176 ==========================================================================*/
177
178/***********************************************************************//**
179 * @brief Clear projection
180 *
181 * This method properly resets the object to an initial state.
182 ***************************************************************************/
184{
185 // Free class members (base and derived classes, derived class first)
186 free_members();
187 this->GWcs::free_members();
189
190 // Initialise members
192 this->GWcs::init_members();
193 init_members();
194
195 // Return
196 return;
197}
198
199
200/***********************************************************************//**
201 * @brief Clone projection
202 *
203 * @return Pointer to deep copy of projection.
204 ***************************************************************************/
206{
207 return new GWcsSIN(*this);
208}
209
210
211/***********************************************************************//**
212 * @brief Print projection information
213 *
214 * @param[in] chatter Chattiness (defaults to NORMAL).
215 * @return String containing projection information.
216 ***************************************************************************/
217std::string GWcsSIN::print(const GChatter& chatter) const
218{
219 // Initialise result string
220 std::string result;
221
222 // Continue only if chatter is not silent
223 if (chatter != SILENT) {
224
225 // Append header
226 result.append("=== GWcsSIN ===");
227
228 // Append information
229 result.append(wcs_print(chatter));
230
231 } // endif: chatter was not silent
232
233 // Return result
234 return result;
235}
236
237
238/*==========================================================================
239 = =
240 = Private methods =
241 = =
242 ==========================================================================*/
243
244/***********************************************************************//**
245 * @brief Initialise class members
246 ***************************************************************************/
248{
249 // Return
250 return;
251}
252
253
254/***********************************************************************//**
255 * @brief Copy class members
256 *
257 * @param[in] wcs World Coordinate System.
258 ***************************************************************************/
260{
261 // Return
262 return;
263}
264
265
266/***********************************************************************//**
267 * @brief Delete class members
268 ***************************************************************************/
270{
271 // Return
272 return;
273}
274
275
276/***********************************************************************//**
277 * @brief Setup of projection
278 *
279 * This method sets up the projection information. The method has been
280 * adapted from the wcslib function prj.c::sinset.
281 *
282 * Given:
283 * m_pv[1] Obliqueness parameter xi.
284 * m_pv[2] Obliqueness parameter eta.
285 *
286 * Given and/or returned:
287 * m_r0 Reset to 180/pi if 0.
288 * m_phi0 Reset to 0.0 if undefined.
289 * m_theta0 Reset to 90.0 if undefined.
290 *
291 * Returned:
292 * m_x0 Fiducial offset in x.
293 * m_y0 Fiducial offset in y.
294 * m_w[0] 1/r0
295 * m_w[1] xi**2 + eta**2
296 * m_w[2] xi**2 + eta**2 + 1
297 * m_w[3] xi**2 + eta**2 - 1
298 ***************************************************************************/
299void GWcsSIN::prj_set(void) const
300{
301 // Signal that projection has been set (needs to be done before calling
302 // the prj_off() method to avoid an endless loop)
303 m_prjset = true;
304
305 // Initialise projection parameters
306 m_w.assign(4,0.0);
307
308 // Set undefined parameters
309 if (undefined(m_pv[1])) {
310 m_pv[1] = 0.0;
311 }
312 if (undefined(m_pv[2])) {
313 m_pv[2] = 0.0;
314 }
315 if (m_r0 == 0.0) {
317 }
318
319 // Precompute
320 m_w[0] = 1.0 / m_r0;
321 m_w[1] = m_pv[1]*m_pv[1] + m_pv[2]*m_pv[2];
322 m_w[2] = m_w[1] + 1.0;
323 m_w[3] = m_w[1] - 1.0;
324
325 // Compute fiducial offset
326 prj_off(0.0, 90.0);
327
328 // Return
329 return;
330}
331
332
333/***********************************************************************//**
334 * @brief Pixel-to-spherical deprojection
335 *
336 * @param[in] nx X vector length.
337 * @param[in] ny Y vector length (0=no replication).
338 * @param[in] sxy Input vector step.
339 * @param[in] spt Output vector step.
340 * @param[in] x Vector of projected x coordinates.
341 * @param[in] y Vector of projected y coordinates.
342 * @param[out] phi Longitude of the projected point in native spherical
343 * coordinates [deg].
344 * @param[out] theta Latitude of the projected point in native spherical
345 * coordinates [deg].
346 * @param[out] stat Status return value for each vector element (always 0)
347 *
348 * Deproject pixel (x,y) coordinates in the plane of projection to native
349 * spherical coordinates (phi,theta).
350 *
351 * This method has been adapted from the wcslib function prj.c::sinx2s().
352 * The interface follows very closely that of wcslib. In contrast to the
353 * wcslib routine, however, the method assumes that the projection has been
354 * setup previously (as this will be done by the constructor).
355 ***************************************************************************/
356void GWcsSIN::prj_x2s(int nx, int ny, int sxy, int spt,
357 const double* x, const double* y,
358 double* phi, double* theta, int* stat) const
359{
360 // Set tolerance
361 const double tol = 1.0e-13;
362
363 // Initialize projection if required
364 if (!m_prjset) {
365 prj_set();
366 }
367
368 // Initialise status code and statistics
369 int status = 0;
370 int n_invalid = 0;
371
372 // Get obliqueness parameters
373 double xi = m_pv[1];
374 double eta = m_pv[2];
375
376 // Set value replication length mx,my
377 int mx;
378 int my;
379 if (ny > 0) {
380 mx = nx;
381 my = ny;
382 }
383 else {
384 mx = 1;
385 my = 1;
386 ny = nx;
387 }
388
389 // Do x dependence
390 const double* xp = x;
391 int rowoff = 0;
392 int rowlen = nx * spt;
393 for (int ix = 0; ix < nx; ++ix, rowoff += spt, xp += sxy) {
394 double x0 = (*xp + m_x0) * m_w[0];
395 double* phip = phi + rowoff;
396 for (int iy = 0; iy < my; ++iy, phip += rowlen) {
397 *phip = x0;
398 }
399 }
400
401 // Do y dependence
402 const double* yp = y;
403 double* phip = phi;
404 double* thetap = theta;
405 int* statp = stat;
406 for (int iy = 0; iy < ny; ++iy, yp += sxy) {
407 double y0 = (*yp + m_y0) * m_w[0];
408 double y02 = y0*y0;
409 for (int ix = 0; ix < mx; ++ix, phip += spt, thetap += spt) {
410
411 // Compute intermediaries
412 double x0 = *phip;
413 double r2 = x0*x0 + y02;
414
415 // Orthographic projection
416 if (m_w[1] == 0.0) {
417
418 // Compute Phi
419 if (r2 != 0.0) {
420 *phip = gammalib::atan2d(x0, -y0);
421 }
422 else {
423 *phip = 0.0;
424 }
425
426 // Compute Theta
427 if (r2 < 0.5) {
428 *thetap = gammalib::acosd(std::sqrt(r2));
429 }
430 else if (r2 <= 1.0) {
431 *thetap = gammalib::asind(std::sqrt(1.0 - r2));
432 }
433 else {
434 *thetap = 0.0;
435 *(statp++) = 1;
436 status = 3;
437 n_invalid++;
438 continue;
439 }
440
441 } // endif: orthographic projection
442
443 // "Synthesis" projection
444 else {
445
446 // ...
447 double z;
448 double xy = x0*xi + y0*eta;
449
450 // Use small angle formula
451 if (r2 < 1.0e-10) {
452 z = r2/2.0;
453 *thetap = 90.0 - gammalib::rad2deg*std::sqrt(r2/(1.0 + xy));
454
455 }
456 else {
457 double a = m_w[2];
458 double b = xy - m_w[1];
459 double c = r2 - xy - xy + m_w[3];
460 double d = b*b - a*c;
461
462 // Check for a solution
463 if (d < 0.0) {
464 *phip = 0.0;
465 *thetap = 0.0;
466 *(statp++) = 1;
467 status = 3;
468 n_invalid++;
469 continue;
470 }
471
472 // ...
473 d = std::sqrt(d);
474
475 // Choose solution closest to pole
476 double sinth1 = (-b + d)/a;
477 double sinth2 = (-b - d)/a;
478 double sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
479 if (sinthe > 1.0) {
480 if (sinthe-1.0 < tol) {
481 sinthe = 1.0;
482 }
483 else {
484 sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
485 }
486 }
487
488 // ...
489 if (sinthe < -1.0) {
490 if (sinthe+1.0 > -tol) {
491 sinthe = -1.0;
492 }
493 }
494
495 // ...
496 if (sinthe > 1.0 || sinthe < -1.0) {
497 *phip = 0.0;
498 *thetap = 0.0;
499 *(statp++) = 1;
500 status = 3;
501 n_invalid++;
502 continue;
503 }
504
505 // ...
506 *thetap = gammalib::asind(sinthe);
507 z = 1.0 - sinthe;
508 }
509
510 // ...
511 double x1 = -y0 + eta * z;
512 double y1 = x0 - xi * z;
513 if (x1 == 0.0 && y1 == 0.0) {
514 *phip = 0.0;
515 }
516 else {
517 *phip = gammalib::atan2d(y1,x1);
518 }
519
520 } // endelse: Synthesis projection
521
522 // Reset error
523 *(statp++) = 0;
524
525 } // endfor
526
527 } // endfor: do Y dependence
528
529 // Check status code
530 gammalib::check_prj_x2s_status(G_PRJ_X2S, status, n_invalid);
531
532 // Return
533 return;
534}
535
536
537/***********************************************************************//**
538 * @brief Generic spherical-to-pixel projection
539 *
540 * @param[in] nphi Longitude vector length.
541 * @param[in] ntheta Latitude vector length (0=no replication).
542 * @param[in] spt Input vector step.
543 * @param[in] sxy Output vector step.
544 * @param[in] phi Longitude vector of the projected point in native spherical
545 * coordinates [deg].
546 * @param[in] theta Latitude vector of the projected point in native spherical
547 * coordinates [deg].
548 * @param[out] x Vector of projected x coordinates.
549 * @param[out] y Vector of projected y coordinates.
550 * @param[out] stat Status return value for each vector element (always 0)
551 *
552 * Project native spherical coordinates (phi,theta) to pixel (x,y)
553 * coordinates in the plane of projection.
554 *
555 * This method has been adapted from the wcslib function prj.c::sins2x().
556 * The interface follows very closely that of wcslib. In contrast to the
557 * wcslib routine, however, the method assumes that the projection has been
558 * setup previously (as this will be done by the constructor).
559 ***************************************************************************/
560void GWcsSIN::prj_s2x(int nphi, int ntheta, int spt, int sxy,
561 const double* phi, const double* theta,
562 double* x, double* y, int* stat) const
563{
564 // Initialize projection if required
565 if (!m_prjset) {
566 prj_set();
567 }
568
569 // Initialise status code and statistics
570 int status = 0;
571 int n_invalid = 0;
572
573 // Set value replication length mphi,mtheta
574 int mphi;
575 int mtheta;
576 if (ntheta > 0) {
577 mphi = nphi;
578 mtheta = ntheta;
579 }
580 else {
581 mphi = 1;
582 mtheta = 1;
583 ntheta = nphi;
584 }
585
586 // Do phi dependence
587 const double* phip = phi;
588 int rowoff = 0;
589 int rowlen = nphi * sxy;
590 for (int iphi = 0; iphi < nphi; ++iphi, rowoff += sxy, phip += spt) {
591 double sinphi;
592 double cosphi;
593 gammalib::sincosd(*phip, &sinphi, &cosphi);
594 double* xp = x + rowoff;
595 double* yp = y + rowoff;
596 for (int itheta = 0; itheta < mtheta; ++itheta) {
597 *xp = sinphi;
598 *yp = cosphi;
599 xp += rowlen;
600 yp += rowlen;
601 }
602 }
603
604 // Do theta dependence
605 const double* thetap = theta;
606 double* xp = x;
607 double* yp = y;
608 int* statp = stat;
609 for (int itheta = 0; itheta < ntheta; ++itheta, thetap += spt) {
610
611 // ...
612 double z;
613 double costhe;
614 double t = (90.0 - std::abs(*thetap)) * gammalib::deg2rad;
615 if (t < 1.0e-5) {
616 if (*thetap > 0.0) {
617 z = t * t / 2.0;
618 }
619 else {
620 z = 2.0 - t * t / 2.0;
621 }
622 costhe = t;
623 }
624 else {
625 z = 1.0 - gammalib::sind(*thetap);
626 costhe = gammalib::cosd(*thetap);
627 }
628 double r = m_r0 * costhe;
629
630 // Orthographic projection
631 if (m_w[1] == 0.0) {
632 int istat = 0;
633 if (m_bounds) {
634 if (*thetap < 0.0) {
635 istat = 1;
636 status = 4;
637 n_invalid++;
638 }
639 }
640 for (int iphi = 0; iphi < mphi; ++iphi, xp += sxy, yp += sxy) {
641 *xp = r*(*xp) - m_x0;
642 *yp = -r*(*yp) - m_y0;
643 *(statp++) = istat;
644 }
645 }
646
647 // Synthesis projection
648 else {
649
650 // ...
651 z *= m_r0;
652 double z1 = m_pv[1] * z - m_x0;
653 double z2 = m_pv[2] * z - m_y0;
654
655 // ...
656 for (int iphi = 0; iphi < mphi; ++iphi, xp += sxy, yp += sxy) {
657 int istat = 0;
658 if (m_bounds) {
659 double t = -gammalib::atand(m_pv[1]*(*xp) - m_pv[2]*(*yp));
660 if (*thetap < t) {
661 istat = 1;
662 status = 4;
663 n_invalid++;
664 }
665 }
666 *xp = r * (*xp) + z1;
667 *yp = -r * (*yp) + z2;
668 *(statp++) = istat;
669 }
670
671 } // endelse: Synthesis projection
672
673 } // endfor: do theta dependence
674
675 // Check status code
676 gammalib::check_prj_s2x_status(G_PRJ_S2X, status, n_invalid);
677
678 // Return
679 return;
680}
Exception handler interface definition.
Mathematical function definitions.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
#define G_PRJ_X2S
Definition GWcsAIT.cpp:38
#define G_PRJ_S2X
Definition GWcsAIT.cpp:40
World Coordinate Projection registry class interface definition.
const GWcsSIN g_wcs_sin_seed
Definition GWcsSIN.cpp:53
Orthographic/synthesis (SIN) projection class definition.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
Interface definition for the WCS registry class.
Orthographic/synthesis (SIN) projection class definition.
Definition GWcsSIN.hpp:43
void prj_x2s(int nx, int ny, int sxy, int spt, const double *x, const double *y, double *phi, double *theta, int *stat) const
Pixel-to-spherical deprojection.
Definition GWcsSIN.cpp:356
GWcsSIN & operator=(const GWcsSIN &wcs)
Assignment operator.
Definition GWcsSIN.cpp:148
GWcsSIN(void)
Void constructor.
Definition GWcsSIN.cpp:66
void init_members(void)
Initialise class members.
Definition GWcsSIN.cpp:247
virtual ~GWcsSIN(void)
Destructor.
Definition GWcsSIN.cpp:126
void prj_set(void) const
Setup of projection.
Definition GWcsSIN.cpp:299
virtual std::string print(const GChatter &chatter=NORMAL) const
Print projection information.
Definition GWcsSIN.cpp:217
void prj_s2x(int nphi, int ntheta, int spt, int sxy, const double *phi, const double *theta, double *x, double *y, int *stat) const
Generic spherical-to-pixel projection.
Definition GWcsSIN.cpp:560
virtual void clear(void)
Clear projection.
Definition GWcsSIN.cpp:183
void copy_members(const GWcsSIN &wcs)
Copy class members.
Definition GWcsSIN.cpp:259
virtual GWcsSIN * clone(void) const
Clone projection.
Definition GWcsSIN.cpp:205
void free_members(void)
Delete class members.
Definition GWcsSIN.cpp:269
Abstract world coordinate system base class.
Definition GWcs.hpp:51
void free_members(void)
Delete class members.
Definition GWcs.cpp:1066
void prj_off(const double &phi0, const double &theta0) const
Compute fiducial offset to force (x,y) = (0,0) at (phi0,theta0)
Definition GWcs.cpp:3232
virtual GWcs & operator=(const GWcs &wcs)
Assignment operator.
Definition GWcs.cpp:180
std::string wcs_print(const GChatter &chatter=NORMAL) const
Print WCS information.
Definition GWcs.cpp:1642
void init_members(void)
Initialise class members.
Definition GWcs.cpp:962
double m_pv[PVN]
Projection parameters.
Definition GWcs.hpp:213
void wcs_set(void) const
Setup of World Coordinate System.
Definition GWcs.cpp:1262
bool m_bounds
Enable strict bounds checking.
Definition GWcs.hpp:214
bool m_prjset
Projection is set.
Definition GWcs.hpp:211
std::vector< double > m_w
Intermediate values.
Definition GWcs.hpp:217
double m_y0
Fiducial y offset.
Definition GWcs.hpp:216
double m_x0
Fiducial x offset.
Definition GWcs.hpp:215
double m_r0
Radius of the generating sphere.
Definition GWcs.hpp:212
bool undefined(const double &value) const
Check if value is undefined.
Definition GWcs.hpp:262
void sincosd(const double &angle, double *s, double *c)
Compute sine and cosine of angle in degrees.
Definition GMath.cpp:342
double asind(const double &value)
Compute arc sine in degrees.
Definition GMath.cpp:250
const double deg2rad
Definition GMath.hpp:43
double cosd(const double &angle)
Compute cosine of angle in degrees.
Definition GMath.cpp:134
double sind(const double &angle)
Compute sine of angle in degrees.
Definition GMath.cpp:163
void check_prj_s2x_status(const std::string &origin, const int &status, const int &number)
Checks status of GWcs::prj_s2x method.
double atan2d(const double &y, const double &x)
Compute arc tangens in degrees.
Definition GMath.cpp:308
double atand(const double &value)
Compute arc tangens in degrees.
Definition GMath.cpp:282
double acosd(const double &value)
Compute arc cosine in degrees.
Definition GMath.cpp:218
void check_prj_x2s_status(const std::string &origin, const int &status, const int &number)
Checks status of GWcs::prj_x2s method.
const double rad2deg
Definition GMath.hpp:44