LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
Coord.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
34 #include <cmath>
35 #include <limits>
36 #include <cstdio>
37 
38 #include "Eigen/Core"
39 #include "Eigen/Geometry"
40 
41 #include "lsst/pex/exceptions.h"
42 #include "boost/algorithm/string.hpp"
43 #include "boost/tuple/tuple.hpp"
44 #include "boost/format.hpp"
45 
46 #include "lsst/afw/coord/Coord.h"
47 #include "lsst/daf/base/DateTime.h"
48 
49 namespace afwCoord = lsst::afw::coord;
50 namespace ex = lsst::pex::exceptions;
51 namespace afwGeom = lsst::afw::geom;
52 namespace dafBase = lsst::daf::base;
53 
54 namespace {
55 
56 typedef std::map<std::string, afwCoord::CoordSystem> CoordSystemMap;
57 
58 CoordSystemMap const getCoordSystemMap() {
59  CoordSystemMap idMap;
60  idMap["FK5"] = afwCoord::FK5;
61  idMap["ICRS"] = afwCoord::ICRS;
62  idMap["ECLIPTIC"] = afwCoord::ECLIPTIC;
63  idMap["GALACTIC"] = afwCoord::GALACTIC;
64  idMap["ELON"] = afwCoord::ECLIPTIC;
65  idMap["GLON"] = afwCoord::GALACTIC;
66  idMap["TOPOCENTRIC"] = afwCoord::TOPOCENTRIC;
67  return idMap;
68 }
69 
74 afwGeom::Angle haversine(afwGeom::Angle const dAlpha,
75  afwGeom::Angle const dDelta,
76  double const cosDelta1,
77  double const cosDelta2
78  )
79 {
80  double const havDDelta = std::sin(dDelta/2.0) * std::sin(dDelta/2.0);
81  double const havDAlpha = std::sin(dAlpha/2.0) * std::sin(dAlpha/2.0);
82  double const havD = havDDelta + cosDelta1 * cosDelta2 * havDAlpha;
83  double const sinDHalf = std::sqrt(havD);
84  afwGeom::Angle dist = (2.0 * std::asin(sinDHalf)) * afwGeom::radians;
85  return dist;
86 }
87 
88 double const epochTolerance = 1.0e-12;
89 
90 // Put a pair of coordinates in a common FK5 system
91 std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> commonFk5(afwCoord::Coord const& c1,
92  afwCoord::Coord const& c2
93  )
94 {
95  // make sure they're fk5
96  afwCoord::Fk5Coord fk51 = c1.toFk5();
97  afwCoord::Fk5Coord fk5tmp = c2.toFk5();
98 
99  // make sure they have the same epoch
100  afwCoord::Fk5Coord fk52;
101  if (fabs(fk51.getEpoch() - fk5tmp.getEpoch()) > epochTolerance) {
102  fk52 = fk5tmp.precess(fk51.getEpoch());
103  } else {
104  fk52 = fk5tmp;
105  }
106 
107  return std::make_pair(fk51, fk52);
108 }
109 
110 } // end anonymous namespace
111 
112 
117  static CoordSystemMap idmap = getCoordSystemMap();
118  if (idmap.find(system) != idmap.end()) {
119  return idmap[system];
120  } else {
121  throw LSST_EXCEPT(ex::InvalidParameterError, "System " + system + " not defined.");
122  }
123 }
124 
125 
126 namespace {
127 
128 double const NaN = std::numeric_limits<double>::quiet_NaN();
129 double const JD2000 = 2451544.50;
130 
131 
132 /*
133  * A local class to handle dd:mm:ss coordinates
134  *
135  * This class allows a decimal or dd:mm:ss coordinate to be
136  * disassembed into d, m, and s components.
137  * It's in an anonymous namespace, but there are public functions
138  * which perform the transformations directly:
139  *
140  * --> std::string dmsStr = degreesToDmsString(double deg);
141  * --> double deg = dmsStringToDegrees(std::string dms);
142  */
143 class Dms {
144 public:
145  Dms() {};
146 
147  // note that isSouth is needed to specify coords between dec = 0, and dec = -1
148  // otherwise, d = -0 gets carried as d = 0 ... need a way to specify it explicitly
149  Dms(int const d, int const m, double const s, bool const isSouth=false) {
150  sign = (d < 0 || isSouth) ? -1 : 1;
151  deg = std::abs(d);
152  min = m;
153  sec = s;
154  };
155  // unit could be "degrees" or "hours"
156  Dms(afwGeom::Angle const deg00, afwGeom::AngleUnit const unit = afwGeom::degrees) {
157  double deg0 = deg00.asAngularUnits(unit);
158  double const absVal = std::fabs(deg0);
159  sign = (deg0 >= 0) ? 1 : -1;
160  deg = static_cast<int>(std::floor(absVal));
161  min = static_cast<int>(std::floor((absVal - deg)*60.0));
162  sec = ((absVal - deg)*60.0 - min)*60.0;
163  }
164 
165  int deg;
166  int min;
167  double sec;
168  int sign;
169 };
170 
171 
172 
177 afwCoord::Coord const& GalacticPoleInFk5()
178 {
179  static afwCoord::Coord pole(192.85950*afwGeom::degrees, 27.12825*afwGeom::degrees, 2000.0); // C&O
180  return pole;
181 }
182 
183 afwCoord::Coord const& Fk5PoleInGalactic()
184 {
185  static afwCoord::Coord pole(122.93200 * afwGeom::degrees, 27.12825 * afwGeom::degrees, 2000.0); // C&O
186  return pole;
187 }
188 
193 afwGeom::Angle meanSiderealTimeGreenwich(
194  double const jd
195  ) {
196  double const T = (jd - 2451545.0)/36525.0;
197  return (280.46061837 + 360.98564736629*(jd - 2451545.0) + 0.000387933*T*T - (T*T*T/38710000.0)) * afwGeom::degrees;
198 }
199 
200 
201 /*
202  * A pair of utility functions to go from cartesian to spherical
203  */
204 double const atPoleEpsilon = 0.0; //std::numeric_limits<double>::epsilon();
205 afwGeom::Angle pointToLongitude(lsst::afw::geom::Point3D const &p3d, double const defaultLongitude=0.0) {
206  afwGeom::Angle lon;
207  if (fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) {
208  lon = afwGeom::Angle(0.0);
209  } else {
210  lon = std::atan2(p3d.getY(), p3d.getX()) * afwGeom::radians;
211  lon.wrap();
212  }
213  return lon;
214 }
215 afwGeom::Angle pointToLatitude(lsst::afw::geom::Point3D const &p3d) {
216  afwGeom::Angle lat;
217  if ( fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) {
218  lat = (p3d.getZ() >= 0) ? afwGeom::Angle(afwGeom::HALFPI) : afwGeom::Angle(-afwGeom::HALFPI);
219  } else {
220  lat = std::asin(p3d.getZ()) * afwGeom::radians;
221  }
222  return lat;
223 }
224 std::pair<afwGeom::Angle, afwGeom::Angle> pointToLonLat(lsst::afw::geom::Point3D const &p3d, double const defaultLongitude=0.0, bool normalize=true) {
225  std::pair<afwGeom::Angle, afwGeom::Angle> lonLat;
226 
227  if (normalize) {
228  double const inorm = 1.0/p3d.asEigen().norm();
229  double const x = inorm*p3d.getX();
230  double const y = inorm*p3d.getY();
231  double const z = inorm*p3d.getZ();
232  if (fabs(x) <= atPoleEpsilon && fabs(y) <= atPoleEpsilon) {
233  lonLat.first = 0.0 * afwGeom::radians;
234  lonLat.second = ((z >= 0) ? 1.0 : -1.0) * afwGeom::HALFPI * afwGeom::radians;
235  } else {
236  lonLat.first = atan2(y, x) * afwGeom::radians;
237  lonLat.first.wrap();
238  lonLat.second = asin(z) * afwGeom::radians;
239  }
240  } else {
241  if (fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) {
242  lonLat.first = 0.0 * afwGeom::radians;
243  lonLat.second = ((p3d.getZ() >= 0) ? 1.0 : -1.0) * afwGeom::HALFPI * afwGeom::radians;
244  } else {
245  lonLat.first = atan2(p3d.getY(), p3d.getX()) * afwGeom::radians;
246  lonLat.first.wrap();
247  lonLat.second = asin(p3d.getZ()) * afwGeom::radians;
248  }
249  }
250  return lonLat;
251 }
252 
253 
254 } // end anonymous namespace
255 
256 
257 
258 /******************* Public functions ********************/
259 
260 static std::string angleToXmsString(afwGeom::Angle const a, afwGeom::AngleUnit const unit) {
261 
262  Dms dms(a, unit);
263 
264  // make sure rounding won't give 60.00 for sec or min
265  if ( (60.00 - dms.sec) < 0.005 ) {
266  dms.sec = 0.0;
267  dms.min += 1;
268  if (dms.min == 60) {
269  dms.min = 0;
270  dms.deg += 1;
271  if (dms.deg == 360) {
272  dms.deg = 0;
273  }
274  }
275  }
276 
277  std::string fmt("%02d:%02d:%05.2f");
278  std::string s = (boost::format(fmt) % dms.deg % dms.min % dms.sec).str();
279  if (dms.sign < 0) {
280  s = "-" + s;
281  }
282  return s;
283 
284 }
285 
286 
293  return angleToXmsString(a, afwGeom::degrees);
294 }
295 
300  return angleToXmsString(a, afwGeom::hours);
301 }
302 
306 static afwGeom::Angle xmsStringToAngle(
307  std::string const dms,
308  afwGeom::AngleUnit unit
309  ) {
310  if (dms.find(":") == std::string::npos) {
311  throw LSST_EXCEPT(ex::InvalidParameterError,
312  (boost::format("String is not in xx:mm:ss format: %s") % dms).str());
313  }
314  std::vector<std::string> elements;
315  boost::split(elements, dms, boost::is_any_of(":"));
316  if (elements.size() != 3) {
317  throw LSST_EXCEPT(ex::InvalidParameterError,
318  (boost::format("Could not parse string as xx:mm:ss format: %s") % dms).str());
319  }
320  int const deg = abs(atoi(elements[0].c_str()));
321  int const min = atoi(elements[1].c_str());
322  double const sec = atof(elements[2].c_str());
323 
324  afwGeom::Angle ang = (deg + min/60.0 + sec/3600.0) * unit;
325  if ( (elements[0].c_str())[0] == '-' ) {
326  ang *= -1.0;
327  }
328  return ang;
329 }
330 
335  std::string const hms
336  ){
337  return xmsStringToAngle(hms, afwGeom::hours);
338 }
339 
344  std::string const dms
345  ) {
346  return xmsStringToAngle(dms, afwGeom::degrees);
347 }
348 
354  double const epoch
355  ) {
356  double const T = (epoch - 2000.0)/100.0;
357  return (23.0 + 26.0/60.0 + (21.448 - 46.82*T - 0.0006*T*T - 0.0018*T*T*T)/3600.0) * afwGeom::degrees;
358 }
359 
360 
361 /* ============================================================
362  *
363  * class Coord
364  *
365  * ============================================================*/
366 
367 
373  lsst::afw::geom::Point2D const &p2d,
374  afwGeom::AngleUnit unit,
375  double const epoch
376  ) :
377  _longitude(NaN), _latitude(NaN), _epoch(epoch) {
378  _longitude = afwGeom::Angle(p2d.getX(), unit);
379  _longitude.wrap();
380  _latitude = afwGeom::Angle(p2d.getY(), unit);
381  _verifyValues();
382 }
383 
388  afwGeom::Point3D const &p3d,
389  double const epoch,
390  bool normalize,
391  afwGeom::Angle const defaultLongitude
392  ) :
393  _longitude(0. * afwGeom::radians),
394  _latitude(0. * afwGeom::radians),
395  _epoch(epoch) {
396 
397  std::pair<afwGeom::Angle, afwGeom::Angle> lonLat = pointToLonLat(p3d, defaultLongitude, normalize);
398  _longitude = lonLat.first;
399  _latitude = lonLat.second;
400  _epoch = epoch;
401 }
402 
408  afwGeom::Angle const ra,
409  afwGeom::Angle const dec,
410  double const epoch
411  ) :
412  _longitude(ra), _latitude(dec), _epoch(epoch) {
413  _longitude.wrap();
414  _verifyValues();
415 }
416 
422  std::string const ra,
423  std::string const dec,
424  double const epoch
425  ) :
426  _longitude(hmsStringToAngle(ra)),
427  _latitude(dmsStringToAngle(dec)),
428  _epoch(epoch) {
429  _longitude.wrap();
430  _verifyValues();
431 }
432 
440 afwCoord::Coord::Coord() : _longitude(afwGeom::Angle(NaN)), _latitude(afwGeom::Angle(NaN)), _epoch(NaN) {}
441 
442 
447  if (_latitude.asRadians() < -afwGeom::HALFPI || _latitude.asRadians() > afwGeom::HALFPI) {
448  throw LSST_EXCEPT(ex::InvalidParameterError,
449  (boost::format("Latitude coord must be: -PI/2 <= lat <= PI/2 (%f).") %
450  _latitude).str());
451  }
452 }
453 
460  afwGeom::Angle const longitude,
461  afwGeom::Angle const latitude,
462  double const epoch
463  ) {
464  _longitude = longitude;
465  _latitude = latitude;
466  _longitude.wrap();
467  _epoch = epoch;
468  _verifyValues();
469 }
470 
471 
477  // treat HOURS specially, they must mean hours for RA, degrees for Dec
478  if (unit == afwGeom::hours) {
479  return afwGeom::Point2D(getLongitude().asHours(), getLatitude().asDegrees());
480  } else {
481  return afwGeom::Point2D(getLongitude().asAngularUnits(unit), getLatitude().asAngularUnits(unit));
482  }
483 }
484 
485 
491  double lng = getLongitude();
492  double lat = getLatitude();
493  double const x = std::cos(lng) * std::cos(lat);
494  double const y = std::sin(lng) * std::cos(lat);
495  double const z = std::sin(lat);
496  return afwGeom::Point3D(x, y, z);
497 }
498 
499 
507  Coord const &poleTo,
508  Coord const &poleFrom
509  ) const {
510  double const alphaGP = poleFrom[0];
511  double const deltaGP = poleFrom[1];
512  double const lCP = poleTo[0];
513 
514  double const alpha = getLongitude();
515  double const delta = getLatitude();
516 
517  afwGeom::Angle const l = (lCP - std::atan2(std::sin(alpha - alphaGP),
518  std::tan(delta)*std::cos(deltaGP) - std::cos(alpha - alphaGP)*std::sin(deltaGP))) * afwGeom::radians;
519  afwGeom::Angle const b = std::asin( (std::sin(deltaGP)*std::sin(delta) + std::cos(deltaGP)*std::cos(delta)*std::cos(alpha - alphaGP))) * afwGeom::radians;
520  return Coord(l, b);
521 }
522 
523 
529  Coord const &axis,
530  afwGeom::Angle const theta
531  ) {
532 
533  double const c = std::cos(theta);
534  double const mc = 1.0 - c;
535  double const s = std::sin(theta);
536 
537  // convert to cartesian
538  afwGeom::Point3D const x = getVector();
539  afwGeom::Point3D const u = axis.getVector();
540  double const ux = u[0];
541  double const uy = u[1];
542  double const uz = u[2];
543 
544  // rotate
545  afwGeom::Point3D xprime;
546  xprime[0] = (ux*ux + (1.0 - ux*ux)*c)*x[0] + (ux*uy*mc - uz*s)*x[1] + (ux*uz*mc + uy*s)*x[2];
547  xprime[1] = (uy*uy + (1.0 - uy*uy)*c)*x[1] + (uy*uz*mc - ux*s)*x[2] + (ux*uy*mc + uz*s)*x[0];
548  xprime[2] = (uz*uz + (1.0 - uz*uz)*c)*x[2] + (uz*ux*mc - uy*s)*x[0] + (uy*uz*mc + ux*s)*x[1];
549 
550  // in-situ
551  std::pair<afwGeom::Angle, afwGeom::Angle> lonLat = pointToLonLat(xprime);
552  _longitude = lonLat.first;
553  _latitude = lonLat.second;
554 }
555 
556 
566  afwGeom::Angle const phi,
567  afwGeom::Angle const arcLen
568  ) {
569 
570  // let v = vector in the direction arcLen points (tangent to surface of sphere)
571  // thus: |v| = arcLen
572  // angle phi = orientation of v in a tangent plane, measured wrt to a parallel of declination
573 
574  // To do the rotation, use rotate() method.
575  // - must provide an axis of rotation: take the cross product r x v to get that axis (pole)
576 
577  // get the vector r
578  Eigen::Vector3d r = getVector().asEigen();
579 
580  // Get the vector v:
581  // let u = unit vector lying on a parallel of declination
582  // let w = unit vector along line of longitude = r x u
583  // the vector v must satisfy the following:
584  // |v| = arcLen
585  // r . v = 0
586  // u . v = |v| cos(phi) = arcLen*cos(phi)
587  // w . v = |v| sin(phi) = arcLen*sin(phi)
588 
589  // v is a linear combination of u and w
590  // v = arcLen*cos(phi)*u + arcLen*sin(phi)*w
591 
592  // Thus, we must:
593  // - create u vector
594  // - solve w vector (r cross u)
595  // - compute v
596  Eigen::Vector3d u;
597  u << -std::sin(getLongitude()), std::cos(getLongitude()), 0.0;
598  Eigen::Vector3d w = r.cross(u);
599  Eigen::Vector3d v = arcLen * std::cos(phi)*u + arcLen * std::sin(phi)*w;
600 
601  // take r x v to get the axis
602  Eigen::Vector3d axisVector = r.cross(v);
603  axisVector.normalize();
604  Coord axisCoord = Coord(afwGeom::Point3D(axisVector), getEpoch());
605 
606  rotate(axisCoord, arcLen);
607 
608  // now get the position angle at our destination
609  // u2 . v2 = arcLen*cos(phi2)
610  // w2 . v2 = arcLen*sin(phi2)
611  // if we normalize v2:
612  // phi2 = atan2(w2.v2, u2.v2)
613  //
614  // we need to compute u2, and then rotate v (exactly as we rotated r) to get v2
615  Eigen::Vector3d r2 = getVector().asEigen();
616  Eigen::Vector3d u2;
617  u2 << -std::sin(getLongitude()), std::cos(getLongitude()), 0.0;
618  Eigen::Vector3d w2 = r2.cross(u2);
619 
620  // make v a unit vector and rotate v exactly as we rotated r
621  v.normalize();
622  Coord v2Coord = Coord(afwGeom::Point3D(v), getEpoch());
623  v2Coord.rotate(axisCoord, arcLen);
624  Eigen::Vector3d v2 = v2Coord.getVector().asEigen();
625 
626  afwGeom::Angle phi2 = std::atan2(w2.dot(v2), u2.dot(v2)) * afwGeom::radians;
627 
628  return phi2;
629 }
630 
631 
632 
637 
638  switch (system) {
639  case FK5:
640  {
641  Fk5Coord c1 = this->toFk5();
642  return boost::shared_ptr<Fk5Coord>(new Fk5Coord(c1.getLongitude(),
643  c1.getLatitude(),
644  c1.getEpoch()));
645  }
646  break;
647  case ICRS:
648  {
649  IcrsCoord c2 = this->toIcrs();
650  return boost::shared_ptr<IcrsCoord>(new IcrsCoord(c2.getLongitude(),
651  c2.getLatitude()));
652  }
653  break;
654  case GALACTIC:
655  {
656  GalacticCoord c4 = this->toGalactic();
657  return boost::shared_ptr<GalacticCoord>(new GalacticCoord(c4.getLongitude(),
658  c4.getLatitude()));
659  }
660  break;
661  case ECLIPTIC:
662  {
663  EclipticCoord c5 = this->toEcliptic();
664  return boost::shared_ptr<EclipticCoord>(new EclipticCoord(c5.getLongitude(),
665  c5.getLatitude(),
666  c5.getEpoch()));
667  }
668  break;
669  case TOPOCENTRIC:
670  throw LSST_EXCEPT(ex::InvalidParameterError,
671  "Cannot make Topocentric with convert() (must also specify Observatory).\n"
672  "Instantiate TopocentricCoord() directly.");
673  break;
674  default:
675  throw LSST_EXCEPT(ex::InvalidParameterError,
676  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC allowed.");
677  break;
678 
679  }
680 
681 }
682 
683 
689  Coord const &c
690  ) const {
691 
692  // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic)
693  // we'll put them in the same system.
694  std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> const& fk5 = commonFk5(*this, c);
695  afwGeom::Angle const alpha1 = fk5.first.getRa();
696  afwGeom::Angle const delta1 = fk5.first.getDec();
697  afwGeom::Angle const alpha2 = fk5.second.getRa();
698  afwGeom::Angle const delta2 = fk5.second.getDec();
699 
700  return haversine(alpha1 - alpha2, delta1 - delta2, std::cos(delta1), std::cos(delta2));
701 }
702 
703 
711 std::pair<afwGeom::Angle, afwGeom::Angle>
713  ) const
714 {
715  // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic)
716  // we'll put them in the same system.
717  std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> const& fk5 = commonFk5(*this, c);
718  afwGeom::Angle const alpha1 = fk5.first.getRa();
719  afwGeom::Angle const delta1 = fk5.first.getDec();
720  afwGeom::Angle const alpha2 = fk5.second.getRa();
721  afwGeom::Angle const delta2 = fk5.second.getDec();
722 
723  afwGeom::Angle const dAlpha = alpha1-alpha2;
724  afwGeom::Angle const dDelta = delta1-delta2;
725 
726  double const cosDelta1 = std::cos(delta1);
727  double const cosDelta2 = std::cos(delta2);
728 
729  afwGeom::Angle separation = haversine(dAlpha, dDelta, cosDelta1, cosDelta2);
730 
731  // Formula from http://www.movable-type.co.uk/scripts/latlong.html
732  double const y = std::sin(dAlpha)*cosDelta2;
733  double const x = cosDelta1*std::sin(delta2) - std::sin(delta1)*cosDelta2*std::cos(dAlpha);
734  afwGeom::Angle bearing = std::atan2(y, x)*afwGeom::radians - 90.0*afwGeom::degrees;
735 
736  return std::make_pair(bearing, separation);
737 }
738 
746 std::pair<afwGeom::Angle, afwGeom::Angle>
748  ) const
749 {
750  // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic)
751  // we'll put them in the same system.
752  std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> const& fk5 = commonFk5(*this, c);
753  afwGeom::Angle const alpha1 = fk5.first.getRa();
754  afwGeom::Angle const delta1 = fk5.first.getDec();
755  afwGeom::Angle const alpha2 = fk5.second.getRa();
756  afwGeom::Angle const delta2 = fk5.second.getDec();
757 
758  // This is a projection of coord2 to the tangent plane at coord1
759  double const sinDelta1 = std::sin(delta1);
760  double const cosDelta1 = std::cos(delta1);
761  double const sinDelta2 = std::sin(delta2);
762  double const cosDelta2 = std::cos(delta2);
763  double const cosAlphaDiff = std::cos(alpha2 - alpha1);
764  double const sinAlphaDiff = std::sin(alpha2 - alpha1);
765 
766  double const div = cosDelta1 * cosAlphaDiff * cosDelta2 + sinDelta1 * sinDelta2;
767  double const xi = cosDelta1 * sinAlphaDiff / div;
768  double const eta = (cosDelta1 * cosAlphaDiff * sinDelta2 - sinDelta1 * cosDelta2) / div;
769 
770  return std::make_pair(xi*afwGeom::radians, eta*afwGeom::radians);
771 }
772 
773 
777 afwCoord::Fk5Coord afwCoord::Coord::toFk5(double const epoch) const {
778  return Fk5Coord(getLongitude(), getLatitude(), getEpoch()).precess(epoch);
779 }
784  return Fk5Coord(getLongitude(), getLatitude(), getEpoch());
785 }
786 
792  return this->toFk5().toIcrs();
793 }
794 
799  return this->toFk5().toGalactic();
800 }
801 
806  return this->toFk5(epoch).toEcliptic();
807 }
812  return this->toFk5().toEcliptic();
813 }
814 
819  Observatory const &obs,
820  lsst::daf::base::DateTime const &obsDate
821  ) const {
822  return this->toFk5().toTopocentric(obs, obsDate);
823 }
824 
825 
826 
827 
828 /* ============================================================
829  *
830  * class Fk5Coord
831  *
832  * ============================================================*/
833 
834 
839  return Fk5Coord(getLongitude(), getLatitude(), getEpoch()).precess(epoch);
840 }
845  return Fk5Coord(getLongitude(), getLatitude(), getEpoch());
846 }
847 
853 
854  // only do the precession to 2000 if we're not already there.
855  if ( fabs(getEpoch() - 2000.0) > epochTolerance ) {
856  afwCoord::Fk5Coord c = precess(2000.0);
857  return IcrsCoord(c.getLongitude(), c.getLatitude());
858  } else {
859  return IcrsCoord(getLongitude(), getLatitude());
860  }
861 }
862 
863 
868 
869  // if we're epoch==2000, we can transform, otherwise we need to precess first
870  Fk5Coord c;
871  if ( fabs(getEpoch() - 2000.0) > epochTolerance ) {
872  c = precess(2000.0);
873  } else {
874  c = *this;
875  }
876 
877  Coord ct = c.transform(Fk5PoleInGalactic(), GalacticPoleInFk5());
878  return GalacticCoord(ct.getLongitude(), ct.getLatitude());
879 
880 }
881 
886  afwGeom::Angle const eclPoleIncl = eclipticPoleInclination(epoch);
887  Coord const eclPoleInEquatorial(270.0 * afwGeom::degrees, (90.0 * afwGeom::degrees) - eclPoleIncl, epoch);
888  Coord const equPoleInEcliptic(90.0 * afwGeom::degrees, (90.0 * afwGeom::degrees) - eclPoleIncl, epoch);
889  Coord c = transform(equPoleInEcliptic, eclPoleInEquatorial);
890  return EclipticCoord(c.getLongitude(), c.getLatitude(), epoch);
891 }
896  return this->toEcliptic(getEpoch());
897 }
898 
903  Observatory const &obs,
904  lsst::daf::base::DateTime const &obsDate
905  ) const {
906 
907  // make sure we precess to the epoch
908  Fk5Coord fk5 = precess(obsDate.get(dafBase::DateTime::EPOCH));
909 
910  // greenwich sidereal time
911  afwGeom::Angle theta0 = meanSiderealTimeGreenwich(obsDate.get(dafBase::DateTime::JD));
912  theta0.wrap();
913 
914  // lat/long of the observatory
915  afwGeom::Angle const phi = obs.getLatitude();
916  afwGeom::Angle const L = obs.getLongitude();
917 
918  // ra/dec of the target
919  afwGeom::Angle const alpha = fk5.getRa();
920  afwGeom::Angle const delta = fk5.getDec();
921 
922  afwGeom::Angle const H = theta0 + L - alpha;
923 
924  // compute the altitude, h
925  double const sinh = std::sin(phi)* std::sin(delta) + std::cos(phi) * std::cos(delta) * std::cos(H);
926  afwGeom::Angle const h = std::asin(sinh) * afwGeom::radians;
927 
928  // compute the azimuth, A
929  double const tanAnumerator = std::sin(H);
930  double const tanAdenominator = (std::cos(H) * std::sin(phi) - std::tan(delta) * std::cos(phi));
931 
932  // Equations used here assume azimuth is with respect to South
933  // but we use the North as our origin ... must add 180 deg
934  afwGeom::Angle A = (180.0*afwGeom::degrees) + atan2(tanAnumerator, tanAdenominator)* afwGeom::radians;
935  A.wrap();
936 
937  return TopocentricCoord(A, h, obsDate.get(dafBase::DateTime::EPOCH), obs);
938 }
939 
940 
941 
947  double const epochTo
948  ) const {
949 
950  // return a copy if the epochs are the same
951  if ( fabs(getEpoch() - epochTo) < epochTolerance) {
952  return Fk5Coord(getLongitude(), getLatitude(), getEpoch());
953  }
954 
957  double const jd0 = dateFrom.get(dafBase::DateTime::JD);
958  double const jd = dateTo.get(dafBase::DateTime::JD);
959 
960  double const T = (jd0 - JD2000)/36525.0;
961  double const t = (jd - jd0)/36525.0;
962  double const tt = t*t;
963  double const ttt = tt*t;
964 
965  afwGeom::Angle const xi = ((2306.2181 + 1.39656*T - 0.000139*T*T)*t +
966  (0.30188 - 0.000344*T)*tt + 0.017998*ttt) * afwGeom::arcseconds;
967  afwGeom::Angle const z = ((2306.2181 + 1.39656*T - 0.000139*T*T)*t +
968  (1.09468 + 0.000066*T)*tt + 0.018203*ttt) * afwGeom::arcseconds;
969  afwGeom::Angle const theta = ((2004.3109 - 0.85330*T - 0.000217*T*T)*t -
970  (0.42665 + 0.000217*T)*tt - 0.041833*ttt) * afwGeom::arcseconds;
971 
972  Fk5Coord fk5 = this->toFk5();
973  afwGeom::Angle const alpha0 = fk5.getRa();
974  afwGeom::Angle const delta0 = fk5.getDec();
975 
976  double const a = std::cos(delta0) * std::sin((alpha0 + xi));
977  double const b = std::cos(theta) * std::cos(delta0) * std::cos((alpha0 + xi)) - std::sin(theta) * std::sin(delta0);
978  double const c = std::sin(theta) * std::cos(delta0) * std::cos((alpha0 + xi)) + std::cos(theta) * std::sin(delta0);
979 
980  afwGeom::Angle const alpha = (std::atan2(a,b) + z) * afwGeom::radians;
981  afwGeom::Angle const delta = std::asin(c) * afwGeom::radians;
982 
983  return Fk5Coord(alpha, delta, epochTo);
984 }
985 
986 
987 /* ============================================================
988  *
989  * class IcrsCoord
990  *
991  * ============================================================*/
992 
996 void afwCoord::IcrsCoord::reset(afwGeom::Angle const longitude, afwGeom::Angle const latitude) {
997  Coord::reset(longitude, latitude, 2000.0);
998 }
999 
1004  return Fk5Coord(getLongitude(), getLatitude(), 2000.0).precess(epoch);
1005 }
1010  return Fk5Coord(getLongitude(), getLatitude(), 2000.0);
1011 }
1012 
1017  return IcrsCoord(getLongitude(), getLatitude());
1018 }
1019 
1020 
1021 
1022 
1023 /* ============================================================
1024  *
1025  * class GalacticCoord
1026  *
1027  * ============================================================*/
1028 
1032 void afwCoord::GalacticCoord::reset(afwGeom::Angle const longitudeDeg, afwGeom::Angle const latitudeDeg) {
1033  Coord::reset(longitudeDeg, latitudeDeg, 2000.0);
1034 }
1035 
1040  // transform to fk5
1041  // galactic coords are ~constant, and the poles used are for epoch=2000, so we get J2000
1042  Coord c = transform(GalacticPoleInFk5(), Fk5PoleInGalactic());
1043  return Fk5Coord(c.getLongitude(), c.getLatitude(), 2000.0).precess(epoch);
1044 }
1049  return this->toFk5(2000.0);
1050 }
1051 
1056  return GalacticCoord(getLongitude(), getLatitude());
1057 }
1058 
1059 
1060 
1061 
1062 /* ============================================================
1063  *
1064  * class EclipticCoord
1065  *
1066  * ============================================================*/
1067 
1072  return EclipticCoord(getLongitude(), getLatitude(), getEpoch()).precess(epoch);
1073 }
1078  return EclipticCoord(getLongitude(), getLatitude(), getEpoch());
1079 }
1080 
1081 
1086  afwGeom::Angle const eclPoleIncl = eclipticPoleInclination(epoch);
1087  afwGeom::Angle ninety = 90. * afwGeom::degrees;
1088  Coord const eclipticPoleInFk5(270.0 * afwGeom::degrees, ninety - eclPoleIncl, epoch);
1089  Coord const fk5PoleInEcliptic(ninety, ninety - eclPoleIncl, epoch);
1090  Coord c = transform(eclipticPoleInFk5, fk5PoleInEcliptic);
1091  return Fk5Coord(c.getLongitude(), c.getLatitude(), epoch);
1092 }
1097  return this->toFk5(getEpoch());
1098 }
1099 
1100 
1107  double const epochTo
1108  ) const {
1109  return this->toFk5().precess(epochTo).toEcliptic();
1110 }
1111 
1112 
1113 
1114 /* ============================================================
1115  *
1116  * class TopocentricCoord
1117  *
1118  * ============================================================*/
1119 
1124 
1125  afwGeom::Angle const phi = _obs.getLatitude();
1126  afwGeom::Angle const L = _obs.getLongitude();
1127 
1128  // Equations used here assume azimuth is with respect to South
1129  // but we use the North as our origin.
1130  afwGeom::Angle A = getAzimuth() + 180.0*afwGeom::degrees;
1131  A.wrap();
1132  afwGeom::Angle const h = getAltitude();
1133 
1134 
1135  double const jd = dafBase::DateTime(epoch,
1138  afwGeom::Angle theta0 = meanSiderealTimeGreenwich(jd);
1139  theta0.wrap();
1140 
1141  double const tanHnum = std::sin(A);
1142  double const tanHdenom = std::cos(A)*std::sin(phi) + std::tan(h)*std::cos(phi);
1143  afwGeom::Angle H = std::atan2(tanHnum, tanHdenom) * afwGeom::radians;
1144 
1145  afwGeom::Angle const alpha = theta0 + L - H;
1146  double const sinDelta = std::sin(phi)*std::sin(h) - std::cos(phi)*std::cos(h)*std::cos(A);
1147  afwGeom::Angle const delta = (std::asin(sinDelta)) * afwGeom::radians;
1148 
1149  return Fk5Coord(alpha, delta, epoch);
1150 }
1155  return this->toFk5(getEpoch());
1156 }
1157 
1158 
1163  lsst::afw::coord::Observatory const &obs,
1164  lsst::daf::base::DateTime const &date
1165  ) const
1166 {
1167  if (obs != _obs) {
1168  throw LSST_EXCEPT(ex::InvalidParameterError,
1169  (boost::format("Expected observatory %s, saw %s") % _obs % obs).str());
1170  }
1171  if (fabs(date.get() - getEpoch()) > std::numeric_limits<double>::epsilon()) {
1172  throw LSST_EXCEPT(ex::InvalidParameterError,
1173  (boost::format("Expected date %g, saw %g") % getEpoch() % date.get()).str());
1174  }
1175 
1176  return TopocentricCoord(getLongitude(), getLatitude(), getEpoch(), _obs);
1177 }
1178 
1185  return TopocentricCoord(getLongitude(), getLatitude(), getEpoch(), _obs);
1186 }
1187 
1188 
1189 
1190 /* ===============================================================================
1191  *
1192  * Factory function definitions:
1193  *
1194  * Each makeCoord() function has overloaded variants with and without epoch specified.
1195  * It was tempting to specify default values, but some coordinate systems have
1196  * no epoch, and this would be confusing to the user. In its current form,
1197  * any epochless coordinate system requested with an epoch specified will throw an exception.
1198  * The epochless factories will always work, but assume default epoch = 2000.
1199  *
1200  * ===============================================================================
1201  */
1202 
1211  CoordSystem const system,
1212  afwGeom::Angle const ra,
1213  afwGeom::Angle const dec,
1214  double const epoch
1215 ) {
1216 
1217  switch (system) {
1218  case FK5:
1219  return boost::shared_ptr<Fk5Coord>(new Fk5Coord(ra, dec, epoch));
1220  break;
1221  case ICRS:
1222  throw LSST_EXCEPT(ex::InvalidParameterError,
1223  "ICRS has no epoch, use overloaded makeCoord with args (system, ra, dec).");
1224  break;
1225  case GALACTIC:
1226  throw LSST_EXCEPT(ex::InvalidParameterError,
1227  "Galactic has no epoch, use overloaded makeCoord with (system, ra, dec).");
1228  break;
1229  case ECLIPTIC:
1230  return boost::shared_ptr<EclipticCoord>(new EclipticCoord(ra, dec, epoch));
1231  break;
1232  case TOPOCENTRIC:
1233  throw LSST_EXCEPT(ex::InvalidParameterError,
1234  "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n"
1235  "Instantiate TopocentricCoord() directly.");
1236  break;
1237  default:
1238  throw LSST_EXCEPT(ex::InvalidParameterError,
1239  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, and TOPOCENTRIC allowed.");
1240  break;
1241 
1242  }
1243 
1244 }
1245 
1246 
1247 
1255  CoordSystem const system,
1256  afwGeom::Angle const ra,
1257  afwGeom::Angle const dec
1258 ) {
1259 
1260  switch (system) {
1261  case FK5:
1262  return boost::shared_ptr<Fk5Coord>(new Fk5Coord(ra, dec, 2000.0));
1263  break;
1264  case ICRS:
1265  return boost::shared_ptr<IcrsCoord>(new IcrsCoord(ra, dec));
1266  break;
1267  case GALACTIC:
1268  return boost::shared_ptr<GalacticCoord>(new GalacticCoord(ra, dec));
1269  break;
1270  case ECLIPTIC:
1271  return boost::shared_ptr<EclipticCoord>(new EclipticCoord(ra, dec, 2000.0));
1272  break;
1273  case TOPOCENTRIC:
1274  throw LSST_EXCEPT(ex::InvalidParameterError,
1275  "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n"
1276  "Instantiate TopocentricCoord() directly.");
1277  break;
1278  default:
1279  throw LSST_EXCEPT(ex::InvalidParameterError,
1280  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, and TOPOCENTRIC allowed.");
1281  break;
1282 
1283  }
1284 
1285 }
1286 
1287 
1288 
1296  CoordSystem const system,
1297  lsst::afw::geom::Point3D const &p3d,
1298  double const epoch,
1299  bool normalize,
1300  afwGeom::Angle const defaultLongitude
1301 ) {
1302  Coord c(p3d, 2000.0, normalize, defaultLongitude);
1303  return makeCoord(system, c.getLongitude(), c.getLatitude(), epoch);
1304 }
1312  CoordSystem const system,
1313  lsst::afw::geom::Point3D const &p3d,
1314  bool normalize,
1315  afwGeom::Angle const defaultLongitude
1316 ) {
1317  Coord c(p3d, 2000.0, normalize, defaultLongitude);
1318  return makeCoord(system, c.getLongitude(), c.getLatitude());
1319 }
1320 
1327  CoordSystem const system,
1328  lsst::afw::geom::Point2D const &p2d,
1329  afwGeom::AngleUnit unit,
1330  double const epoch
1331 ) {
1332  if (unit == afwGeom::hours) {
1333  return makeCoord(system, afwGeom::Angle(p2d.getX(), afwGeom::hours), afwGeom::Angle(p2d.getY(), afwGeom::degrees), epoch);
1334  } else {
1335  return makeCoord(system, afwGeom::Angle(p2d.getX(), unit), afwGeom::Angle(p2d.getY(), unit), epoch);
1336  }
1337 }
1338 
1346  CoordSystem const system,
1347  lsst::afw::geom::Point2D const &p2d,
1348  afwGeom::AngleUnit unit
1349 ) {
1350  if (unit == afwGeom::hours) {
1351  return makeCoord(system, afwGeom::Angle(p2d.getX(), afwGeom::hours), afwGeom::Angle(p2d.getY(), afwGeom::degrees));
1352  } else {
1353  return makeCoord(system, afwGeom::Angle(p2d.getX(), unit), afwGeom::Angle(p2d.getY(), unit));
1354  }
1355 }
1356 
1363  CoordSystem const system,
1364  std::string const ra,
1365  std::string const dec,
1366  double const epoch
1367  ) {
1368  return makeCoord(system, dmsStringToAngle(ra), dmsStringToAngle(dec), epoch);
1369 }
1376  CoordSystem const system,
1377  std::string const ra,
1378  std::string const dec
1379  ) {
1380  return makeCoord(system, dmsStringToAngle(ra), dmsStringToAngle(dec));
1381 }
1382 
1383 
1384 
1389  CoordSystem const system
1390  ) {
1391  switch (system) {
1392  case FK5:
1393  return boost::shared_ptr<Fk5Coord>(new Fk5Coord());
1394  break;
1395  case ICRS:
1396  return boost::shared_ptr<IcrsCoord>(new IcrsCoord());
1397  break;
1398  case GALACTIC:
1399  return boost::shared_ptr<GalacticCoord>(new GalacticCoord());
1400  break;
1401  case ECLIPTIC:
1402  return boost::shared_ptr<EclipticCoord>(new EclipticCoord());
1403  break;
1404  case TOPOCENTRIC:
1405  throw LSST_EXCEPT(ex::InvalidParameterError,
1406  "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n"
1407  "Instantiate TopocentricCoord() directly.");
1408  break;
1409  default:
1410  throw LSST_EXCEPT(ex::InvalidParameterError,
1411  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, allowed.");
1412  break;
1413 
1414  }
1415 }
1416 
1417 std::ostream & afwCoord::operator<<(std::ostream & os, afwCoord::Coord const & coord) {
1418  return os << coord.getPosition() << "@" << coord.getEpoch();
1419 }
int y
virtual Fk5Coord toFk5() const
Convert ourself from Ecliptic to Fk5 (use current epoch)
Definition: Coord.cc:1096
virtual IcrsCoord toIcrs() const
Icrs converter for IcrsCoord. (ie. a no-op)
Definition: Coord.cc:1016
boost::shared_ptr< Coord > Ptr
Definition: Coord.h:72
virtual EclipticCoord toEcliptic() const
Convert ourself to Ecliptic: lambda, beta (use existing epoch)
Definition: Coord.cc:811
Class for handling dates/times, including MJD, UTC, and TAI.
Definition: DateTime.h:58
lsst::afw::coord::Coord Coord
Definition: misc.h:39
lsst::afw::geom::Angle _longitude
Definition: Coord.h:144
virtual GalacticCoord toGalactic() const
Convert ourself to Galactic: l, b.
Definition: Coord.cc:798
virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude)
special reset() overload to make sure no epoch can be set
Definition: Coord.cc:996
A class to handle Galactic coordinates (inherits from Coord)
Definition: Coord.h:231
lsst::afw::geom::Angle hmsStringToAngle(std::string const hms)
Convert a hh:mm:ss string to Angle.
Definition: Coord.cc:334
double asAngularUnits(AngleUnit const &units) const
Definition: Angle.h:118
AngleUnit const radians
constant with units of radians
Definition: Angle.h:91
virtual Fk5Coord toFk5() const
Convert ourself to Fk5 (ie. a no-op): RA, Dec (keep current epoch)
Definition: Coord.cc:844
Store information about an observatory ... lat/long, elevation.
Definition: Observatory.h:48
EclipticCoord precess(double const epochTo) const
precess to new epoch
Definition: Coord.cc:1106
virtual Fk5Coord toFk5() const
Convert outself from Topocentric to Fk5 (use current epoch)
Definition: Coord.cc:1154
AngleUnit const hours
Definition: Angle.h:93
virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &obsDate) const
Convert ourself to Altitude/Azimuth: alt, az.
Definition: Coord.cc:902
std::pair< lsst::afw::geom::Angle, lsst::afw::geom::Angle > getTangentPlaneOffset(Coord const &c) const
Get the offset on the tangent plane.
Definition: Coord.cc:747
Fk5Coord precess(double const epochTo) const
Precess ourselves from whence we are to a new epoch.
Definition: Coord.cc:946
virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &date) const
Convert ourself from Topocentric to Topocentric ... a no-op.
Definition: Coord.cc:1162
virtual TopocentricCoord toTopocentric() const
Convert ourself from Topocentric to Topocentric with no observatory or date arguments.
Definition: Coord.cc:1184
virtual EclipticCoord toEcliptic(double const epoch) const
Convert ourself from Ecliptic to Ecliptic ... a no-op (but precess to new epoch)
Definition: Coord.cc:1071
Coord()
Default constructor for the Coord base class.
Definition: Coord.cc:440
std::pair< lsst::afw::geom::Angle, lsst::afw::geom::Angle > getOffsetFrom(Coord const &c) const
Compute the offset from a coordinate.
Definition: Coord.cc:712
lsst::afw::coord::IcrsCoord IcrsCoord
Definition: misc.h:41
virtual IcrsCoord toIcrs() const
Convert ourself to ICRS: RA, Dec (basically J2000)
Definition: Coord.cc:852
void rotate(Coord const &axis, lsst::afw::geom::Angle const theta)
Rotate our current coords about a pole.
Definition: Coord.cc:528
A class used to convert scalar POD types such as double to Angle.
Definition: Angle.h:71
void _verifyValues() const
Make sure the values we&#39;ve got are in the range 0 &lt;= x &lt; 2PI.
Definition: Coord.cc:446
virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude)
Definition: Coord.h:86
A coordinate class intended to represent absolute positions.
Definition: PSF.h:39
Matrix alpha
double min
Definition: attributes.cc:216
lsst::afw::geom::Angle _latitude
Definition: Coord.h:145
int d
Definition: KDTree.cc:89
virtual Fk5Coord toFk5(double const epoch) const
Convert ourself to Fk5: RA, Dec (precess to new epoch)
Definition: Coord.cc:777
AngleUnit const degrees
Definition: Angle.h:92
virtual Fk5Coord toFk5() const
Convert ourself from galactic to Fk5 (no epoch specified)
Definition: Coord.cc:1048
A class to handle topocentric (AltAz) coordinates (inherits from Coord)
Definition: Coord.h:319
virtual Fk5Coord toFk5() const
Convert ourself to Fk5: RA, Dec (use current epoch)
Definition: Coord.cc:783
double w
Definition: CoaddPsf.cc:57
virtual EclipticCoord toEcliptic() const
Convert ourself to Ecliptic: lambda, beta (use current epoch)
Definition: Coord.cc:895
double get(DateSystem system=MJD, Timescale scale=TAI) const
Definition: DateTime.cc:418
EigenVector const & asEigen() const
Return a fixed-size Eigen representation of the coordinate object.
lsst::afw::geom::Angle getDec() const
Definition: Coord.h:209
Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Angle const ra, lsst::afw::geom::Angle const dec, double const epoch)
Factory function to create a Coord of arbitrary type with decimal RA,Dec.
Definition: Coord.cc:1210
Point2D const * v2
Definition: ImageUtils.cc:89
double getEpoch() const
Definition: Coord.h:93
std::string angleToDmsString(lsst::afw::geom::Angle const deg)
a Function to convert a coordinate in decimal degrees to a string with form dd:mm:ss ...
Definition: Coord.cc:292
lsst::afw::geom::Angle offset(lsst::afw::geom::Angle const phi, lsst::afw::geom::Angle const arcLen)
offset our current coords along a great circle defined by an angle wrt a declination parallel ...
Definition: Coord.cc:565
std::string angleToHmsString(lsst::afw::geom::Angle const deg)
a function to convert decimal degrees to a string with form hh:mm:ss.s
Definition: Coord.cc:299
Interface for DateTime class.
virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude)
special reset() overload to make sure no epoch can be set
Definition: Coord.cc:1032
Point< double, 3 > Point3D
Definition: Point.h:287
int x
A class to handle Fk5 coordinates (inherits from Coord)
Definition: Coord.h:187
virtual GalacticCoord toGalactic() const
Convert ourself to Galactic: l, b.
Definition: Coord.cc:867
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
A class to handle Ecliptic coordinates (inherits from Coord)
Definition: Coord.h:270
double _epoch
Extent< int, N > floor(Extent< double, N > const &input)
lsst::afw::geom::Angle Angle
Definition: misc.h:42
lsst::afw::geom::Angle getRa() const
Definition: Coord.h:208
lsst::afw::geom::Angle getLongitude() const
The main access method for the longitudinal coordinate.
Definition: Coord.h:111
double const HALFPI
Definition: Angle.h:20
virtual IcrsCoord toIcrs() const
Convert ourself to ICRS: RA, Dec (basically J2000)
Definition: Coord.cc:791
AngleUnit const arcseconds
Definition: Angle.h:95
lsst::afw::geom::Angle getLongitude() const
The main access method for the longitudinal coordinate.
Definition: Observatory.cc:88
afw::table::Key< double > b
Point< double, 2 > Point2D
Definition: Point.h:286
CoordSystem makeCoordEnum(std::string const system)
A utility function to get the enum value of a coordinate system from a string name.
Definition: Coord.cc:116
virtual Fk5Coord toFk5() const
Fk5 converter for IcrsCoord. (no epoch specified)
Definition: Coord.cc:1009
std::ostream & operator<<(std::ostream &stream, Exception const &e)
Definition: Exception.cc:124
virtual GalacticCoord toGalactic() const
Convert ourself from Galactic to Galactic ... a no-op.
Definition: Coord.cc:1055
Coord::Ptr convert(CoordSystem system) const
Convert to a specified Coord type.
Definition: Coord.cc:636
lsst::afw::geom::Point3D getVector() const
Return our contents in a position vector.
Definition: Coord.cc:490
lsst::afw::geom::Angle getLatitude() const
The main access method for the latitudinal coordinate.
Definition: Coord.h:118
lsst::afw::geom::Angle getLatitude() const
The main access method for the longitudinal coordinate.
Definition: Observatory.cc:99
A class to handle Icrs coordinates (inherits from Coord)
Definition: Coord.h:155
lsst::afw::geom::Angle dmsStringToAngle(std::string const dms)
Convert a dd:mm:ss string to Angle.
Definition: Coord.cc:343
Include files required for standard LSST Exception handling.
virtual EclipticCoord toEcliptic() const
Convert ourself from Ecliptic to Ecliptic ... a no-op (use the current epoch)
Definition: Coord.cc:1077
lsst::afw::geom::Point2D getPosition(lsst::afw::geom::AngleUnit unit=lsst::afw::geom::degrees) const
Return our contents in a Point2D object.
Definition: Coord.cc:476
lsst::afw::geom::Angle eclipticPoleInclination(double const epoch)
get the inclination of the ecliptic pole (obliquity) at epoch
Definition: Coord.cc:353
Coord transform(Coord const &poleFrom, Coord const &poleTo) const
Tranform our current coords to another spherical polar system.
Definition: Coord.cc:506
lsst::afw::geom::Angle angularSeparation(Coord const &c) const
compute the angular separation between two Coords
Definition: Coord.cc:688
virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &obsDate) const
Convert ourself to Altitude/Azimuth: alt, az.
Definition: Coord.cc:818
Functions to handle coordinates.