home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / star.lzh / star.19 < prev    next >
Encoding:
Text File  |  1990-04-06  |  32.8 KB  |  1,141 lines

  1.  
  2. #! /bin/sh
  3. # This is a shell archive.  Remove anything before this line, then unpack
  4. # it by saving it into a file and typing "sh file".  To overwrite existing
  5. # files, type "sh file -c".  You can also feed this as standard input via
  6. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  7. # will see the following message at the end:
  8. #        "End of archive 19 (of 32)."
  9. # Contents:  starchart/ssup.c.aa
  10. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  11. if test -f 'starchart/ssup.c.aa' -a "${1}" != "-c" ; then 
  12.   echo shar: Will not clobber existing file \"'starchart/ssup.c.aa'\"
  13. else
  14. echo shar: Extracting \"'starchart/ssup.c.aa'\" \(31121 characters\)
  15. sed "s/^X//" >'starchart/ssup.c.aa' <<'END_OF_FILE'
  16. X/*
  17. X * starsupp.c, extracted from starchart.c (now starmain.c)
  18. X * starchart.c -- version 2, September 1987
  19. X *        revision 2.1 December, 1987
  20. X *        revision 3.0beta January, 1989 
  21. X *
  22. X * Portions Copyright (c) 1987 by Alan Paeth (awpaeth@watcgl)
  23. X *
  24. X * Copyright (c) 1990 by Craig Counterman. All rights reserved.
  25. X *
  26. X * This software may be redistributed freely, not sold.
  27. X * This copyright notice and disclaimer of warranty must remain
  28. X *    unchanged. 
  29. X *
  30. X * No representation is made about the suitability of this
  31. X * software for any purpose.  It is provided "as is" without express or
  32. X * implied warranty, to the extent permitted by applicable law.
  33. X *
  34. X */
  35. X
  36. X
  37. X/*
  38. X ! Version 2 modification authors:
  39. X !
  40. X !   [a] Petri Launiainen, pl@intrin.FI (with Jyrki Yli-Nokari, jty@intrin.FI)
  41. X !   [b] Bob Tidd, inp@VIOLET.BERKELEY.EDU
  42. X !   [c] Alan Paeth, awpaeth@watcgl
  43. X !
  44. X */
  45. X
  46. Xstatic char rcsid[]="$Header: starsupp.c,v 2.13 90/03/10 15:31:51 ccount Exp $";
  47. X
  48. X#include <stdio.h>
  49. X#include <math.h>
  50. X#ifndef SYSV
  51. X#include <strings.h>
  52. X#else
  53. X#include <string.h>
  54. X#endif
  55. X#include <ctype.h>
  56. X
  57. X#include "star3.h"
  58. X
  59. X#ifndef READMODE
  60. X#define READMODE "r"
  61. X#endif
  62. X#define OPENFAIL 0
  63. X#define LINELEN 82
  64. X
  65. X
  66. X/* PI / 180 = .0174532925199 */
  67. X#define DCOS(x) (cos((x)*.0174532925199))
  68. X#define DSIN(x) (sin((x)*.0174532925199))
  69. X#define DTAN(x) (tan((x)*.0174532925199))
  70. X#define DASIN(x) (asin(x)/.0174532925199)
  71. X#define DATAN2(x,y) (atan2(x,y)/.0174532925199)
  72. X#define MAX(a,b) ((a)>(b)?(a):(b))
  73. X#define MIN(a,b) ((a)<(b)?(a):(b))
  74. X
  75. X/* externals from starmain.c */
  76. Xextern mapwindow *mapwin[];
  77. Xextern int numwins;
  78. X
  79. X
  80. X/* exportable */
  81. Xdouble xf_west, xf_east, xf_north, xf_south, xf_bottom;
  82. Xint xf_xcen, xf_ycen, xf_ybot;
  83. Xint xf_w_left, xf_w_right, xf_w_top, xf_w_bot;
  84. X
  85. Xdouble xf_c_scale;
  86. X
  87. X/* local storage */
  88. Xstatic int xfs_proj_mode;
  89. X/* sin_dlcen = sin (phi0) = sin (declination of center), cos_dlcen similar */
  90. Xstatic double xfs_ra_cen, xfs_dl_cen, sin_dlcen, cos_dlcen, chart_scale;
  91. Xstatic double xfs_scale;        /* Formerly yscale */
  92. Xstatic double xfs_inv;
  93. Xstatic int xfs_wide_warn;
  94. X
  95. X
  96. X/* TRANSFORMATION FUNCTIONS */
  97. X
  98. X/**
  99. X    stereographic projection:
  100. X        Imagine object projected on a sphere of radius 1.
  101. X        Center of chart is against a piece of paper.
  102. X        You are looking at the center of the chart through the
  103. X                center of the sphere.
  104. X        The objects are seen projected on the piece of paper.
  105. X
  106. X    to do it:
  107. X        1) get angle from center to object, call this theta.
  108. X        2) get direction from center to object, call this phi.
  109. X        3) projection of object will be 2*tan(theta/2) from the center
  110. X                of the paper, in the direction phi.
  111. X
  112. X    to do steps 1 & 2, use alt-azimuth formula, with theta = 90 - alt.
  113. X
  114. X    scale: when theta = scale, projected object = min(ww,wh)/2 from center.
  115. X        i.e. 2*tan(scale/2)*xfs_scale = min(ww,wh)/2.
  116. X        or xfs_scale = (min(ww,wh)/2)/(2*tan(scale/2))
  117. X                  = min(ww,wh)/(4*tan(scale/2))
  118. X        put factor of 2 in xfs_scale to save a little computation
  119. X           xfs_scale = min(ww,wh)/(2*tan(scale/2))
  120. X        R = tan(theta/2)*xfs_scale.
  121. X*/
  122. X/**
  123. X    alt-azimuth:
  124. X      sin(alt) = sin(obs_lat)sin(obj_dl) + cos(obs_lat)cos(obj_dl)cos(hour)
  125. X
  126. X      cos(azi) = (cos(obs_lat)sin(obj_dl) - sin(obs_lat)cos(obj_dl)cos(hour))
  127. X            / cos(alt)
  128. X      sin(azi) = (-cos(obj_dl)sin(hour)) / cos(alt)
  129. X      tan(azi) = -cos((obj_dl)sin(hour)
  130. X              / (cos(obs_lat)sin(obj_dl) - sin(obs_lat)cos(obj_dl)cos(hour))
  131. X
  132. X
  133. X    with alt = 90 - theta, azi = phi, hour = lon - racen, obj_dl =lat,
  134. X                and obs_lat = dlcen, this becomes:
  135. X
  136. X    cos(theta) = sin(dlcen)sin(lat) + cos(dlcen)cos(lat)cos(lon - racen)
  137. X
  138. X    tan(phi) = -cos(lat)sin(lon - racen)
  139. X              / (cos(dlcen)sin(lat) - sin(dlcen)cos(lat)cos(lon - racen))
  140. X
  141. X
  142. X        racen and dlcen are constants for a chart, so introduce variables
  143. X            racen, sin_dlcen, cos_dlcen.
  144. X        also add chart_scale which is chart->scale in radians.
  145. X        initxform sets these static variables.
  146. X
  147. X
  148. X
  149. X    Other projections from book.
  150. X**/
  151. X
  152. X
  153. Xinitxform(win)
  154. X     mapwindow *win;
  155. X{
  156. X  double adj, xscale, tscale;
  157. X    
  158. X  xfs_proj_mode = win->proj_mode;
  159. X
  160. X  if (win->scale <= 0.0) return (FALSE);
  161. X  if (win->height == 0) return (FALSE);
  162. X
  163. X  xfs_ra_cen = win->racen;
  164. X  xfs_dl_cen = win->dlcen;
  165. X  xf_xcen = win->x_offset + (win->width)/2;
  166. X  xf_ycen = win->y_offset + (win->height)/2;
  167. X  xf_ybot = win->y_offset;
  168. X
  169. X  xf_north = (win->dlcen + win->scale / 2);
  170. X  xf_south = (win->dlcen - win->scale / 2);
  171. X
  172. X  if (xf_north > 90.0) xf_north = 90.0;
  173. X  if (xf_south < -90.0) xf_south = -90.0;
  174. X
  175. X  if (win->invert) {
  176. X    xfs_inv = -1.0;
  177. X    xf_bottom = xf_north;
  178. X  } else {
  179. X    xfs_inv = 1.0;
  180. X    xf_bottom = xf_south;
  181. X  }
  182. X
  183. X  if (xfs_proj_mode == SANSONS) {
  184. X/*
  185. X * calculate xf_east and xf_west by calculating the widest range of lon
  186. X * which will be within the chart.
  187. X * xscale is other than win->scale in order to widen the horizontal viewing
  188. X * area, which otherwise shrinks near the poles under Sanson's projection
  189. X * this happens in polar maps which do not span the celestial equator
  190. X */
  191. X    adj = 1.0;
  192. X    if (xf_north * xf_south > 0.0)
  193. X      adj = MAX(DCOS(xf_north), DCOS(xf_south));
  194. X    xscale = win->scale/adj;
  195. X
  196. X    tscale = xscale*win->width/win->height / 2.0;
  197. X    if (tscale > 180.0) tscale = 180.0;
  198. X  } else if (xfs_proj_mode == RECTANGULAR) {
  199. X    tscale = win->scale * win->width / (2*win->height);
  200. X    if (tscale > 180.0) tscale = 180.0;
  201. X  };
  202. X
  203. X  xf_east  = win->racen + tscale;
  204. X  xf_west  = win->racen - tscale;
  205. X
  206. X  /* set warning, may have problems in SANSONS or RECTANGULAR
  207. X     with lines which should wrap around */
  208. X  if (((xfs_proj_mode == SANSONS) || (xfs_proj_mode == RECTANGULAR))
  209. X      && (tscale > 90.0)) xfs_wide_warn = TRUE;
  210. X  else xfs_wide_warn = FALSE;
  211. X
  212. X
  213. X  xf_w_left = win->x_offset;
  214. X  xf_w_right = win->x_offset + win->width;
  215. X  xf_w_bot = win->y_offset;
  216. X  xf_w_top = win->y_offset + win->height;
  217. X
  218. X  switch (xfs_proj_mode) {
  219. X  case GNOMONIC:
  220. X  case ORTHOGR:
  221. X  case STEREOGR:
  222. X    sin_dlcen = DSIN(win->dlcen);
  223. X    cos_dlcen = DCOS(win->dlcen);
  224. X    chart_scale = win->scale * .0174532925199; /* Radians */
  225. X    break;
  226. X  case SANSONS:
  227. X  case RECTANGULAR:
  228. X  default:
  229. X    break;
  230. X  }
  231. X
  232. X/* xf_c_scale is the size in degrees which one pixel occupies on the map */
  233. X/* xfs_scale is the conversion factor for size of the picture
  234. X     (= R in some formulas for stereographic,
  235. X     gnomonic and orthographic projections) */
  236. X  if (xfs_proj_mode == STEREOGR) {
  237. X    xfs_scale = MIN(win->height, win->width) / (4.0*DTAN(win->scale/2.0));
  238. X    xf_c_scale = win->c_scale = 1.0/(2.0 * DTAN(0.5) * xfs_scale);
  239. X  } else if (xfs_proj_mode == SANSONS) {
  240. X    xfs_scale = win->height / win->scale;
  241. X    xf_c_scale = win->c_scale = win->scale / win->height;
  242. X  } else if (xfs_proj_mode == GNOMONIC) {
  243. X    xfs_scale = MIN(win->height, win->width) / (2.0 * DTAN(win->scale/2.0));
  244. X    xf_c_scale = win->c_scale = 1.0/(DTAN(1.0) * xfs_scale);
  245. X  } else if (xfs_proj_mode == ORTHOGR) {
  246. X    xfs_scale = MIN(win->height, win->width) / (2.0 * DSIN(win->scale/2.0));
  247. X    xf_c_scale = win->c_scale = 1.0/(DSIN(1.0) * xfs_scale);
  248. X  } else if (xfs_proj_mode == RECTANGULAR) {
  249. X    xfs_scale = win->height / win->scale;
  250. X    xf_c_scale = win->c_scale = 1.0/ xfs_scale;
  251. X  }
  252. X
  253. X  /* initialize gnomonic transform function */
  254. X  init_gt(win);
  255. X
  256. X  return (TRUE);
  257. X}
  258. X
  259. X
  260. X
  261. Xxform(lat, lon, xloc, yloc, inregion)
  262. X     double lat, lon;
  263. X     int *xloc, *yloc, *inregion;
  264. X{
  265. X  double theta, rac_l;
  266. X  double denom;
  267. X  double Dcoslat, Dsinlat, Dcosrac_l, Dsinrac_l;
  268. X  /* Dcoslat, Dsinlat: of object latitude in degrees = phi
  269. X     Dcosrac_l, Dsinrac_l: of object ra - longditude of center = d(lambda) */
  270. X
  271. X  switch (xfs_proj_mode) {
  272. X  case SANSONS:
  273. X /*
  274. X  * This is Sanson's Sinusoidal projection. Its properties:
  275. X  *   (1) area preserving
  276. X  *   (2) preserves linearity along y axis (declination/azimuth)
  277. X  */
  278. X/* because of the (xfs_ra_cen-lon) below, lon must be continuous across the
  279. X   plotted region.
  280. X   xf_west is xfs_ra_cen - (scale factor),
  281. X   xf_east is xfs_ra_cen + (scale factor), 
  282. X   so xf_west may be negative, and xf_east may be > 360.0.
  283. X   lon should be 0 <= lon < 360.0.  we must bring lon into the range.
  284. X   if xf_west < 0 and (xf_west + 360) < lon then lon is in the right half
  285. X       of the chart and needs to be adjusted
  286. X   if xf_east > 360 and (xf_east - 360) > lon then lon is in the left half
  287. X       of the chart and needs to be adjusted
  288. X*/
  289. X
  290. X
  291. X    if ((xf_west < 0.0) && (lon>(xf_west+360.0))) lon -= 360.0;
  292. X    if ((xf_east > 360.0) && (lon<(xf_east-360.0))) lon += 360.0;
  293. X
  294. X    *xloc = xf_xcen + (xfs_ra_cen-lon)*xfs_scale*DCOS(lat) + 0.5;
  295. X    *yloc = xf_ybot + (int)xfs_inv*((lat - xf_bottom) * xfs_scale) + 0.5;
  296. X    *inregion = ((lon >= xf_west) && (lon <= xf_east) &&
  297. X         (lat >= xf_south) && (lat <= xf_north));
  298. X    break;
  299. X  case STEREOGR:
  300. X/* stereographic projection */
  301. X    rac_l = lon - xfs_ra_cen;
  302. X    Dsinlat = DSIN(lat);
  303. X    Dcoslat = DCOS(lat);
  304. X    Dcosrac_l = DCOS(rac_l);
  305. X    Dsinrac_l = DSIN(rac_l);
  306. X    theta = acos(sin_dlcen*Dsinlat + cos_dlcen*Dcoslat*Dcosrac_l);
  307. X
  308. X    *inregion = (theta <= chart_scale);
  309. X    if (*inregion) {
  310. X      denom = (1+sin_dlcen*Dsinlat + cos_dlcen*Dcoslat*Dcosrac_l) / xfs_scale;
  311. X      *xloc = xf_xcen - 2*Dcoslat*Dsinrac_l / denom + 0.5;
  312. X      *yloc = xf_ycen + 2*xfs_inv*(cos_dlcen*Dsinlat
  313. X                 - sin_dlcen*Dcoslat*Dcosrac_l) / denom + 0.5;
  314. X    }
  315. X    break;
  316. X  case GNOMONIC:
  317. X/* gnomonic projection */
  318. X    rac_l = lon - xfs_ra_cen;
  319. X    Dsinlat = DSIN(lat);
  320. X    Dcoslat = DCOS(lat);
  321. X    Dcosrac_l = DCOS(rac_l);
  322. X    Dsinrac_l = DSIN(rac_l);
  323. X
  324. X    theta = acos(sin_dlcen*Dsinlat + cos_dlcen*Dcoslat*Dcosrac_l);
  325. X
  326. X    if (theta <= 1.57) { /* avoid wrapping */
  327. X      denom = (sin_dlcen*Dsinlat + cos_dlcen*Dcoslat*Dcosrac_l)    / xfs_scale;
  328. X      *yloc = xf_ycen +
  329. X    (int)xfs_inv*
  330. X     (cos_dlcen * Dsinlat - sin_dlcen * Dcoslat * Dcosrac_l) / denom + 0.5;
  331. X      *xloc = xf_xcen - Dcoslat * Dsinrac_l / denom + 0.5;
  332. X      *inregion = ((*xloc >= xf_w_left) && (*xloc <= xf_w_right)
  333. X           && (*yloc <= xf_w_top) && (*yloc >= xf_w_bot));
  334. X    } else *inregion = FALSE;
  335. X    break;
  336. X  case ORTHOGR:
  337. X    rac_l = lon - xfs_ra_cen;
  338. X    Dsinlat = DSIN(lat);
  339. X    Dcoslat = DCOS(lat);
  340. X    Dcosrac_l = DCOS(rac_l);
  341. X    Dsinrac_l = DSIN(rac_l);
  342. X
  343. X    theta = acos(sin_dlcen*Dsinlat + cos_dlcen*Dcoslat*Dcosrac_l);
  344. X
  345. X    if (theta <= 1.57) { /* avoid wrapping */
  346. X      *yloc = xf_ycen +
  347. X    (int)xfs_inv * xfs_scale
  348. X      * (cos_dlcen * Dsinlat - sin_dlcen * Dcoslat * Dcosrac_l);
  349. X      *xloc = xf_xcen - xfs_scale * Dcoslat * Dsinrac_l;
  350. X      *inregion = ((*xloc >= xf_w_left) && (*xloc <= xf_w_right)
  351. X           && (*yloc <= xf_w_top) && (*yloc >= xf_w_bot));
  352. X    } else *inregion = FALSE;
  353. X    break;
  354. X  case RECTANGULAR:
  355. X    if ((xf_west < 0.0) && (lon>(xf_west+360.0))) lon -= 360.0;
  356. X    if ((xf_east > 360.0) && (lon<(xf_east-360.0))) lon += 360.0;
  357. X
  358. X    *yloc = xf_ycen + (int)xfs_inv * xfs_scale * (lat - xfs_dl_cen);
  359. X    *xloc = xf_xcen + xfs_scale * (xfs_ra_cen - lon);
  360. X    *inregion = ((*xloc >= xf_w_left) && (*xloc <= xf_w_right)
  361. X         && (*yloc <= xf_w_top) && (*yloc >= xf_w_bot));
  362. X    break;
  363. X  default:
  364. X    break;
  365. X  }
  366. X}
  367. X
  368. X/* Given x and y of a point on the display,
  369. X   return the latitude and longitude */
  370. Xint invxform(x, y, latp, lonp)
  371. X     int x, y;
  372. X     double *latp, *lonp;
  373. X{
  374. X  int i;
  375. X  int winnum;
  376. X  mapwindow *win;
  377. X
  378. X  /* temporaries to hold values set by initxform */
  379. X  double t_xf_west, t_xf_east, t_xf_north, t_xf_south, t_xf_bottom;
  380. X  int t_xf_w_left, t_xf_w_right, t_xf_w_top, t_xf_w_bot;
  381. X  int t_xf_xcen, t_xf_ycen, t_xf_ybot;
  382. X  double t_xf_c_scale;
  383. X
  384. X  int t_xfs_proj_mode;
  385. X  double t_xfs_ra_cen, t_sin_dlcen, t_cos_dlcen, t_chart_scale;
  386. X  double t_xfs_scale;
  387. X  double t_xfs_inv;
  388. X
  389. X
  390. X  double rho;
  391. X  double R, theta;
  392. X  double l, m, n;
  393. X  double l_, m_, n_;
  394. X
  395. X
  396. X
  397. X  *latp = 0.0;
  398. X  *lonp = 0.0;
  399. X
  400. X  /* First, find which mapwindow the point is in */
  401. X  for (i = 0; i < numwins; i++) {
  402. X    if ((x >= mapwin[i]->x_offset) && (y >= mapwin[i]->y_offset)
  403. X    && (x <= (mapwin[i]->x_offset+mapwin[i]->width))
  404. X    && (y <= (mapwin[i]->y_offset+mapwin[i]->height)))
  405. X      /* point is in window i */
  406. X      break;
  407. X  }
  408. X  if (i == numwins) return -1; /* outside all windows */
  409. X
  410. X  winnum = i;
  411. X  win = mapwin[winnum];
  412. X
  413. X  /* Now, initialize inverse transformation for window winnum */
  414. X  t_xf_west = xf_west;
  415. X  t_xf_east = xf_east;
  416. X  t_xf_north = xf_north;
  417. X  t_xf_south = xf_south;
  418. X  t_xf_bottom = xf_bottom;
  419. X
  420. X  t_xf_xcen = xf_xcen;
  421. X  t_xf_ycen = xf_ycen;
  422. X  t_xf_ybot = xf_ybot;
  423. X
  424. X  t_xf_w_left = xf_w_left;
  425. X  t_xf_w_right = xf_w_right;
  426. X  t_xf_w_top = xf_w_top;
  427. X  t_xf_w_bot = xf_w_bot;
  428. X
  429. X  t_xf_c_scale = xf_c_scale;
  430. X
  431. X  t_xfs_proj_mode = xfs_proj_mode;
  432. X
  433. X  t_xfs_ra_cen = xfs_ra_cen;
  434. X
  435. X  t_sin_dlcen = sin_dlcen;
  436. X  t_cos_dlcen = cos_dlcen;
  437. X  t_chart_scale = chart_scale;
  438. X
  439. X  t_xfs_scale = xfs_scale;
  440. X
  441. X  t_xfs_inv = xfs_inv;
  442. X
  443. X  initxform(win);
  444. X
  445. X  /* Calculate lat and lon */
  446. X  switch (win->proj_mode) {
  447. X  case SANSONS:
  448. X    *latp = (y - xf_ybot)/xfs_scale*xfs_inv + xf_bottom;
  449. X    *lonp = -((x - xf_xcen)/(xfs_scale*DCOS(*latp)) - xfs_ra_cen);
  450. X    break;
  451. X  case GNOMONIC:
  452. X  case ORTHOGR:
  453. X  case STEREOGR:
  454. X    x -= xf_xcen;
  455. X    y -= xf_ycen;
  456. X    y *= xfs_inv;
  457. X
  458. X    R = sqrt((double) (x*x + y*y));
  459. X    theta = atan2((double) y, (double) x);
  460. X
  461. X    /* rho is the angle from the center of the display to the object on the
  462. X       unit sphere. */
  463. X    switch (win-> proj_mode) {
  464. X    case STEREOGR:
  465. X      rho = 2.0*atan(R/(2.0*xfs_scale));
  466. X      break;
  467. X    case GNOMONIC:
  468. X      rho = atan(R/xfs_scale);
  469. X      break;
  470. X    case ORTHOGR:
  471. X      rho = asin(R/xfs_scale);
  472. X      break;
  473. X    }
  474. X
  475. X    /* transform from (rho, theta) to l m n direction cosines */
  476. X    l = sin(rho)*cos(theta);    /* rho and theta are in radians */
  477. X    m = sin(rho)*sin(theta);
  478. X    n = cos(rho);
  479. X
  480. X    /* transform to new declination at center
  481. X       new axes rotated about x axis (l) */
  482. X    l_ = l;
  483. X    m_ = m*sin_dlcen - n*cos_dlcen;
  484. X    n_ = m*cos_dlcen + n*sin_dlcen;
  485. X
  486. X    /* calculate lon and lat */
  487. X    *lonp = atan2(l_, m_) /  0.0174532925199 + xfs_ra_cen - 180.0;
  488. X    *latp = 90 - acos(n_) /  0.0174532925199;
  489. X
  490. X    break;
  491. X  case RECTANGULAR:
  492. X    *latp = (y - xf_ycen) / (xfs_inv * xfs_scale) + xfs_dl_cen;
  493. X    *lonp = (xf_xcen - x) / xfs_scale + xfs_ra_cen;
  494. X    break;
  495. X  default:            /* error */
  496. X    winnum = -1;
  497. X  }
  498. X
  499. X
  500. X  /* restore initxform's variables */
  501. X  xf_west = t_xf_west;
  502. X  xf_east = t_xf_east;
  503. X  xf_north = t_xf_north;
  504. X  xf_south = t_xf_south;
  505. X  xf_bottom = t_xf_bottom;
  506. X
  507. X  xf_xcen = t_xf_xcen;
  508. X  xf_ycen = t_xf_ycen;
  509. X  xf_ybot = t_xf_ybot;
  510. X
  511. X  xf_w_left = t_xf_w_left;
  512. X  xf_w_right = t_xf_w_right;
  513. X  xf_w_top = t_xf_w_top;
  514. X  xf_w_bot = t_xf_w_bot;
  515. X
  516. X  xf_c_scale = t_xf_c_scale;
  517. X
  518. X  xfs_proj_mode = t_xfs_proj_mode;
  519. X
  520. X  xfs_ra_cen = t_xfs_ra_cen;
  521. X
  522. X  sin_dlcen = t_sin_dlcen;
  523. X  cos_dlcen = t_cos_dlcen;
  524. X  chart_scale = t_chart_scale;
  525. X
  526. X  xfs_scale = t_xfs_scale;
  527. X
  528. X  xfs_inv = t_xfs_inv;
  529. X
  530. X  if (*lonp >= 360.0) *lonp -= 360.0;
  531. X  if (*lonp < 0.0) *lonp += 360.0;
  532. X
  533. X  return winnum;
  534. X}
  535. X
  536. X
  537. X
  538. X/* Gnomonic transformation
  539. X   Used to draw vectors as great circles
  540. X   in Gnomonic transform a great circle is projected to a line.
  541. X*/
  542. Xstatic double gt_sin_dlcen, gt_cos_dlcen, gt_chart_scale;
  543. Xstatic double gt_scale;
  544. X
  545. X/* endpoints of west and east boundaries in SANSONS and RECTANGULAR */
  546. Xstatic double gt_wx1, gt_wy1, gt_wx2, gt_wy2;
  547. Xstatic double gt_ex1, gt_ey1, gt_ex2, gt_ey2;
  548. X
  549. X/* midpoint, a and b for north and south boundaries.
  550. X   y = a*x*x + y0 for parabola (b == 0.0)
  551. X   1 = x*x/a + (y-y0)*(y-y0)/b for ellipse */
  552. Xstatic double gt_ny0, gt_na, gt_nb;
  553. Xstatic double gt_sy0, gt_sa, gt_sb;
  554. X
  555. X/* radius for STEREOGRAPHIC, GNOMONIC, and ORTHOGRAPHIC */
  556. Xstatic double gt_r;
  557. X
  558. X/* Can we clip to boundaries analytically? */
  559. Xstatic int gt_use_boundaries;
  560. X
  561. X
  562. Xinit_gt(win)
  563. X     mapwindow *win;
  564. X{
  565. X  double x_1, x_2, y_1, y_2;
  566. X  double r_theta;
  567. X  double adj;
  568. X
  569. X  gt_use_boundaries = TRUE;
  570. X
  571. X  gt_sin_dlcen = DSIN(win->dlcen);
  572. X  gt_cos_dlcen = DCOS(win->dlcen);
  573. X  gt_chart_scale = win->scale * .0174532925199; /* Radians */
  574. X
  575. X/* gt_scale is the conversion factor for size of the picture ( = R) */
  576. X  if (xfs_proj_mode == STEREOGR)
  577. X    gt_scale = MIN(win->height, win->width) / (2.0 * DTAN(win->scale));
  578. X  else
  579. X    gt_scale = MIN(win->height, win->width) / (2.0 * DTAN(win->scale/2.0));
  580. X
  581. X  adj = xf_c_scale*0.9;            /* use boundaries slightly
  582. X                     more restricted than full plot */
  583. X
  584. X  /* calculate boundaries of region */
  585. X  switch (xfs_proj_mode) {
  586. X  case SANSONS:
  587. X  case RECTANGULAR:
  588. X    do_gt(xf_south+adj, xf_west+adj, >_wx1, >_wy1, &r_theta);
  589. X    gt_use_boundaries &= (r_theta <= 1.57);
  590. X    do_gt(xf_north-adj, xf_west+adj, >_wx2, >_wy2, &r_theta);
  591. X    gt_use_boundaries &= (r_theta <= 1.57);
  592. X    do_gt(xf_south+adj, xf_east-adj, >_ex1, >_ey1, &r_theta);
  593. X    gt_use_boundaries &= (r_theta <= 1.57);
  594. X    do_gt(xf_north-adj, xf_east-adj, >_ex2, >_ey2, &r_theta);
  595. X    gt_use_boundaries &= (r_theta <= 1.57);
  596. X
  597. X    do_gt(xf_north-adj, xfs_ra_cen, &x_1, &y_1, &r_theta);
  598. X    gt_use_boundaries &= (r_theta <= 1.57);
  599. X    gt_ny0 = y_1;
  600. X
  601. X    if (fabs(xf_north-adj) > (90 - fabs(win->dlcen))) {
  602. X      /* ellipse */
  603. X      do_gt(xf_north-adj, xfs_ra_cen + 180, &x_2, &y_2, &r_theta);
  604. X      gt_use_boundaries &= (r_theta <= 1.57);
  605. X      gt_nb = (y_2 - y_1)/2;
  606. X      gt_ny0 = y_1 + gt_nb ;
  607. X      gt_nb = gt_nb*gt_nb;
  608. X      do_gt(xf_north-adj, xfs_ra_cen + 90, &x_1, &y_1, &r_theta);
  609. X      gt_use_boundaries &= (r_theta <= 1.57);
  610. X
  611. X      gt_na = x_1*x_1 / (1 - (y_1 - gt_ny0)*(y_1 - gt_ny0)/gt_nb);
  612. X    } else {
  613. X      /* parabola */
  614. X      if (gt_use_boundaries) {
  615. X    gt_nb = 0.0;
  616. X    gt_na = (gt_ey2 - gt_ny0) / (gt_ex2 * gt_ex2);
  617. X    /* error if gt_ex2 == 0.0, as when r_theta was > 1.57 */
  618. X      }    
  619. X    }
  620. X
  621. X    do_gt(xf_south+adj, xfs_ra_cen, &x_1, &y_1, &r_theta);
  622. X    gt_use_boundaries &= (r_theta <= 1.57);
  623. X    gt_sy0 = y_1;
  624. X
  625. X    if (fabs(xf_south+adj) > (90 - fabs(win->dlcen))) {
  626. X      /* ellipse */
  627. X      do_gt(xf_south+adj, xfs_ra_cen + 180, &x_2, &y_2, &r_theta);
  628. X      gt_use_boundaries &= (r_theta <= 1.57);
  629. X      gt_sb = (y_2 - y_1)/2;
  630. X      gt_sy0 = y_1 - gt_sb ;
  631. X      gt_sb = gt_sb*gt_sb;
  632. X
  633. X      do_gt(xf_south+adj, xfs_ra_cen + 90, &x_1, &y_1, &r_theta);
  634. X      gt_use_boundaries &= (r_theta <= 1.57);
  635. X      do_gt(xf_south+adj, xfs_ra_cen + 270, &x_2, &y_2, &r_theta);
  636. X      gt_use_boundaries &= (r_theta <= 1.57);
  637. X      gt_sa = (x_2 - x_1)/2;
  638. X      gt_sa = gt_sa*gt_sa;
  639. X    } else {
  640. X      /* parabola */
  641. X      if (gt_use_boundaries) {
  642. X    gt_sb = 0.0;
  643. X    gt_sa = (gt_ey1 - gt_sy0) / (gt_ex1 * gt_ex1);
  644. X    /* error if gt_ex2 == 0.0, as when r_theta was > 1.57 */
  645. X      }
  646. X    }
  647. X    break;
  648. X  case STEREOGR:
  649. X    gt_r = MIN(win->height, win->width)/2.0 - 1;
  650. X    break;
  651. X  case ORTHOGR:
  652. X    gt_use_boundaries = FALSE; /* can't handle this analytically */
  653. X    break;
  654. X  case GNOMONIC:
  655. X    gt_wx1 = gt_wx2 = xf_w_left - xf_xcen + 1;
  656. X    gt_ex1 = gt_ex2 = xf_w_right - xf_xcen - 1;
  657. X    gt_ey1 = gt_wy1 = xf_w_bot - xf_ycen + 1;
  658. X    gt_ey2 = gt_wy2 = xf_w_top - xf_ycen - 1;
  659. X    break;
  660. X  default:            /* error */
  661. X    break;
  662. X  }
  663. X}
  664. X
  665. X
  666. X/* Note, returns xloc and yloc as doubles */
  667. Xdo_gt(lat, lon, xloc, yloc, r_theta)
  668. X     double lat, lon, *r_theta;
  669. X     double *xloc, *yloc;
  670. X{
  671. X  double theta, rac_l;
  672. X  double denom;
  673. X  double Dcoslat, Dsinlat, Dcosrac_l, Dsinrac_l;
  674. X  /* Dcoslat, Dsinlat: of object latitude in degrees = phi
  675. X     Dcosrac_l, Dsinrac_l: of object ra - longditude of center = d(lambda) */
  676. X
  677. X  rac_l = lon - xfs_ra_cen;
  678. X  Dsinlat = DSIN(lat);
  679. X  Dcoslat = DCOS(lat);
  680. X  Dcosrac_l = DCOS(rac_l);
  681. X  Dsinrac_l = DSIN(rac_l);
  682. X
  683. X  *r_theta =
  684. X    theta = acos(gt_sin_dlcen*Dsinlat + gt_cos_dlcen*Dcoslat*Dcosrac_l);
  685. X
  686. X  if (theta <= 1.57) { /* avoid wrapping */
  687. X    denom = (gt_sin_dlcen*Dsinlat + gt_cos_dlcen*Dcoslat*Dcosrac_l) / gt_scale;
  688. X    *yloc = xfs_inv*
  689. X    (gt_cos_dlcen * Dsinlat - gt_sin_dlcen * Dcoslat * Dcosrac_l) / denom;
  690. X    *xloc = - Dcoslat * Dsinrac_l / denom;
  691. X  };
  692. X}
  693. X
  694. X/* Given x and y of a point on the display,
  695. X   return the latitude and longitude */
  696. Xinv_gt(x, y, latp, lonp)
  697. X     double x, y;
  698. X     double *latp, *lonp;
  699. X{
  700. X  double rho;
  701. X  double R, theta;
  702. X  double l, m, n;
  703. X  double l_, m_, n_;
  704. X
  705. X  y *= xfs_inv;
  706. X
  707. X  *latp = 0.0;
  708. X  *lonp = 0.0;
  709. X
  710. X  /* Calculate lat and lon */
  711. X  R = sqrt((double) (x*x + y*y));
  712. X  theta = atan2((double) y, (double) x);
  713. X
  714. X  /* rho is the angle from the center of the display to the object on the
  715. X     unit sphere. */
  716. X  rho = atan(R/gt_scale);
  717. X
  718. X  /* transform from (rho, theta) to l m n direction cosines */
  719. X  l = sin(rho)*cos(theta);    /* rho and theta are in radians */
  720. X  m = sin(rho)*sin(theta);
  721. X  n = cos(rho);
  722. X
  723. X  /* transform to new declination at center
  724. X     new axes rotated about x axis (l) */
  725. X  l_ = l;
  726. X  m_ = m*gt_sin_dlcen - n*gt_cos_dlcen;
  727. X  n_ = m*gt_cos_dlcen + n*gt_sin_dlcen;
  728. X
  729. X  /* calculate lon and lat */
  730. X  *lonp = atan2(l_, m_) / 0.0174532925199 + xfs_ra_cen - 180.0;
  731. X  if (n_ > 1) n_ = 1;
  732. X  if (n_ < -1) n_ = -1;
  733. X  *latp = 90 - acos(n_) / 0.0174532925199;
  734. X
  735. X  if (*lonp >= 360.0) *lonp -= 360.0;
  736. X  if (*lonp < 0.0) *lonp += 360.0;
  737. X}
  738. X
  739. X
  740. X/*
  741. X * clipping extentions (ccount)
  742. X */
  743. X
  744. X/* defines and clipped_at are for use in area drawing,
  745. X   to indicate that a corner has fallen in the area */
  746. X#define NO_CLIP 0
  747. X#define WEST_CLIP 1
  748. X#define EAST_CLIP 2
  749. X#define NORTH_CLIP 4
  750. X#define SOUTH_CLIP 8
  751. X#define RADIUS_CLIP 16
  752. X#define NE_CORNER 6
  753. X#define SE_CORNER 10
  754. X#define NW_CORNER 5
  755. X#define SW_CORNER 9
  756. X
  757. Xstatic int clip_at1, clip_at2;
  758. X
  759. X/* return transformed values clipped so both endpoints are inregion */
  760. X/* return lats and lons */
  761. X/* The line is a great circle on the celestial sphere,
  762. X   or a line in lat and long (e.g. the line 0h 0d to 2h 10d
  763. X                              contains the point at 0.5h 5d).
  764. X
  765. X   Gnomonic transformation maps a great circle to a line.
  766. X
  767. X   There are three possibilities:
  768. X   1) both endpoints are in the region.
  769. X   2) one endpoint is in the region.
  770. X   3) both endpoints are outside of the drawn region.
  771. X
  772. XIn case 1, nothing needs to be done.
  773. XIn case 2, a second point at the intersection of the line and the boundary of
  774. Xthe drawn region is calculated.
  775. XIn case 3, it is possible that some segment of the line is in the drawn region,
  776. Xand two points along the boundary are calculated.
  777. X
  778. XThe boundary of the drawn region, projected through gnomonic transformation,
  779. Xare:
  780. XSansons: lines on east and west, a line, a parabola, or an ellipse
  781. X                to the north and south.
  782. X        ellipse iff declination of boundary > (90 - decl. of center)
  783. XStereographic: circle
  784. XGnomonic: rectangle
  785. XOrthographic: rectangle in orthographic is very comples, use a circle.
  786. XSimple: same as sansons.
  787. X*/
  788. X
  789. X
  790. Xclipr_xform(lat1, lon1, lat2, lon2, xloc1, yloc1, xloc2, yloc2, great_circle,
  791. X      plat1, plon1, plat2, plon2)
  792. X     double  lon1, lat1, lon2, lat2;
  793. X     int *xloc1, *yloc1, *xloc2, *yloc2;
  794. X     int great_circle;     /* draw as great circle */
  795. X     double  *plon1, *plat1, *plon2, *plat2;
  796. X{
  797. X  int Lisin, Risin;
  798. X  double x_1, y_1, x_2, y_2;
  799. X  double theta_1, theta_2;
  800. X  int int_w, int_e, int_n, int_s, int_r1, int_r2;
  801. X  double xw, xe, xn, xs, xr1, xr2, yw, ye, yn, ys, yr1, yr2;
  802. X
  803. X  double Llat, Llon, Rlat, Rlon, Mlat, Mlon;
  804. X  int Lx, Ly, Rx, Ry, Mx, My;
  805. X  int inL, inR, inM;
  806. X
  807. X
  808. X  *plon1 = lon1;
  809. X  *plon2 = lon2;
  810. X  *plat1 = lat1;
  811. X  *plat2 = lat2;
  812. X  clip_at1 = clip_at2 = NO_CLIP;
  813. X  xform(lat1, lon1, xloc1, yloc1, &Lisin);
  814. X  xform(lat2, lon2, xloc2, yloc2, &Risin);
  815. X  if (Lisin && Risin)        /* is already ok: case 1 */
  816. X    return TRUE;
  817. X
  818. X  if (great_circle && gt_use_boundaries) {
  819. X    /* Transform to gnomonic */
  820. X    do_gt(lat1, lon1, &x_1, &y_1, &theta_1);
  821. X    do_gt(lat2, lon2, &x_2, &y_2, &theta_2);
  822. X
  823. X    if ((theta_1 > 1.57) || (theta_2 > 1.57)) /* out of field, skip */
  824. X      return FALSE;
  825. X
  826. X    /* Find intersections with boundaries */
  827. X    switch (xfs_proj_mode) {
  828. X    case SANSONS:
  829. X    case RECTANGULAR:
  830. X      line_intersect(x_1, y_1, x_2, y_2, gt_wx1, gt_wy1, gt_wx2, gt_wy2,
  831. X             &xw, &yw, &int_w);
  832. X      line_intersect(x_1, y_1, x_2, y_2, gt_ex1, gt_ey1, gt_ex2, gt_ey2,
  833. X             &xe, &ye, &int_e);
  834. X
  835. X      if (gt_nb == 0.0) {          /* parabola */
  836. X    para_intersect(x_1, y_1, x_2, y_2, gt_na, gt_ny0,
  837. X               &xn, &yn, &int_n);
  838. X      } else {
  839. X    ellip_intersect(x_1, y_1, x_2, y_2, gt_na, gt_nb, gt_ny0,
  840. X            &xn, &yn, &int_n);
  841. X      }
  842. X
  843. X      if (gt_sb == 0.0) {          /* parabola */
  844. X    para_intersect(x_1, y_1, x_2, y_2, gt_sa, gt_sy0,
  845. X               &xs, &ys, &int_s);
  846. X      } else {
  847. X    ellip_intersect(x_1, y_1, x_2, y_2, gt_sa, gt_sb, gt_sy0,
  848. X            &xs, &ys, &int_s);
  849. X      }
  850. X      int_r1 = int_r2 = FALSE;
  851. X      break;
  852. X    case GNOMONIC:
  853. X      line_intersect(x_1, y_1, x_2, y_2, gt_wx1, gt_wy1, gt_wx2, gt_wy2,
  854. X             &xw, &yw, &int_w);
  855. X      line_intersect(x_1, y_1, x_2, y_2, gt_ex1, gt_ey1, gt_ex2, gt_ey2,
  856. X             &xe, &ye, &int_e);
  857. X      line_intersect(x_1, y_1, x_2, y_2, gt_ex2, gt_ey2, gt_wx2, gt_wy2,
  858. X             &xn, &yn, &int_n);
  859. X      line_intersect(x_1, y_1, x_2, y_2, gt_wx1, gt_wy1, gt_ex1, gt_ey1,
  860. X             &xs, &ys, &int_s);
  861. X      int_r1 = int_r2 = FALSE;
  862. X      break;
  863. X    case STEREOGR:
  864. X      circ_intersect(x_1, y_1, x_2, y_2, gt_r, &xr1, &yr1, &int_r1,
  865. X              &xr2, &yr2, &int_r2);
  866. X      int_w = int_n = int_s = int_e = FALSE;
  867. X    case ORTHOGR:
  868. X      break;
  869. X    default:                  /* error */
  870. X      break;
  871. X    };
  872. X
  873. X   if (!(!Lisin && !Risin)) {          /* case 2 */
  874. X      if (int_w) {
  875. X    x_1 = xw; y_1 = yw;
  876. X    if (Risin)
  877. X      clip_at1 = WEST_CLIP;
  878. X    else
  879. X      clip_at2 = WEST_CLIP;
  880. X      } else if (int_e) {
  881. X    x_1 = xe; y_1 = ye;
  882. X    if (Risin)
  883. X      clip_at1 = EAST_CLIP;
  884. X    else
  885. X      clip_at2 = EAST_CLIP;
  886. X      } else if (int_n) {
  887. X    x_1 = xn; y_1 = yn;
  888. X    if (Risin)
  889. X      clip_at1 = NORTH_CLIP;
  890. X    else
  891. X      clip_at2 = NORTH_CLIP;
  892. X      } else if (int_s) {
  893. X    x_1 = xs; y_1 = ys;
  894. X    if (Risin)
  895. X      clip_at1 = SOUTH_CLIP;
  896. X    else
  897. X      clip_at2 = SOUTH_CLIP;
  898. X      } else if (int_r1) {
  899. X    x_1 = xr1; y_1 = yr1;
  900. X    if (Risin)
  901. X      clip_at1 = RADIUS_CLIP;
  902. X    else
  903. X      clip_at2 = RADIUS_CLIP;
  904. X      } else {
  905. X/*    fprintf(stderr, "Error drawing vector\n");
  906. X    fprintf(stderr, "from (%.3f %.3f) to (%.3f %.3f)\n",
  907. X        lat1, lon1, lat2, lon2);*/
  908. X    return FALSE;
  909. X      };
  910. X      if (Lisin) {              /* Need to find new point 2 */
  911. X    inv_gt(x_1, y_1, plat2, plon2);
  912. X    xform(*plat2, *plon2, xloc2, yloc2, &inM);
  913. X      } else {                  /* Need to find new point 1 */
  914. X    inv_gt(x_1, y_1, plat1, plon1);
  915. X    xform(*plat1, *plon1, xloc1, yloc1, &inM);
  916. X      };
  917. X    } else {                  /* case 3 */
  918. X      if (int_w && int_e) {
  919. X    x_1 = xw; y_1 = yw;
  920. X    x_2 = xe; y_2 = ye;
  921. X    clip_at1 = WEST_CLIP;
  922. X    clip_at2 = EAST_CLIP;
  923. X      } else if (int_w && int_n) {
  924. X    x_1 = xw; y_1 = yw;
  925. X    x_2 = xn; y_2 = yn;
  926. X    clip_at1 = WEST_CLIP;
  927. X    clip_at2 = NORTH_CLIP;
  928. X      } else if (int_w && int_s) {
  929. X    x_1 = xw; y_1 = yw;
  930. X    x_2 = xs; y_2 = ys;
  931. X    clip_at1 = WEST_CLIP;
  932. X    clip_at2 = SOUTH_CLIP;
  933. X      } else if (int_e && int_n) {
  934. X    x_1 = xe; y_1 = ye;
  935. X    x_2 = xn; y_2 = yn;
  936. X    clip_at1 = EAST_CLIP;
  937. X    clip_at2 = NORTH_CLIP;
  938. X      } else if (int_e && int_s) {
  939. X    x_1 = xe; y_1 = ye;
  940. X    x_2 = xs; y_2 = ys;
  941. X    clip_at1 = EAST_CLIP;
  942. X    clip_at2 = SOUTH_CLIP;
  943. X      } else if (int_n && int_s) {
  944. X    x_1 = xn; y_1 = yn;
  945. X    x_2 = xs; y_2 = ys;
  946. X    clip_at1 = NORTH_CLIP;
  947. X    clip_at2 = SOUTH_CLIP;
  948. X      } else if (int_r1 && int_r2) {
  949. X    x_1 = xr1; y_1 = yr1;
  950. X    x_2 = xr2; y_2 = yr2;
  951. X    clip_at1 = clip_at2 = RADIUS_CLIP;
  952. X      } else return FALSE;
  953. X
  954. X      inv_gt(x_1, y_1, plat1, plon1);
  955. X      inv_gt(x_2, y_2, plat2, plon2);
  956. X      xform(*plat1, *plon1, xloc1, yloc1, &inM);
  957. X      xform(*plat2, *plon2, xloc2, yloc2, &inM);
  958. X    }
  959. X    return TRUE;
  960. X  } else {                  /* find boundaries by bisection */
  961. X
  962. X    if (!Lisin && !Risin)     /* is hopeless */
  963. X      return FALSE;
  964. X
  965. X    /* Now, one side is in, and the other out.  Make sure we won't have
  966. X       problems with crossing 0h */
  967. X    /* If the difference between lon1 and lon2 is greater than
  968. X       the difference if you subtract 360 from the larger,
  969. X       then shift the larger by 360 degrees */
  970. X
  971. X    if (fabs(MAX(lon1,lon2) - MIN(lon1,lon2))
  972. X    > fabs(MAX(lon1,lon2) - 360.0 - MIN(lon1,lon2)))
  973. X      if (lon2 > 180.0) lon2 -= 360.0;
  974. X      else lon1 -= 360.0;
  975. X
  976. X    Llat = lat1;
  977. X    Llon = lon1;
  978. X    Rlat = lat2;
  979. X    Rlon = lon2;
  980. X    xform(Llat, Llon, &Lx, &Ly, &inL);
  981. X    xform(Rlat, Rlon, &Rx, &Ry, &inR);
  982. X
  983. X
  984. X    /* One endpoint is in.
  985. X       Now use bisection to find point at edge */
  986. X    do {
  987. X      if (great_circle) {
  988. X    gcmidpoint(Llat, Llon, Rlat, Rlon, &Mlat, &Mlon);
  989. X      } else {
  990. X    Mlat = (Llat + Rlat) / 2.0;
  991. X    Mlon = (Llon + Rlon) / 2.0;
  992. X      };
  993. X      xform(Mlat, Mlon, &Mx, &My, &inM);
  994. X      
  995. X      if (inL)             /* L in R out */
  996. X    if (inM) {         /* between M and R */
  997. X      Llat = Mlat;
  998. X      Llon = Mlon;
  999. X      inL = inM;
  1000. X      Lx = Mx;
  1001. X      Ly = My;
  1002. X    } else {         /* between M and L */
  1003. X      Rlat = Mlat;
  1004. X      Rlon = Mlon;
  1005. X      inR = inM;
  1006. X      Rx = Mx;
  1007. X      Ry = My;
  1008. X    }
  1009. X      else             /* L out R in */
  1010. X    if (inM) {         /* between M and L */
  1011. X      Rlat = Mlat;
  1012. X      Rlon = Mlon;
  1013. X      inR = inM;
  1014. X      Rx = Mx;
  1015. X      Ry = My;
  1016. X    } else {         /* between M and R */
  1017. X      Llat = Mlat;
  1018. X      Llon = Mlon;
  1019. X      inL = inM;
  1020. X      Lx = Mx;
  1021. X      Ly = My;
  1022. X    };
  1023. X    } while ((fabs((Llat - Rlat)) > xf_c_scale) ||
  1024. X         (fabs((Llon - Rlon)) > xf_c_scale));
  1025. X
  1026. X    if (Lisin) {         /* Left point is in,
  1027. X                    bisection found right point */
  1028. X      *xloc2 = Lx;         /* Use Lx, Ly, since they're inside bounds */
  1029. X      *yloc2 = Ly;
  1030. X      *plon2 = Llon;
  1031. X      *plat2 = Llat;
  1032. X    } else {             /* Bisection found left point */
  1033. X      *xloc1 = Rx;         /* Use Rx, Ry, since they're inside bounds */
  1034. X      *yloc1 = Ry;
  1035. X      *plon1 = Rlon;
  1036. X      *plat1 = Rlat;
  1037. X    }
  1038. X
  1039. X    return TRUE;
  1040. X  }
  1041. X}
  1042. X
  1043. X/* For the macintosh using MPW C */
  1044. X#ifdef macintosh
  1045. X#pragma segment 3b
  1046. X#endif
  1047. X
  1048. X#define Fuz 0.1
  1049. X
  1050. X/* calculate and return the intersection point of two lines given
  1051. X   two points on each line */
  1052. Xline_intersect(x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4, x, y, int_1)
  1053. X     double x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4;
  1054. X     double *x, *y;
  1055. X     int *int_1;            /* FALSE if parallel */
  1056. X{
  1057. X  double a, b, c, d;
  1058. X  int x1, y1;
  1059. X  double lat_1, lon_1;
  1060. X  int in;
  1061. X
  1062. X  if (fabs(x_2 - x_1) > 1e-5) {    /* Slope may be calculated */
  1063. X    a = (y_2 - y_1)/(x_2 - x_1);
  1064. X    b = y_1 - a * x_1;
  1065. X    if ((fabs(x_4 - x_3) < 1e-5)) {    /* This slope is infinite */
  1066. X      /* calculate intersection */
  1067. X      *x = x_3;
  1068. X      *y = a*x_3 + b;
  1069. X      *int_1 = TRUE;
  1070. X    } else {                /* Both slopes may be calculated */
  1071. X      c = (y_4 - y_3)/(x_4 - x_3);
  1072. X      d = y_3 - c * x_3;
  1073. X      if (fabs(a - c) < 1e-5) {        /* Slopes the same, no intersection */
  1074. X    *int_1 = FALSE;
  1075. X      } else {                /* calculate intersection */
  1076. X    *x = (d - b)/(a - c);
  1077. X    *y = (a*d - b*c)/(a - c);
  1078. X    *int_1 = TRUE;
  1079. X      };
  1080. X    };
  1081. X  } else {                /* Slope is infinite */
  1082. X    if ((fabs(x_4 - x_3) < 1e-5)) {    /* this slope is also infinite */
  1083. X      *int_1 = FALSE;
  1084. X    } else {                /* There's an intersection */
  1085. X      c = (y_4 - y_3)/(x_4 - x_3);
  1086. X      d = y_3 - c * x_3;
  1087. X      *x = x_1;
  1088. X      *y = c*x_1 + d;
  1089. X      *int_1 = TRUE;
  1090. X    };
  1091. X  };
  1092. X
  1093. X  if (*int_1)
  1094. X    if (((((y_1-Fuz) <= *y) && (*y <= (y_2+Fuz)))
  1095. X     || (((y_2-Fuz) <= *y) && (*y <= (y_1+Fuz))))
  1096. X    && ((((x_1-Fuz) <= *x) && (*x <= (x_2+Fuz)))
  1097. X        || (((x_2-Fuz) <= *x) && (*x <= (x_1+Fuz)))))
  1098. X      *int_1 = TRUE;
  1099. X    else
  1100. X      *int_1 = FALSE;
  1101. X
  1102. X  if (*int_1) {
  1103. X    inv_gt(*x, *y, &lat_1, &lon_1);
  1104. X    xform(lat_1, lon_1, &x1, &y1, &in);
  1105. X    if (!in) *int_1 = FALSE;
  1106. X  }
  1107. X}
  1108. X
  1109. Xpara_intersect(x_1, y_1, x_2, y_2, a, b, x, y, int_1)
  1110. X     double x_1, y_1, x_2, y_2, *x, *y;
  1111. X     double a, b;        /* y = a*x*x + b */
  1112. X     int *int_1;
  1113. X{
  1114. X  double c, d;
  1115. END_OF_FILE
  1116. if test 31121 -ne `wc -c <'starchart/ssup.c.aa'`; then
  1117.     echo shar: \"'starchart/ssup.c.aa'\" unpacked with wrong size!
  1118. fi
  1119. # end of 'starchart/ssup.c.aa'
  1120. fi
  1121. echo shar: End of archive 19 \(of 32\).
  1122. cp /dev/null ark19isdone
  1123. MISSING=""
  1124. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ; do
  1125.     if test ! -f ark${I}isdone ; then
  1126.     MISSING="${MISSING} ${I}"
  1127.     fi
  1128. done
  1129. if test "${MISSING}" = "" ; then
  1130.     echo You have unpacked all 32 archives.
  1131.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1132. else
  1133.     echo You still need to unpack the following archives:
  1134.     echo "        " ${MISSING}
  1135. fi
  1136. ##  End of shell archive.
  1137. exit 0
  1138.  
  1139.  
  1140.