"Fossies" - the Fresh Open Source Software Archive 
Member "xearth-1.1/xearth.c" (7 Nov 1999, 31823 Bytes) of package /linux/misc/old/xearth-1.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * xearth.c
3 * kirk johnson
4 * july 1993
5 *
6 * Copyright (C) 1989, 1990, 1993-1995, 1999 Kirk Lauritz Johnson
7 *
8 * Parts of the source code (as marked) are:
9 * Copyright (C) 1989, 1990, 1991 by Jim Frost
10 * Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com>
11 *
12 * Permission to use, copy, modify and freely distribute xearth for
13 * non-commercial and not-for-profit purposes is hereby granted
14 * without fee, provided that both the above copyright notice and this
15 * permission notice appear in all copies and in supporting
16 * documentation.
17 *
18 * Unisys Corporation holds worldwide patent rights on the Lempel Zev
19 * Welch (LZW) compression technique employed in the CompuServe GIF
20 * image file format as well as in other formats. Unisys has made it
21 * clear, however, that it does not require licensing or fees to be
22 * paid for freely distributed, non-commercial applications (such as
23 * xearth) that employ LZW/GIF technology. Those wishing further
24 * information about licensing the LZW patent should contact Unisys
25 * directly at (lzw_info@unisys.com) or by writing to
26 *
27 * Unisys Corporation
28 * Welch Licensing Department
29 * M/S-C1SW19
30 * P.O. Box 500
31 * Blue Bell, PA 19424
32 *
33 * The author makes no representations about the suitability of this
34 * software for any purpose. It is provided "as is" without express or
35 * implied warranty.
36 *
37 * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
39 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
40 * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
41 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
42 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
43 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46 #include "xearth.h"
47 #include "kljcpyrt.h"
48 extern int errno;
49
50 #ifndef NO_SETPRIORITY
51 /* apparently some systems (possibly mt.xinu 4.3bsd?) may need
52 * <sys/time.h> to be included here before <sys/resource.h>.
53 */
54 #include <sys/resource.h> /* for setpriority() */
55 #endif
56
57 #define ModeX (0) /* possible output_mode values */
58 #define ModePPM (1)
59 #define ModeGIF (2)
60 #define ModeTest (3)
61
62 /* tokens in specifiers are delimited by spaces, tabs, commas, and
63 * forward slashes
64 */
65 #define IsTokenDelim(x) (((x)==' ')||((x)=='\t')||((x)==',')||((x)=='/'))
66 #define NotTokenDelim(x) (!IsTokenDelim(x))
67
68 int main _P((int, char *[]));
69 void set_priority _P((int));
70 void output _P((void));
71 void test_mode _P((void));
72 void sun_relative_position _P((double *, double *));
73 void simple_orbit _P((time_t, double *, double *));
74 void pick_random_position _P((double *, double *));
75 void set_defaults _P((void));
76 int using_x _P((int, char *[]));
77 void command_line _P((int, char *[]));
78
79 char *progname; /* program name */
80 int proj_type; /* projection type */
81 int output_mode; /* output mode (X, PPM, ...) */
82 double view_lon; /* viewing position longitude */
83 double view_lat; /* viewing position latitude */
84 double view_rot; /* viewing rotation (degrees) */
85 int rotate_type; /* type of rotation */
86 int view_pos_type; /* type of viewing position */
87 double sun_rel_lon; /* view lon, relative to sun */
88 double sun_rel_lat; /* view lat, relative to sun */
89 double orbit_period; /* orbit period (seconds) */
90 double orbit_inclin; /* orbit inclination (degrees) */
91 double view_mag; /* viewing magnification */
92 int do_shade; /* render with shading? */
93 double sun_lon; /* sun position longitude */
94 double sun_lat; /* sun position latitude */
95 int compute_sun_pos; /* compute sun's position? */
96 int wdth; /* image width (pixels) */
97 int hght; /* image height (pixels) */
98 int shift_x; /* image shift (x, pixels) */
99 int shift_y; /* image shift (y, pixels) */
100 int do_stars; /* show stars in background? */
101 double star_freq; /* frequency of stars */
102 int big_stars; /* percent of doublewide stars */
103 int do_grid; /* show lon/lat grid? */
104 int grid_big; /* lon/lat grid line spacing */
105 int grid_small; /* dot spacing along grids */
106 int do_label; /* label image */
107 int do_markers; /* display markers (X only) */
108 char *markerfile; /* for user-spec. marker info */
109 int wait_time; /* wait time between redraw */
110 double time_warp; /* passage of time multiplier */
111 int fixed_time; /* fixed viewing time (ssue) */
112 int day; /* day side brightness (%) */
113 int night; /* night side brightness (%) */
114 int terminator; /* terminator discontinuity, % */
115 double xgamma; /* gamma correction (X only) */
116 int use_two_pixmaps; /* use two pixmaps? (X only) */
117 int num_colors; /* number of colors to use */
118 int do_fork; /* fork child process? */
119 int priority; /* desired process priority */
120
121 time_t start_time = 0;
122 time_t current_time;
123 char errmsgbuf[1024]; /* for formatting warning/error msgs */
124
125
126 int main(argc, argv)
127 int argc;
128 char *argv[];
129 {
130 set_defaults();
131
132 if (using_x(argc, argv))
133 command_line_x(argc, argv);
134 else
135 command_line(argc, argv);
136
137 if (priority != 0)
138 set_priority(priority);
139
140 srandom(((int) time(NULL)) + ((int) getpid()));
141
142 output();
143
144 return 0;
145 }
146
147
148 #ifdef NO_SETPRIORITY
149
150 /* setpriority()-like functionality for System V
151 * derivates that only provide nice()
152 */
153 void set_priority(new)
154 int new;
155 {
156 int old;
157
158 /* determine current priority of the process
159 */
160 errno = 0;
161 old = nice(0);
162 if ((old == -1) && (errno != 0))
163 {
164 perror("nice");
165 exit(-1);
166 }
167
168 /* try to change priority to new
169 */
170 new = nice(new - old);
171 if ((new == -1) && (errno != 0))
172 {
173 perror("nice");
174 exit(-1);
175 }
176 }
177
178 #else /* NO_SETPRIORITY */
179
180 /* for systems that provide setpriority(),
181 * set_priority() is just a wrapper
182 */
183 void set_priority(new)
184 int new;
185 {
186 if ((setpriority(PRIO_PROCESS, getpid(), new) == -1))
187 {
188 perror("setpriority");
189 exit(-1);
190 }
191 }
192
193 #endif /* NO_SETPRIORITY */
194
195
196 void output()
197 {
198 switch (output_mode)
199 {
200 case ModePPM:
201 ppm_output();
202 break;
203
204 case ModeGIF:
205 gif_output();
206 break;
207
208 case ModeX:
209 if ((!do_fork) || (fork() == 0))
210 x11_output();
211 break;
212
213 case ModeTest:
214 test_mode();
215 break;
216
217 default:
218 assert(0);
219 }
220 }
221
222
223 void test_mode()
224 {
225 }
226
227
228 void compute_positions()
229 {
230 /* determine "current" time
231 */
232 if (fixed_time == 0)
233 {
234 current_time = time(NULL);
235 if (start_time == 0)
236 start_time = current_time;
237 else
238 current_time = start_time + (current_time - start_time) * time_warp;
239 }
240 else
241 {
242 current_time = fixed_time;
243 }
244
245 /* determine position on earth's surface where sun is directly
246 * overhead
247 */
248 if (compute_sun_pos)
249 sun_position(current_time, &sun_lat, &sun_lon);
250
251 /* determine viewing position
252 */
253 if (view_pos_type == ViewPosTypeSun)
254 {
255 sun_relative_position(&view_lat, &view_lon);
256 }
257 else if (view_pos_type == ViewPosTypeOrbit)
258 {
259 simple_orbit(current_time, &view_lat, &view_lon);
260 }
261 else if (view_pos_type == ViewPosTypeRandom)
262 {
263 pick_random_position(&view_lat, &view_lon);
264 }
265 else if (view_pos_type == ViewPosTypeMoon)
266 {
267 moon_position(current_time, &view_lat, &view_lon);
268 }
269
270 /* for ViewRotGalactic, compute appropriate viewing rotation
271 */
272 if (rotate_type == ViewRotGalactic)
273 {
274 view_rot = sun_lat * sin((view_lon - sun_lon) * (M_PI / 180));
275 }
276 }
277
278
279 void sun_relative_position(lat_ret, lon_ret)
280 double *lat_ret; /* (return) latitude */
281 double *lon_ret; /* (return) longitude */
282 {
283 double lat, lon;
284
285 lat = sun_lat + sun_rel_lat;
286 lon = sun_lon + sun_rel_lon;
287
288 /* sanity check */
289 assert((lat >= -180) && (lat <= 180));
290 assert((lon >= -360) && (lon <= 360));
291
292 if (lat > 90)
293 {
294 lat = 180 - lat;
295 lon += 180;
296 }
297 else if (lat < -90)
298 {
299 lat = -180 - lat;
300 lon += 180;
301 }
302
303 if (lon > 180)
304 {
305 do
306 lon -= 360;
307 while (lon > 180);
308 }
309 else if (lon < -180)
310 {
311 do
312 lon += 360;
313 while (lon < -180);
314 }
315
316 *lat_ret = lat;
317 *lon_ret = lon;
318 }
319
320
321 void simple_orbit(ssue, lat, lon)
322 time_t ssue; /* seconds since unix epoch */
323 double *lat; /* (return) latitude */
324 double *lon; /* (return) longitude */
325 {
326 double x, y, z;
327 double a, c, s;
328 double t1, t2;
329
330 /* start at 0 N 0 E */
331 x = 0;
332 y = 0;
333 z = 1;
334
335 /* rotate in about y axis (from z towards x) according to the number
336 * of orbits we've completed
337 */
338 a = ((double) ssue / orbit_period) * (2*M_PI);
339 c = cos(a);
340 s = sin(a);
341 t1 = c*z - s*x;
342 t2 = s*z + c*x;
343 z = t1;
344 x = t2;
345
346 /* rotate about z axis (from x towards y) according to the
347 * inclination of the orbit
348 */
349 a = orbit_inclin * (M_PI/180);
350 c = cos(a);
351 s = sin(a);
352 t1 = c*x - s*y;
353 t2 = s*x + c*y;
354 x = t1;
355 y = t2;
356
357 /* rotate about y axis (from x towards z) according to the number of
358 * rotations the earth has made
359 */
360 a = ((double) ssue / EarthPeriod) * (2*M_PI);
361 c = cos(a);
362 s = sin(a);
363 t1 = c*x - s*z;
364 t2 = s*x + c*z;
365 x = t1;
366 z = t2;
367
368 *lat = asin(y) * (180/M_PI);
369 *lon = atan2(x, z) * (180/M_PI);
370 }
371
372
373 /* pick a position (lat, lon) at random
374 */
375 void pick_random_position(lat_ret, lon_ret)
376 double *lat_ret; /* (return) latitude */
377 double *lon_ret; /* (return) longitude */
378 {
379 int i;
380 double pos[3];
381 double mag;
382 double s_lat, c_lat;
383 double s_lon, c_lon;
384
385 /* select a vector at random */
386 do
387 {
388 mag = 0;
389 for (i=0; i<3; i++)
390 {
391 pos[i] = ((random() % 20001) * 1e-4) - 1;
392 mag += pos[i] * pos[i];
393 }
394 } while ((mag > 1.0) || (mag < 0.01));
395
396 /* normalize the vector */
397 mag = sqrt(mag);
398 for (i=0; i<3; i++)
399 pos[i] /= mag;
400
401 /* convert to (lat, lon) */
402 s_lat = pos[1];
403 c_lat = sqrt(1 - s_lat*s_lat);
404 s_lon = pos[0] / c_lat;
405 c_lon = pos[2] / c_lat;
406
407 *lat_ret = atan2(s_lat, c_lat) * (180/M_PI);
408 *lon_ret = atan2(s_lon, c_lon) * (180/M_PI);
409 }
410
411
412 /* look through the command line arguments to figure out if we're
413 * using X or not (if "-ppm", "-gif", or "-test" is found, we're not
414 * using X, otherwise we are).
415 */
416 int using_x(argc, argv)
417 int argc;
418 char *argv[];
419 {
420 int i;
421
422 /* loop through the args, break if we find "-ppm", "-gif", or
423 * "-test"
424 */
425 for (i=1; i<argc; i++)
426 if ((strcmp(argv[i], "-ppm") == 0) ||
427 (strcmp(argv[i], "-gif") == 0) ||
428 (strcmp(argv[i], "-test") == 0))
429 break;
430
431 /* if we made it through the loop without finding "-ppm", "-gif", or
432 * "-test" (and breaking out), assume we're using X.
433 */
434 return (i == argc);
435 }
436
437
438 /* set_defaults() gets called at xearth startup (before command line
439 * arguments are handled), regardless of what output mode (x, ppm,
440 * gif) is being used.
441 */
442 void set_defaults()
443 {
444 output_mode = ModeX;
445 proj_type = ProjTypeOrthographic;
446 view_pos_type = ViewPosTypeSun;
447 sun_rel_lat = 0;
448 sun_rel_lon = 0;
449 compute_sun_pos = 1;
450 view_rot = 0;
451 rotate_type = ViewRotNorth;
452 wdth = DefaultWdthHght;
453 hght = DefaultWdthHght;
454 shift_x = 0;
455 shift_y = 0;
456 view_mag = 1.0;
457 do_shade = 1;
458 do_label = 0;
459 do_markers = 1;
460 wait_time = 300;
461 time_warp = 1;
462 day = 100;
463 night = 5;
464 terminator = 1;
465 use_two_pixmaps = 1;
466 num_colors = 64;
467 do_fork = 0;
468 priority = 0;
469 do_stars = 1;
470 star_freq = 0.002;
471 big_stars = 0;
472 do_grid = 0;
473 grid_big = 6;
474 grid_small = 15;
475 fixed_time = 0;
476 xgamma = 1.0;
477 }
478
479
480 /* procedure for interpreting command line arguments when we're not
481 * using X; command_line_x() is used when we are.
482 */
483 void command_line(argc, argv)
484 int argc;
485 char *argv[];
486 {
487 int i;
488
489 progname = argv[0];
490
491 for (i=1; i<argc; i++)
492 {
493 if (strcmp(argv[i], "-proj") == 0)
494 {
495 i += 1;
496 if (i >= argc) usage("missing arg to -proj");
497 decode_proj_type(argv[i]);
498 }
499 else if (strcmp(argv[i], "-pos") == 0)
500 {
501 i += 1;
502 if (i >= argc) usage("missing arg to -pos");
503 decode_viewing_pos(argv[i]);
504 }
505 else if (strcmp(argv[i], "-rot") == 0)
506 {
507 i += 1;
508 if (i >= argc) usage("missing arg to -rot");
509 decode_rotation(argv[i]);
510 }
511 else if (strcmp(argv[i], "-sunpos") == 0)
512 {
513 i += 1;
514 if (i >= argc) usage("missing arg to -sunpos");
515 decode_sun_pos(argv[i]);
516 }
517 else if (strcmp(argv[i], "-mag") == 0)
518 {
519 i += 1;
520 if (i >= argc) usage("missing arg to -mag");
521 sscanf(argv[i], "%lf", &view_mag);
522 if (view_mag <= 0)
523 fatal("viewing magnification must be positive");
524 }
525 else if (strcmp(argv[i], "-size") == 0)
526 {
527 i += 1;
528 if (i >= argc) usage("missing arg to -size");
529 decode_size(argv[i]);
530 }
531 else if (strcmp(argv[i], "-shift") == 0)
532 {
533 i += 1;
534 if (i >= argc) usage("missing arg to -shift");
535 decode_shift(argv[i]);
536 }
537 else if (strcmp(argv[i], "-shade") == 0)
538 {
539 do_shade = 1;
540 }
541 else if (strcmp(argv[i], "-noshade") == 0)
542 {
543 do_shade = 0;
544 }
545 else if (strcmp(argv[i], "-label") == 0)
546 {
547 do_label = 1;
548 warning("labeling not supported with GIF and PPM output");
549 }
550 else if (strcmp(argv[i], "-nolabel") == 0)
551 {
552 do_label = 0;
553 }
554 else if (strcmp(argv[i], "-labelpos") == 0)
555 {
556 i += 1;
557 if (i >= argc) usage("missing arg to -labelpos");
558 warning("-labelpos not relevant for GIF or PPM output");
559 }
560 else if (strcmp(argv[i], "-markers") == 0)
561 {
562 do_markers = 1;
563 warning("markers not supported with GIF and PPM output");
564 }
565 else if (strcmp(argv[i], "-nomarkers") == 0)
566 {
567 do_markers = 0;
568 }
569 else if (strcmp(argv[i], "-markerfile") == 0)
570 {
571 i += 1;
572 if (i >= argc) usage("missing arg to -markerfile");
573 warning("-markerfile not relevant for GIF or PPM output");
574 }
575 else if (strcmp(argv[i], "-showmarkers") == 0)
576 {
577 warning("-showmarkers not relevant for GIF or PPM output");
578 }
579 else if (strcmp(argv[i], "-stars") == 0)
580 {
581 do_stars = 1;
582 }
583 else if (strcmp(argv[i], "-nostars") == 0)
584 {
585 do_stars = 0;
586 }
587 else if (strcmp(argv[i], "-starfreq") == 0)
588 {
589 i += 1;
590 if (i >= argc) usage("missing arg to -starfreq");
591 sscanf(argv[i], "%lf", &star_freq);
592 if ((star_freq < 0) || (star_freq > 1))
593 fatal("arg to -starfreq must be between 0 and 1");
594 }
595 else if (strcmp(argv[i], "-bigstars") == 0)
596 {
597 i += 1;
598 if (i >= argc) usage("missing arg to -bigstars");
599 sscanf(argv[i], "%d", &big_stars);
600 if ((big_stars < 0) || (big_stars > 100))
601 fatal("arg to -bigstars must be between 0 and 100");
602 }
603 else if (strcmp(argv[i], "-grid") == 0)
604 {
605 do_grid = 1;
606 }
607 else if (strcmp(argv[i], "-nogrid") == 0)
608 {
609 do_grid = 0;
610 }
611 else if (strcmp(argv[i], "-grid1") == 0)
612 {
613 i += 1;
614 if (i >= argc) usage("missing arg to -grid1");
615 sscanf(argv[i], "%d", &grid_big);
616 if (grid_big <= 0)
617 fatal("arg to -grid1 must be positive");
618 }
619 else if (strcmp(argv[i], "-grid2") == 0)
620 {
621 i += 1;
622 if (i >= argc) usage("missing arg to -grid2");
623 sscanf(argv[i], "%d", &grid_small);
624 if (grid_small <= 0)
625 fatal("arg to -grid2 must be positive");
626 }
627 else if (strcmp(argv[i], "-day") == 0)
628 {
629 i += 1;
630 if (i >= argc) usage("missing arg to -day");
631 sscanf(argv[i], "%d", &day);
632 if ((day > 100) || (day < 0))
633 fatal("arg to -day must be between 0 and 100");
634 }
635 else if (strcmp(argv[i], "-night") == 0)
636 {
637 i += 1;
638 if (i >= argc) usage("missing arg to -night");
639 sscanf(argv[i], "%d", &night);
640 if ((night > 100) || (night < 0))
641 fatal("arg to -night must be between 0 and 100");
642 }
643 else if (strcmp(argv[i], "-term") == 0)
644 {
645 i += 1;
646 if (i >= argc) usage("missing arg to -term");
647 sscanf(argv[i], "%d", &terminator);
648 if ((terminator > 100) || (terminator < 0))
649 fatal("arg to -term must be between 0 and 100");
650 }
651 else if (strcmp(argv[i], "-gamma") == 0)
652 {
653 i += 1;
654 if (i >= argc) usage("missing arg to -gamma");
655 sscanf(argv[i], "%lf", &xgamma);
656 if (xgamma <= 0)
657 fatal("arg to -gamma must be positive");
658 warning("gamma correction not supported with GIF and PPM output");
659 }
660 else if (strcmp(argv[i], "-wait") == 0)
661 {
662 i += 1;
663 if (i >= argc) usage("missing arg to -wait");
664 sscanf(argv[i], "%d", &wait_time);
665 if (wait_time < 0)
666 fatal("arg to -wait must be non-negative");
667 }
668 else if (strcmp(argv[i], "-timewarp") == 0)
669 {
670 i += 1;
671 if (i >= argc) usage("missing arg to -timewarp");
672 sscanf(argv[i], "%lf", &time_warp);
673 if (time_warp <= 0)
674 fatal("arg to -timewarp must be positive");
675 }
676 else if (strcmp(argv[i], "-time") == 0)
677 {
678 i += 1;
679 if (i >= argc) usage("missing arg to -time");
680 sscanf(argv[i], "%d", &fixed_time);
681 }
682 else if (strcmp(argv[i], "-onepix") == 0)
683 {
684 use_two_pixmaps = 0;
685 warning("-onepix not relevant for GIF or PPM output");
686 }
687 else if (strcmp(argv[i], "-twopix") == 0)
688 {
689 use_two_pixmaps = 1;
690 warning("-twopix not relevant for GIF or PPM output");
691 }
692 else if (strcmp(argv[i], "-mono") == 0)
693 {
694 warning("monochrome mode not supported with GIF and PPM output");
695 }
696 else if (strcmp(argv[i], "-nomono") == 0)
697 {
698 warning("monochrome mode not supported with GIF and PPM output");
699 }
700 else if (strcmp(argv[i], "-ncolors") == 0)
701 {
702 i += 1;
703 if (i >= argc) usage("missing arg to -ncolors");
704 sscanf(argv[i], "%d", &num_colors);
705 if ((num_colors < 3) || (num_colors > 1024))
706 fatal("arg to -ncolors must be between 3 and 1024");
707 }
708 else if (strcmp(argv[i], "-font") == 0)
709 {
710 i += 1;
711 if (i >= argc) usage("missing arg to -font");
712 warning("-font not relevant for GIF or PPM output");
713 }
714 else if (strcmp(argv[i], "-root") == 0)
715 {
716 warning("-root not relevant for GIF or PPM output");
717 }
718 else if (strcmp(argv[i], "-noroot") == 0)
719 {
720 warning("-noroot not relevant for GIF or PPM output");
721 }
722 else if (strcmp(argv[i], "-geometry") == 0)
723 {
724 warning("-geometry not relevant for GIF or PPM output");
725 }
726 else if (strcmp(argv[i], "-title") == 0)
727 {
728 warning("-title not relevant for GIF or PPM output");
729 }
730 else if (strcmp(argv[i], "-iconname") == 0)
731 {
732 warning("-iconname not relevant for GIF or PPM output");
733 }
734 else if (strcmp(argv[i], "-name") == 0)
735 {
736 warning("-name not relevant for GIF or PPM output");
737 }
738 else if (strcmp(argv[i], "-fork") == 0)
739 {
740 do_fork = 1;
741 }
742 else if (strcmp(argv[i], "-nofork") == 0)
743 {
744 do_fork = 0;
745 }
746 else if (strcmp(argv[i], "-once") == 0)
747 {
748 warning("-once not relevant for GIF or PPM output");
749 }
750 else if (strcmp(argv[i], "-noonce") == 0)
751 {
752 warning("-once not relevant for GIF or PPM output");
753 }
754 else if (strcmp(argv[i], "-nice") == 0)
755 {
756 i += 1;
757 if (i >= argc) usage("missing arg to -nice");
758 sscanf(argv[i], "%d", &priority);
759 }
760 else if (strcmp(argv[i], "-version") == 0)
761 {
762 version_info(1);
763 }
764 else if (strcmp(argv[i], "-ppm") == 0)
765 {
766 output_mode = ModePPM;
767 }
768 else if (strcmp(argv[i], "-gif") == 0)
769 {
770 output_mode = ModeGIF;
771 }
772 else if (strcmp(argv[i], "-test") == 0)
773 {
774 output_mode = ModeTest;
775 }
776 else if (strcmp(argv[i], "-display") == 0)
777 {
778 warning("-display not relevant for GIF or PPM output");
779 }
780 else
781 {
782 usage(NULL);
783 }
784 }
785 }
786
787
788 /* if efficiency really mattered here (which it doesn't), this code
789 * could definitely be made quite a bit more efficient.
790 */
791 char **tokenize(s, argc_ret, msg)
792 char *s;
793 int *argc_ret;
794 const char **msg;
795 {
796 int lim;
797 int argc;
798 char **argv;
799
800 *msg = NULL;
801 lim = 4;
802 argc = 0;
803 argv = (char **) malloc((unsigned) sizeof(char *) * lim);
804 assert(argv != NULL);
805
806 while (1)
807 {
808 /* skip delimiters (space, tab, comma, forward slash)
809 */
810 while (1)
811 {
812 if (NotTokenDelim(*s)) break;
813 *s = '\0';
814 s += 1;
815 }
816
817 if ((*s) == '\0')
818 {
819 /* if we're at the end of s, no more tokens
820 */
821 break;
822 }
823 else if ((*s) == '#')
824 {
825 /* if we find a comment character (#), replace it
826 * with a NUL and act like we found the end s
827 */
828 *s = '\0';
829 break;
830 }
831
832 /* make sure there's room for another token
833 */
834 if (argc == lim)
835 {
836 lim *= 2;
837 argv = (char **) realloc(argv, (unsigned) sizeof(char *) * lim);
838 assert(argv != NULL);
839 }
840
841 /* get the next token
842 */
843 if ((*s) == '"')
844 {
845 /* string token
846 */
847 *s = '\0';
848 s += 1;
849 argv[argc++] = s;
850
851 while (((*s) != '"') && ((*s) != '\0'))
852 s += 1;
853
854 if ((*s) == '\0')
855 {
856 /* oops, never found closing double quote
857 */
858 *msg = "unterminated string (missing \")";
859 }
860 else
861 {
862 /* string token terminated normally
863 */
864 *s = '\0';
865 s += 1;
866 }
867 }
868 else
869 {
870 /* normal token
871 */
872 argv[argc++] = s;
873
874 while (NotTokenDelim(*s) &&
875 ((*s) != '#') && ((*s) != '"') && ((*s) != '\0'))
876 s += 1;
877 }
878 }
879
880 *argc_ret = argc;
881 return argv;
882 }
883
884
885 /* decode projection type; three possibilities:
886 * orthographic - orthographic projection (short form: orth)
887 * mercator - mercator projection (short form: merc)
888 * cylindrical - cylindrical projection (short form: cyl)
889 */
890 void decode_proj_type(s)
891 char *s;
892 {
893 if ((strcmp(s, "orthographic") == 0) || (strcmp(s, "orth") == 0))
894 {
895 proj_type = ProjTypeOrthographic;
896 }
897 else if ((strcmp(s, "mercator") == 0) || (strcmp(s, "merc") == 0))
898 {
899 proj_type = ProjTypeMercator;
900 }
901 else if ((strcmp(s, "cylindrical") == 0) || (strcmp(s, "cyl") == 0))
902 {
903 proj_type = ProjTypeCylindrical;
904 }
905 else
906 {
907 sprintf(errmsgbuf, "unknown projection type (%s)", s);
908 fatal(errmsgbuf);
909 }
910 }
911
912
913 /* decode viewing position specifier; five possibilities:
914 *
915 * fixed lat lon - viewing position fixed wrt earth at (lat, lon)
916 *
917 * sunrel lat lon - viewing position fixed wrt sun at (lat, lon)
918 * [position interpreted as if sun was at (0, 0)]
919 *
920 * orbit per inc - moving viewing position following simple orbit
921 * with period per and inclination inc
922 *
923 * random - random viewing position
924 *
925 * moon - current location of the moon
926 *
927 * fields can be separated with either spaces, commas, or slashes.
928 */
929 void decode_viewing_pos(s)
930 char *s;
931 {
932 int argc;
933 char **argv;
934 const char *msg;
935 double arg1;
936 double arg2;
937
938 argv = tokenize(s, &argc, &msg);
939 if (msg != NULL)
940 {
941 sprintf(errmsgbuf, "viewing position specifier: %s", msg);
942 warning(errmsgbuf);
943 }
944
945 if (argc == 3)
946 {
947 arg1 = 0;
948 arg2 = 0;
949 sscanf(argv[1], "%lf", &arg1);
950 sscanf(argv[2], "%lf", &arg2);
951 }
952
953 if (strcmp(argv[0], "fixed") == 0)
954 {
955 if (argc != 3)
956 fatal("wrong number of args in viewing position specifier");
957
958 view_lat = arg1;
959 view_lon = arg2;
960 view_pos_type = ViewPosTypeFixed;
961
962 if ((view_lat > 90) || (view_lat < -90))
963 fatal("viewing latitude must be between -90 and 90");
964 if ((view_lon > 180) || (view_lon < -180))
965 fatal("viewing longitude must be between -180 and 180");
966 }
967 else if (strcmp(argv[0], "sunrel") == 0)
968 {
969 if (argc != 3)
970 fatal("wrong number of args in viewing position specifier");
971
972 sun_rel_lat = arg1;
973 sun_rel_lon = arg2;
974 view_pos_type = ViewPosTypeSun;
975
976 if ((sun_rel_lat > 90) || (sun_rel_lat < -90))
977 fatal("latitude relative to sun must be between -90 and 90");
978 if ((sun_rel_lon > 180) || (sun_rel_lon < -180))
979 fatal("longitude relative to sun must be between -180 and 180");
980 }
981 else if (strcmp(argv[0], "orbit") == 0)
982 {
983 if (argc != 3)
984 fatal("wrong number of args in viewing position specifier");
985
986 orbit_period = arg1 * 3600;
987 orbit_inclin = arg2;
988 view_pos_type = ViewPosTypeOrbit;
989
990 if (orbit_period <= 0)
991 fatal("orbital period must be positive");
992 if ((orbit_inclin > 90) || (orbit_inclin < -90))
993 fatal("orbital inclination must be between -90 and 90");
994 }
995 else if (strcmp(argv[0], "random") == 0)
996 {
997 if (argc != 1)
998 fatal("wrong number of args in viewing position specifier");
999
1000 view_pos_type = ViewPosTypeRandom;
1001 }
1002 else if (strcmp(argv[0], "moon") == 0)
1003 {
1004 if (argc != 1)
1005 fatal("wrong number of args in viewing position specifier");
1006
1007 view_pos_type = ViewPosTypeMoon;
1008 }
1009 else
1010 {
1011 fprintf(stderr, "`%s'\n", argv[0]);
1012 fatal("unrecognized keyword in viewing position specifier");
1013 }
1014
1015 free(argv);
1016 }
1017
1018
1019 /* decode rotation; two possibilities:
1020 *
1021 * <angle> - in degrees
1022 * galactic - galactic north
1023 */
1024 void decode_rotation(s)
1025 char *s;
1026 {
1027 int argc;
1028 char **argv;
1029 const char *msg;
1030
1031 argv = tokenize (s, &argc, &msg);
1032 if (msg != NULL)
1033 {
1034 sprintf(errmsgbuf, "rotation specifier: %s", msg);
1035 warning(errmsgbuf);
1036 }
1037 if (argc != 1)
1038 fatal("wrong number of args in rotation specifier");
1039
1040 if (strcmp (argv[0], "galactic") == 0)
1041 {
1042 rotate_type = ViewRotGalactic;
1043 }
1044 else
1045 {
1046 sscanf (argv[0], "%lf", &view_rot);
1047 if ((view_rot < -180) || (view_rot > 360))
1048 fatal("viewing rotation must be between -180 and 360");
1049 }
1050
1051 free (argv);
1052 }
1053
1054
1055 /* decode sun position specifier:
1056 *
1057 * lat lon - sun position fixed wrt earth at (lat, lon)
1058 *
1059 * fields can be separated with either spaces, commas, or slashes.
1060 */
1061 void decode_sun_pos(s)
1062 char *s;
1063 {
1064 int argc;
1065 char **argv;
1066 const char *msg;
1067
1068 argv = tokenize(s, &argc, &msg);
1069 if (msg != NULL)
1070 {
1071 sprintf(errmsgbuf, "sun position specifier: %s", msg);
1072 warning(errmsgbuf);
1073 }
1074
1075 if (argc != 2)
1076 fatal("wrong number of args in sun position specifier");
1077
1078 sscanf(argv[0], "%lf", &sun_lat);
1079 sscanf(argv[1], "%lf", &sun_lon);
1080
1081 if ((sun_lat > 90) || (sun_lat < -90))
1082 fatal("sun latitude must be between -90 and 90");
1083 if ((sun_lon > 180) || (sun_lon < -180))
1084 fatal("sun longitude must be between -180 and 180");
1085
1086 compute_sun_pos = 0;
1087
1088 free(argv);
1089 }
1090
1091
1092 /* decode size specifier:
1093 *
1094 * width height - width and height of image (in pixels)
1095 *
1096 * fields can be separated with either spaces, commas, or slashes.
1097 */
1098 void decode_size(s)
1099 char *s;
1100 {
1101 int argc;
1102 char **argv;
1103 const char *msg;
1104
1105 argv = tokenize(s, &argc, &msg);
1106 if (msg != NULL)
1107 {
1108 sprintf(errmsgbuf, "size specifier: %s", msg);
1109 warning(errmsgbuf);
1110 }
1111
1112 if (argc != 2)
1113 fatal("wrong number of args in size specifier");
1114
1115 sscanf(argv[0], "%d", &wdth);
1116 sscanf(argv[1], "%d", &hght);
1117
1118 if (wdth <= 0)
1119 fatal("wdth arg must be positive");
1120 if (hght <= 0)
1121 fatal("hght arg must be positive");
1122
1123 free(argv);
1124 }
1125
1126
1127 /* decode shift specifier:
1128 *
1129 * xofs yofs - offset in x and y dimensions
1130 *
1131 * fields can be separated with either spaces, commas, or slashes.
1132 */
1133 void decode_shift(s)
1134 char *s;
1135 {
1136 int argc;
1137 char **argv;
1138 const char *msg;
1139
1140 argv = tokenize(s, &argc, &msg);
1141 if (msg != NULL)
1142 {
1143 sprintf(errmsgbuf, "shift specifier: %s", msg);
1144 warning(errmsgbuf);
1145 }
1146
1147 if (argc != 2)
1148 fatal("wrong number of args in shift specifier");
1149
1150 sscanf(argv[0], "%d", &shift_x);
1151 sscanf(argv[1], "%d", &shift_y);
1152
1153 free(argv);
1154 }
1155
1156
1157 void xearth_bzero(buf, len)
1158 char *buf;
1159 unsigned len;
1160 {
1161 int *tmp;
1162
1163 /* assume sizeof(int) is a power of two
1164 */
1165 assert((sizeof(int) == 4) || (sizeof(int) == 8));
1166
1167 if (len < sizeof(int))
1168 {
1169 /* special case small regions
1170 */
1171 while (len > 0)
1172 {
1173 *buf = 0;
1174 buf += 1;
1175 len -= 1;
1176 }
1177 }
1178 else
1179 {
1180 /* zero leading non-word-aligned bytes
1181 */
1182 while (((long) buf) & (sizeof(int)-1))
1183 {
1184 *buf = 0;
1185 buf += 1;
1186 len -= 1;
1187 }
1188
1189 /* zero trailing non-word-aligned bytes
1190 */
1191 while (len & (sizeof(int)-1))
1192 {
1193 len -= 1;
1194 buf[len] = 0;
1195 }
1196
1197 /* convert remaining len to words
1198 */
1199 tmp = (int *) buf;
1200 if (sizeof(int) == 4)
1201 len >>= 2;
1202 else if (sizeof(int) == 8)
1203 len >>= 3;
1204 else
1205 assert(0);
1206
1207 /* zero trailing non-quadword-aligned words
1208 */
1209 while (len & 0x03)
1210 {
1211 len -= 1;
1212 tmp[len] = 0;
1213 }
1214
1215 /* zero remaining data four words at a time
1216 */
1217 while (len)
1218 {
1219 tmp[0] = 0;
1220 tmp[1] = 0;
1221 tmp[2] = 0;
1222 tmp[3] = 0;
1223 tmp += 4;
1224 len -= 4;
1225 }
1226 }
1227 }
1228
1229
1230 void version_info(flag)
1231 int flag;
1232 {
1233 fflush(stdout);
1234 fprintf(stderr, "\n");
1235 fprintf(stderr, "This is xearth version %s.\n", VersionString);
1236 fprintf(stderr, "(Home page URL: %s)\n", HomePageURL);
1237 fprintf(stderr, "\n");
1238
1239 if (flag) exit(0);
1240 }
1241
1242
1243 void usage(msg)
1244 const char *msg;
1245 {
1246 version_info(0);
1247 if (msg != NULL)
1248 fprintf(stderr, "%s\n", msg);
1249 fprintf(stderr, "usage: %s\n", progname);
1250 fprintf(stderr, " [-proj proj_type] [-pos pos_spec] [-rot angle]\n");
1251 fprintf(stderr, " [-sunpos sun_pos_spec] [-mag factor] [-size size_spec]\n");
1252 fprintf(stderr, " [-shift shift_spec] [-shade|-noshade] [-label|-nolabel]\n");
1253 fprintf(stderr, " [-labelpos geom] [-markers|-nomarkers] [-markerfile file]\n");
1254 fprintf(stderr, " [-showmarkers] [-stars|-nostars] [-starfreq frequency]\n");
1255 fprintf(stderr, " [-bigstars percent] [-grid|-nogrid] [-grid1 grid1] [-grid2 grid2]\n");
1256 fprintf(stderr, " [-day pct] [-night pct] [-term pct] [-gamma gamma_value]\n");
1257 fprintf(stderr, " [-wait secs] [-timewarp factor] [-time fixed_time]\n");
1258 fprintf(stderr, " [-onepix|-twopix] [-mono|-nomono] [-ncolors num_colors]\n");
1259 fprintf(stderr, " [-font font_name] [-root|-noroot] [-geometry geom] [-title title]\n");
1260 fprintf(stderr, " [-iconname iconname] [-name name] [-fork|-nofork] [-once|-noonce]\n");
1261 fprintf(stderr, " [-nice priority] [-gif] [-ppm] [-display dpyname] [-version]\n");
1262 fprintf(stderr, "\n");
1263 exit(1);
1264 }
1265
1266
1267 void warning(msg)
1268 const char *msg;
1269 {
1270 fflush(stdout);
1271 fprintf(stderr, "xearth %s: warning - %s\n", VersionString, msg);
1272 fflush(stderr);
1273 }
1274
1275
1276 void fatal(msg)
1277 const char *msg;
1278 {
1279 fflush(stdout);
1280 fprintf(stderr, "xearth %s: fatal - %s\n", VersionString, msg);
1281 fprintf(stderr, "\n");
1282 exit(1);
1283 }