[comp.sources.misc] v09i013: FPLAN 3/6

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (11/27/89)

Posting-number: Volume 9, Issue 13
Submitted-by: tynor@prism.gatech.edu (Steve Tynor)
Archive-name: fplan/part03

#This is part 3/6 of FPLAN
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#	Packed Mon Nov 20 19:28:37 EST 1989 by gaffa!tynor
#	from directory /files/home/users/tynor/src/fplan
#
#	Run the following text with /bin/sh to create:
#	  add.c
#	  compute.c
#
echo "x - extracting add.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > add.c &&
X/*
X * $Id: add.c,v 2.5 89/11/11 19:09:43 tynor Exp $
X *----------------------------------------------------------------------------
X *	FPLAN - Flight Planner
X *	Steve Tynor
X *	tynor@prism.gatech.edu
X *
X *	This program is in the public domain. Permission to copy,
X * distribute, modify this program is hearby given as long as this header
X * remains. If you redistribute this program after modifying it, please
X * document your changes so that I do not take the blame (or credit) for
X * those changes.  If you fix bugs or add features, please send me a
X * patch so that I can keep the 'official' version up-to-date.
X *
X *	Bug reports are welcome and I'll make an attempt to fix those
X * that are reported.
X *
X *	USE AT YOUR OWN RISK! I assume no responsibility for any
X * errors in this program, its database or documentation. I will make an
X * effort to fix bugs, but if you crash and burn because, for example,
X * fuel estimates in this program were inaccurate, it's your own fault
X * for trusting somebody else's code! Remember, as PIC, it's _your_
X * responsibility to do complete preflight planning. Use this program as
X * a flight planning aid, but verify its results before using them.
X *----------------------------------------------------------------------------
X */
X
Xstatic char rcsid[] = "$Id: add.c,v 2.5 89/11/11 19:09:43 tynor Exp $";
X
X#include "wp_info.h"
X
Xextern char *malloc();
Xextern BOOLEAN lookup_desig ();
X
Xstatic BOOLEAN brief_mode = FALSE;
X
X#if 0
X/*----------------------------------------------------------------------------*/
Xstatic void find_intersection (desig1, radial1, desig2, radial2,
X			       latitude, longitude)
X     double  radial1, radial2;
X     char    *desig1, *desig2;
X     double  *latitude, *longitude;
X{
X   yyerror ("don't know how to find intersection yet");
X}
X#endif
X
X/*----------------------------------------------------------------------------*/
Xstatic void init_db (db)
XDATABASE_INFO *db;
X{
X   if (db) {
X      db->freq.valid = FALSE;
X      db->desig = (char*)0;
X      db->name = (char*)0;
X      db->city = (char*)0;
X      db->comment = (char*)0;
X      db->altitude.valid = FALSE;
X   }
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic void new_waypoint ()
X{
X   extern yyerror();
X
X   if (num_waypoints >= MAX_NUM_WAYPOINTS)
X      yyerror ("too many waypoints");
X   
X   if (num_waypoints > 0) {
X      waypoints[num_waypoints] = waypoints[num_waypoints-1]; 
X      waypoints[num_waypoints].refuel = FALSE;
X      waypoints[num_waypoints].extra_fuel_burn.valid = FALSE;
X   }
X   
X   num_waypoints++;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid add_named_waypoint (kind, desig)
X     WAYPOINT_KIND kind;
X     char *desig;
X{
X   DATABASE_INFO *db;
X
X   if (lookup_desig (kind, desig, &db)) {
X      new_waypoint ();   
X      waypoints[num_waypoints-1].wp_kind = kind;
X      waypoints[num_waypoints-1].db = db;
X   }
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid add_inc_waypoint (dist_since_last_wp, 
X		       name_str, city_str, comment_str)
X     double dist_since_last_wp;
X     char   *name_str;
X     char   *city_str;
X     char   *comment_str;
X{
X   if (brief_mode)
X      return;
X
X   new_waypoint ();
X
X   waypoints[num_waypoints-1].db = 
X      (DATABASE_INFO*) malloc (sizeof (DATABASE_INFO));
X   if (! waypoints[num_waypoints-1].db)
X      yyerror ("unable to allocate space for waypoint");
X
X   init_db (waypoints[num_waypoints-1].db);
X
X   waypoints[num_waypoints-1].db->mode = WP_INCREMENTAL;
X   waypoints[num_waypoints-1].wp_kind = WP_VIA;
X   waypoints[num_waypoints-1].db->name = name_str;
X   waypoints[num_waypoints-1].db->city = city_str;
X   waypoints[num_waypoints-1].db->comment = comment_str;
X
X   /*
X    * NOTE: we can't compute lat/long since we don't know the true course
X    * yet. So, just store the distance until print time.
X    */
X   waypoints[num_waypoints-1].db->u.dist_since_last_wp = dist_since_last_wp;
X}
X
X#if 0
X/*----------------------------------------------------------------------------*/
Xvoid add_int_waypoint (kind, desig1, radial1, desig2, radial2, 
X		       name_str, city_str, comment_str)
X     WAYPOINT_KIND kind;
X     double  radial1, radial2;
X     char    *desig1, *desig2, *name_str, *city_str, *comment_str;
X{
X   new_waypoint ();
X   waypoints[num_waypoints-1].db = 
X      (DATABASE_INFO*) malloc (sizeof (DATABASE_INFO));
X   if (! waypoints[num_waypoints-1].db)
X      yyerror ("unable to allocate space for waypoint");
X
X   init_db (waypoints[num_waypoints-1].db);
X
X   find_intersection (desig1, radial1, desig2, radial2, 
X		      &waypoints[num_waypoints-1].db->latitude, 
X		      &waypoints[num_waypoints-1].db->longitude);
X   waypoints[num_waypoints-1].db->mode = WP_INTERSECTION;
X   waypoints[num_waypoints-1].wp_kind = kind;
X   waypoints[num_waypoints-1].db->name = name_str;
X   waypoints[num_waypoints-1].db->city = city_str;
X   waypoints[num_waypoints-1].db->comment = comment_str;
X}
X#endif
X
X/*----------------------------------------------------------------------------*/
Xvoid add_lat_waypoint (kind, latitude, longitude, 
X		       name_str, city_str, comment_str)
X     WAYPOINT_KIND kind;
X     double  latitude, longitude;
X     char    *name_str;
X     char    *city_str;
X     char    *comment_str;
X{
X   new_waypoint ();
X   waypoints[num_waypoints-1].db = 
X      (DATABASE_INFO*) malloc (sizeof (DATABASE_INFO));
X   if (! waypoints[num_waypoints-1].db)
X      yyerror ("unable to allocate space for waypoint");
X
X   init_db (waypoints[num_waypoints-1].db);
X
X   waypoints[num_waypoints-1].db->mode = WP_LAT_LONG;
X   waypoints[num_waypoints-1].wp_kind = kind;
X   waypoints[num_waypoints-1].db->latitude = latitude;
X   waypoints[num_waypoints-1].db->longitude = longitude;
X   waypoints[num_waypoints-1].db->name = name_str;
X   waypoints[num_waypoints-1].db->city = city_str;
X   waypoints[num_waypoints-1].db->comment = comment_str;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_xfix (vor_num, vor_desig)
Xint vor_num;
Xchar *vor_desig;
X{
X   char buffer[80];
X   int i = MAX (0, num_waypoints-1);
X
X   if ((vor_num < 1) || (vor_num > MAX_NUM_VOR_FIXES)) {
X      sprintf (buffer, "Invalid NAV number. Must be between 1 and %d", 
X	       MAX_NUM_VOR_FIXES);
X      yyerror (buffer);
X   }
X   if (lookup_desig (WP_VIA, vor_desig, &waypoints[i].vor_fix[vor_num-1].db)) {
X      waypoints[i].vor_fix[vor_num-1].valid = TRUE;
X      max_nav = MAX (max_nav, vor_num-1);
X   }
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_tas (tas)
X     double tas;
X{
X   int i = MAX (0, num_waypoints-1);
X
X   waypoints[i].tas.valid = TRUE;
X   waypoints[i].tas.value = tas;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_wind (heading, speed)
X     double heading, speed;
X{
X   int i = MAX (0, num_waypoints-1);
X
X   waypoints[i].wind_speed.valid = TRUE;
X   waypoints[i].wind_speed.value = speed;
X   waypoints[i].wind_direction.valid = TRUE;
X   waypoints[i].wind_direction.value = heading;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_fuel_amt (amt)
X     double amt;
X{
X   int i = MAX (0, num_waypoints-1);
X
X   waypoints[i].refuel         = TRUE;
X   waypoints[i].fuel_amt.valid = TRUE;
X   waypoints[i].fuel_amt.value = amt;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_extra_fuel_burn (amt)
X     double amt;
X{
X   int i = MAX (0, num_waypoints-1);
X
X   waypoints[i].extra_fuel_burn.valid = TRUE;
X   waypoints[i].extra_fuel_burn.value = amt;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_fuel_rate (rate)
X     double rate;
X{
X   int i = MAX (0, num_waypoints-1);
X
X   waypoints[i].fuel_rate.valid = TRUE;
X   waypoints[i].fuel_rate.value = rate;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_altitude (feet)
X     double feet;
X{
X   int i = MAX (0, num_waypoints-1);
X
X   waypoints[i].altitude.valid = TRUE;
X   waypoints[i].altitude.value = feet;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid set_brief (on_off)
X     BOOLEAN on_off;
X{
X   brief_mode = on_off;
X}
X
X
SHAR_EOF
chmod 0444 add.c || echo "restore of add.c fails"
echo "x - extracting compute.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > compute.c &&
X/*
X * $Id: compute.c,v 2.6 89/11/14 20:27:46 tynor Exp $
X *----------------------------------------------------------------------------
X *	FPLAN - Flight Planner
X *	Steve Tynor
X *	tynor@prism.gatech.edu
X *
X *	This program is in the public domain. Permission to copy,
X * distribute, modify this program is hearby given as long as this header
X * remains. If you redistribute this program after modifying it, please
X * document your changes so that I do not take the blame (or credit) for
X * those changes.  If you fix bugs or add features, please send me a
X * patch so that I can keep the 'official' version up-to-date.
X *
X *	Bug reports are welcome and I'll make an attempt to fix those
X * that are reported.
X *
X *	USE AT YOUR OWN RISK! I assume no responsibility for any
X * errors in this program, its database or documentation. I will make an
X * effort to fix bugs, but if you crash and burn because, for example,
X * fuel estimates in this program were inaccurate, it's your own fault
X * for trusting somebody else's code! Remember, as PIC, it's _your_
X * responsibility to do complete preflight planning. Use this program as
X * a flight planning aid, but verify its results before using them.
X *----------------------------------------------------------------------------
X */
X
Xstatic char rcsid[] = "$Id: compute.c,v 2.6 89/11/14 20:27:46 tynor Exp $";
X
X#include "wp_info.h"
X#include <math.h>
X
X/*----------------------------------------------------------------------------*/
Xstatic void wind_correct (true_air_speed, mag_course, 
X			  wind_speed, wind_heading,
X			  ground_speed, mag_heading)
X     double true_air_speed, mag_course, 
X	wind_speed, wind_heading, 
X	*ground_speed, *mag_heading;
X{
X   double hdiff, tx, ty, wca;
X
X   if (wind_heading <= 180.0)
X      wind_heading += 180.0;
X   else
X      wind_heading -= 180.0;
X   hdiff = DEG2RAD (mag_course - wind_heading);
X   tx = wind_speed * sin (hdiff);
X   ty = wind_speed * cos (hdiff);
X   wca = asin (tx / true_air_speed);
X   *ground_speed = cos (wca) * true_air_speed + ty;
X   *mag_heading = mag_course + RAD2DEG (wca);
X   if (*mag_heading >= 360.0)
X      *mag_heading -= 360.0;
X   else if (*mag_heading <= 0.0)
X      *mag_heading += 360.0;
X}
X
X/*----------------------------------------------------------------------------*/
Xvoid distance_and_heading (lat1, long1, lat2, long2, distance, heading)
X     double lat1, long1, lat2, long2;
X     double *distance, *heading;
X{
X   double tmp;
X
X   lat1  = DEG2RAD (lat1);
X   long1 = DEG2RAD (long1);
X   lat2  = DEG2RAD (lat2);
X   long2 = DEG2RAD (long2);
X
X   if ((lat1 == lat2) && (long1 == long2)) {
X      *distance = 0.0;
X      *heading  = 0.0;
X      return;
X   }
X
X   tmp = atan2 (2.0 * asin (sin ((long1 - long2) / 2.0)),
X		log (tan (PI / 4.0 + lat2 / 2.0)) - 
X		log (tan (PI / 4.0 + lat1 / 2.0)) );
X   if (lat1 == lat2)
X      *distance = 60.0 *
X	 fabs (RAD2DEG (2.0 * asin (sin ((long1 - long2) / 2.0)))) *
X	    cos (lat1);
X   else
X      *distance = 60.0 * RAD2DEG (lat2 - lat1) / cos (fabs (tmp));
X   
X   if (asin (sin (long1-long2)) >= 0.0)
X      *heading = RAD2DEG (fabs(tmp));
X   else
X      *heading = 360.0 - RAD2DEG (fabs(tmp));
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic int next_non_incremental (start)
X     int start;
X{
X   int i = start;
X
X   for (i = start; i < num_waypoints; i++)
X      if (waypoints[i].db->mode != WP_INCREMENTAL)
X	 return i;
X   return -1;
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic void locate_incrementals ()
X{
X   int    j, prev, next;
X   double d, heading;
X
X   for (prev = 0; ((prev >= 0) && (prev < num_waypoints)); ) {
X      next = next_non_incremental (prev+1);
X      if (next >= 0) {
X	 distance_and_heading (waypoints[prev].db->latitude,
X			       waypoints[prev].db->longitude, 
X			       waypoints[next].db->latitude, 
X			       waypoints[next].db->longitude, 
X			       &d, &heading);
X	 for (j = prev+1; j < next; j++) {
X	    if (waypoints[j].db->u.dist_since_last_wp >= 0.0) {
X	       waypoints[j].db->latitude =  waypoints[prev].db->latitude +
X		  (waypoints[next].db->latitude - waypoints[prev].db->latitude)
X		     * waypoints[j].db->u.dist_since_last_wp / d;
X	       waypoints[j].db->longitude =  waypoints[prev].db->longitude +
X		  (waypoints[next].db->longitude -
X		   waypoints[prev].db->longitude) * 
X		      waypoints[j].db->u.dist_since_last_wp / d;
X	    } else {
X	       waypoints[j].db->latitude =  waypoints[next].db->latitude +
X		  (waypoints[next].db->latitude - waypoints[prev].db->latitude)
X		     * waypoints[j].db->u.dist_since_last_wp / d;
X	       waypoints[j].db->longitude =  waypoints[next].db->longitude +
X		  (waypoints[next].db->longitude -
X		   waypoints[prev].db->longitude) * 
X		      waypoints[j].db->u.dist_since_last_wp / d;
X	    }
X	 }
X      }
X      prev = next;
X   }
X}
X
X/*----------------------------------------------------------------------------*/
X#define IS_NAVAID(mode) (((mode) == WP_VOR) || ((mode) == WP_NDB) || \
X			 ((mode) == WP_DME) || ((mode) == WP_TAC) || \
X			 ((mode) == WP_ILS) || ((mode) == WP_LOM) || \
X			 ((mode) == WP_LMM))
X
X/*----------------------------------------------------------------------------
X * FUZZ is the number of degrees two points can be apart and still be considered
X * colocated - we let this be fuzzy, since it's often the case that onfield VORs
X * are reported with slightly different lat/long, but we still want to view them
X * as the same point...
X */
X#define FUZZ 0.01
X#define COLOCATED(db1,db2) \
X   ((fabs ((db1)->latitude - (db2)->latitude) <= FUZZ) && \
X    (fabs ((db1)->longitude - (db2)->longitude) <= FUZZ))
X
X/*----------------------------------------------------------------------------*/
Xstatic DATABASE_INFO *get_navaid (wp)
X     WAYPOINT_INFO wp;
X     /*
X      * If the waypoint is a navaid return its db pointer. If it's an airport 
X      * and there's a navaid colocated on the field, return it's db pointer,
X      * else return NULL.
X      */
X{
X   DATABASE_INFO *db;
X   extern BOOLEAN lookup_desig ();
X
X   if (IS_NAVAID (wp.db->mode)) {
X      return (wp.db);
X   } else if ((wp.db->mode == WP_AIRPORT) && 
X	      (lookup_desig (WP_VIA, wp.db->desig, &db)) &&
X	      IS_NAVAID (db->mode) &&
X	      COLOCATED (db, wp.db) ) {
X      return (db);
X   } else {
X      return ((DATABASE_INFO*) 0);
X   }
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic track_nav1 ()
X     /*
X      * for each waypoint, determine what VOR to tune in on NAV1.
X      *
X      * This is tricky - some waypoints are navaids - so we want to track to 
X      * (and sometimes from) them - others are just "distance-since-last-
X      * -waypoint" or "lat/long" waypoints, and we can't track to those. 
X      * From and To Airports also sometimes have VORS on-field, so we need to 
X      * recognize when that happens so that we can track to/from airport 
X      * waypoints. 
X      *
X      * The vor_fix[0] for each waypoint is for the leg _between_ that waypoint
X      * and the next one. If there is no navaid that can be used to track along
X      * that leg, set the .valid falg to FALSE.
X      */
X{
X   int this, to;
X   DATABASE_INFO *db;
X
X   /*
X    * invalidate all the current NAV1 settings
X    */
X   for (this = 0; this < num_waypoints; this++) 
X      waypoints[this].vor_fix[0].valid = FALSE;
X
X   to = 0;
X   for (this = 0; (to != -1) && (this < num_waypoints); this++) {
X      to = next_non_incremental (this+1);
X      if (
X	  /*
X	   * if the next non-incremental waypoint is a navaid (or if an
X	   * airport and there's a navaid colocated on the field) then use that 
X	   * as NAV1 for this waypoint and those up to that one
X	   */
X	  ((to >= 0) && 
X	   (db = get_navaid (waypoints[to]))) ||
X	  /*
X	  * else, if this waypoint is a navaid, use it
X	  */
X	   (db = get_navaid (waypoints[this])) ) {
X	 for (; this < to; this++) {
X	    waypoints[this].vor_fix[0].valid = TRUE;
X	    waypoints[this].vor_fix[0].db    = db;
X	 }
X	 this = to - 1;
X      } 
X      /*
X       * else, we're out of luck - leave the fix invalid.
X       */
X   }
X}
X
X/*----------------------------------------------------------------------------*/
Xnormalize_heading (head)
X     double *head;
X{
X   if (*head < 0.0)
X      *head += 360.0;
X   else if (*head > 360.0)
X      *head -= 360.0;
X}
X
X/*----------------------------------------------------------------------------*/
Xstatic BOOLEAN do_fix (plane_heading, latitude, longitude, vor_fix, force_from)
X     double plane_heading;
X     double latitude;
X     double longitude;
X     VOR_FIX *vor_fix;
X     BOOLEAN force_from;
X{
X   double d;
X   double lat_from  = latitude;
X   double long_from = longitude;
X   double lat_to    = vor_fix->db->latitude;
X   double long_to   = vor_fix->db->longitude;
X   
X   if (! vor_fix->db)
X      return FALSE;
X
X   if ((lat_from == lat_to) && (long_from == long_to))
X      return FALSE;
X
X   distance_and_heading (lat_from, long_from, lat_to, long_to,
X			 &vor_fix->distance, &vor_fix->heading); 
X   vor_fix->heading += vor_fix->db->mag_variation;
X   d = plane_heading - vor_fix->heading;
X   vor_fix->from_to = TO;
X   if (force_from || (d > 180.0) || (d < -180.0)) {
X      vor_fix->from_to = FROM;
X      vor_fix->heading += 180.0;
X   }
X   normalize_heading (&vor_fix->heading);
X   return TRUE;
X}
X
X/*----------------------------------------------------------------------------*/
XBOOLEAN compute_plan (auto_nav1)
X     BOOLEAN auto_nav1;
X{
X   int i;
X   int num_pairs = 0;
X#define MAX_NUM_PAIRS 30
X   double total_dist [MAX_NUM_PAIRS];
X   double distance, heading;
X
X   /*
X    * locate the waypoints specified only by distance from last waypoint:
X    */
X   locate_incrementals ();
X
X   /*
X    * accumulate the total distance between each from/to pair
X    */
X   num_pairs = 0;
X   for (i = 0; i < num_waypoints; i++) {
X      if (waypoints[i].wp_kind == WP_FROM) {
X	 waypoints[i].eta.valid = TRUE;
X	 waypoints[i].eta.value = 0.0;
X	 total_dist [num_pairs] = 0.0;
X      }
X      if ((i+1 < num_waypoints) && (waypoints[i].wp_kind != WP_TO)) {
X	 distance_and_heading (waypoints[i].db->latitude,
X			       waypoints[i].db->longitude,
X			       waypoints[i+1].db->latitude,
X			       waypoints[i+1].db->longitude,
X			       &distance, &heading);
X	 waypoints[i].dist_leg.valid = TRUE;
X	 waypoints[i].tc.valid       = TRUE;
X	 waypoints[i].mc.valid       = TRUE;
X	 waypoints[i].dist_leg.value = distance;
X	 waypoints[i].tc.value       = heading;
X	 waypoints[i].mc.value       = heading + waypoints[i].db->mag_variation;
X	 normalize_heading (&waypoints[i].mc.value);
X	 normalize_heading (&waypoints[i].tc.value);
X      } else {
X	 waypoints[i].dist_leg.valid = FALSE;
X	 waypoints[i].tc.valid       = FALSE;
X	 waypoints[i].mc.valid       = FALSE;
X      }
X
X      waypoints[i].dist.valid = TRUE;
X      waypoints[i].dist.value = total_dist [num_pairs];
X
X      total_dist [num_pairs] += waypoints[i].dist_leg.value;
X
X      if (waypoints[i].wp_kind == WP_TO)
X	 num_pairs++;
X   }
X
X   /*
X    * now, do the distance remaining:
X    */
X   num_pairs = 0.0;
X   for (i = 0; i < num_waypoints; i++) {
X      waypoints[i].dist_remain.value = 
X	 total_dist [num_pairs] - waypoints[i].dist.value;
X      waypoints[i].dist_remain.valid = TRUE;
X      if (waypoints[i].wp_kind == WP_TO)
X	 num_pairs++;
X   }
X
X   /*
X    * wind correction (heading, ground speed)
X    */
X   for (i = 0; i < num_waypoints; i++) {
X      if (waypoints[i].tas.valid && 
X	  waypoints[i].mc.valid) {
X
X	 if (!waypoints[i].wind_speed.valid)
X	    waypoints[i].wind_speed.value = 0.0; 
X	 if (!waypoints[i].wind_direction.valid)
X	    waypoints[i].wind_direction.value = 0.0;
X 
X	 wind_correct (waypoints[i].tas.value, 
X		       waypoints[i].mc.value, 
X		       waypoints[i].wind_speed.value,
X		       waypoints[i].wind_direction.value,
X		       &waypoints[i].egs.value,
X		       &waypoints[i].mh.value);
X
X	 waypoints[i].egs.valid  = TRUE;
X	 waypoints[i].mh.valid   = TRUE;
X	 normalize_heading (&waypoints[i].mh.value);
X
X	 /*
X	  * time in hours
X	  */
X	 waypoints[i].eta_leg.valid = waypoints[i].dist_leg.valid;
X	 waypoints[i].eta_leg.value = waypoints[i].dist_leg.value / 
X	    waypoints[i].egs.value;
X      } else {
X	 waypoints[i].egs.valid     = FALSE;
X	 waypoints[i].mh.valid      = FALSE;
X	 waypoints[i].eta.valid     = FALSE;
X	 waypoints[i].eta_leg.valid = FALSE;
X      }
X      waypoints[i].eta.valid     = (BOOLEAN) (waypoints[i].wp_kind != WP_FROM);
X      waypoints[i].eta.value     = (waypoints[i].dist.value == 0.0) ? 0.0 :
X	 waypoints[i-1].eta_leg.value + waypoints[i-1].eta.value;
X   }
X
X   /*
X    * fuel burn:
X    */
X   for (i = 0; i < num_waypoints; i++) {
X      waypoints[i].fuel_leg.valid = (BOOLEAN) (waypoints[i].fuel_rate.valid &&
X					       waypoints[i].eta_leg.valid);
X      if (waypoints[i].fuel_leg.valid)
X	 waypoints[i].fuel_leg.value = 
X	    waypoints[i].fuel_rate.value * waypoints[i].eta_leg.value;
X      if (waypoints[i].refuel) {
X	 waypoints[i].fuel_amt.valid = TRUE;
X      } else if (i && (waypoints[i].wp_kind == WP_FROM) &&
X		 (!waypoints[i].refuel)) {
X	 waypoints[i].fuel_amt.valid = waypoints[i-1].fuel_amt.valid;
X	 waypoints[i].fuel_amt.value = waypoints[i-1].fuel_amt.value;
X      } else if (i && waypoints[i-1].fuel_leg.valid &&
X		 waypoints[i-1].fuel_amt.valid) {
X	 waypoints[i].fuel_amt.value = 
X	    waypoints[i-1].fuel_amt.value - waypoints[i-1].fuel_leg.value;
X      }
X      if (waypoints[i].extra_fuel_burn.valid)
X	 waypoints[i].fuel_amt.value -= waypoints[i].extra_fuel_burn.value;
X   }
X
X   if (auto_nav1)
X      track_nav1 ();
X
X   /*
X    * VOR cross fixes:
X    */
X   {
X      int vor;
X      for (i = 0; i < num_waypoints; i++) {
X	 for (vor = 0; vor < MAX_NUM_VOR_FIXES; vor++) {
X	    if (waypoints[i].vor_fix[vor].valid) {
X	       if (! do_fix (waypoints[i].mh.value, waypoints[i].db->latitude,
X			     waypoints[i].db->longitude, 
X			     &waypoints[i].vor_fix[vor], FALSE) ) {
X		  /*
X		   * if we failed to compute an xfix, it could be because we're
X		   * right on top of the navaid - pretend we're at the next
X		   * waypoint (since that's where we're going...)
X		   */
X		  if ((i+1) < num_waypoints) {
X		     if (!do_fix (waypoints[i].mh.value, 
X				  waypoints[i+1].db->latitude,
X				  waypoints[i+1].db->longitude, 
X				  &waypoints[i].vor_fix[vor], TRUE))
X			waypoints[i].vor_fix[vor].valid = FALSE;
X		  } else
X		     waypoints[i].vor_fix[vor].valid = FALSE;
X	       }
X	    }
X	 }
X      }
X   }
X   return TRUE;
X}
X
X
SHAR_EOF
chmod 0444 compute.c || echo "restore of compute.c fails"
exit 0