Sun position
Sun position algorithm
|
This has been done to assist compiler error checking, and reduce the chances of bugs that can potentially be rather difficult to diagnose.
Take for example the following code. It has a vector of rectangular coordinates vec
[], which contains the values one gets from converting polar angles of 45° and 45° to rectangular form. This program simply converts this rectangular vector back to polar form and writes out the two angles, after converting from radian back to degrees.
#include <math.h> #include <stdio.h> void rectToPolar(double *alpha, double *delta, double rect[]) { alpha = atan2(rect[1], rect[0]); delta = atan2(rect[2], sqrt(rect[0] * rect[0] + rect[1] * rect[1])); } int main(void) { double azimuth = 0.5; // Dummy initial value, will be replaced double elevation = 0.5; // Ditto double vec[3] = { 0.5, 0.5, 0.70710678119 }; rectToPolar(vec, &azimuth, &elevation); printf("Azimuth = %f, Elevation = %f\n", azimuth * 180.0 / 3.141592653589793, elevation * 180.0 / 3.141592653589793); }
There is a bug in the code, which in this short example is rather easy to see, but in a large program might not be. The expected output from this code is
Azimuth = 45.000000, Elevation = 45.000000
But what do you get if you compile and run it? On my running this program, I got
Azimuth = 48.002776, Elevation = 28.647890
You may get something else. But in any case, the results may look sufficiently plausible that you might not immediately notice that you have got a garbage answer. Depending on your program, this might end up being quite time-consuming to debug.
Now instead, compile the following code, which uses our V3D_Vector struct instead of using a simple array:
#include <math.h> #include <stdio.h> #include "vectors3d.h" int main(void) { double azimuth = 0.5; // Dummy initial value, will be replaced double elevation = 0.5; // Ditto V3D_Vector vec = {{ 0.5, 0.5, 0.70710678119 }}; v3d_rectToPolar(&vec, &azimuth, &elevation); printf("Azimuth = %f, Elevation = %f\n", azimuth * 180.0 / 3.141592653589793, elevation * 180.0 / 3.141592653589793); }
This time, you get two warning messages from the compiler. With the clang compiler, the messages are as follows:
vec2.c:12:21: warning: incompatible pointer types passing 'V3D_Vector *' to parameter of type 'double *' [-Wincompatible-pointer-types] v3d_rectToPolar(&vec, &azimuth, &elevation); ^~~~ ./vectors3d.h:74:30: note: passing argument to parameter 'alpha_rad' here void v3d_rectToPolar(double *alpha_rad, ^ vec2.c:12:37: warning: incompatible pointer types passing 'double *' to parameter of type 'const V3D_Vector *' [-Wincompatible-pointer-types] v3d_rectToPolar(&vec, &azimuth, &elevation); ^~~~~~~~~~ ./vectors3d.h:76:40: note: passing argument to parameter 'srcV' here const V3D_Vector *srcV);
(Actually, there is a case here for elevating this warning to an error that stops compilation, using -Werror=incompatible-pointer-types)
I believe that this justifies using this slightly more awkward way of implementing the vectors and arrays needed for 3-D geometry.
It also allows one to use a simple assignment statement to copy a vector or matrix, as opposed to needing to write a function to do it. (Or in the case of the IAU SOFA routines for matrix copying - two functions!)