ReferenceEllipsoid.cc
Go to the documentation of this file.
1 #include <string>
2 #include <sstream>
3 #include <cmath>
4 #include <utl/ReferenceEllipsoid.h>
5 #include <utl/CoordinateSystem.h>
6 #include <utl/AugerUnits.h>
7 #include <utl/ErrorLogger.h>
8 #include <utl/AugerException.h>
9 #include <utl/Point.h>
10 #include <utl/StringCompare.h>
11 
12 using namespace utl;
13 using namespace std;
14 
15 
16 double
18  const
19 {
20  // we need to take the negative sign of the solution...
21  return 1 - sqrt(1-fEccentricity2);
22 }
23 
24 
25 double
27  const
28 {
29  return fEquatorialRadius * (1 - GetFlattening());
30 }
31 
32 
33 double
34 ReferenceEllipsoid::GetRn(const double phi)
35  const
36 {
37  using namespace std;
38 
39  const double& a = fEquatorialRadius;
40  const double& e2 = fEccentricity2;
41  const double sinPhi = sin(phi);
42 
43  return a / sqrt(1 - e2*sinPhi*sinPhi);
44 }
45 
46 
58  const
59 {
60  using namespace std; // for math functions
61 
62  double x;
63  double y;
64  double z;
65  Point pt(thePoint);
66  boost::tie(x, y, z) = pt.GetCoordinates(fECEF);
67 
68  const double& e2 = fEccentricity2;
69 
70  double p = sqrt(x*x + y*y);
71 
72  double longitude = atan2(y, x);
73 
74  // first guess of latitude
75  double latitude = atan(z/p); // this is given wrongly in the paper cited
76  double height;
77 
78  if(p == 0.) { // at the poles
79  height = abs(z) - GetPolarRadius();
80  } else { // not at the poles
81  // solve iteratively for latitude and height
82  const int iterations = 4;
83  for (int i = 0; i < iterations; ++i) {
84  double Rn = GetRn(latitude);
85  height = p / cos(latitude) - Rn;
86  latitude = atan(z/p/(1 - e2*(Rn / (Rn+height) ) ) );
87  }
88  }
89 
90  return boost::make_tuple(latitude, longitude, height);
91 }
92 
93 
99 Point
101  double const longitude,
102  double const height)
103  const
104 {
105  using namespace std; // for math functions
106 
107  const double& e2 = fEccentricity2;
108 
109  double Rn = GetRn(latitude);
110 
111  double x = (Rn + height) * cos(latitude) * cos(longitude);
112  double y = (Rn + height) * cos(latitude) * sin(longitude);
113  double z = (Rn*(1-e2) + height) * sin(latitude);
114 
115  return Point(x, y, z, fECEF);
116 
117 }
118 
119 
120 Point
122  const
123 {
124  return LatitudeLongitudeHeightToPoint(theGeodeticCoordinates.get<0>(),
125  theGeodeticCoordinates.get<1>(),
126  theGeodeticCoordinates.get<2>());
127 }
128 
129 
144 boost::tuple<TransformationMatrix, TransformationMatrix>
146  const
147 {
148  using namespace std;
149 
150  double latitude, longitude, height;
151  boost::tie(latitude, longitude, height) =
152  PointToLatitudeLongitudeHeight(theOrigin);
153  double x, y, z;
154  boost::tie(x, y, z) = Point(theOrigin).GetCoordinates(fECEF);
155 
156  const double cosLat = cos(latitude);
157  const double sinLat = sin(latitude);
158  const double cosLon = cos(longitude);
159  const double sinLon = sin(longitude);
160 
161  const TransformationMatrix rot =
163  -sinLon, -sinLat*cosLon, cosLat*cosLon,
164  cosLon, -sinLat*sinLon, cosLat*sinLon,
165  0, cosLat, sinLat
166  );
167  const TransformationMatrix trans =
169 
170  return boost::make_tuple(trans, rot);
171 }
172 
173 
174 /***************************************************************************
175  * code for the ellipsoid registry
176  ***************************************************************************/
178 
179 
185 const ReferenceEllipsoid&
187 {
188  if (!gfRegistry) {
189  InitWithECEF(CoordinateSystem::GetRootCoordinateSystem());
190  }
191  Registry::iterator i = gfRegistry->find(theID);
192  if (i == gfRegistry->end()) {
193  ostringstream msg;
194  msg << "Ellipsoid with id " << theID << " not existent.";
195  ERROR(msg);
196  throw InvalidEllipsoidException(msg.str());
197  } else {
198  return i->second;
199  }
200 }
201 
202 
212 void
214 {
215  if (!gfRegistry) {
216  gfRegistry = new Registry;
217  } else {
218  string msg("Calling InitWithECEF, "
219  "but ReferenceEllipsoidRegistry already initialised.");
220  ERROR(msg);
221  throw InitSequenceException(msg);
222  }
223  //RegisterOneEllipsoid("WGS84", 6378137.*m, 0.00669438);
224  // changed to the more precise values from Peter H Dana's page. LN.
225  RegisterOneEllipsoid(eWGS84, 6378137.*m, 0.00669437999013, theCS);
226 }
227 
228 
242 {
243  if (StringEquivalent(str, "WGS84"))
244  return eWGS84;
245 
246  string msg("Unknown reference ellipsoid ");
247  msg += str;
248  ERROR(msg);
249  throw InvalidEllipsoidException(msg);
250 }
251 
252 
253 void
255  double theEquatorialRadius,
256  double theEccentricity,
257  const CoordinateSystemPtr& theCS)
258 {
259  ReferenceEllipsoid e(theEquatorialRadius, theEccentricity, theCS);
260  bool ok = gfRegistry->insert(make_pair(theID, e)).second;
261  if (!ok) {
262  ostringstream msg;
263  msg << "Double insertion of ellipsoid with id" << theID;
264  WARNING(msg);
265  }
266 }
267 
268 // Configure (x)emacs for this file ...
269 // Local Variables:
270 // mode: c++
271 // End:
Point object.
Definition: Point.h:32
static TransformationMatrix TransformToBasis(const double x1, const double y1, const double z1, const double x2, const double y2, const double z2, const double x3, const double y3, const double z3)
From dreibein (basis vectors)
Point LatitudeLongitudeHeightToPoint(double const latitude, double const longitude, double const height) const
Convert Lat/Long/Height to Point.
bool ok(bool okay)
Definition: testlib.cc:89
static const ReferenceEllipsoid & Get(const EllipsoidID theID)
Get known ellipsoid by registered ID.
bool StringEquivalent(const std::string &a, const std::string &b, Predicate p)
Utility to compare strings for equivalence. It takes a predicate to determine the equivalence of indi...
Definition: StringCompare.h:38
static void RegisterOneEllipsoid(const EllipsoidID theID, double theEquatorialRadius, double theEccentricity, const CoordinateSystemPtr &theECEF)
boost::tuple< TransformationMatrix, TransformationMatrix > TransformECEFToLocalSystem(const Point &theOrigin) const
Translation and rotation to go to local coordinate system.
Exception to use if sequence of initialisations violated.
Transformations matrices for afine transformations.
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
static Registry * gfRegistry
Reference ellipsoids for UTM transformations.
double abs(const SVector< n, T > &v)
static TransformationMatrix Translation(const double x, const double y, const double z)
Translation.
double GetFlattening() const
Get flattening.
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
Report request for non-existent ellipsoid.
boost::tuple< double, double, double > Triple
Coordinate triple.
double GetPolarRadius() const
Get Polar radius ( )
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
std::map< EllipsoidID, const ReferenceEllipsoid > Registry
static void InitWithECEF(const CoordinateSystemPtr &theECEF)
Initialise the registry specifying the ECEF (instead of the Root CS)
EllipsoidID
ID&#39;s of known reference ellipsoid&#39;s.
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
static EllipsoidID GetEllipsoidIDFromString(const std::string &str)
Get EllipsoidID from string.
double GetRn(const double phi) const

, generated on Tue Sep 26 2023.