mirror of
https://github.com/cosinekitty/astronomy.git
synced 2026-05-24 08:45:55 -04:00
C: Added Astronomy_VectorFromSphere, astro_spherical_t.
Added new data type astro_spherical_t that represents generic spherical coordinates. Implemented Astronomy_VectorFromSphere to convert spherical coordinates to Cartesian coordinates. Included unit test to verify it is working as expected.
This commit is contained in:
@@ -1835,11 +1835,61 @@ fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int TestVectorFromAngles(double lat, double lon, double x, double y, double z)
|
||||
{
|
||||
astro_spherical_t sphere;
|
||||
astro_vector_t vector;
|
||||
astro_time_t time;
|
||||
double diff, dx, dy, dz;
|
||||
|
||||
/* Confirm the expected vector really is a unit vector. */
|
||||
diff = fabs((x*x + y*y + z*z) - 1.0);
|
||||
if (diff > 1.0e-16)
|
||||
{
|
||||
fprintf(stderr, "TestVectorFromAngles: EXCESSIVE unit error = %lg\n", diff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sphere.status = ASTRO_SUCCESS;
|
||||
sphere.lat = lat;
|
||||
sphere.lon = lon;
|
||||
sphere.dist = 1.0;
|
||||
|
||||
time = Astronomy_MakeTime(2015, 3, 5, 12, 0, 0.0);
|
||||
vector = Astronomy_VectorFromSphere(sphere, time);
|
||||
|
||||
if (vector.status != ASTRO_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "ERROR(TestVectorFromAngles): vector.status = %d\n", vector.status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dx = x - vector.x;
|
||||
dy = y - vector.y;
|
||||
dz = z - vector.z;
|
||||
diff = sqrt(dx*dx + dy*dy + dz*dz);
|
||||
|
||||
printf("TestVectorFromAngles(%lf, %lf): diff = %lg\n", lat, lon, diff);
|
||||
if (diff > 2.0e-16)
|
||||
{
|
||||
fprintf(stderr, "TestVectorFromAngles: EXCESSIVE ERROR.\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RotationTest(void)
|
||||
{
|
||||
int error;
|
||||
CHECK(Rotation_MatrixInverse());
|
||||
CHECK(Rotation_MatrixMultiply());
|
||||
CHECK(TestVectorFromAngles(0.0, 0.0, 1.0, 0.0, 0.0));
|
||||
CHECK(TestVectorFromAngles(0.0, 90.0, 0.0, 1.0, 0.0));
|
||||
CHECK(TestVectorFromAngles(0.0, 180.0, -1.0, 0.0, 0.0));
|
||||
CHECK(TestVectorFromAngles(0.0, 270.0, 0.0, -1.0, 0.0));
|
||||
CHECK(TestVectorFromAngles(+90.0, 0.0, 0.0, 0.0, 1.0));
|
||||
CHECK(TestVectorFromAngles(-90.0, 0.0, 0.0, 0.0, -1.0));
|
||||
CHECK(TestVectorFromAngles(-30.0, +60.0, 0.43301270189221946, 0.75, -0.5));
|
||||
error = 0;
|
||||
fail:
|
||||
return error;
|
||||
|
||||
@@ -4143,6 +4143,44 @@ astro_rotation_t Astronomy_CombineRotation(astro_rotation_t a, astro_rotation_t
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts spherical coordinates to Cartesian coordinates.
|
||||
*
|
||||
* Given spherical coordinates and a time at which they are valid,
|
||||
* returns a vector of Cartesian coordinates. The returned value
|
||||
* includes the time, as required by the type #astro_vector_t.
|
||||
*
|
||||
* @param sphere
|
||||
* Spherical coordinates to be converted.
|
||||
*
|
||||
* @param time
|
||||
* The time that should be included in the return value.
|
||||
*
|
||||
* @return
|
||||
* The vector form of the supplied spherical coordinates.
|
||||
*/
|
||||
astro_vector_t Astronomy_VectorFromSphere(astro_spherical_t sphere, astro_time_t time)
|
||||
{
|
||||
astro_vector_t vector;
|
||||
double radlat, radlon, rcoslat;
|
||||
|
||||
if (sphere.status != ASTRO_SUCCESS)
|
||||
return VecError(ASTRO_INVALID_PARAMETER, time);
|
||||
|
||||
radlat = sphere.lat * DEG2RAD;
|
||||
radlon = sphere.lon * DEG2RAD;
|
||||
rcoslat = sphere.dist * cos(radlat);
|
||||
|
||||
vector.status = ASTRO_SUCCESS;
|
||||
vector.t = time;
|
||||
vector.x = rcoslat * cos(radlon);
|
||||
vector.y = rcoslat * sin(radlon);
|
||||
vector.z = sphere.dist * sin(radlat);
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief
|
||||
|
||||
@@ -1136,6 +1136,31 @@ After calculating the date and time of an astronomical event in the form of an [
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
<a name="Astronomy_VectorFromSphere"></a>
|
||||
### Astronomy_VectorFromSphere(sphere, time) ⇒ [`astro_vector_t`](#astro_vector_t)
|
||||
|
||||
**Converts spherical coordinates to Cartesian coordinates.**
|
||||
|
||||
|
||||
|
||||
Given spherical coordinates and a time at which they are valid, returns a vector of Cartesian coordinates. The returned value includes the time, as required by the type [`astro_vector_t`](#astro_vector_t).
|
||||
|
||||
|
||||
|
||||
**Returns:** The vector form of the supplied spherical coordinates.
|
||||
|
||||
|
||||
|
||||
| Type | Parameter | Description |
|
||||
| --- | --- | --- |
|
||||
| [`astro_spherical_t`](#astro_spherical_t) | `sphere` | Spherical coordinates to be converted. |
|
||||
| [`astro_time_t`](#astro_time_t) | `time` | The time that should be included in the return value. |
|
||||
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
<a name="Astronomy_VectorLength"></a>
|
||||
@@ -1588,6 +1613,23 @@ You can create this structure directly, or you can call the convenience function
|
||||
| [`astro_time_t`](#astro_time_t) | `dec_solstice` | The date and time of the December solstice for the specified year. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
<a name="astro_spherical_t"></a>
|
||||
### `astro_spherical_t`
|
||||
|
||||
**Spherical coordinates: latitude, longitude, distance.**
|
||||
|
||||
|
||||
|
||||
| Type | Member | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| [`astro_status_t`](#astro_status_t) | `status` | ASTRO_SUCCESS if this struct is valid; otherwise an error code. |
|
||||
| `double` | `lat` | The latitude angle: -90..+90 degrees. |
|
||||
| `double` | `lon` | The longitude angle: 0..360 degrees. |
|
||||
| `double` | `dist` | Distance in AU. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
<a name="astro_time_t"></a>
|
||||
|
||||
@@ -5382,6 +5382,44 @@ astro_rotation_t Astronomy_CombineRotation(astro_rotation_t a, astro_rotation_t
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts spherical coordinates to Cartesian coordinates.
|
||||
*
|
||||
* Given spherical coordinates and a time at which they are valid,
|
||||
* returns a vector of Cartesian coordinates. The returned value
|
||||
* includes the time, as required by the type #astro_vector_t.
|
||||
*
|
||||
* @param sphere
|
||||
* Spherical coordinates to be converted.
|
||||
*
|
||||
* @param time
|
||||
* The time that should be included in the return value.
|
||||
*
|
||||
* @return
|
||||
* The vector form of the supplied spherical coordinates.
|
||||
*/
|
||||
astro_vector_t Astronomy_VectorFromSphere(astro_spherical_t sphere, astro_time_t time)
|
||||
{
|
||||
astro_vector_t vector;
|
||||
double radlat, radlon, rcoslat;
|
||||
|
||||
if (sphere.status != ASTRO_SUCCESS)
|
||||
return VecError(ASTRO_INVALID_PARAMETER, time);
|
||||
|
||||
radlat = sphere.lat * DEG2RAD;
|
||||
radlon = sphere.lon * DEG2RAD;
|
||||
rcoslat = sphere.dist * cos(radlat);
|
||||
|
||||
vector.status = ASTRO_SUCCESS;
|
||||
vector.t = time;
|
||||
vector.x = rcoslat * cos(radlon);
|
||||
vector.y = rcoslat * sin(radlon);
|
||||
vector.z = sphere.dist * sin(radlat);
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief
|
||||
|
||||
@@ -170,6 +170,18 @@ typedef struct
|
||||
}
|
||||
astro_vector_t;
|
||||
|
||||
/**
|
||||
* @brief Spherical coordinates: latitude, longitude, distance.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< ASTRO_SUCCESS if this struct is valid; otherwise an error code. */
|
||||
double lat; /**< The latitude angle: -90..+90 degrees. */
|
||||
double lon; /**< The longitude angle: 0..360 degrees. */
|
||||
double dist; /**< Distance in AU. */
|
||||
}
|
||||
astro_spherical_t;
|
||||
|
||||
/**
|
||||
* @brief An angular value expressed in degrees.
|
||||
*/
|
||||
@@ -602,6 +614,7 @@ astro_apsis_t Astronomy_NextLunarApsis(astro_apsis_t apsis);
|
||||
|
||||
astro_rotation_t Astronomy_InverseRotation(astro_rotation_t rotation);
|
||||
astro_rotation_t Astronomy_CombineRotation(astro_rotation_t a, astro_rotation_t b);
|
||||
astro_vector_t Astronomy_VectorFromSphere(astro_spherical_t sphere, astro_time_t time);
|
||||
|
||||
#if 0
|
||||
astro_rotation_t Astronomy_Rotation_EQD_EQJ(astro_time_t time);
|
||||
|
||||
Reference in New Issue
Block a user