-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathEllipsoid.cpp
111 lines (100 loc) · 3.23 KB
/
Ellipsoid.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//#############################################################################
//
// FILENAME: Ellipsoid.cpp
//
// CLASSIFICATION: Unclassified
//
// DESCRIPTION:
//
// This file provides implementation for methods declared in the
// Ellipsoid class.
//
// SOFTWARE HISTORY:
// Date Author Comment
// ----------- ------ -------
// 06-Aug-2016 Krinsky Initial Coding
// 03-Sep-2021 SCM Use cmath.
//
//#############################################################################
#ifndef CSM_LIBRARY
#define CSM_LIBRARY
#endif
#include "Ellipsoid.h"
#include <cmath>
namespace csm
{
//*****************************************************************************
// Ellipsoid::Ellipsoid()
//*****************************************************************************
Ellipsoid::Ellipsoid()
{
setEllipsoid(CSM_WGS84_SEMI_MAJOR_AXIS, CSM_WGS84_SEMI_MINOR_AXIS);
}
//**************************************************************************
// Ellipsoid::Ellipsoid()
//**************************************************************************
Ellipsoid::Ellipsoid(
double semiMajorRadius,
double semiMinorRadius)
{
setEllipsoid( semiMajorRadius, semiMinorRadius );
}
//**************************************************************************
// Ellipsoid::~Ellipsoid()
//**************************************************************************
Ellipsoid::~Ellipsoid() {}
double Ellipsoid::calculateHeight(
const csm::EcefCoord& geocentric,
double desiredPrecision,
double* achievedPrecision,
csm::WarningList* warnings) const
{
const int MKTR = 10;
double eccSquare = 1.0 - mSemiMinorAxis * mSemiMinorAxis / mSemiMajorAxis / mSemiMajorAxis;
double ep2 = 1.0 - eccSquare;
double d2 = geocentric.x * geocentric.x + geocentric.y * geocentric.y;
double d = sqrt(d2);
double h = 0.0;
int ktr = 0;
double hPrev, r;
// Suited for points near equator
if (d >= geocentric.z)
{
double tt, zz, n;
double tanPhi = geocentric.z / d;
do
{
hPrev = h;
tt = tanPhi * tanPhi;
r = mSemiMajorAxis / sqrt(1.0 + ep2 * tt);
zz = geocentric.z + r * eccSquare * tanPhi;
n = r * sqrt(1.0 + tt);
h = sqrt(d2 + zz * zz) - n;
tanPhi = zz / d;
ktr++;
} while (MKTR > ktr && fabs(h - hPrev) > desiredPrecision);
}
// Suited for points near the poles
else
{
double cc, dd, nn;
double cotPhi = d / geocentric.z;
do
{
hPrev = h;
cc = cotPhi * cotPhi;
r = mSemiMajorAxis / sqrt(ep2 + cc);
dd = d - r * eccSquare * cotPhi;
nn = r * sqrt(1.0 + cc) * ep2;
h = sqrt(dd * dd + geocentric.z * geocentric.z) - nn;
cotPhi = dd / geocentric.z;
ktr++;
} while (MKTR > ktr && fabs(h - hPrev) > desiredPrecision);
}
if (achievedPrecision)
{
*achievedPrecision = fabs(h - hPrev);
}
return h;
}
} // namespace csm