21 _setPosFromSph(equatAng, polarAng, parallax);
26 Coord::Coord(
double equatAng,
double polarAng,
double parallax,
double equatPM,
double polarPM,
double radVel) {
27 _setPosFromSph(equatAng, polarAng, parallax);
33 const double sinEquat =
sind(equatAng);
34 const double cosEquat =
cosd(equatAng);
35 const double sinPolar =
sind(polarAng);
36 const double cosPolar =
cosd(polarAng);;
40 const double pmAUPerYear1 = equatPM * _dist * RadPerYear_per_ArcsecPerCentury;
41 const double pmAUPerYear2 = polarPM * _dist * RadPerYear_per_ArcsecPerCentury;
44 const double radVelAUPerYear = radVel * AUPerYear_per_KmPerSec;
49 - (pmAUPerYear2 * sinPolar * cosEquat) - (pmAUPerYear1 * cosPolar * sinEquat) + (radVelAUPerYear * cosPolar * cosEquat),
50 - (pmAUPerYear2 * sinPolar * sinEquat) + (pmAUPerYear1 * cosPolar * cosEquat) + (radVelAUPerYear * cosPolar * sinEquat),
51 + (pmAUPerYear2 * cosPolar) + (radVelAUPerYear * sinPolar);
57 _pm(Eigen::Vector3d::Constant(0.0))
62 Coord::Coord(Eigen::Vector3d
const &pos, Eigen::Vector3d
const &pm)
72 _pos(Eigen::Vector3d::Constant(
DoubleNaN)),
89 polarAng = (z > 0.0) ? 90.0 : -90.0;
91 double posXYMag =
hypot(x, y);
93 polarAng =
atan2d(z, posXYMag);
117 double magPxy =
hypot(x, y);
118 double magPxySq = magPxy * magPxy;
119 double magPSq = _dist * _dist;
129 equatPM = (((x * vY) - (y * vX)) / magPxySq) * ArcsecPerCentury_per_RadPerYear;
130 polarPM = (((vZ * magPxy) - ((z / magPxy) * ((x * vX) + (y * vY)))) / magPSq) * ArcsecPerCentury_per_RadPerYear;
137 return (_pos / _dist).dot(_pm) * KMPerSec_per_AUPerYear;
142 for (
int i = 0; i < 3; ++i) {
143 if (!std::isfinite(_pos(i)))
return false;
144 if (!std::isfinite(_pm(i)))
return false;
146 if (!std::isfinite(_dist))
return false;
151 double crossMag = _pos.cross(coord.
getVecPos()).norm();
152 double dotProd = _pos.dot(coord.
getVecPos());
153 return atan2d(crossMag, dotProd);
157 Eigen::Vector3d fromU = _pos / _dist;
161 double sinVal = (toU(1) * fromU(0)) - (toU(0) * fromU(1));
162 double cosVal = (toU(2) * ((fromU(0) * fromU(0)) + (fromU(1) * fromU(1))))
163 - (fromU(2) * ((toU(0) * fromU(0)) + (toU(1) * fromU(1))));
165 if ((std::abs(sinVal) > 2e-10) || (std::abs(cosVal) > 2e-10)) {
174 throw std::runtime_error(
"cannot offset; at pole");
178 toOrient =
wrapCtr(fromOrient);
207 Eigen::Vector3d u = Eigen::Vector3d(-_pos(1), _pos(0), 0) /
hypot(_pos(0), _pos(1));
208 Eigen::Vector3d w = (_pos / _dist).cross(u);
209 Eigen::Vector3d v = (
cosd(fromOrient) * u) + (
sind(fromOrient) * w);
212 Eigen::Vector3d axisVector = (_pos / _dist).cross(v);
213 Eigen::Matrix3d rotMat;
215 Eigen::Vector3d toPos = rotMat * _pos;
216 Eigen::Vector3d toVel = rotMat * _pm;
217 Coord toCoord(toPos, toVel);
218 double unwrappedToOrient = toCoord.
orientationTo(*
this) + 180.0;
219 if (!std::isfinite(unwrappedToOrient)) {
221 unwrappedToOrient = fromOrient;
223 toOrient =
wrapCtr(unwrappedToOrient);
228 std::ostringstream os;
233 void Coord::_setPosFromSph(
double equatAng,
double polarAng,
double parallax) {
234 if ((polarAng < -90.0) || (polarAng > 90.0)) {
235 std::ostringstream os;
236 os <<
"polarAng = " << polarAng <<
" not in range [-90, 90]";
237 throw std::runtime_error(os.str());
243 dist *
cosd(polarAng) *
cosd(equatAng),
244 dist *
cosd(polarAng) *
sind(equatAng),
245 dist *
sind(polarAng);
248 void Coord::_setCache() {
252 if (_dist * _dist < std::numeric_limits<double>::min()) {
253 std::ostringstream os;
254 os <<
"Magnitude of _pos = (" << _pos(0) <<
", " << _pos(1) <<
", " << _pos(2) <<
") too small";
255 throw std::runtime_error(os.str());
259 double xyFracMag =
hypot(_pos(0), _pos(1)) / _dist;
260 _atPole = (xyFracMag * xyFracMag < std::numeric_limits<double>::epsilon());
264 double equatAng, polarAng, equatPM, polarPM;
266 coord.
getPM(equatPM, polarPM);
269 std::ios_base::fmtflags oldFlags = os.flags();
270 std::streamsize
const oldPrecision = os.precision();
272 <<
"Coord(" << std::setprecision(6) << equatAng <<
", " << polarAng <<
", "
273 << std::setprecision(5) << parallax;
274 if ((equatPM != 0) || (polarPM != 0) || (radVel != 0)) {
275 os << std::setprecision(2) <<
", " << equatPM <<
", " << polarPM <<
", " << radVel;
277 os <<
")" << std::setprecision(oldPrecision);
double angularSeparation(Coord const &coord) const
std::string __repr__() const
bool getSphPos(double &equatAng, double &polarAng) const
double hypot(double x, double y)
double cosd(double ang)
cosine of angle in degrees
double wrapCtr(double ang)
double sind(double ang)
sine of angle in degrees
double distanceFromParallax(double parallax)
bool getPM(double &equatPM, double &polarPM) const
double parallaxFromDistance(double dist)
double atan2d(double x, double y)
arctangent2 in degrees
Coord offset(double &toOrient, double fromOrient, double dist) const
Eigen::Vector3d const getVecPos() const
double getParallax() const
void computeRotationMatrix(Eigen::Matrix3d &rotMat, Eigen::Vector3d const &axis, double rotAngle)
double orientationTo(Coord const &coord) const
std::ostream & operator<<(std::ostream &out, Coord const &coord)
double wrapPos(double ang)
const double ArcsecPerDeg