File indexing completed on 2024-04-28 15:09:05

0001 /*
0002     SPDX-FileCopyrightText: 2020 Chris Rowland <chris.rowland@cherryfield.me.uk>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "poleaxis.h"
0008 
0009 #include <cmath>
0010 
0011 
0012 /******************************************************************
0013 poleAxis(sp1, sp2, sp3) finds the mount's RA axis of rotation determined
0014 by three points sampled by fixing the mount's DEC and sampling a point
0015 a three different RA position.
0016 
0017 For each SkyPoint sp, it finds its corresponding x,y,z coordinates,
0018 which are points on a unit sphere.  Those 3 coordinates define a plane.
0019 That plane intesects the sphere, and the intersection of a plane and a
0020 sphere is a circle. The center of that circle would be the axis of rotation
0021 defined by the origial 3 points.  So, finding the normal to the plane,
0022 and pointing in that (normal) direction from the center of the sphere
0023 (the origin) gives the axis of rotation of the mount.
0024 
0025 poleAxis returns the normal. The way to interpret this vector
0026 is a unit vector (direction) in the x,y,z space. To convert this back to an
0027 angle useful for polar alignment, the ra and dec angles can be
0028 retrieved with the primary(V) and secondary(V) functions.
0029 These can then be turned into an altitude and azimuth angles using methods
0030 in the SkyPoint class.
0031 
0032 Further detail
0033 
0034 Definitions: SkyPoint sp contains an hour angle ha and declication dec,
0035 with the usual convention that dec=0 is the equator, dec=90 is the north pole
0036 about which the axis spins, and ha is the spin angle
0037 (positive is counter clockwise when looking north from the center of the sphere)
0038 where 0-degrees would be pointing "up", e.g. toward the zenith when
0039 looking at the north pole. The sphere has radius 1.0.
0040 
0041 dirCos(sp) will return a 3D vector V whose components x,y,z
0042 are 3D cartesean coordinate positions given these ha & dec angles
0043 for points on the surface of a unit sphere.
0044 The z direction points towards the north pole.
0045 The y direction points left when looking at the north pole
0046 The x direction points "up".
0047 
0048 primary(V) where V contains the above x,y,z coordinates,
0049 will return the ha angle pointing to V.
0050 
0051 secondary(V) where V contains the above x,y,z coordinates,
0052 will return the dec angle pointing to V.
0053 ******************************************************************/
0054 
0055 Rotations::V3 PoleAxis::dirCos(const dms primary, const dms secondary)
0056 {
0057     return Rotations::V3(
0058                static_cast<float>(secondary.cos() * primary.cos()),
0059                static_cast<float>(secondary.cos() * primary.sin()),
0060                static_cast<float>(secondary.sin()));
0061 }
0062 
0063 Rotations::V3 PoleAxis::dirCos(const SkyPoint sp)
0064 {
0065     return dirCos(sp.ra(), sp.dec());
0066 }
0067 
0068 dms PoleAxis::primary(Rotations::V3 dirCos)
0069 {
0070     dms p;
0071     p.setRadians(static_cast<double>(std::atan2(dirCos.y(), dirCos.x())));
0072     return p;
0073 }
0074 
0075 dms PoleAxis::secondary(Rotations::V3 dirCos)
0076 {
0077     dms p;
0078     p.setRadians(static_cast<double>(std::asin(dirCos.z())));
0079     return p;
0080 }
0081 
0082 SkyPoint PoleAxis::skyPoint(Rotations::V3 dc)
0083 {
0084     return SkyPoint(primary(dc), secondary(dc));
0085 }
0086 
0087 Rotations::V3 PoleAxis::poleAxis(SkyPoint p1, SkyPoint p2, SkyPoint p3)
0088 {
0089     // convert the three positions to vectors, these define the plane
0090     // of the Ha axis rotation
0091     Rotations::V3 v1 = PoleAxis::dirCos(p1);
0092     Rotations::V3 v2 = PoleAxis::dirCos(p2);
0093     Rotations::V3 v3 = PoleAxis::dirCos(p3);
0094 
0095     // the Ha axis direction is the normal to the plane
0096     Rotations::V3 p = Rotations::V3::normal(v1, v2, v3);
0097 
0098     // p points to the north or south pole depending on the rotation of the points
0099     // the other pole position can be determined by reversing the sign of the Dec and
0100     // adding 12hrs to the Ha value.
0101     // if we want only the north then this would do it
0102     //if (p.z() < 0)
0103     //    p = -p;
0104     return p;
0105 }