Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.apo.nmsu.edu/Telescopes/coordConv/html/ang_side_ang_8cc_source.html
Дата изменения: Thu May 7 21:42:46 2015
Дата индексирования: Sun Apr 10 04:22:08 2016
Кодировка:

Поисковые слова: universe
lsst.coordConv: src/angSideAng.cc Source File
lsst.coordConv  unknown
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
angSideAng.cc
Go to the documentation of this file.
1 #include <cmath>
2 #include <limits>
3 #include <sstream>
4 #include <stdexcept>
5 #include "coordConv/mathUtils.h"
6 
7 namespace coordConv {
8 
9  bool angSideAng(double &angA, double &sideB, double &angC, double sideA, double angB, double sideC) {
10  double const Epsilon = std::numeric_limits<double>::epsilon();
11 
12  bool unknownAng = false; // assume we can compute angA and angC
13 
14  double sinHalfAngB = sind(angB * 0.5);
15  double cosHalfAngB = cosd(angB * 0.5);
16  double sinHalfSideA = sind(sideA * 0.5);
17  double cosHalfSideA = cosd(sideA * 0.5);
18  double sinHalfSideC = sind(sideC * 0.5);
19  double cosHalfSideC = cosd(sideC * 0.5);
20 
21  if (std::abs(sinHalfSideA) < Epsilon) {
22  // sideA is nearly zero (modulo 360)
23  if (std::abs(sinHalfSideC) < Epsilon) {
24  // sideC is nearly 0 (modulo 360)
25  angA = 90.0;
26  sideB = 0.0;
27  angC = 90.0;
28  unknownAng = true;
29  } else if (std::abs(cosHalfSideC) < Epsilon) {
30  // sideC is nearly 180 (modulo 360)
31  angA = 90.0;
32  sideB = 180.0;
33  angC = 90.0;
34  unknownAng = true;
35  } else {
36  // sideC is not nearly 0 or 180
37  angA = 0.0;
38  sideB = sideC;
39  angC = 180.0 - angB;
40  }
41  } else if (std::abs(cosHalfSideA) < Epsilon) {
42  // sideA is nearly 180 (modulo 360)
43  if (std::abs(cosHalfSideC) < Epsilon) {
44  // sideC is nearly 180 (modulo 360)
45  angA = 90.0;
46  sideB = 0.0;
47  angC = 90.0;
48  unknownAng = true;
49  } else if (std::abs(sinHalfSideC) < Epsilon) {
50  // sideC is nearly 0 (modulo 360)
51  angA = 90.0;
52  sideB = 180.0;
53  angC = 90.0;
54  unknownAng = true;
55  } else {
56  // sideC is not nearly 0 or 180 (modulo 360)
57  angA = 180.0;
58  sideB = 180.0 - sideC;
59  angC = angB;
60  }
61  } else if (std::abs(sinHalfSideC) < Epsilon) {
62  // sideC is nearly zero (modulo 360) and sideA is not
63  angA = 180.0 - angB;
64  sideB = sideA;
65  angC = 0.0;
66  } else if (std::abs(cosHalfSideC) < Epsilon) {
67  // sideC is nearly 180 (modulo 360) and sideA is not
68  angA = angB;
69  sideB = 180.0 - sideA;
70  angC = 180.0;
71  } else if (std::abs(sinHalfAngB) < Epsilon) {
72  // B is nearly 0 (modulo 360)
73  if (std::abs(sideA - sideC) < Epsilon) {
74  // angB ~= 0 (modulo 360) and sideA ~= sideC (modulo 360); cannot compute angA or angC:
75  angA = 90.0;
76  sideB = 0.0;
77  angC = 90.0;
78  unknownAng = true;
79  } else if (sideC < sideA) {
80  angA = 180.0;
81  sideB = sideA - sideC;
82  angC = 0.0;
83  } else {
84  angA = 0.0;
85  sideB = sideC - sideA;
86  angC = 180.0;
87  }
88  } else {
89  // +
90  // compute angA and angC using Napier's analogies
91  // -
92  // compute numerator and denominator, where tan((a +/- c) / 2) = num/den
93  double num1 = cosHalfAngB * ((cosHalfSideA * cosHalfSideC) + (sinHalfSideA * sinHalfSideC));
94  double den1 = sinHalfAngB * ((cosHalfSideA * cosHalfSideC) - (sinHalfSideA * sinHalfSideC));
95  double num2 = cosHalfAngB * ((sinHalfSideA * cosHalfSideC) - (cosHalfSideA * sinHalfSideC));
96  double den2 = sinHalfAngB * ((sinHalfSideA * cosHalfSideC) + (cosHalfSideA * sinHalfSideC));
97 
98  // if numerator and denominator are too small
99  // to accurately determine angle = atan2(num, den), give up
100  if ( ((std::abs(num1) <= Epsilon) && (std::abs(den1) <= Epsilon))
101  || ((std::abs(num2) <= Epsilon) && (std::abs(den2) <= Epsilon))) {
102  std::ostringstream os;
103  os << "Bug: can't compute angA and angC with sideA=" << sideA << ", angB=" << angB << ", sideC=" << sideC;
104  throw std::runtime_error(os.str());
105  }
106 
107  // compute (a +/- c) / 2, and use to compute angles a and c
108  double h_sum_AC = atan2d (num1, den1);
109  double h_diff_AC = atan2d (num2, den2);
110 
111  angA = h_sum_AC + h_diff_AC;
112  angC = h_sum_AC - h_diff_AC;
113 
114  // +
115  // compute sideB using one of two Napier's analogies
116  // (one is for sideB - sideA, one for sideB + sideA)
117  // -
118  double sinHalfAngA = sind(angA * 0.5);
119  double cosHalfAngA = cosd(angA * 0.5);
120 
121  // numerator and denominator for Napier's analogy for sideB - sideA
122  double num3 = sinHalfSideC * ((sinHalfAngB * cosHalfAngA) - (cosHalfAngB * sinHalfAngA));
123  double den3 = cosHalfSideC * ((sinHalfAngB * cosHalfAngA) + (cosHalfAngB * sinHalfAngA));
124 
125  // numerator and denominator for Napier's analogy for sideB + sideA
126  double num4 = sinHalfSideC * ((cosHalfAngB * cosHalfAngA) + (sinHalfAngB * sinHalfAngA));
127  double den4 = cosHalfSideC * ((cosHalfAngB * cosHalfAngA) - (sinHalfAngB * sinHalfAngA));
128 
129  // pick the more suitable Napier's analogy to compute sideB
130  if (std::abs(num3) + std::abs(den3) > std::abs(num4) + std::abs(den4)) {
131  // use Napier's analogy for sideB - sideA
132  sideB = 2.0 * atan2d(num3, den3) + sideA;
133  } else {
134  sideB = 2.0 * atan2d(num4, den4) - sideA;
135  }
136  }
137  angA = wrapPos(angA);
138  sideB = wrapPos(sideB);
139  angC = wrapPos(angC);
140  return unknownAng;
141  }
142 
143 }
double cosd(double ang)
cosine of angle in degrees
Definition: mathUtils.h:55
double sind(double ang)
sine of angle in degrees
Definition: mathUtils.h:52
double atan2d(double x, double y)
arctangent2 in degrees
Definition: mathUtils.h:70
bool angSideAng(double &angA, double &sideB, double &angC, double sideA, double angB, double sideC)
Definition: angSideAng.cc:9
double wrapPos(double ang)
Definition: mathUtils.cc:20