LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
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 #include <iomanip>
38 
39 #include "Eigen/Core"
40 #include "Eigen/Geometry"
41 
42 #include "lsst/pex/exceptions.h"
43 #include "boost/algorithm/string.hpp"
44 #include "boost/tuple/tuple.hpp"
45 #include "boost/format.hpp"
46 
47 #include "lsst/afw/coord/Coord.h"
48 #include "lsst/daf/base/DateTime.h"
49 
50 namespace afwCoord = lsst::afw::coord;
51 namespace ex = lsst::pex::exceptions;
52 namespace afwGeom = lsst::afw::geom;
53 namespace dafBase = lsst::daf::base;
54 
55 namespace {
56 
57 typedef std::map<std::string, afwCoord::CoordSystem> CoordSystemMap;
58 
59 CoordSystemMap const getCoordSystemMap() {
60  CoordSystemMap idMap;
61  idMap["FK5"] = afwCoord::FK5;
62  idMap["ICRS"] = afwCoord::ICRS;
63  idMap["ECLIPTIC"] = afwCoord::ECLIPTIC;
64  idMap["GALACTIC"] = afwCoord::GALACTIC;
65  idMap["ELON"] = afwCoord::ECLIPTIC;
66  idMap["GLON"] = afwCoord::GALACTIC;
67  idMap["TOPOCENTRIC"] = afwCoord::TOPOCENTRIC;
68  return idMap;
69 }
70 
75 afwGeom::Angle haversine(afwGeom::Angle const dAlpha,
76  afwGeom::Angle const dDelta,
77  double const cosDelta1,
78  double const cosDelta2
79  )
80 {
81  double const havDDelta = std::sin(dDelta/2.0) * std::sin(dDelta/2.0);
82  double const havDAlpha = std::sin(dAlpha/2.0) * std::sin(dAlpha/2.0);
83  double const havD = havDDelta + cosDelta1 * cosDelta2 * havDAlpha;
84  double const sinDHalf = std::sqrt(havD);
85  afwGeom::Angle dist = (2.0 * std::asin(sinDHalf)) * afwGeom::radians;
86  return dist;
87 }
88 
89 double const epochTolerance = 1.0e-12;
90 
91 // Put a pair of coordinates in a common FK5 system
92 std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> commonFk5(afwCoord::Coord const& c1,
93  afwCoord::Coord const& c2
94  )
95 {
96  // make sure they're fk5
97  afwCoord::Fk5Coord fk51 = c1.toFk5();
98  afwCoord::Fk5Coord fk5tmp = c2.toFk5();
99 
100  // make sure they have the same epoch
101  afwCoord::Fk5Coord fk52;
102  if (fabs(fk51.getEpoch() - fk5tmp.getEpoch()) > epochTolerance) {
103  fk52 = fk5tmp.precess(fk51.getEpoch());
104  } else {
105  fk52 = fk5tmp;
106  }
107 
108  return std::make_pair(fk51, fk52);
109 }
110 
111 } // end anonymous namespace
112 
113 
118  static CoordSystemMap idmap = getCoordSystemMap();
119  if (idmap.find(system) != idmap.end()) {
120  return idmap[system];
121  } else {
122  throw LSST_EXCEPT(ex::InvalidParameterError, "System " + system + " not defined.");
123  }
124 }
125 
126 
127 namespace {
128 
129 double const NaN = std::numeric_limits<double>::quiet_NaN();
130 double const JD2000 = 2451544.50;
131 
132 
133 /*
134  * A local class to handle dd:mm:ss coordinates
135  *
136  * This class allows a decimal or dd:mm:ss coordinate to be
137  * disassembed into d, m, and s components.
138  * It's in an anonymous namespace, but there are public functions
139  * which perform the transformations directly:
140  *
141  * --> std::string dmsStr = degreesToDmsString(double deg);
142  * --> double deg = dmsStringToDegrees(std::string dms);
143  */
144 class Dms {
145 public:
146  Dms() {};
147 
148  // note that isSouth is needed to specify coords between dec = 0, and dec = -1
149  // otherwise, d = -0 gets carried as d = 0 ... need a way to specify it explicitly
150  Dms(int const d, int const m, double const s, bool const isSouth=false) {
151  sign = (d < 0 || isSouth) ? -1 : 1;
152  deg = std::abs(d);
153  min = m;
154  sec = s;
155  };
156  // unit could be "degrees" or "hours"
157  Dms(afwGeom::Angle const deg00, afwGeom::AngleUnit const unit = afwGeom::degrees) {
158  double deg0 = deg00.asAngularUnits(unit);
159  double const absVal = std::fabs(deg0);
160  sign = (deg0 >= 0) ? 1 : -1;
161  deg = static_cast<int>(std::floor(absVal));
162  min = static_cast<int>(std::floor((absVal - deg)*60.0));
163  sec = ((absVal - deg)*60.0 - min)*60.0;
164  }
165 
166  int deg;
167  int min;
168  double sec;
169  int sign;
170 };
171 
172 
173 
178 afwCoord::Coord const& GalacticPoleInFk5()
179 {
180  static afwCoord::Coord pole(192.85950*afwGeom::degrees, 27.12825*afwGeom::degrees, 2000.0); // C&O
181  return pole;
182 }
183 
184 afwCoord::Coord const& Fk5PoleInGalactic()
185 {
186  static afwCoord::Coord pole(122.93200 * afwGeom::degrees, 27.12825 * afwGeom::degrees, 2000.0); // C&O
187  return pole;
188 }
189 
194 afwGeom::Angle meanSiderealTimeGreenwich(
195  double const jd
196  ) {
197  double const T = (jd - 2451545.0)/36525.0;
198  return (280.46061837 + 360.98564736629*(jd - 2451545.0) + 0.000387933*T*T - (T*T*T/38710000.0)) * afwGeom::degrees;
199 }
200 
201 
202 /*
203  * A pair of utility functions to go from cartesian to spherical
204  */
205 double const atPoleEpsilon = 0.0; //std::numeric_limits<double>::epsilon();
206 afwGeom::Angle pointToLongitude(lsst::afw::geom::Point3D const &p3d, double const defaultLongitude=0.0) {
207  afwGeom::Angle lon;
208  if (fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) {
209  lon = afwGeom::Angle(0.0);
210  } else {
211  lon = std::atan2(p3d.getY(), p3d.getX()) * afwGeom::radians;
212  lon.wrap();
213  }
214  return lon;
215 }
216 afwGeom::Angle pointToLatitude(lsst::afw::geom::Point3D const &p3d) {
217  afwGeom::Angle lat;
218  if ( fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) {
219  lat = (p3d.getZ() >= 0) ? afwGeom::Angle(afwGeom::HALFPI) : afwGeom::Angle(-afwGeom::HALFPI);
220  } else {
221  lat = std::asin(p3d.getZ()) * afwGeom::radians;
222  }
223  return lat;
224 }
225 std::pair<afwGeom::Angle, afwGeom::Angle> pointToLonLat(lsst::afw::geom::Point3D const &p3d, double const defaultLongitude=0.0, bool normalize=true) {
226  std::pair<afwGeom::Angle, afwGeom::Angle> lonLat;
227 
228  if (normalize) {
229  double const inorm = 1.0/p3d.asEigen().norm();
230  double const x = inorm*p3d.getX();
231  double const y = inorm*p3d.getY();
232  double const z = inorm*p3d.getZ();
233  if (fabs(x) <= atPoleEpsilon && fabs(y) <= atPoleEpsilon) {
234  lonLat.first = 0.0 * afwGeom::radians;
235  lonLat.second = ((z >= 0) ? 1.0 : -1.0) * afwGeom::HALFPI * afwGeom::radians;
236  } else {
237  lonLat.first = atan2(y, x) * afwGeom::radians;
238  lonLat.first.wrap();
239  lonLat.second = asin(z) * afwGeom::radians;
240  }
241  } else {
242  if (fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) {
243  lonLat.first = 0.0 * afwGeom::radians;
244  lonLat.second = ((p3d.getZ() >= 0) ? 1.0 : -1.0) * afwGeom::HALFPI * afwGeom::radians;
245  } else {
246  lonLat.first = atan2(p3d.getY(), p3d.getX()) * afwGeom::radians;
247  lonLat.first.wrap();
248  lonLat.second = asin(p3d.getZ()) * afwGeom::radians;
249  }
250  }
251  return lonLat;
252 }
253 
254 
255 } // end anonymous namespace
256 
257 
258 
259 /******************* Public functions ********************/
260 
261 static std::string angleToXmsString(afwGeom::Angle const a, afwGeom::AngleUnit const unit) {
262 
263  Dms dms(a, unit);
264 
265  // make sure rounding won't give 60.00 for sec or min
266  if ( (60.00 - dms.sec) < 0.005 ) {
267  dms.sec = 0.0;
268  dms.min += 1;
269  if (dms.min == 60) {
270  dms.min = 0;
271  dms.deg += 1;
272  if (dms.deg == 360) {
273  dms.deg = 0;
274  }
275  }
276  }
277 
278  std::string fmt("%02d:%02d:%05.2f");
279  std::string s = (boost::format(fmt) % dms.deg % dms.min % dms.sec).str();
280  if (dms.sign < 0) {
281  s = "-" + s;
282  }
283  return s;
284 
285 }
286 
287 
294  return angleToXmsString(a, afwGeom::degrees);
295 }
296 
301  return angleToXmsString(a, afwGeom::hours);
302 }
303 
307 static afwGeom::Angle xmsStringToAngle(
308  std::string const dms,
309  afwGeom::AngleUnit unit
310  ) {
311  if (dms.find(":") == std::string::npos) {
312  throw LSST_EXCEPT(ex::InvalidParameterError,
313  (boost::format("String is not in xx:mm:ss format: %s") % dms).str());
314  }
315  std::vector<std::string> elements;
316  boost::split(elements, dms, boost::is_any_of(":"));
317  if (elements.size() != 3) {
318  throw LSST_EXCEPT(ex::InvalidParameterError,
319  (boost::format("Could not parse string as xx:mm:ss format: %s") % dms).str());
320  }
321  int const deg = abs(atoi(elements[0].c_str()));
322  int const min = atoi(elements[1].c_str());
323  double const sec = atof(elements[2].c_str());
324 
325  afwGeom::Angle ang = (deg + min/60.0 + sec/3600.0) * unit;
326  if ( (elements[0].c_str())[0] == '-' ) {
327  ang *= -1.0;
328  }
329  return ang;
330 }
331 
336  std::string const hms
337  ){
338  return xmsStringToAngle(hms, afwGeom::hours);
339 }
340 
345  std::string const dms
346  ) {
347  return xmsStringToAngle(dms, afwGeom::degrees);
348 }
349 
355  double const epoch
356  ) {
357  double const T = (epoch - 2000.0)/100.0;
358  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;
359 }
360 
361 
362 /* ============================================================
363  *
364  * class Coord
365  *
366  * ============================================================*/
367 
368 
374  lsst::afw::geom::Point2D const &p2d,
375  afwGeom::AngleUnit unit,
376  double const epoch
377  ) :
378  _longitude(NaN), _latitude(NaN), _epoch(epoch) {
379  _longitude = afwGeom::Angle(p2d.getX(), unit);
380  _longitude.wrap();
381  _latitude = afwGeom::Angle(p2d.getY(), unit);
382  _verifyValues();
383 }
384 
389  afwGeom::Point3D const &p3d,
390  double const epoch,
391  bool normalize,
392  afwGeom::Angle const defaultLongitude
393  ) :
394  _longitude(0. * afwGeom::radians),
395  _latitude(0. * afwGeom::radians),
396  _epoch(epoch) {
397 
398  std::pair<afwGeom::Angle, afwGeom::Angle> lonLat = pointToLonLat(p3d, defaultLongitude, normalize);
399  _longitude = lonLat.first;
400  _latitude = lonLat.second;
401  _epoch = epoch;
402 }
403 
409  afwGeom::Angle const ra,
410  afwGeom::Angle const dec,
411  double const epoch
412  ) :
413  _longitude(ra), _latitude(dec), _epoch(epoch) {
414  _longitude.wrap();
415  _verifyValues();
416 }
417 
423  std::string const ra,
424  std::string const dec,
425  double const epoch
426  ) :
427  _longitude(hmsStringToAngle(ra)),
428  _latitude(dmsStringToAngle(dec)),
429  _epoch(epoch) {
430  _longitude.wrap();
431  _verifyValues();
432 }
433 
441 afwCoord::Coord::Coord() : _longitude(afwGeom::Angle(NaN)), _latitude(afwGeom::Angle(NaN)), _epoch(NaN) {}
442 
443 
448  if (_latitude.asRadians() < -afwGeom::HALFPI || _latitude.asRadians() > afwGeom::HALFPI) {
449  throw LSST_EXCEPT(ex::InvalidParameterError,
450  (boost::format("Latitude coord must be: -PI/2 <= lat <= PI/2 (%f).") %
451  _latitude).str());
452  }
453 }
454 
461  afwGeom::Angle const longitude,
462  afwGeom::Angle const latitude,
463  double const epoch
464  ) {
465  _longitude = longitude;
466  _latitude = latitude;
467  _longitude.wrap();
468  _epoch = epoch;
469  _verifyValues();
470 }
471 
472 
478  // treat HOURS specially, they must mean hours for RA, degrees for Dec
479  if (unit == afwGeom::hours) {
480  return afwGeom::Point2D(getLongitude().asHours(), getLatitude().asDegrees());
481  } else {
482  return afwGeom::Point2D(getLongitude().asAngularUnits(unit), getLatitude().asAngularUnits(unit));
483  }
484 }
485 
486 
492  double lng = getLongitude();
493  double lat = getLatitude();
494  double const x = std::cos(lng) * std::cos(lat);
495  double const y = std::sin(lng) * std::cos(lat);
496  double const z = std::sin(lat);
497  return afwGeom::Point3D(x, y, z);
498 }
499 
500 
508  Coord const &poleTo,
509  Coord const &poleFrom
510  ) const {
511  double const alphaGP = poleFrom[0];
512  double const deltaGP = poleFrom[1];
513  double const lCP = poleTo[0];
514 
515  double const alpha = getLongitude();
516  double const delta = getLatitude();
517 
518  afwGeom::Angle const l = (lCP - std::atan2(std::sin(alpha - alphaGP),
519  std::tan(delta)*std::cos(deltaGP) - std::cos(alpha - alphaGP)*std::sin(deltaGP))) * afwGeom::radians;
520  afwGeom::Angle const b = std::asin( (std::sin(deltaGP)*std::sin(delta) + std::cos(deltaGP)*std::cos(delta)*std::cos(alpha - alphaGP))) * afwGeom::radians;
521  return Coord(l, b);
522 }
523 
524 
530  Coord const &axis,
531  afwGeom::Angle const theta
532  ) {
533 
534  double const c = std::cos(theta);
535  double const mc = 1.0 - c;
536  double const s = std::sin(theta);
537 
538  // convert to cartesian
539  afwGeom::Point3D const x = getVector();
540  afwGeom::Point3D const u = axis.getVector();
541  double const ux = u[0];
542  double const uy = u[1];
543  double const uz = u[2];
544 
545  // rotate
546  afwGeom::Point3D xprime;
547  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];
548  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];
549  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];
550 
551  // in-situ
552  std::pair<afwGeom::Angle, afwGeom::Angle> lonLat = pointToLonLat(xprime);
553  _longitude = lonLat.first;
554  _latitude = lonLat.second;
555 }
556 
557 
567  afwGeom::Angle const phi,
568  afwGeom::Angle const arcLen
569  ) {
570 
571  // let v = vector in the direction arcLen points (tangent to surface of sphere)
572  // thus: |v| = arcLen
573  // angle phi = orientation of v in a tangent plane, measured wrt to a parallel of declination
574 
575  // To do the rotation, use rotate() method.
576  // - must provide an axis of rotation: take the cross product r x v to get that axis (pole)
577 
578  // get the vector r
579  Eigen::Vector3d r = getVector().asEigen();
580 
581  // Get the vector v:
582  // let u = unit vector lying on a parallel of declination
583  // let w = unit vector along line of longitude = r x u
584  // the vector v must satisfy the following:
585  // |v| = arcLen
586  // r . v = 0
587  // u . v = |v| cos(phi) = arcLen*cos(phi)
588  // w . v = |v| sin(phi) = arcLen*sin(phi)
589 
590  // v is a linear combination of u and w
591  // v = arcLen*cos(phi)*u + arcLen*sin(phi)*w
592 
593  // Thus, we must:
594  // - create u vector
595  // - solve w vector (r cross u)
596  // - compute v
597  Eigen::Vector3d u;
598  u << -std::sin(getLongitude()), std::cos(getLongitude()), 0.0;
599  Eigen::Vector3d w = r.cross(u);
600  Eigen::Vector3d v = arcLen * std::cos(phi)*u + arcLen * std::sin(phi)*w;
601 
602  // take r x v to get the axis
603  Eigen::Vector3d axisVector = r.cross(v);
604  axisVector.normalize();
605  Coord axisCoord = Coord(afwGeom::Point3D(axisVector), getEpoch());
606 
607  rotate(axisCoord, arcLen);
608 
609  // now get the position angle at our destination
610  // u2 . v2 = arcLen*cos(phi2)
611  // w2 . v2 = arcLen*sin(phi2)
612  // if we normalize v2:
613  // phi2 = atan2(w2.v2, u2.v2)
614  //
615  // we need to compute u2, and then rotate v (exactly as we rotated r) to get v2
616  Eigen::Vector3d r2 = getVector().asEigen();
617  Eigen::Vector3d u2;
618  u2 << -std::sin(getLongitude()), std::cos(getLongitude()), 0.0;
619  Eigen::Vector3d w2 = r2.cross(u2);
620 
621  // make v a unit vector and rotate v exactly as we rotated r
622  v.normalize();
623  Coord v2Coord = Coord(afwGeom::Point3D(v), getEpoch());
624  v2Coord.rotate(axisCoord, arcLen);
625  Eigen::Vector3d v2 = v2Coord.getVector().asEigen();
626 
627  afwGeom::Angle phi2 = std::atan2(w2.dot(v2), u2.dot(v2)) * afwGeom::radians;
628 
629  return phi2;
630 }
631 
632 
642 PTR(afwCoord::Coord) afwCoord::Coord::convert(CoordSystem system, double epoch) const {
643 
644  switch (system) {
645  case FK5:
646  {
647  Fk5Coord c1 = this->toFk5(epoch);
648  return std::shared_ptr<Fk5Coord>(new Fk5Coord(c1.getLongitude(),
649  c1.getLatitude(),
650  c1.getEpoch()));
651  }
652  break;
653  case ICRS:
654  {
655  IcrsCoord c2 = this->toIcrs();
656  return std::shared_ptr<IcrsCoord>(new IcrsCoord(c2.getLongitude(),
657  c2.getLatitude()));
658  }
659  break;
660  case GALACTIC:
661  {
662  GalacticCoord c4 = this->toGalactic();
663  return std::shared_ptr<GalacticCoord>(new GalacticCoord(c4.getLongitude(),
664  c4.getLatitude()));
665  }
666  break;
667  case ECLIPTIC:
668  {
669  EclipticCoord c5 = this->toEcliptic(epoch);
670  return std::shared_ptr<EclipticCoord>(new EclipticCoord(c5.getLongitude(),
671  c5.getLatitude(),
672  c5.getEpoch()));
673  }
674  break;
675  case TOPOCENTRIC:
676  throw LSST_EXCEPT(ex::InvalidParameterError,
677  "Cannot make Topocentric with convert() (must also specify Observatory).\n"
678  "Instantiate TopocentricCoord() directly.");
679  break;
680  case UNKNOWN:
681  throw LSST_EXCEPT(ex::InvalidParameterError,
682  "Cannot convert to UNKNOWN coordinate system");
683  break;
684  default:
685  throw LSST_EXCEPT(ex::InvalidParameterError,
686  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC allowed.");
687  break;
688 
689  }
690 
691 }
692 
693 
699  Coord const &c
700  ) const {
701 
702  // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic)
703  // we'll put them in the same system.
704  std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> const& fk5 = commonFk5(*this, c);
705  afwGeom::Angle const alpha1 = fk5.first.getRa();
706  afwGeom::Angle const delta1 = fk5.first.getDec();
707  afwGeom::Angle const alpha2 = fk5.second.getRa();
708  afwGeom::Angle const delta2 = fk5.second.getDec();
709 
710  return haversine(alpha1 - alpha2, delta1 - delta2, std::cos(delta1), std::cos(delta2));
711 }
712 
713 
721 std::pair<afwGeom::Angle, afwGeom::Angle>
723  ) const
724 {
725  // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic)
726  // we'll put them in the same system.
727  std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> const& fk5 = commonFk5(*this, c);
728  afwGeom::Angle const alpha1 = fk5.first.getRa();
729  afwGeom::Angle const delta1 = fk5.first.getDec();
730  afwGeom::Angle const alpha2 = fk5.second.getRa();
731  afwGeom::Angle const delta2 = fk5.second.getDec();
732 
733  afwGeom::Angle const dAlpha = alpha1-alpha2;
734  afwGeom::Angle const dDelta = delta1-delta2;
735 
736  double const cosDelta1 = std::cos(delta1);
737  double const cosDelta2 = std::cos(delta2);
738 
739  afwGeom::Angle separation = haversine(dAlpha, dDelta, cosDelta1, cosDelta2);
740 
741  // Formula from http://www.movable-type.co.uk/scripts/latlong.html
742  double const y = std::sin(dAlpha)*cosDelta2;
743  double const x = cosDelta1*std::sin(delta2) - std::sin(delta1)*cosDelta2*std::cos(dAlpha);
744  afwGeom::Angle bearing = std::atan2(y, x)*afwGeom::radians - 90.0*afwGeom::degrees;
745 
746  return std::make_pair(bearing, separation);
747 }
748 
756 std::pair<afwGeom::Angle, afwGeom::Angle>
758  ) const
759 {
760  // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic)
761  // we'll put them in the same system.
762  std::pair<afwCoord::Fk5Coord, afwCoord::Fk5Coord> const& fk5 = commonFk5(*this, c);
763  afwGeom::Angle const alpha1 = fk5.first.getRa();
764  afwGeom::Angle const delta1 = fk5.first.getDec();
765  afwGeom::Angle const alpha2 = fk5.second.getRa();
766  afwGeom::Angle const delta2 = fk5.second.getDec();
767 
768  // This is a projection of coord2 to the tangent plane at coord1
769  double const sinDelta1 = std::sin(delta1);
770  double const cosDelta1 = std::cos(delta1);
771  double const sinDelta2 = std::sin(delta2);
772  double const cosDelta2 = std::cos(delta2);
773  double const cosAlphaDiff = std::cos(alpha2 - alpha1);
774  double const sinAlphaDiff = std::sin(alpha2 - alpha1);
775 
776  double const div = cosDelta1 * cosAlphaDiff * cosDelta2 + sinDelta1 * sinDelta2;
777  double const xi = cosDelta1 * sinAlphaDiff / div;
778  double const eta = (cosDelta1 * cosAlphaDiff * sinDelta2 - sinDelta1 * cosDelta2) / div;
779 
780  return std::make_pair(xi*afwGeom::radians, eta*afwGeom::radians);
781 }
782 
783 
787 afwCoord::Fk5Coord afwCoord::Coord::toFk5(double const epoch) const {
788  return Fk5Coord(getLongitude(), getLatitude(), getEpoch()).precess(epoch);
789 }
794  return Fk5Coord(getLongitude(), getLatitude(), getEpoch());
795 }
796 
802  return this->toFk5().toIcrs();
803 }
804 
809  return this->toFk5().toGalactic();
810 }
811 
816  return this->toFk5(epoch).toEcliptic();
817 }
822  return this->toFk5().toEcliptic();
823 }
824 
829  Observatory const &obs,
830  lsst::daf::base::DateTime const &obsDate
831  ) const {
832  return this->toFk5().toTopocentric(obs, obsDate);
833 }
834 
835 
836 
837 
838 /* ============================================================
839  *
840  * class Fk5Coord
841  *
842  * ============================================================*/
843 
844 
849  return Fk5Coord(getLongitude(), getLatitude(), getEpoch()).precess(epoch);
850 }
855  return Fk5Coord(getLongitude(), getLatitude(), getEpoch());
856 }
857 
863 
864  // only do the precession to 2000 if we're not already there.
865  if ( fabs(getEpoch() - 2000.0) > epochTolerance ) {
866  afwCoord::Fk5Coord c = precess(2000.0);
867  return IcrsCoord(c.getLongitude(), c.getLatitude());
868  } else {
869  return IcrsCoord(getLongitude(), getLatitude());
870  }
871 }
872 
873 
878 
879  // if we're epoch==2000, we can transform, otherwise we need to precess first
880  Fk5Coord c;
881  if ( fabs(getEpoch() - 2000.0) > epochTolerance ) {
882  c = precess(2000.0);
883  } else {
884  c = *this;
885  }
886 
887  Coord ct = c.transform(Fk5PoleInGalactic(), GalacticPoleInFk5());
888  return GalacticCoord(ct.getLongitude(), ct.getLatitude());
889 
890 }
891 
896  afwGeom::Angle const eclPoleIncl = eclipticPoleInclination(epoch);
897  Coord const eclPoleInEquatorial(270.0 * afwGeom::degrees, (90.0 * afwGeom::degrees) - eclPoleIncl, epoch);
898  Coord const equPoleInEcliptic(90.0 * afwGeom::degrees, (90.0 * afwGeom::degrees) - eclPoleIncl, epoch);
899  Coord c = transform(equPoleInEcliptic, eclPoleInEquatorial);
900  return EclipticCoord(c.getLongitude(), c.getLatitude(), epoch);
901 }
906  return this->toEcliptic(getEpoch());
907 }
908 
913  Observatory const &obs,
914  lsst::daf::base::DateTime const &obsDate
915  ) const {
916 
917  // make sure we precess to the epoch
918  Fk5Coord fk5 = precess(obsDate.get(dafBase::DateTime::EPOCH));
919 
920  // greenwich sidereal time
921  afwGeom::Angle theta0 = meanSiderealTimeGreenwich(obsDate.get(dafBase::DateTime::JD));
922  theta0.wrap();
923 
924  // lat/long of the observatory
925  afwGeom::Angle const phi = obs.getLatitude();
926  afwGeom::Angle const L = obs.getLongitude();
927 
928  // ra/dec of the target
929  afwGeom::Angle const alpha = fk5.getRa();
930  afwGeom::Angle const delta = fk5.getDec();
931 
932  afwGeom::Angle const H = theta0 + L - alpha;
933 
934  // compute the altitude, h
935  double const sinh = std::sin(phi)* std::sin(delta) + std::cos(phi) * std::cos(delta) * std::cos(H);
936  afwGeom::Angle const h = std::asin(sinh) * afwGeom::radians;
937 
938  // compute the azimuth, A
939  double const tanAnumerator = std::sin(H);
940  double const tanAdenominator = (std::cos(H) * std::sin(phi) - std::tan(delta) * std::cos(phi));
941 
942  // Equations used here assume azimuth is with respect to South
943  // but we use the North as our origin ... must add 180 deg
944  afwGeom::Angle A = (180.0*afwGeom::degrees) + atan2(tanAnumerator, tanAdenominator)* afwGeom::radians;
945  A.wrap();
946 
947  return TopocentricCoord(A, h, obsDate.get(dafBase::DateTime::EPOCH), obs);
948 }
949 
950 
951 
957  double const epochTo
958  ) const {
959 
960  // return a copy if the epochs are the same
961  if ( fabs(getEpoch() - epochTo) < epochTolerance) {
962  return Fk5Coord(getLongitude(), getLatitude(), getEpoch());
963  }
964 
967  double const jd0 = dateFrom.get(dafBase::DateTime::JD);
968  double const jd = dateTo.get(dafBase::DateTime::JD);
969 
970  double const T = (jd0 - JD2000)/36525.0;
971  double const t = (jd - jd0)/36525.0;
972  double const tt = t*t;
973  double const ttt = tt*t;
974 
975  afwGeom::Angle const xi = ((2306.2181 + 1.39656*T - 0.000139*T*T)*t +
976  (0.30188 - 0.000344*T)*tt + 0.017998*ttt) * afwGeom::arcseconds;
977  afwGeom::Angle const z = ((2306.2181 + 1.39656*T - 0.000139*T*T)*t +
978  (1.09468 + 0.000066*T)*tt + 0.018203*ttt) * afwGeom::arcseconds;
979  afwGeom::Angle const theta = ((2004.3109 - 0.85330*T - 0.000217*T*T)*t -
980  (0.42665 + 0.000217*T)*tt - 0.041833*ttt) * afwGeom::arcseconds;
981 
982  Fk5Coord fk5 = this->toFk5();
983  afwGeom::Angle const alpha0 = fk5.getRa();
984  afwGeom::Angle const delta0 = fk5.getDec();
985 
986  double const a = std::cos(delta0) * std::sin((alpha0 + xi));
987  double const b = std::cos(theta) * std::cos(delta0) * std::cos((alpha0 + xi)) - std::sin(theta) * std::sin(delta0);
988  double const c = std::sin(theta) * std::cos(delta0) * std::cos((alpha0 + xi)) + std::cos(theta) * std::sin(delta0);
989 
990  afwGeom::Angle const alpha = (std::atan2(a,b) + z) * afwGeom::radians;
991  afwGeom::Angle const delta = std::asin(c) * afwGeom::radians;
992 
993  return Fk5Coord(alpha, delta, epochTo);
994 }
995 
996 
997 /* ============================================================
998  *
999  * class IcrsCoord
1000  *
1001  * ============================================================*/
1002 
1007  Coord::reset(longitude, latitude, 2000.0);
1008 }
1009 
1014  return Fk5Coord(getLongitude(), getLatitude(), 2000.0).precess(epoch);
1015 }
1020  return Fk5Coord(getLongitude(), getLatitude(), 2000.0);
1021 }
1022 
1027  return IcrsCoord(getLongitude(), getLatitude());
1028 }
1029 
1030 
1031 
1032 
1033 /* ============================================================
1034  *
1035  * class GalacticCoord
1036  *
1037  * ============================================================*/
1038 
1042 void afwCoord::GalacticCoord::reset(afwGeom::Angle const longitudeDeg, afwGeom::Angle const latitudeDeg) {
1043  Coord::reset(longitudeDeg, latitudeDeg, 2000.0);
1044 }
1045 
1050  // transform to fk5
1051  // galactic coords are ~constant, and the poles used are for epoch=2000, so we get J2000
1052  Coord c = transform(GalacticPoleInFk5(), Fk5PoleInGalactic());
1053  return Fk5Coord(c.getLongitude(), c.getLatitude(), 2000.0).precess(epoch);
1054 }
1059  return this->toFk5(2000.0);
1060 }
1061 
1066  return GalacticCoord(getLongitude(), getLatitude());
1067 }
1068 
1069 
1070 
1071 
1072 /* ============================================================
1073  *
1074  * class EclipticCoord
1075  *
1076  * ============================================================*/
1077 
1082  return EclipticCoord(getLongitude(), getLatitude(), getEpoch()).precess(epoch);
1083 }
1088  return EclipticCoord(getLongitude(), getLatitude(), getEpoch());
1089 }
1090 
1091 
1096  afwGeom::Angle const eclPoleIncl = eclipticPoleInclination(epoch);
1097  afwGeom::Angle ninety = 90. * afwGeom::degrees;
1098  Coord const eclipticPoleInFk5(270.0 * afwGeom::degrees, ninety - eclPoleIncl, epoch);
1099  Coord const fk5PoleInEcliptic(ninety, ninety - eclPoleIncl, epoch);
1100  Coord c = transform(eclipticPoleInFk5, fk5PoleInEcliptic);
1101  return Fk5Coord(c.getLongitude(), c.getLatitude(), epoch);
1102 }
1107  return this->toFk5(getEpoch());
1108 }
1109 
1110 
1117  double const epochTo
1118  ) const {
1119  return this->toFk5().precess(epochTo).toEcliptic();
1120 }
1121 
1122 
1123 
1124 /* ============================================================
1125  *
1126  * class TopocentricCoord
1127  *
1128  * ============================================================*/
1129 
1134 
1135  afwGeom::Angle const phi = _obs.getLatitude();
1136  afwGeom::Angle const L = _obs.getLongitude();
1137 
1138  // Equations used here assume azimuth is with respect to South
1139  // but we use the North as our origin.
1140  afwGeom::Angle A = getAzimuth() + 180.0*afwGeom::degrees;
1141  A.wrap();
1142  afwGeom::Angle const h = getAltitude();
1143 
1144 
1145  double const jd = dafBase::DateTime(epoch,
1148  afwGeom::Angle theta0 = meanSiderealTimeGreenwich(jd);
1149  theta0.wrap();
1150 
1151  double const tanHnum = std::sin(A);
1152  double const tanHdenom = std::cos(A)*std::sin(phi) + std::tan(h)*std::cos(phi);
1153  afwGeom::Angle H = std::atan2(tanHnum, tanHdenom) * afwGeom::radians;
1154 
1155  afwGeom::Angle const alpha = theta0 + L - H;
1156  double const sinDelta = std::sin(phi)*std::sin(h) - std::cos(phi)*std::cos(h)*std::cos(A);
1157  afwGeom::Angle const delta = (std::asin(sinDelta)) * afwGeom::radians;
1158 
1159  return Fk5Coord(alpha, delta, epoch);
1160 }
1165  return this->toFk5(getEpoch());
1166 }
1167 
1168 
1173  lsst::afw::coord::Observatory const &obs,
1174  lsst::daf::base::DateTime const &date
1175  ) const
1176 {
1177  if (obs != _obs) {
1178  throw LSST_EXCEPT(ex::InvalidParameterError,
1179  (boost::format("Expected observatory %s, saw %s") % _obs % obs).str());
1180  }
1181  if (fabs(date.get() - getEpoch()) > std::numeric_limits<double>::epsilon()) {
1182  throw LSST_EXCEPT(ex::InvalidParameterError,
1183  (boost::format("Expected date %g, saw %g") % getEpoch() % date.get()).str());
1184  }
1185 
1186  return TopocentricCoord(getLongitude(), getLatitude(), getEpoch(), _obs);
1187 }
1188 
1195  return TopocentricCoord(getLongitude(), getLatitude(), getEpoch(), _obs);
1196 }
1197 
1198 
1199 
1200 /* ===============================================================================
1201  *
1202  * Factory function definitions:
1203  *
1204  * Each makeCoord() function has overloaded variants with and without epoch specified.
1205  * It was tempting to specify default values, but some coordinate systems have
1206  * no epoch, and this would be confusing to the user. In its current form,
1207  * any epochless coordinate system requested with an epoch specified will throw an exception.
1208  * The epochless factories will always work, but assume default epoch = 2000.
1209  *
1210  * ===============================================================================
1211  */
1212 
1221  CoordSystem const system,
1222  afwGeom::Angle const ra,
1223  afwGeom::Angle const dec,
1224  double const epoch
1225 ) {
1226 
1227  switch (system) {
1228  case FK5:
1229  return std::shared_ptr<Fk5Coord>(new Fk5Coord(ra, dec, epoch));
1230  break;
1231  case ICRS:
1232  throw LSST_EXCEPT(ex::InvalidParameterError,
1233  "ICRS has no epoch, use overloaded makeCoord with args (system, ra, dec).");
1234  break;
1235  case GALACTIC:
1236  throw LSST_EXCEPT(ex::InvalidParameterError,
1237  "Galactic has no epoch, use overloaded makeCoord with (system, ra, dec).");
1238  break;
1239  case ECLIPTIC:
1240  return std::shared_ptr<EclipticCoord>(new EclipticCoord(ra, dec, epoch));
1241  break;
1242  case TOPOCENTRIC:
1243  throw LSST_EXCEPT(ex::InvalidParameterError,
1244  "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n"
1245  "Instantiate TopocentricCoord() directly.");
1246  break;
1247  default:
1248  throw LSST_EXCEPT(ex::InvalidParameterError,
1249  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, and TOPOCENTRIC allowed.");
1250  break;
1251 
1252  }
1253 
1254 }
1255 
1256 
1257 
1265  CoordSystem const system,
1266  afwGeom::Angle const ra,
1267  afwGeom::Angle const dec
1268 ) {
1269 
1270  switch (system) {
1271  case FK5:
1272  return std::shared_ptr<Fk5Coord>(new Fk5Coord(ra, dec, 2000.0));
1273  break;
1274  case ICRS:
1275  return std::shared_ptr<IcrsCoord>(new IcrsCoord(ra, dec));
1276  break;
1277  case GALACTIC:
1278  return std::shared_ptr<GalacticCoord>(new GalacticCoord(ra, dec));
1279  break;
1280  case ECLIPTIC:
1281  return std::shared_ptr<EclipticCoord>(new EclipticCoord(ra, dec, 2000.0));
1282  break;
1283  case TOPOCENTRIC:
1284  throw LSST_EXCEPT(ex::InvalidParameterError,
1285  "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n"
1286  "Instantiate TopocentricCoord() directly.");
1287  break;
1288  default:
1289  throw LSST_EXCEPT(ex::InvalidParameterError,
1290  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, and TOPOCENTRIC allowed.");
1291  break;
1292 
1293  }
1294 
1295 }
1296 
1297 
1298 
1306  CoordSystem const system,
1307  lsst::afw::geom::Point3D const &p3d,
1308  double const epoch,
1309  bool normalize,
1310  afwGeom::Angle const defaultLongitude
1311 ) {
1312  Coord c(p3d, 2000.0, normalize, defaultLongitude);
1313  return makeCoord(system, c.getLongitude(), c.getLatitude(), epoch);
1314 }
1322  CoordSystem const system,
1323  lsst::afw::geom::Point3D const &p3d,
1324  bool normalize,
1325  afwGeom::Angle const defaultLongitude
1326 ) {
1327  Coord c(p3d, 2000.0, normalize, defaultLongitude);
1328  return makeCoord(system, c.getLongitude(), c.getLatitude());
1329 }
1330 
1337  CoordSystem const system,
1338  lsst::afw::geom::Point2D const &p2d,
1339  afwGeom::AngleUnit unit,
1340  double const epoch
1341 ) {
1342  if (unit == afwGeom::hours) {
1343  return makeCoord(system, afwGeom::Angle(p2d.getX(), afwGeom::hours), afwGeom::Angle(p2d.getY(), afwGeom::degrees), epoch);
1344  } else {
1345  return makeCoord(system, afwGeom::Angle(p2d.getX(), unit), afwGeom::Angle(p2d.getY(), unit), epoch);
1346  }
1347 }
1348 
1356  CoordSystem const system,
1357  lsst::afw::geom::Point2D const &p2d,
1358  afwGeom::AngleUnit unit
1359 ) {
1360  if (unit == afwGeom::hours) {
1361  return makeCoord(system, afwGeom::Angle(p2d.getX(), afwGeom::hours), afwGeom::Angle(p2d.getY(), afwGeom::degrees));
1362  } else {
1363  return makeCoord(system, afwGeom::Angle(p2d.getX(), unit), afwGeom::Angle(p2d.getY(), unit));
1364  }
1365 }
1366 
1373  CoordSystem const system,
1374  std::string const ra,
1375  std::string const dec,
1376  double const epoch
1377  ) {
1378  return makeCoord(system, dmsStringToAngle(ra), dmsStringToAngle(dec), epoch);
1379 }
1386  CoordSystem const system,
1387  std::string const ra,
1388  std::string const dec
1389  ) {
1390  return makeCoord(system, dmsStringToAngle(ra), dmsStringToAngle(dec));
1391 }
1392 
1393 
1394 
1399  CoordSystem const system
1400  ) {
1401  switch (system) {
1402  case FK5:
1403  return std::shared_ptr<Fk5Coord>(new Fk5Coord());
1404  break;
1405  case ICRS:
1406  return std::shared_ptr<IcrsCoord>(new IcrsCoord());
1407  break;
1408  case GALACTIC:
1409  return std::shared_ptr<GalacticCoord>(new GalacticCoord());
1410  break;
1411  case ECLIPTIC:
1412  return std::shared_ptr<EclipticCoord>(new EclipticCoord());
1413  break;
1414  case TOPOCENTRIC:
1415  throw LSST_EXCEPT(ex::InvalidParameterError,
1416  "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n"
1417  "Instantiate TopocentricCoord() directly.");
1418  break;
1419  default:
1420  throw LSST_EXCEPT(ex::InvalidParameterError,
1421  "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, allowed.");
1422  break;
1423 
1424  }
1425 }
1426 
1427 std::ostream & afwCoord::operator<<(std::ostream & os, afwCoord::Coord const & coord) {
1428  auto const className = coord.getClassName();
1429  auto const coordSystem = coord.getCoordSystem();
1430  os << (boost::format("%s(%.7f, %.7f")
1431  % className
1432  % coord[0].asDegrees()
1433  % coord[1].asDegrees()).str();
1434  if (coordSystem == TOPOCENTRIC) {
1435  os << (boost::format(", %.12f, (%s)")
1436  % coord.getEpoch()
1437  % dynamic_cast<afwCoord::TopocentricCoord const &>(coord).getObservatory()).str();
1438  } else if (coordSystem != ICRS && coordSystem != GALACTIC) {
1439  os << (boost::format(", %.2f") % coord.getEpoch()).str();
1440  }
1441  os << ")";
1442  return os;
1443 }
1444 
1445 namespace {
1446 
1447 // Heavy lifting for averageCoord
1448 PTR(afwCoord::Coord) doAverageCoord(
1449  std::vector<PTR(afwCoord::Coord const)> const coords,
1450  afwCoord::CoordSystem system
1451  )
1452 {
1453  assert(system != afwCoord::UNKNOWN); // Handled by caller
1454  assert(coords.size() > 0); // Handled by caller
1455  afwGeom::Point3D sum(0, 0, 0);
1456  afwGeom::Point3D corr(0, 0, 0); // Kahan summation correction
1457  for (auto&& cc : coords) {
1458  afwGeom::Point3D const point = cc->getVector();
1459  // Kahan summation
1460  afwGeom::Extent3D const add = point - corr;
1461  afwGeom::Point3D const temp = sum + add;
1462  corr = (temp - afwGeom::Extent3D(sum)) - add;
1463  sum = temp;
1464  }
1465  sum.scale(1.0/coords.size());
1466  return makeCoord(system, sum);
1467 }
1468 
1469 } // anonymous namespace
1470 
1471 PTR(afwCoord::Coord) afwCoord::averageCoord(
1472  std::vector<PTR(afwCoord::Coord const)> const coords,
1473  afwCoord::CoordSystem system
1474  )
1475 {
1476  if (coords.size() == 0) {
1477  throw LSST_EXCEPT(ex::LengthError, "No coordinates provided to average");
1478  }
1479 
1480  if (system == UNKNOWN) {
1481  // Determine which system we're using, and check that every coordinate is in that system
1482  system = coords[0]->getCoordSystem();
1483  for (auto&& cc : coords) {
1484  if (cc->getCoordSystem() != system) {
1485  throw LSST_EXCEPT(ex::InvalidParameterError,
1486  (boost::format("Coordinates are not all in the same system: %d vs %d") %
1487  cc->getCoordSystem() % system).str());
1488  }
1489  }
1490  return doAverageCoord(coords, system);
1491  }
1492 
1493  // Convert everything to the nominated coordinate system if necessary
1494  std::vector<PTR(afwCoord::Coord const)> converted;
1495  converted.reserve(coords.size());
1496  for (auto&& cc : coords) {
1497  converted.push_back(cc->getCoordSystem() == system ? cc : cc->convert(system));
1498  }
1499  return doAverageCoord(converted, system);
1500 }
int y
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:477
virtual CoordSystem getCoordSystem() const
Definition: Coord.h:100
virtual Fk5Coord toFk5() const
Convert ourself to Fk5: RA, Dec (use current epoch)
Definition: Coord.cc:793
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:1042
Class for handling dates/times, including MJD, UTC, and TAI.
Definition: DateTime.h:62
lsst::afw::coord::Coord Coord
Definition: misc.h:35
A class to handle Galactic coordinates (inherits from Coord)
Definition: Coord.h:237
lsst::afw::geom::Angle _latitude
Definition: Coord.h:146
lsst::afw::geom::Angle hmsStringToAngle(std::string const hms)
Convert a hh:mm:ss string to Angle.
Definition: Coord.cc:335
lsst::afw::geom::Angle angularSeparation(Coord const &c) const
compute the angular separation between two Coords
Definition: Coord.cc:698
AngleUnit const radians
constant with units of radians
Definition: Angle.h:90
std::pair< lsst::afw::geom::Angle, lsst::afw::geom::Angle > getOffsetFrom(Coord const &c) const
Compute the offset from a coordinate.
Definition: Coord.cc:722
Hold the location of an observatory.
Definition: Observatory.h:47
virtual GalacticCoord toGalactic() const
Convert ourself to Galactic: l, b.
Definition: Coord.cc:877
Include files required for standard LSST Exception handling.
A coordinate class intended to represent offsets and dimensions.
lsst::afw::geom::Angle getLongitude() const
The main access method for the longitudinal coordinate.
Definition: Coord.h:112
virtual Fk5Coord toFk5(double const epoch) const
Convert ourself to Fk5: RA, Dec (precess to new epoch)
Definition: Coord.cc:787
AngleUnit const hours
Definition: Angle.h:92
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:1006
virtual GalacticCoord toGalactic() const
Convert ourself to Galactic: l, b.
Definition: Coord.cc:808
lsst::afw::geom::Angle _longitude
Definition: Coord.h:145
EigenVector const & asEigen() const
Return a fixed-size Eigen representation of the coordinate object.
virtual IcrsCoord toIcrs() const
Convert ourself to ICRS: RA, Dec (basically J2000)
Definition: Coord.cc:862
lsst::afw::coord::IcrsCoord IcrsCoord
Definition: misc.h:37
table::Key< geom::Angle > latitude
Definition: VisitInfo.cc:172
virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &date) const
Convert ourself from Topocentric to Topocentric ...
Definition: Coord.cc:1172
A class used to convert scalar POD types such as double to Angle.
Definition: Angle.h:70
virtual Fk5Coord toFk5() const
Convert ourself from galactic to Fk5 (no epoch specified)
Definition: Coord.cc:1058
Extent< double, 3 > Extent3D
Definition: Extent.h:362
A coordinate class intended to represent absolute positions.
Matrix alpha
virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &obsDate) const
Convert ourself to Altitude/Azimuth: alt, az.
Definition: Coord.cc:912
Fk5Coord precess(double const epochTo) const
Precess ourselves from whence we are to a new epoch.
Definition: Coord.cc:956
double get(DateSystem system=MJD, Timescale scale=TAI) const
Get date as a double in a specified representation, such as MJD.
Definition: DateTime.cc:439
AngleUnit const degrees
Definition: Angle.h:91
virtual EclipticCoord toEcliptic(double const epoch) const
Convert ourself from Ecliptic to Ecliptic ...
Definition: Coord.cc:1081
A class representing an Angle.
Definition: Angle.h:103
A class to handle topocentric (AltAz) coordinates (inherits from Coord)
Definition: Coord.h:329
void rotate(Coord const &axis, lsst::afw::geom::Angle const theta)
Rotate our current coords about a pole.
Definition: Coord.cc:529
double w
Definition: CoaddPsf.cc:57
lsst::afw::geom::Angle getLongitude() const
get telescope longitude (positive values are E of Greenwich)
Definition: Observatory.cc:58
table::Key< geom::Angle > longitude
Definition: VisitInfo.cc:173
boost::shared_ptr< Coord > averageCoord(std::vector< boost::shared_ptr< Coord const >> const coords, CoordSystem system=UNKNOWN)
Return average of a list of coordinates.
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:757
lsst::afw::geom::Point3D getVector() const
Return our contents in a position vector.
Definition: Coord.cc:491
double asAngularUnits(AngleUnit const &units) const
Convert an Angle to a float in radians.
Definition: Angle.h:117
virtual TopocentricCoord toTopocentric() const
Convert ourself from Topocentric to Topocentric with no observatory or date arguments.
Definition: Coord.cc:1194
virtual Fk5Coord toFk5() const
Convert outself from Topocentric to Fk5 (use current epoch)
Definition: Coord.cc:1164
double x
virtual Fk5Coord toFk5() const
Convert ourself to Fk5 (ie.
Definition: Coord.cc:854
virtual IcrsCoord toIcrs() const
Icrs converter for IcrsCoord.
Definition: Coord.cc:1026
virtual Fk5Coord toFk5() const
Convert ourself from Ecliptic to Fk5 (use current epoch)
Definition: Coord.cc:1106
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:293
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:566
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:300
Interface for DateTime class.
virtual EclipticCoord toEcliptic() const
Convert ourself from Ecliptic to Ecliptic ...
Definition: Coord.cc:1087
Point< double, 3 > Point3D
Definition: Point.h:289
A class to handle Fk5 coordinates (inherits from Coord)
Definition: Coord.h:191
void _verifyValues() const
Make sure the values we&#39;ve got are in the range 0 &lt;= x &lt; 2PI.
Definition: Coord.cc:447
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
A class to handle Ecliptic coordinates (inherits from Coord)
Definition: Coord.h:278
double getEpoch() const
Definition: Coord.h:90
EclipticCoord precess(double const epochTo) const
precess to new epoch
Definition: Coord.cc:1116
tuple m
Definition: lsstimport.py:48
virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude)
Definition: Coord.h:83
Extent< int, N > floor(Extent< double, N > const &input)
Return the component-wise floor (round towards more negative).
lsst::afw::geom::Angle Angle
Definition: misc.h:38
#define PTR(...)
Definition: base.h:41
Coord()
Default constructor for the Coord base class.
Definition: Coord.cc:441
double const HALFPI
Definition: Angle.h:19
virtual Fk5Coord toFk5() const
Fk5 converter for IcrsCoord.
Definition: Coord.cc:1019
AngleUnit const arcseconds
Definition: Angle.h:94
virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &obsDate) const
Convert ourself to Altitude/Azimuth: alt, az.
Definition: Coord.cc:828
boost::shared_ptr< Coord > 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:1220
void scale(double factor)
Definition: Point.h:118
lsst::afw::geom::Angle getDec() const
Definition: Coord.h:215
afw::table::Key< double > b
Point< double, 2 > Point2D
Definition: Point.h:288
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:117
virtual std::string getClassName() const
Definition: Coord.h:98
virtual EclipticCoord toEcliptic() const
Convert ourself to Ecliptic: lambda, beta (use existing epoch)
Definition: Coord.cc:821
std::ostream & operator<<(std::ostream &stream, Exception const &e)
Push the text representation of an exception onto a stream.
Definition: Exception.cc:124
virtual EclipticCoord toEcliptic() const
Convert ourself to Ecliptic: lambda, beta (use current epoch)
Definition: Coord.cc:905
virtual IcrsCoord toIcrs() const
Convert ourself to ICRS: RA, Dec (basically J2000)
Definition: Coord.cc:801
lsst::afw::geom::Angle getLatitude() const
The main access method for the latitudinal coordinate.
Definition: Coord.h:119
lsst::afw::geom::Angle getRa() const
Definition: Coord.h:214
This is the base class for spherical coordinates.
Definition: Coord.h:69
void wrap()
Wraps this angle to the range [0, 2 pi)
Definition: Angle.h:145
lsst::afw::geom::Angle getLatitude() const
get telescope latitude
Definition: Observatory.cc:62
A class to handle Icrs coordinates (inherits from Coord)
Definition: Coord.h:156
lsst::afw::geom::Angle dmsStringToAngle(std::string const dms)
Convert a dd:mm:ss string to Angle.
Definition: Coord.cc:344
virtual GalacticCoord toGalactic() const
Convert ourself from Galactic to Galactic ...
Definition: Coord.cc:1065
lsst::afw::geom::Angle eclipticPoleInclination(double const epoch)
get the inclination of the ecliptic pole (obliquity) at epoch
Definition: Coord.cc:354
Coord transform(Coord const &poleFrom, Coord const &poleTo) const
Tranform our current coords to another spherical polar system.
Definition: Coord.cc:507
Functions to handle coordinates.