SunEarthSatGeometry.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
47 #include <map>
48 #include "GPSEllipsoid.hpp"
49 #include "SunEarthSatGeometry.hpp"
50 
51 using namespace std;
52 
53 namespace gnsstk
54 {
55 
58  {
59  try {
60  Matrix<double> R(3,3);
61  pos.transformTo(geocentric ? Position::Geocentric : Position::Geodetic);
62 
63  double lat = (geocentric ? pos.getGeocentricLatitude()
64  : pos.getGeodeticLatitude()) * DEG_TO_RAD;
65  double lon = pos.getLongitude() * DEG_TO_RAD;
66  double ca = ::cos(lat);
67  double sa = ::sin(lat);
68  double co = ::cos(lon);
69  double so = ::sin(lon);
70 
71  // Rotation matrix that transforms X=(x,y,z) into (R*X)(north,east,up).
72  R(0,0) = -sa*co; R(0,1) = -sa*so; R(0,2) = ca;
73  R(1,0) = -so; R(1,1) = co; R(1,2) = 0.;
74  R(2,0) = ca*co; R(2,1) = ca*so; R(2,2) = sa;
75 
76  // The rows of R are also the unit vectors, in ECEF, of north,east,up;
77  // R = (N && E && U) = transpose(N || E || U).
78  // Vector<double> N = R.rowCopy(0);
79  // Vector<double> E = R.rowCopy(1);
80  // Vector<double> U = R.rowCopy(2);
81 
82  return R;
83  }
84  catch(Exception& e) { GNSSTK_RETHROW(e); }
85  catch(exception& e) {
86  Exception E("std except: " + string(e.what()));
87  GNSSTK_THROW(E);
88  }
89  catch(...)
90  {
91  Exception e("Unknown exception.");
92  GNSSTK_THROW(e);
93  }
94  }
95 
98  { return northEastUp(pos, true); }
99 
102  { return northEastUp(pos, false); }
103 
112  {
113  try {
114  Matrix<double> R = northEastUp(pos, geocentric);
115  for(int i=0; i<3; i++) { double r=R(0,i); R(0,i)=R(2,i); R(2,i)=r; }
116  return R;
117  }
118  catch(Exception& e) { GNSSTK_RETHROW(e); }
119  catch(exception& e) {
120  Exception E("std except: " + string(e.what()));
121  GNSSTK_THROW(E);
122  }
123  catch(...) { Exception e("Unknown exception."); GNSSTK_THROW(e); }
124  }
125 
131  { return upEastNorth(pos, true); }
132 
135  { return upEastNorth(pos, false); }
136 
141  /*
142  * Consider the Sun and the Earth as seen from the satellite. Let the Sun be a
143  * circle of angular radius r, center in direction s, and the Earth be a (larger)
144  * circle of angular radius R, center in direction e. The circles overlap if
145  * |e-s| < R+r; complete overlap if |e-s| < R-r.
146  * The satellite is in penumbra if R-r < |e-s| < R+r, umbra if |e-s| < R-r.
147  * Let L == |e-s|. What is the area of overlap in penumbra: R-r < L < R+r ?
148  * Call the two points where the circles intersect p1 and p2. Draw a line from
149  * e to s; call the points where this line intersects the two circles r1 and R1,
150  * respectively.
151  * Draw lines from e to s, e to p1, e to p2, s to p1 and s to p2. Call the angle
152  * between e-s and e-p1 alpha, and that between s-e and s-p1, beta.
153  * Draw a rectangle with top and bottom parallel to e-s passing through p1 and p2,
154  * and with sides passing through s and r1. Similarly for e and R1. Note that the
155  * area of intersection lies within the intersection of these two rectangles.
156  * Call the area of the rectangle outside the circles A and B.
157  * The height H of the rectangles is
158  * H = 2Rsin(alpha) = 2rsin(beta)
159  * also, L = rcos(beta)+Rcos(alpha)
160  * The area A will be the area of the rectangle
161  * minus the area of the wedge formed by the angle 2*alpha
162  * minus the area of the two triangles which meet at s :
163  * A = RH - (2alpha/2pi)*pi*R*R - 2*(1/2)*(H/2)Rcos(alpha)
164  * Similarly,
165  * B = rH - (2beta/2pi)*pi*r*r - 2*(1/2)*(H/2)rcos(beta)
166  * The area of intersection will be the area of the rectangular intersection
167  * minus the area A
168  * minus the area B
169  * Intersection = H(R+r-L) - A - B
170  * = HR+Hr-HL -HR+alpha*R*R+(H/2)Rcos(alpha) -Hr+beta*r*r+(H/2)rcos(beta)
171  * Cancel terms, and substitute for L using above equation L = ..
172  * = -(H/2)rcos(beta)-(H/2)Rcos(alpha)+alpha*R*R+beta*r*r
173  * substitute for H/2
174  * = -R*R*sin(alpha)cos(alpha)-r*r*sin(beta)cos(beta)+alpha*R*R+beta*r*r
175  * Intersection = R*R*[alpha-sin(alpha)cos(alpha)]+r*r*[beta-sin(beta)cos(beta)]
176  * Solve for alpha and beta in terms of R, r and L using H and L relations above
177  * (r/R)cos(beta)=(L/R)-cos(alpha)
178  * (r/R)sin(beta)=sin(alpha)
179  * so
180  * (r/R)^2 = (L/R)^2 - (2L/R)cos(alpha) + 1
181  * cos(alpha) = (R/2L)(1+(L/R)^2-(r/R)^2)
182  * cos(beta) = (L/r) - (R/r)cos(alpha)
183  * and 0 <= alpha or beta <= pi
184  */
185  double shadowFactor(double angRadEarth, double angRadSun, double angSeparation)
186  {
187  try {
188  if(angSeparation >= angRadEarth+angRadSun)
189  {
190  return 0.0;
191  }
192  if(angSeparation <= fabs(angRadEarth-angRadSun))
193  {
194  return 1.0;
195  }
196  double r=angRadSun, R=angRadEarth, L=angSeparation;
197  if(angRadSun > angRadEarth)
198  {
199  r=angRadEarth; R=angRadSun;
200  }
201  double cosalpha = (R/L)*(1.0+(L/R)*(L/R)-(r/R)*(r/R))/2.0;
202  double cosbeta = (L/r) - (R/r)*cosalpha;
203  double sinalpha = ::sqrt(1.0-cosalpha*cosalpha);
204  double sinbeta = ::sqrt(1.0-cosbeta*cosbeta);
205  double alpha = ::asin(sinalpha);
206  double beta = ::asin(sinbeta);
207  double shadow = r*r*(beta-sinbeta*cosbeta)+R*R*(alpha-sinalpha*cosalpha);
208  shadow /= ::acos(-1.0)*angRadSun*angRadSun;
209  return shadow;
210  }
211  catch(Exception& e) { GNSSTK_RETHROW(e); }
212  catch(exception& e) {
213  Exception E("std except: " + string(e.what()));
214  GNSSTK_THROW(E);
215  }
216  catch(...)
217  {
218  Exception e("Unknown exception."); GNSSTK_THROW(e);
219  }
220  }
221 
222  double shadowFactor(const Position& sv, const Position& sun)
223  {
224  try {
225  Position z(sv);
226  // z points from satellite to Earth center along the antenna boresight.
227  z.transformTo(Position::Cartesian);
228  double svrange = z.mag();
229  double d = -1.0/svrange;
230  z = d * z; // reverse and normalize z
231 
232  // Find distance to Sun, and unit vector Earth to Sun.
233  Position sSun(sun);
234  sSun.transformTo(Position::Cartesian);
235  double dSun = sSun.radius(); // distance to Sun
236  d = 1.0/dSun;
237  sSun = d * sSun; // unit vector Earth-to-Sun
238 
239  // Sun-Earth-satellite angle = angular separation sat and Sun seen at Earth;
240  // same as satelliteEarthSunAngle(SV,Sun).
241  double sesa = ::acos(-z.dot(sSun));
242 
243  // Apparent angular radius (deg) of Sun = 0.2666/(distance in AU)/
244  double angRadSun = DEG_TO_RAD * 0.2666 / (dSun/149598.0e6);
245  // Angular radius of Earth at sattelite.
246  double angRadEarth = ::asin(6378137.0/svrange);
247 
248  return shadowFactor(angRadEarth, angRadSun, sesa);
249  }
250  catch(Exception& e)
251  {
252  GNSSTK_RETHROW(e);
253  }
254  }
255 
267  {
268  try {
269  Position pSun(sun), pSat(sat);
270  Triple sSun(pSun.asECEF()), sSat(pSat.asECEF()); // must be Cartesian
271 
272  // Make orthonormal triad parallel to satellite body axes.
273  Triple X,Y,Z,T;
274 
275  // Z points from satellite to Earth center along the antenna boresight.
276  Z = sSat;
277  double d = -1.0/sSat.mag(); // reverse Z and normalize
278  Z = d * Z;
279 
280  // Let T point from satellite to Sun.
281  T = sSun - sSat; // sat-to-Sun = (Earth-to-Sun) - (Earth-to-sat)
282  d = 1.0/T.mag();
283  T = d * T; // normalize
284 
285  // Y is perpendicular to Z and T ...
286  Y = Z.cross(T);
287  d = 1.0/Y.mag();
288  Y = d * Y; // normalize Y
289 
290  // ... such that X points generally in the direction of the Sun.
291  X = Y.cross(Z); // X will be unit vector since Y and Z are
292 
293  if(X.dot(T) < 0)
294  {
295  // Need to reverse X, hence Y also.
296  X = -1.0 * X;
297  Y = -1.0 * Y;
298  }
299 
300  // Fill the rotation matrix: rows are X, Y and Z,
301  // so R*V(ECEF XYZ) = V(body frame components) = (V dot X,Y,Z).
302  Matrix<double> R(3,3);
303  for(int i=0; i<3; i++) {
304  R(0,i) = X[i];
305  R(1,i) = Y[i];
306  R(2,i) = Z[i];
307  }
308 
309  return R;
310  }
311  catch(Exception& e) { GNSSTK_RETHROW(e); }
312  catch(exception& e)
313  {
314  Exception E("std except: " + string(e.what()));
315  GNSSTK_THROW(E);
316  }
317  catch(...)
318  {
319  Exception e("Unknown exception.");
320  GNSSTK_THROW(e);
321  }
322  }
323 
331  {
332  try {
333  int i;
334  double svrange, angmom;
335  Position X,Y,Z;
336  Matrix<double> R(3,3);
337 
338  // Z points from satellite to Earth center along the antenna boresight.
339  svrange = pos.mag();
340  Z = pos*(-1.0/svrange); // reverse and normalize Z
341  Z.transformTo(Position::Cartesian);
342 
343  // Y points opposite the angular momentum vector.
344  Y = pos.cross(vel);
345  angmom = Y.mag();
346  Y = Y*(-1.0/angmom);
347  Y.transformTo(Position::Cartesian);
348 
349  // X completes the right-handed system.
350  X = Y.cross(Z);
351 
352  // Fill the matrix and return it.
353  for(i=0; i<3; i++) {
354  R(0,i) = X[i];
355  R(1,i) = Y[i];
356  R(2,i) = Z[i];
357  }
358 
359  return R;
360  }
361  catch(Exception& e) { GNSSTK_RETHROW(e); }
362  catch(std::exception& e) {Exception E("std except: "+string(e.what())); GNSSTK_THROW(E);}
363  catch(...) { Exception e("Unknown exception."); GNSSTK_THROW(e); }
364  }
365 
378  const Position& rx,
379  const Matrix<double>& rot,
380  double& nadir,
381  double& azimuth)
382  {
383  try {
384  if(rot.rows() != 3 || rot.cols() != 3) {
385  Exception e("Rotation matrix invalid.");
386  GNSSTK_THROW(e);
387  }
388 
389  double d;
390  Position RmS;
391  // RmS points from satellite to receiver.
392  RmS = rx - sv;
393  RmS.transformTo(Position::Cartesian);
394  d = RmS.mag();
395  if(d == 0.0) {
396  Exception e("Satellite and receiver positions identical.");
397  GNSSTK_THROW(e);
398  }
399  RmS = (1.0/d) * RmS;
400 
401  Vector<double> xyz(3),body(3);
402  xyz(0) = RmS.X();
403  xyz(1) = RmS.Y();
404  xyz(2) = RmS.Z();
405  body = rot * xyz;
406 
407  nadir = ::acos(body(2)) * RAD_TO_DEG;
408  azimuth = ::atan2(body(1),body(0)) * RAD_TO_DEG;
409  if(azimuth < 0.0) azimuth += 360.;
410  }
411  catch(Exception& e) { GNSSTK_RETHROW(e); }
412  catch(exception& e) {
413  Exception E("std except: " + string(e.what()));
414  GNSSTK_THROW(E);
415  }
416  catch(...) { Exception e("Unknown exception."); GNSSTK_THROW(e); }
417  }
418 
426  double satelliteEarthSunAngle(const Position& sat, const Position& sun)
427  {
428  try {
429  Position pSun(sun), pSat(sat);
430  Triple sSun(pSun.asECEF()), sSat(pSat.asECEF());
431 
432  // Normalize the vectors.
433  double d;
434  d = 1.0/sSun.mag(); sSun = sSun * d;
435  d = 1.0/sSat.mag(); sSat = sSat * d;
436 
437  // Compute the angle.
438  return (::acos(sSat.dot(sSun)));
439  }
440  catch(Exception& e) { GNSSTK_RETHROW(e); }
441  catch(exception& e) {
442  Exception E("std except: " + string(e.what()));
443  GNSSTK_THROW(E);
444  }
445  catch(...) { Exception e("Unknown exception."); GNSSTK_THROW(e); }
446  }
447 
465  void sunOrbitAngles(const Position& pos, const Position& vel, const Position& sun,
466  double& beta, double& phi)
467  {
468  try {
469  Position satR(pos),satV(vel),pSun(sun);
470  GPSEllipsoid ellips;
471  double omega(ellips.angVelocity()); // 7.292115e-5 rad/sec
472 
473  // Compute inertial velocity.
474  Position inertialV;
475  inertialV.setECEF(satV.X()-omega*satR.Y(),satV.Y()+omega*satR.X(),satV.Z());
476 
477  // Use Triples.
478  Triple sSun(pSun.asECEF()),sSat(satR.asECEF());
479  Triple sVel(inertialV.asECEF()), u, w;
480 
481  // Normalize the vectors.
482  double d;
483  d = 1.0/sSun.mag(); sSun = sSun * d;
484  d = 1.0/sSat.mag(); sSat = d * sSat;
485  d = 1.0/sVel.mag(); sVel = d * sVel;
486 
487  // u is R cross V -- normal to the satellite orbit plane.
488  u = sSat.cross(sVel);
489 
490  // Compute the angle beta: u dot sun = sin(beta) = cos(PI/2-beta)
491  double udotsun(u.dot(sSun));
492  beta = PI/2.0 - ::acos(udotsun);
493 
500  w = sSun - udotsun*u;
501  d = w.mag();
502  if(d > 1.e-14) {
503  d = 1.0/d;
504  w = d * w; // normalize w
505  phi = ::acos(sSat.dot(w)); // zero at noon where sat||w and dot=1
506  if(sSat.dot(u.cross(w)) < 0.0) // make phi zero at midnight
507  phi = PI - phi;
508  else
509  phi += PI;
510  }
511  else
512  phi = 0.0;
513  }
514  catch(Exception& e) { GNSSTK_RETHROW(e); }
515  catch(exception& e) {
516  Exception E("std except: " + string(e.what()));
517  GNSSTK_THROW(E);
518  }
519  catch(...) { Exception e("Unknown exception."); GNSSTK_THROW(e); }
520  }
521 
534  double satelliteYawAngle(const Position& pos, const Position& vel,
535  const Position& sun, const bool& blkIIRF, double& yawrate)
536  {
537  try {
538  // Get orbit tilt beta, and in-plane orbit angle from midnight, mu.
539  double beta, mu;
540  sunOrbitAngles(pos, vel, sun, beta, mu);
541  double sinmu = ::sin(mu); // mu is the in-orbit-plane "azimuth" from midnight,
542  double cosmu = ::cos(mu); // increasing in direction of satellite motion.
543 
544  // Nominal yaw angle - cf. Kouba(2009).
545  double tanb(::tan(beta)), yaw;
546  if(blkIIRF)
547  yaw = ::atan2(tanb, -sinmu);
548  else
549  yaw = ::atan2(-tanb, sinmu);
550 
551  // Orbit velocity (rad/s).
552  double orbv = TWO_PI * vel.mag() / pos.mag();
553 
554  // Nominal yaw rate.
555  yawrate = orbv * tanb * cosmu / (sinmu*sinmu+tanb*tanb);
556 
557  return yaw;
558  }
559  catch(Exception& e) { GNSSTK_RETHROW(e); }
560  }
561 
562 } // end namespace
gnsstk::satelliteYawAngle
double satelliteYawAngle(const Position &pos, const Position &vel, const Position &sun, const bool &blkIIRF, double &yawrate)
Definition: SunEarthSatGeometry.cpp:534
gnsstk::northEastUp
Matrix< double > northEastUp(Position &pos, bool geocentric)
Same as upEastNorth(), but with rows re-ordered.
Definition: SunEarthSatGeometry.cpp:57
gnsstk::Position::transformTo
Position & transformTo(CoordinateSystem sys) noexcept
Definition: Position.cpp:247
SunEarthSatGeometry.hpp
gnsstk::northEastUpGeocentric
Matrix< double > northEastUpGeocentric(Position &pos)
Same as northEastUp(pos, true).
Definition: SunEarthSatGeometry.cpp:97
gnsstk::GPSEllipsoid::angVelocity
virtual double angVelocity() const noexcept
Definition: GPSEllipsoid.hpp:72
gnsstk::upEastNorthGeodetic
Matrix< double > upEastNorthGeodetic(Position &pos)
Same as upEastNorth, but using geodetic coordinates.
Definition: SunEarthSatGeometry.cpp:134
gnsstk::TrackingCode::Y
@ Y
Encrypted legacy GPS precise code.
gnsstk::Matrix::cols
size_t cols() const
The number of columns in the matrix.
Definition: Matrix.hpp:167
gnsstk::Position::Y
double Y() const noexcept
return Y coordinate (meters)
Definition: Position.cpp:364
gnsstk::Position::Z
double Z() const noexcept
return Z coordinate (meters)
Definition: Position.cpp:375
gnsstk::TWO_PI
const double TWO_PI
GPS value of PI*2.
Definition: GNSSconstants.hpp:68
gnsstk::GPSEllipsoid
Definition: GPSEllipsoid.hpp:67
gnsstk::Matrix::rows
size_t rows() const
The number of rows in the matrix.
Definition: Matrix.hpp:165
gnsstk::upEastNorth
Matrix< double > upEastNorth(Position &pos, bool geocentric)
Definition: SunEarthSatGeometry.cpp:111
gnsstk::PI
const double PI
GPS value of PI; also specified by GAL.
Definition: GNSSconstants.hpp:62
gnsstk::Triple
Definition: Triple.hpp:68
gnsstk::Position::asECEF
Position & asECEF() noexcept
Definition: Position.hpp:390
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
std::sin
double sin(gnsstk::Angle x)
Definition: Angle.hpp:144
gnsstk::shadowFactor
double shadowFactor(const Position &sv, const Position &sun)
Definition: SunEarthSatGeometry.cpp:222
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::Position::setECEF
Position & setECEF(const double X, const double Y, const double Z) noexcept
Definition: Position.cpp:601
gnsstk::Triple::dot
double dot(const Triple &right) const noexcept
Definition: Triple.cpp:107
gnsstk::satelliteNadirAzimuthAngles
void satelliteNadirAzimuthAngles(const Position &sv, const Position &rx, const Matrix< double > &rot, double &nadir, double &azimuth)
Definition: SunEarthSatGeometry.cpp:377
gnsstk::RAD_TO_DEG
static const double RAD_TO_DEG
Conversion Factor from radians to degrees (units: degrees)
Definition: GNSSconstants.hpp:78
gnsstk::satelliteAttitude
Matrix< double > satelliteAttitude(const Position &sat, const Position &sun)
Definition: SunEarthSatGeometry.cpp:266
gnsstk::Matrix< double >
gnsstk::Position::radius
double radius() const noexcept
Definition: Position.cpp:444
gnsstk::satelliteEarthSunAngle
double satelliteEarthSunAngle(const Position &sat, const Position &sun)
Definition: SunEarthSatGeometry.cpp:426
std::cos
double cos(gnsstk::Angle x)
Definition: Angle.hpp:146
gnsstk::beta
double beta(double x, double y)
Definition: SpecialFuncs.cpp:204
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
example4.pos
pos
Definition: example4.py:125
gnsstk::Vector< double >
GPSEllipsoid.hpp
gnsstk::orbitNormalAttitude
Matrix< double > orbitNormalAttitude(const Position &pos, const Position &vel)
Definition: SunEarthSatGeometry.cpp:330
gnsstk::Position::X
double X() const noexcept
return X coordinate (meters)
Definition: Position.cpp:353
std::tan
double tan(gnsstk::Angle x)
Definition: Angle.hpp:148
gnsstk::upEastNorthGeocentric
Matrix< double > upEastNorthGeocentric(Position &pos)
Definition: SunEarthSatGeometry.cpp:130
gnsstk::sunOrbitAngles
void sunOrbitAngles(const Position &pos, const Position &vel, const Position &sun, double &beta, double &phi)
Definition: SunEarthSatGeometry.cpp:465
std
Definition: Angle.hpp:142
so
page HOWTO subpage DoxygenGuide Documenting Your Code page DoxygenGuide Documenting Your Code todo Flesh out this document section doctips Tips for Documenting When defining make sure that the prototype is identical between the cpp and hpp including both the namespaces and the parameter names for you have std::string as the return type in the hpp file and string as the return type in the cpp Doxygen may get confused and autolink to the cpp version with no documentation If you don t use the same parameter names between the cpp and hpp that will also confuse Doxygen Don t put type information in return or param documentation It doesn t really add anything and will often cause Doxygen to complain and not produce the documentation< br > use note Do not put a comma after a param name unless you mean to document multiple parameters< br/> the output stream</code >< br/> z the ECEF position of the antenna</code > Don t put your Doxygen documentation for shared functions methods in the cpp put it in the hpp group them like so
Definition: DOCUMENTING.dox:22
gnsstk::Triple::cross
Triple cross(const Triple &right) const noexcept
Definition: Triple.cpp:118
gnsstk::northEastUpGeodetic
Matrix< double > northEastUpGeodetic(Position &pos)
Same as northEastUp(pos, false).
Definition: SunEarthSatGeometry.cpp:101
gnsstk::Position
Definition: Position.hpp:136
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
example3.mu
int mu
Definition: example3.py:36
gnsstk::DEG_TO_RAD
static const double DEG_TO_RAD
Conversion Factor from degrees to radians (units: degrees^-1)
Definition: GNSSconstants.hpp:76
gnsstk::Triple::mag
double mag() const noexcept
Definition: Triple.cpp:129


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:41