1
0
Fork 0

Fix the calculation of the moons longitude since the moon does not specify xs but xg instead. This required a nasty strcmp of the body name so switch to parsing a boolean instead and convert to strings when required.

This commit is contained in:
Erik Hofman 2020-10-26 10:23:54 +01:00
parent afb43edbdf
commit 9a54ff575c
5 changed files with 51 additions and 39 deletions

View file

@ -416,19 +416,19 @@ void TimeManager::setTimeOffset(const std::string& offset_type, long int offset)
if ( offset_type == "real" ) {
warp = 0;
} else if ( offset_type == "dawn" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 90.0, true, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 90.0, true, true );
} else if ( offset_type == "morning" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 75.0, true, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 75.0, true, true );
} else if ( offset_type == "noon" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 0.0, true, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 0.0, true, true );
} else if ( offset_type == "afternoon" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 75.0, false, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 75.0, false, true );
} else if ( offset_type == "dusk" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 90.0, false, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 90.0, false, true );
} else if ( offset_type == "evening" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 100.0, false, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 100.0, false, true );
} else if ( offset_type == "midnight" ) {
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 180.0, false, "sun" );
warp = fgTimeSecondsUntilBodyAngle( cur_time, loc, 180.0, false, true );
} else if ( offset_type == "system-offset" ) {
warp = offset;
orig_warp = 0;

View file

@ -50,16 +50,18 @@ static const time_t step_secs = 60;
* solar system body is directly overhead. (lat, lon are reported in
* radians) */
void fgBodyPositionGST(double gst, double *lon, double *lat, const char *body) {
void fgBodyPositionGST(double gst, double& lon, double& lat, bool sun_not_moon) {
/* time_t ssue; seconds since unix epoch */
/* double *lat; (return) latitude */
/* double *lon; (return) longitude */
/* double& lat; (return) latitude */
/* double& lon; (return) longitude */
double tmp;
SGPropertyNode* body_node = fgGetNode("/ephemeris/" + std::string(body));
std::string body = sun_not_moon ? "sun" : "moon";
SGPropertyNode* body_node = fgGetNode("/ephemeris/" + body);
assert(body_node);
double xs = body_node->getDoubleValue("xs");
double xs = sun_not_moon ? body_node->getDoubleValue("xs")
: body_node->getDoubleValue("xg");
//double ys = body_node->getDoubleValue("ys");
double ye = body_node->getDoubleValue("ye");
double ze = body_node->getDoubleValue("ze");
@ -71,16 +73,17 @@ void fgBodyPositionGST(double gst, double *lon, double *lat, const char *body) {
double signedPI = (tmp < 0.0) ? -SGD_PI : SGD_PI;
tmp = fmod(tmp+signedPI, SGD_2PI) - signedPI;
*lon = tmp;
*lat = dec;
lon = tmp;
lat = dec;
}
static double body_angle( const SGTime &t, const SGVec3d& world_up, const char* body) {
static double body_angle( const SGTime &t, const SGVec3d& world_up, bool sun_not_moon) {
const char *body = sun_not_moon ? "sun" : "moon";
SG_LOG( SG_EVENT, SG_DEBUG, " Updating " << body << " position" );
SG_LOG( SG_EVENT, SG_DEBUG, " Gst = " << t.getGst() );
double lon, gc_lat;
fgBodyPositionGST( t.getGst(), &lon, &gc_lat, body );
fgBodyPositionGST( t.getGst(), lon, gc_lat, body );
SGVec3d bodypos = SGVec3d::fromGeoc(SGGeoc::fromRadM(lon, gc_lat,
SGGeodesy::EQURAD));
@ -121,7 +124,7 @@ time_t fgTimeSecondsUntilBodyAngle( time_t cur_time,
const SGGeod& loc,
double target_angle_deg,
bool ascending,
const char *body )
bool sun_not_moon )
{
SGVec3d world_up = SGVec3d::fromGeod(loc);
SGTime t = SGTime( loc, SGPath(), 0 );
@ -135,7 +138,7 @@ time_t fgTimeSecondsUntilBodyAngle( time_t cur_time,
secs += step_secs )
{
t.update( loc, secs, 0 );
double angle_deg = body_angle( t, world_up, body );
double angle_deg = body_angle( t, world_up, sun_not_moon );
double diff = fabs( angle_deg - target_angle_deg );
if ( diff < best_diff ) {
if ( last_angle <= 180.0 && ascending

View file

@ -51,7 +51,7 @@ time_t fgTimeSecondsUntilBodyAngle( time_t cur_time,
const SGGeod& loc,
double target_angle_deg,
bool ascending,
const char *body );
bool sun_not_moon );
/**
* given a particular time expressed in side real time at prime
@ -59,7 +59,7 @@ time_t fgTimeSecondsUntilBodyAngle( time_t cur_time,
* solar system body is directly overhead. (lat, lon are reported in
* radians)
*/
void fgBodyPositionGST(double gst, double *lon, double *lat, const char *body);
void fgBodyPositionGST(double gst, double& lon, double& lat, bool sun_not_moon);
#endif /* _BODYSOLVER_HXX */

View file

@ -354,34 +354,42 @@ void FGLight::update_adj_fog_color () {
void FGLight::updateObjects()
{
// update the sun position
updateBodyPos("sun", &_sun_lon, &_sun_lat, &_sun_vec, &_sun_vec_inv,
&_sun_angle, _sunAngleRad, &_sun_rotation);
bool sun_not_moon = true;
updateBodyPos(sun_not_moon, _sun_lon, _sun_lat,
_sun_vec, _sun_vec_inv,
_sun_angle, _sunAngleRad,
_sun_rotation);
// update the moon position
updateBodyPos("moon", &_moon_lon, &_moon_gc_lat, &_moon_vec, &_moon_vec_inv,
&_moon_angle, _moonAngleRad, &_moon_rotation);
sun_not_moon = false;
updateBodyPos(sun_not_moon, _moon_lon, _moon_gc_lat,
_moon_vec, _moon_vec_inv,
_moon_angle, _moonAngleRad,
_moon_rotation);
}
// update the position of one solar system body
void FGLight::updateBodyPos(const char *body, double *lon, double *lat,
SGVec4f *vec, SGVec4f *vec_inv, double *angle, SGPropertyNode_ptr AngleRad,
double *rotation)
void FGLight::updateBodyPos(bool sun_not_moon, double& lon, double& lat,
SGVec4f& vec, SGVec4f& vec_inv,
double& angle, SGPropertyNode_ptr AngleRad,
double& rotation)
{
SGTime *t = globals->get_time_params();
fgBodyPositionGST(t->getGst(), lon, lat, body);
// returns lon and lat based on GST
fgBodyPositionGST(t->getGst(), lon, lat, sun_not_moon);
// It might seem that gc_lat needs to be converted to geodetic
// latitude here, but it doesn't. The body latitude is the latitude
// of the point on the earth where the up vector has the same
// angle from geocentric Z as the body direction. But geodetic
// latitude is defined as 90 - angle of up vector from Z!
SGVec3d bodypos = SGVec3d::fromGeoc(SGGeoc::fromRadM(*lon, *lat,
SGVec3d bodypos = SGVec3d::fromGeoc(SGGeoc::fromRadM(lon, lat,
SGGeodesy::EQURAD));
// update the body vector
*vec = SGVec4f(toVec3f(normalize(bodypos)), 0);
*vec_inv = - *vec;
vec = SGVec4f(toVec3f(normalize(bodypos)), 0);
vec_inv = - vec;
// calculate the body's relative angle to local up
SGQuatd hlOr = SGQuatd::fromLonLat( globals->get_view_position() );
@ -393,10 +401,10 @@ void FGLight::updateBodyPos(const char *body, double *lon, double *lat,
SGVec3d nbody = normalize(bodypos);
SGVec3d nup = normalize(world_up);
*angle = acos( dot( nup, nbody ) );
angle = acos( dot( nup, nbody ) );
double signedPI = (*angle < 0.0) ? -SGD_PI : SGD_PI;
*angle = fmod(*angle+signedPI, SGD_2PI) - signedPI;
double signedPI = (angle < 0.0) ? -SGD_PI : SGD_PI;
angle = fmod(angle+signedPI, SGD_2PI) - signedPI;
// Get direction to the body in the local frame.
SGVec3d local_vec = hlOr.transform(nbody);
@ -408,12 +416,12 @@ void FGLight::updateBodyPos(const char *body, double *lon, double *lat,
// y-positive pointing East we need to negate local_vec.x()
// rotation is positive counterclockwise from South (body in the East)
// and negative clockwise from South (body in the West)
*rotation = atan2(local_vec.y(), -local_vec.x());
rotation = atan2(local_vec.y(), -local_vec.x());
// cout << " Sky needs to rotate = " << rotation << " rads = "
// << rotation * SGD_RADIANS_TO_DEGREES << " degrees." << endl;
AngleRad->setDoubleValue(*angle);
AngleRad->setDoubleValue(angle);
}

View file

@ -114,9 +114,10 @@ private:
void updateObjects();
// update the position of one solar system body
void updateBodyPos(const char *body, double *lon, double *lat,
SGVec4f *vec, SGVec4f *vec_inv, double *angle, SGPropertyNode_ptr AngleRad,
double *rotation);
void updateBodyPos(bool sun_not_moon, double& lon, double& lat,
SGVec4f& vec, SGVec4f& vec_inv,
double& angle, SGPropertyNode_ptr AngleRad,
double& rotation);
// properties for chrome light; not a tie because I want to fire
// property listeners when the values change.