home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume9 / fplan / part03 < prev    next >
Text File  |  1989-11-26  |  24KB  |  744 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v09i013: FPLAN 3/6
  3. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  4. Reply-To: tynor@prism.gatech.edu (Steve Tynor)
  5.  
  6. Posting-number: Volume 9, Issue 13
  7. Submitted-by: tynor@prism.gatech.edu (Steve Tynor)
  8. Archive-name: fplan/part03
  9.  
  10. #This is part 3/6 of FPLAN
  11. #!/bin/sh
  12. # shar:    Shell Archiver  (v1.22)
  13. #    Packed Mon Nov 20 19:28:37 EST 1989 by gaffa!tynor
  14. #    from directory /files/home/users/tynor/src/fplan
  15. #
  16. #    Run the following text with /bin/sh to create:
  17. #      add.c
  18. #      compute.c
  19. #
  20. echo "x - extracting add.c (Text)"
  21. sed 's/^X//' << 'SHAR_EOF' > add.c &&
  22. X/*
  23. X * $Id: add.c,v 2.5 89/11/11 19:09:43 tynor Exp $
  24. X *----------------------------------------------------------------------------
  25. X *    FPLAN - Flight Planner
  26. X *    Steve Tynor
  27. X *    tynor@prism.gatech.edu
  28. X *
  29. X *    This program is in the public domain. Permission to copy,
  30. X * distribute, modify this program is hearby given as long as this header
  31. X * remains. If you redistribute this program after modifying it, please
  32. X * document your changes so that I do not take the blame (or credit) for
  33. X * those changes.  If you fix bugs or add features, please send me a
  34. X * patch so that I can keep the 'official' version up-to-date.
  35. X *
  36. X *    Bug reports are welcome and I'll make an attempt to fix those
  37. X * that are reported.
  38. X *
  39. X *    USE AT YOUR OWN RISK! I assume no responsibility for any
  40. X * errors in this program, its database or documentation. I will make an
  41. X * effort to fix bugs, but if you crash and burn because, for example,
  42. X * fuel estimates in this program were inaccurate, it's your own fault
  43. X * for trusting somebody else's code! Remember, as PIC, it's _your_
  44. X * responsibility to do complete preflight planning. Use this program as
  45. X * a flight planning aid, but verify its results before using them.
  46. X *----------------------------------------------------------------------------
  47. X */
  48. X
  49. Xstatic char rcsid[] = "$Id: add.c,v 2.5 89/11/11 19:09:43 tynor Exp $";
  50. X
  51. X#include "wp_info.h"
  52. X
  53. Xextern char *malloc();
  54. Xextern BOOLEAN lookup_desig ();
  55. X
  56. Xstatic BOOLEAN brief_mode = FALSE;
  57. X
  58. X#if 0
  59. X/*----------------------------------------------------------------------------*/
  60. Xstatic void find_intersection (desig1, radial1, desig2, radial2,
  61. X                   latitude, longitude)
  62. X     double  radial1, radial2;
  63. X     char    *desig1, *desig2;
  64. X     double  *latitude, *longitude;
  65. X{
  66. X   yyerror ("don't know how to find intersection yet");
  67. X}
  68. X#endif
  69. X
  70. X/*----------------------------------------------------------------------------*/
  71. Xstatic void init_db (db)
  72. XDATABASE_INFO *db;
  73. X{
  74. X   if (db) {
  75. X      db->freq.valid = FALSE;
  76. X      db->desig = (char*)0;
  77. X      db->name = (char*)0;
  78. X      db->city = (char*)0;
  79. X      db->comment = (char*)0;
  80. X      db->altitude.valid = FALSE;
  81. X   }
  82. X}
  83. X
  84. X/*----------------------------------------------------------------------------*/
  85. Xstatic void new_waypoint ()
  86. X{
  87. X   extern yyerror();
  88. X
  89. X   if (num_waypoints >= MAX_NUM_WAYPOINTS)
  90. X      yyerror ("too many waypoints");
  91. X   
  92. X   if (num_waypoints > 0) {
  93. X      waypoints[num_waypoints] = waypoints[num_waypoints-1]; 
  94. X      waypoints[num_waypoints].refuel = FALSE;
  95. X      waypoints[num_waypoints].extra_fuel_burn.valid = FALSE;
  96. X   }
  97. X   
  98. X   num_waypoints++;
  99. X}
  100. X
  101. X/*----------------------------------------------------------------------------*/
  102. Xvoid add_named_waypoint (kind, desig)
  103. X     WAYPOINT_KIND kind;
  104. X     char *desig;
  105. X{
  106. X   DATABASE_INFO *db;
  107. X
  108. X   if (lookup_desig (kind, desig, &db)) {
  109. X      new_waypoint ();   
  110. X      waypoints[num_waypoints-1].wp_kind = kind;
  111. X      waypoints[num_waypoints-1].db = db;
  112. X   }
  113. X}
  114. X
  115. X/*----------------------------------------------------------------------------*/
  116. Xvoid add_inc_waypoint (dist_since_last_wp, 
  117. X               name_str, city_str, comment_str)
  118. X     double dist_since_last_wp;
  119. X     char   *name_str;
  120. X     char   *city_str;
  121. X     char   *comment_str;
  122. X{
  123. X   if (brief_mode)
  124. X      return;
  125. X
  126. X   new_waypoint ();
  127. X
  128. X   waypoints[num_waypoints-1].db = 
  129. X      (DATABASE_INFO*) malloc (sizeof (DATABASE_INFO));
  130. X   if (! waypoints[num_waypoints-1].db)
  131. X      yyerror ("unable to allocate space for waypoint");
  132. X
  133. X   init_db (waypoints[num_waypoints-1].db);
  134. X
  135. X   waypoints[num_waypoints-1].db->mode = WP_INCREMENTAL;
  136. X   waypoints[num_waypoints-1].wp_kind = WP_VIA;
  137. X   waypoints[num_waypoints-1].db->name = name_str;
  138. X   waypoints[num_waypoints-1].db->city = city_str;
  139. X   waypoints[num_waypoints-1].db->comment = comment_str;
  140. X
  141. X   /*
  142. X    * NOTE: we can't compute lat/long since we don't know the true course
  143. X    * yet. So, just store the distance until print time.
  144. X    */
  145. X   waypoints[num_waypoints-1].db->u.dist_since_last_wp = dist_since_last_wp;
  146. X}
  147. X
  148. X#if 0
  149. X/*----------------------------------------------------------------------------*/
  150. Xvoid add_int_waypoint (kind, desig1, radial1, desig2, radial2, 
  151. X               name_str, city_str, comment_str)
  152. X     WAYPOINT_KIND kind;
  153. X     double  radial1, radial2;
  154. X     char    *desig1, *desig2, *name_str, *city_str, *comment_str;
  155. X{
  156. X   new_waypoint ();
  157. X   waypoints[num_waypoints-1].db = 
  158. X      (DATABASE_INFO*) malloc (sizeof (DATABASE_INFO));
  159. X   if (! waypoints[num_waypoints-1].db)
  160. X      yyerror ("unable to allocate space for waypoint");
  161. X
  162. X   init_db (waypoints[num_waypoints-1].db);
  163. X
  164. X   find_intersection (desig1, radial1, desig2, radial2, 
  165. X              &waypoints[num_waypoints-1].db->latitude, 
  166. X              &waypoints[num_waypoints-1].db->longitude);
  167. X   waypoints[num_waypoints-1].db->mode = WP_INTERSECTION;
  168. X   waypoints[num_waypoints-1].wp_kind = kind;
  169. X   waypoints[num_waypoints-1].db->name = name_str;
  170. X   waypoints[num_waypoints-1].db->city = city_str;
  171. X   waypoints[num_waypoints-1].db->comment = comment_str;
  172. X}
  173. X#endif
  174. X
  175. X/*----------------------------------------------------------------------------*/
  176. Xvoid add_lat_waypoint (kind, latitude, longitude, 
  177. X               name_str, city_str, comment_str)
  178. X     WAYPOINT_KIND kind;
  179. X     double  latitude, longitude;
  180. X     char    *name_str;
  181. X     char    *city_str;
  182. X     char    *comment_str;
  183. X{
  184. X   new_waypoint ();
  185. X   waypoints[num_waypoints-1].db = 
  186. X      (DATABASE_INFO*) malloc (sizeof (DATABASE_INFO));
  187. X   if (! waypoints[num_waypoints-1].db)
  188. X      yyerror ("unable to allocate space for waypoint");
  189. X
  190. X   init_db (waypoints[num_waypoints-1].db);
  191. X
  192. X   waypoints[num_waypoints-1].db->mode = WP_LAT_LONG;
  193. X   waypoints[num_waypoints-1].wp_kind = kind;
  194. X   waypoints[num_waypoints-1].db->latitude = latitude;
  195. X   waypoints[num_waypoints-1].db->longitude = longitude;
  196. X   waypoints[num_waypoints-1].db->name = name_str;
  197. X   waypoints[num_waypoints-1].db->city = city_str;
  198. X   waypoints[num_waypoints-1].db->comment = comment_str;
  199. X}
  200. X
  201. X/*----------------------------------------------------------------------------*/
  202. Xvoid set_xfix (vor_num, vor_desig)
  203. Xint vor_num;
  204. Xchar *vor_desig;
  205. X{
  206. X   char buffer[80];
  207. X   int i = MAX (0, num_waypoints-1);
  208. X
  209. X   if ((vor_num < 1) || (vor_num > MAX_NUM_VOR_FIXES)) {
  210. X      sprintf (buffer, "Invalid NAV number. Must be between 1 and %d", 
  211. X           MAX_NUM_VOR_FIXES);
  212. X      yyerror (buffer);
  213. X   }
  214. X   if (lookup_desig (WP_VIA, vor_desig, &waypoints[i].vor_fix[vor_num-1].db)) {
  215. X      waypoints[i].vor_fix[vor_num-1].valid = TRUE;
  216. X      max_nav = MAX (max_nav, vor_num-1);
  217. X   }
  218. X}
  219. X
  220. X/*----------------------------------------------------------------------------*/
  221. Xvoid set_tas (tas)
  222. X     double tas;
  223. X{
  224. X   int i = MAX (0, num_waypoints-1);
  225. X
  226. X   waypoints[i].tas.valid = TRUE;
  227. X   waypoints[i].tas.value = tas;
  228. X}
  229. X
  230. X/*----------------------------------------------------------------------------*/
  231. Xvoid set_wind (heading, speed)
  232. X     double heading, speed;
  233. X{
  234. X   int i = MAX (0, num_waypoints-1);
  235. X
  236. X   waypoints[i].wind_speed.valid = TRUE;
  237. X   waypoints[i].wind_speed.value = speed;
  238. X   waypoints[i].wind_direction.valid = TRUE;
  239. X   waypoints[i].wind_direction.value = heading;
  240. X}
  241. X
  242. X/*----------------------------------------------------------------------------*/
  243. Xvoid set_fuel_amt (amt)
  244. X     double amt;
  245. X{
  246. X   int i = MAX (0, num_waypoints-1);
  247. X
  248. X   waypoints[i].refuel         = TRUE;
  249. X   waypoints[i].fuel_amt.valid = TRUE;
  250. X   waypoints[i].fuel_amt.value = amt;
  251. X}
  252. X
  253. X/*----------------------------------------------------------------------------*/
  254. Xvoid set_extra_fuel_burn (amt)
  255. X     double amt;
  256. X{
  257. X   int i = MAX (0, num_waypoints-1);
  258. X
  259. X   waypoints[i].extra_fuel_burn.valid = TRUE;
  260. X   waypoints[i].extra_fuel_burn.value = amt;
  261. X}
  262. X
  263. X/*----------------------------------------------------------------------------*/
  264. Xvoid set_fuel_rate (rate)
  265. X     double rate;
  266. X{
  267. X   int i = MAX (0, num_waypoints-1);
  268. X
  269. X   waypoints[i].fuel_rate.valid = TRUE;
  270. X   waypoints[i].fuel_rate.value = rate;
  271. X}
  272. X
  273. X/*----------------------------------------------------------------------------*/
  274. Xvoid set_altitude (feet)
  275. X     double feet;
  276. X{
  277. X   int i = MAX (0, num_waypoints-1);
  278. X
  279. X   waypoints[i].altitude.valid = TRUE;
  280. X   waypoints[i].altitude.value = feet;
  281. X}
  282. X
  283. X/*----------------------------------------------------------------------------*/
  284. Xvoid set_brief (on_off)
  285. X     BOOLEAN on_off;
  286. X{
  287. X   brief_mode = on_off;
  288. X}
  289. X
  290. X
  291. SHAR_EOF
  292. chmod 0444 add.c || echo "restore of add.c fails"
  293. echo "x - extracting compute.c (Text)"
  294. sed 's/^X//' << 'SHAR_EOF' > compute.c &&
  295. X/*
  296. X * $Id: compute.c,v 2.6 89/11/14 20:27:46 tynor Exp $
  297. X *----------------------------------------------------------------------------
  298. X *    FPLAN - Flight Planner
  299. X *    Steve Tynor
  300. X *    tynor@prism.gatech.edu
  301. X *
  302. X *    This program is in the public domain. Permission to copy,
  303. X * distribute, modify this program is hearby given as long as this header
  304. X * remains. If you redistribute this program after modifying it, please
  305. X * document your changes so that I do not take the blame (or credit) for
  306. X * those changes.  If you fix bugs or add features, please send me a
  307. X * patch so that I can keep the 'official' version up-to-date.
  308. X *
  309. X *    Bug reports are welcome and I'll make an attempt to fix those
  310. X * that are reported.
  311. X *
  312. X *    USE AT YOUR OWN RISK! I assume no responsibility for any
  313. X * errors in this program, its database or documentation. I will make an
  314. X * effort to fix bugs, but if you crash and burn because, for example,
  315. X * fuel estimates in this program were inaccurate, it's your own fault
  316. X * for trusting somebody else's code! Remember, as PIC, it's _your_
  317. X * responsibility to do complete preflight planning. Use this program as
  318. X * a flight planning aid, but verify its results before using them.
  319. X *----------------------------------------------------------------------------
  320. X */
  321. X
  322. Xstatic char rcsid[] = "$Id: compute.c,v 2.6 89/11/14 20:27:46 tynor Exp $";
  323. X
  324. X#include "wp_info.h"
  325. X#include <math.h>
  326. X
  327. X/*----------------------------------------------------------------------------*/
  328. Xstatic void wind_correct (true_air_speed, mag_course, 
  329. X              wind_speed, wind_heading,
  330. X              ground_speed, mag_heading)
  331. X     double true_air_speed, mag_course, 
  332. X    wind_speed, wind_heading, 
  333. X    *ground_speed, *mag_heading;
  334. X{
  335. X   double hdiff, tx, ty, wca;
  336. X
  337. X   if (wind_heading <= 180.0)
  338. X      wind_heading += 180.0;
  339. X   else
  340. X      wind_heading -= 180.0;
  341. X   hdiff = DEG2RAD (mag_course - wind_heading);
  342. X   tx = wind_speed * sin (hdiff);
  343. X   ty = wind_speed * cos (hdiff);
  344. X   wca = asin (tx / true_air_speed);
  345. X   *ground_speed = cos (wca) * true_air_speed + ty;
  346. X   *mag_heading = mag_course + RAD2DEG (wca);
  347. X   if (*mag_heading >= 360.0)
  348. X      *mag_heading -= 360.0;
  349. X   else if (*mag_heading <= 0.0)
  350. X      *mag_heading += 360.0;
  351. X}
  352. X
  353. X/*----------------------------------------------------------------------------*/
  354. Xvoid distance_and_heading (lat1, long1, lat2, long2, distance, heading)
  355. X     double lat1, long1, lat2, long2;
  356. X     double *distance, *heading;
  357. X{
  358. X   double tmp;
  359. X
  360. X   lat1  = DEG2RAD (lat1);
  361. X   long1 = DEG2RAD (long1);
  362. X   lat2  = DEG2RAD (lat2);
  363. X   long2 = DEG2RAD (long2);
  364. X
  365. X   if ((lat1 == lat2) && (long1 == long2)) {
  366. X      *distance = 0.0;
  367. X      *heading  = 0.0;
  368. X      return;
  369. X   }
  370. X
  371. X   tmp = atan2 (2.0 * asin (sin ((long1 - long2) / 2.0)),
  372. X        log (tan (PI / 4.0 + lat2 / 2.0)) - 
  373. X        log (tan (PI / 4.0 + lat1 / 2.0)) );
  374. X   if (lat1 == lat2)
  375. X      *distance = 60.0 *
  376. X     fabs (RAD2DEG (2.0 * asin (sin ((long1 - long2) / 2.0)))) *
  377. X        cos (lat1);
  378. X   else
  379. X      *distance = 60.0 * RAD2DEG (lat2 - lat1) / cos (fabs (tmp));
  380. X   
  381. X   if (asin (sin (long1-long2)) >= 0.0)
  382. X      *heading = RAD2DEG (fabs(tmp));
  383. X   else
  384. X      *heading = 360.0 - RAD2DEG (fabs(tmp));
  385. X}
  386. X
  387. X/*----------------------------------------------------------------------------*/
  388. Xstatic int next_non_incremental (start)
  389. X     int start;
  390. X{
  391. X   int i = start;
  392. X
  393. X   for (i = start; i < num_waypoints; i++)
  394. X      if (waypoints[i].db->mode != WP_INCREMENTAL)
  395. X     return i;
  396. X   return -1;
  397. X}
  398. X
  399. X/*----------------------------------------------------------------------------*/
  400. Xstatic void locate_incrementals ()
  401. X{
  402. X   int    j, prev, next;
  403. X   double d, heading;
  404. X
  405. X   for (prev = 0; ((prev >= 0) && (prev < num_waypoints)); ) {
  406. X      next = next_non_incremental (prev+1);
  407. X      if (next >= 0) {
  408. X     distance_and_heading (waypoints[prev].db->latitude,
  409. X                   waypoints[prev].db->longitude, 
  410. X                   waypoints[next].db->latitude, 
  411. X                   waypoints[next].db->longitude, 
  412. X                   &d, &heading);
  413. X     for (j = prev+1; j < next; j++) {
  414. X        if (waypoints[j].db->u.dist_since_last_wp >= 0.0) {
  415. X           waypoints[j].db->latitude =  waypoints[prev].db->latitude +
  416. X          (waypoints[next].db->latitude - waypoints[prev].db->latitude)
  417. X             * waypoints[j].db->u.dist_since_last_wp / d;
  418. X           waypoints[j].db->longitude =  waypoints[prev].db->longitude +
  419. X          (waypoints[next].db->longitude -
  420. X           waypoints[prev].db->longitude) * 
  421. X              waypoints[j].db->u.dist_since_last_wp / d;
  422. X        } else {
  423. X           waypoints[j].db->latitude =  waypoints[next].db->latitude +
  424. X          (waypoints[next].db->latitude - waypoints[prev].db->latitude)
  425. X             * waypoints[j].db->u.dist_since_last_wp / d;
  426. X           waypoints[j].db->longitude =  waypoints[next].db->longitude +
  427. X          (waypoints[next].db->longitude -
  428. X           waypoints[prev].db->longitude) * 
  429. X              waypoints[j].db->u.dist_since_last_wp / d;
  430. X        }
  431. X     }
  432. X      }
  433. X      prev = next;
  434. X   }
  435. X}
  436. X
  437. X/*----------------------------------------------------------------------------*/
  438. X#define IS_NAVAID(mode) (((mode) == WP_VOR) || ((mode) == WP_NDB) || \
  439. X             ((mode) == WP_DME) || ((mode) == WP_TAC) || \
  440. X             ((mode) == WP_ILS) || ((mode) == WP_LOM) || \
  441. X             ((mode) == WP_LMM))
  442. X
  443. X/*----------------------------------------------------------------------------
  444. X * FUZZ is the number of degrees two points can be apart and still be considered
  445. X * colocated - we let this be fuzzy, since it's often the case that onfield VORs
  446. X * are reported with slightly different lat/long, but we still want to view them
  447. X * as the same point...
  448. X */
  449. X#define FUZZ 0.01
  450. X#define COLOCATED(db1,db2) \
  451. X   ((fabs ((db1)->latitude - (db2)->latitude) <= FUZZ) && \
  452. X    (fabs ((db1)->longitude - (db2)->longitude) <= FUZZ))
  453. X
  454. X/*----------------------------------------------------------------------------*/
  455. Xstatic DATABASE_INFO *get_navaid (wp)
  456. X     WAYPOINT_INFO wp;
  457. X     /*
  458. X      * If the waypoint is a navaid return its db pointer. If it's an airport 
  459. X      * and there's a navaid colocated on the field, return it's db pointer,
  460. X      * else return NULL.
  461. X      */
  462. X{
  463. X   DATABASE_INFO *db;
  464. X   extern BOOLEAN lookup_desig ();
  465. X
  466. X   if (IS_NAVAID (wp.db->mode)) {
  467. X      return (wp.db);
  468. X   } else if ((wp.db->mode == WP_AIRPORT) && 
  469. X          (lookup_desig (WP_VIA, wp.db->desig, &db)) &&
  470. X          IS_NAVAID (db->mode) &&
  471. X          COLOCATED (db, wp.db) ) {
  472. X      return (db);
  473. X   } else {
  474. X      return ((DATABASE_INFO*) 0);
  475. X   }
  476. X}
  477. X
  478. X/*----------------------------------------------------------------------------*/
  479. Xstatic track_nav1 ()
  480. X     /*
  481. X      * for each waypoint, determine what VOR to tune in on NAV1.
  482. X      *
  483. X      * This is tricky - some waypoints are navaids - so we want to track to 
  484. X      * (and sometimes from) them - others are just "distance-since-last-
  485. X      * -waypoint" or "lat/long" waypoints, and we can't track to those. 
  486. X      * From and To Airports also sometimes have VORS on-field, so we need to 
  487. X      * recognize when that happens so that we can track to/from airport 
  488. X      * waypoints. 
  489. X      *
  490. X      * The vor_fix[0] for each waypoint is for the leg _between_ that waypoint
  491. X      * and the next one. If there is no navaid that can be used to track along
  492. X      * that leg, set the .valid falg to FALSE.
  493. X      */
  494. X{
  495. X   int this, to;
  496. X   DATABASE_INFO *db;
  497. X
  498. X   /*
  499. X    * invalidate all the current NAV1 settings
  500. X    */
  501. X   for (this = 0; this < num_waypoints; this++) 
  502. X      waypoints[this].vor_fix[0].valid = FALSE;
  503. X
  504. X   to = 0;
  505. X   for (this = 0; (to != -1) && (this < num_waypoints); this++) {
  506. X      to = next_non_incremental (this+1);
  507. X      if (
  508. X      /*
  509. X       * if the next non-incremental waypoint is a navaid (or if an
  510. X       * airport and there's a navaid colocated on the field) then use that 
  511. X       * as NAV1 for this waypoint and those up to that one
  512. X       */
  513. X      ((to >= 0) && 
  514. X       (db = get_navaid (waypoints[to]))) ||
  515. X      /*
  516. X      * else, if this waypoint is a navaid, use it
  517. X      */
  518. X       (db = get_navaid (waypoints[this])) ) {
  519. X     for (; this < to; this++) {
  520. X        waypoints[this].vor_fix[0].valid = TRUE;
  521. X        waypoints[this].vor_fix[0].db    = db;
  522. X     }
  523. X     this = to - 1;
  524. X      } 
  525. X      /*
  526. X       * else, we're out of luck - leave the fix invalid.
  527. X       */
  528. X   }
  529. X}
  530. X
  531. X/*----------------------------------------------------------------------------*/
  532. Xnormalize_heading (head)
  533. X     double *head;
  534. X{
  535. X   if (*head < 0.0)
  536. X      *head += 360.0;
  537. X   else if (*head > 360.0)
  538. X      *head -= 360.0;
  539. X}
  540. X
  541. X/*----------------------------------------------------------------------------*/
  542. Xstatic BOOLEAN do_fix (plane_heading, latitude, longitude, vor_fix, force_from)
  543. X     double plane_heading;
  544. X     double latitude;
  545. X     double longitude;
  546. X     VOR_FIX *vor_fix;
  547. X     BOOLEAN force_from;
  548. X{
  549. X   double d;
  550. X   double lat_from  = latitude;
  551. X   double long_from = longitude;
  552. X   double lat_to    = vor_fix->db->latitude;
  553. X   double long_to   = vor_fix->db->longitude;
  554. X   
  555. X   if (! vor_fix->db)
  556. X      return FALSE;
  557. X
  558. X   if ((lat_from == lat_to) && (long_from == long_to))
  559. X      return FALSE;
  560. X
  561. X   distance_and_heading (lat_from, long_from, lat_to, long_to,
  562. X             &vor_fix->distance, &vor_fix->heading); 
  563. X   vor_fix->heading += vor_fix->db->mag_variation;
  564. X   d = plane_heading - vor_fix->heading;
  565. X   vor_fix->from_to = TO;
  566. X   if (force_from || (d > 180.0) || (d < -180.0)) {
  567. X      vor_fix->from_to = FROM;
  568. X      vor_fix->heading += 180.0;
  569. X   }
  570. X   normalize_heading (&vor_fix->heading);
  571. X   return TRUE;
  572. X}
  573. X
  574. X/*----------------------------------------------------------------------------*/
  575. XBOOLEAN compute_plan (auto_nav1)
  576. X     BOOLEAN auto_nav1;
  577. X{
  578. X   int i;
  579. X   int num_pairs = 0;
  580. X#define MAX_NUM_PAIRS 30
  581. X   double total_dist [MAX_NUM_PAIRS];
  582. X   double distance, heading;
  583. X
  584. X   /*
  585. X    * locate the waypoints specified only by distance from last waypoint:
  586. X    */
  587. X   locate_incrementals ();
  588. X
  589. X   /*
  590. X    * accumulate the total distance between each from/to pair
  591. X    */
  592. X   num_pairs = 0;
  593. X   for (i = 0; i < num_waypoints; i++) {
  594. X      if (waypoints[i].wp_kind == WP_FROM) {
  595. X     waypoints[i].eta.valid = TRUE;
  596. X     waypoints[i].eta.value = 0.0;
  597. X     total_dist [num_pairs] = 0.0;
  598. X      }
  599. X      if ((i+1 < num_waypoints) && (waypoints[i].wp_kind != WP_TO)) {
  600. X     distance_and_heading (waypoints[i].db->latitude,
  601. X                   waypoints[i].db->longitude,
  602. X                   waypoints[i+1].db->latitude,
  603. X                   waypoints[i+1].db->longitude,
  604. X                   &distance, &heading);
  605. X     waypoints[i].dist_leg.valid = TRUE;
  606. X     waypoints[i].tc.valid       = TRUE;
  607. X     waypoints[i].mc.valid       = TRUE;
  608. X     waypoints[i].dist_leg.value = distance;
  609. X     waypoints[i].tc.value       = heading;
  610. X     waypoints[i].mc.value       = heading + waypoints[i].db->mag_variation;
  611. X     normalize_heading (&waypoints[i].mc.value);
  612. X     normalize_heading (&waypoints[i].tc.value);
  613. X      } else {
  614. X     waypoints[i].dist_leg.valid = FALSE;
  615. X     waypoints[i].tc.valid       = FALSE;
  616. X     waypoints[i].mc.valid       = FALSE;
  617. X      }
  618. X
  619. X      waypoints[i].dist.valid = TRUE;
  620. X      waypoints[i].dist.value = total_dist [num_pairs];
  621. X
  622. X      total_dist [num_pairs] += waypoints[i].dist_leg.value;
  623. X
  624. X      if (waypoints[i].wp_kind == WP_TO)
  625. X     num_pairs++;
  626. X   }
  627. X
  628. X   /*
  629. X    * now, do the distance remaining:
  630. X    */
  631. X   num_pairs = 0.0;
  632. X   for (i = 0; i < num_waypoints; i++) {
  633. X      waypoints[i].dist_remain.value = 
  634. X     total_dist [num_pairs] - waypoints[i].dist.value;
  635. X      waypoints[i].dist_remain.valid = TRUE;
  636. X      if (waypoints[i].wp_kind == WP_TO)
  637. X     num_pairs++;
  638. X   }
  639. X
  640. X   /*
  641. X    * wind correction (heading, ground speed)
  642. X    */
  643. X   for (i = 0; i < num_waypoints; i++) {
  644. X      if (waypoints[i].tas.valid && 
  645. X      waypoints[i].mc.valid) {
  646. X
  647. X     if (!waypoints[i].wind_speed.valid)
  648. X        waypoints[i].wind_speed.value = 0.0; 
  649. X     if (!waypoints[i].wind_direction.valid)
  650. X        waypoints[i].wind_direction.value = 0.0;
  651. X     wind_correct (waypoints[i].tas.value, 
  652. X               waypoints[i].mc.value, 
  653. X               waypoints[i].wind_speed.value,
  654. X               waypoints[i].wind_direction.value,
  655. X               &waypoints[i].egs.value,
  656. X               &waypoints[i].mh.value);
  657. X
  658. X     waypoints[i].egs.valid  = TRUE;
  659. X     waypoints[i].mh.valid   = TRUE;
  660. X     normalize_heading (&waypoints[i].mh.value);
  661. X
  662. X     /*
  663. X      * time in hours
  664. X      */
  665. X     waypoints[i].eta_leg.valid = waypoints[i].dist_leg.valid;
  666. X     waypoints[i].eta_leg.value = waypoints[i].dist_leg.value / 
  667. X        waypoints[i].egs.value;
  668. X      } else {
  669. X     waypoints[i].egs.valid     = FALSE;
  670. X     waypoints[i].mh.valid      = FALSE;
  671. X     waypoints[i].eta.valid     = FALSE;
  672. X     waypoints[i].eta_leg.valid = FALSE;
  673. X      }
  674. X      waypoints[i].eta.valid     = (BOOLEAN) (waypoints[i].wp_kind != WP_FROM);
  675. X      waypoints[i].eta.value     = (waypoints[i].dist.value == 0.0) ? 0.0 :
  676. X     waypoints[i-1].eta_leg.value + waypoints[i-1].eta.value;
  677. X   }
  678. X
  679. X   /*
  680. X    * fuel burn:
  681. X    */
  682. X   for (i = 0; i < num_waypoints; i++) {
  683. X      waypoints[i].fuel_leg.valid = (BOOLEAN) (waypoints[i].fuel_rate.valid &&
  684. X                           waypoints[i].eta_leg.valid);
  685. X      if (waypoints[i].fuel_leg.valid)
  686. X     waypoints[i].fuel_leg.value = 
  687. X        waypoints[i].fuel_rate.value * waypoints[i].eta_leg.value;
  688. X      if (waypoints[i].refuel) {
  689. X     waypoints[i].fuel_amt.valid = TRUE;
  690. X      } else if (i && (waypoints[i].wp_kind == WP_FROM) &&
  691. X         (!waypoints[i].refuel)) {
  692. X     waypoints[i].fuel_amt.valid = waypoints[i-1].fuel_amt.valid;
  693. X     waypoints[i].fuel_amt.value = waypoints[i-1].fuel_amt.value;
  694. X      } else if (i && waypoints[i-1].fuel_leg.valid &&
  695. X         waypoints[i-1].fuel_amt.valid) {
  696. X     waypoints[i].fuel_amt.value = 
  697. X        waypoints[i-1].fuel_amt.value - waypoints[i-1].fuel_leg.value;
  698. X      }
  699. X      if (waypoints[i].extra_fuel_burn.valid)
  700. X     waypoints[i].fuel_amt.value -= waypoints[i].extra_fuel_burn.value;
  701. X   }
  702. X
  703. X   if (auto_nav1)
  704. X      track_nav1 ();
  705. X
  706. X   /*
  707. X    * VOR cross fixes:
  708. X    */
  709. X   {
  710. X      int vor;
  711. X      for (i = 0; i < num_waypoints; i++) {
  712. X     for (vor = 0; vor < MAX_NUM_VOR_FIXES; vor++) {
  713. X        if (waypoints[i].vor_fix[vor].valid) {
  714. X           if (! do_fix (waypoints[i].mh.value, waypoints[i].db->latitude,
  715. X                 waypoints[i].db->longitude, 
  716. X                 &waypoints[i].vor_fix[vor], FALSE) ) {
  717. X          /*
  718. X           * if we failed to compute an xfix, it could be because we're
  719. X           * right on top of the navaid - pretend we're at the next
  720. X           * waypoint (since that's where we're going...)
  721. X           */
  722. X          if ((i+1) < num_waypoints) {
  723. X             if (!do_fix (waypoints[i].mh.value, 
  724. X                  waypoints[i+1].db->latitude,
  725. X                  waypoints[i+1].db->longitude, 
  726. X                  &waypoints[i].vor_fix[vor], TRUE))
  727. X            waypoints[i].vor_fix[vor].valid = FALSE;
  728. X          } else
  729. X             waypoints[i].vor_fix[vor].valid = FALSE;
  730. X           }
  731. X        }
  732. X     }
  733. X      }
  734. X   }
  735. X   return TRUE;
  736. X}
  737. X
  738. X
  739. SHAR_EOF
  740. chmod 0444 compute.c || echo "restore of compute.c fails"
  741. exit 0
  742.  
  743.