home *** CD-ROM | disk | FTP | other *** search
- /* File drawmap.c */
-
- #include "intuition/intuition.h"
- #include "graphics/gfxmacros.h"
- #include "exec/memory.h"
- #include <stdio.h>
- #include <fcntl.h>
- #include <math.h>
- #include <popmenu.h>
- #include <drawmap.h>
- #include <drawmap-req.h>
- #include <drawmap-menu.h>
-
- short *map, *map_trig; /* workspaces for map */
- short *td, *td_trig;
-
- struct Screen *s; /* pointer to screen */
- struct Window *w; /* pointer to Window */
- struct RastPort *rp; /* pointer to RastPort */
- struct ViewPort *vp; /* pointer to ViewPort */
- struct AreaInfo mapAreaInfo;
- struct TmpRas mapTmpRas;
- struct Library *GfxBase;
- struct Library *IntuitionBase;
- short areaArray[5*NUMPTS]; /* 5 words per point for drawing */
- short area[2*NUMPTS]; /* storage for each individual area */
-
- unsigned short *arrow, *cross; /* storage for mouse pointers */
- unsigned short *waiter, *transparent;
-
- UBYTE *bp[DEPTH]; /* bitplane pointers */
- short ytable[WHEIGHT]; /* offsets from beginning of */
- /* each screen row */
- short rowoffset;
-
- struct Requester req;
-
- /* ============================================================= */
-
- main ()
-
- {
-
- struct IntuiMessage *msg;
- PLANEPTR workspace;
- extern void free_svector(), InitTextRequest();
- extern int readmap();
- extern int HandleEvent();
- extern short *svector();
- int ix;
-
- if ((GfxBase = OpenLibrary ("graphics.library",0)) == NULL) {
- printf ("Can't open graphics library\n");
- exit (10);
- }
- if ((IntuitionBase = OpenLibrary ("intuition.library",0)) == NULL) {
- printf ("Can't open intuition library\n");
- goto end1;
- }
- if ((s = OpenScreen (&mapscreen)) == NULL) {
- printf ("Can't open screen\n");
- goto end2;
- }
- mapWindow.Screen = s;
- if ((w = OpenWindow (&mapWindow)) == NULL) {
- printf ("Can't open window\n");
- goto end3;
- }
- vp = &(s->ViewPort); /* pointer to viewport */
- LoadRGB4 (vp, &mapcolors[0], 4); /* init. color values */
- /* init. mouse pointers */
- arrow = (UWORD *) AllocMem (arrow_size, MEMF_CHIP);
- for (ix=0; ix<arrow_size/2; ++ix)
- arrow[ix] = arrow_data[ix];
- SetPointer (w, arrow, arrow_size/4-2, 16, arrow_x_offset, arrow_y_offset);
-
- cross = (UWORD *) AllocMem (cross_size, MEMF_CHIP);
- for (ix=0; ix<cross_size/2; ++ix)
- cross[ix] = cross_data[ix];
-
- waiter = (UWORD *) AllocMem (waiter_size, MEMF_CHIP);
- for (ix=0; ix<waiter_size/2; ++ix)
- waiter[ix] = waiter_data[ix];
-
- transparent = (UWORD *) AllocMem (transparent_size, MEMF_CHIP);
- for (ix=0; ix<transparent_size/2; ++ix)
- transparent[ix] = transparent_data[ix];
-
- rp = w->RPort;
- if ((workspace = (PLANEPTR) AllocRaster (WWIDTH,WHEIGHT)) == NULL) {
- printf ("No space for Temporary Raster\n");
- goto end4;
- }
- InitTmpRas (&mapTmpRas, workspace, RASSIZE(WWIDTH,WHEIGHT));
- rp->TmpRas = &mapTmpRas; /* link it to the RastPort */
- InitArea (&mapAreaInfo, &areaArray[0], NUMPTS);
- rp->AreaInfo = &mapAreaInfo; /* link it to the RastPort */
-
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- if ((map = svector (0, MAXVAL-1)) == NULL) {
- printf ("Can't get space for map\n");
- goto end5;
- }
- if ((ix = readmap (map, mapname, MAXVAL)) != OK) { /* read map file */
- printf ("Error reading map file\n");
- goto end6;
- }
- if ((map_trig = svector (0, MAXVAL-1)) == NULL) {
- printf ("Can't get space for map_trig\n");
- goto end6;
- }
- if ((ix = readmap (map_trig, mapname_trig, MAXVAL)) != OK) { /* read map_trig file */
- printf ("Error reading map-trig file\n");
- goto end7;
- }
- if ((td = svector (0, MAXTIDY-1)) == NULL) {
- printf ("Can't get space for td\n");
- goto end7;
- }
- if ((ix = readmap (td, tdname, MAXTIDY)) != OK) { /* read td file */
- printf ("Error reading td file\n");
- goto end8;
- }
- if ((td_trig = svector (0, MAXTIDY-1)) == NULL) {
- printf ("Can't get space for td_trig\n");
- goto end8;
- }
- if ((ix = readmap (td_trig, tdname_trig, MAXTIDY)) != OK) { /* read td_trig file */
- printf ("Error reading td_trig file\n");
- goto end9;
- }
- SetPointer (w, arrow, arrow_size/4-2, 16, arrow_x_offset, arrow_y_offset);
-
- SetAPen (rp,ORANGE); /* land */
- SetBPen (rp,BLUE); /* water */
- SetDrMd (rp,JAM2);
-
- InitTextRequest (); /* initialize the string requester */
-
- pi2 = pi/2.; /* initialize constants */
- twopi = 2.*pi;
- rad = pi/180.;
-
- view_height = VIEW_HEIGHT; /* constants for globe view */
- eta = view_height/RE;
- facp = 1. + eta;
- etap = 1./facp;
-
- for (ix=0; ix<DEPTH; ++ix) /* initialize bitplane pointers */
- bp[ix] = w->RPort->BitMap->Planes[ix];
- ytable[0] = 0; /* initialize screen offsets */
- rowoffset = WWIDTH/8;
- for (ix=1; ix<WHEIGHT; ++ix)
- ytable[ix] = ytable[ix-1] + rowoffset;
-
- WaitPort ( w->UserPort ); /* wait for message from */
- /* Intuition */
- while (1) {
- msg = (struct IntuiMessage *)GetMsg (w->UserPort);
- if (msg==NULL)
- WaitPort (w->UserPort);
- else
- if (HandleEvent (msg) != OK)
- break;
- }
-
- end9:
- free_svector (td_trig, 0, MAXTIDY-1); /* done, so clean up */
- end8:
- free_svector (td, 0, MAXTIDY-1);
- end7:
- free_svector (map_trig, 0, MAXVAL-1);
- end6:
- free_svector (map, 0, MAXVAL-1);
- end5:
- FreeRaster (workspace, WWIDTH, WHEIGHT);
- end4:
- FreeMem (transparent, transparent_size);
- FreeMem (cross, cross_size);
- FreeMem (arrow, arrow_size);
- FreeMem (waiter, waiter_size);
- ClearPointer (w);
- CloseWindow (w);
- end3:
- CloseScreen (s);
- end2:
- CloseLibrary (IntuitionBase);
- end1:
- CloseLibrary (GfxBase);
- }
-
- /* ============================================================= */
-
- int readmap (ws, fname, num) /* reads map files into memory */
-
- short *ws;
- char *fname;
- int num;
-
- {
-
- int ibin, disp, numrd;
-
- if ((ibin = open (fname, O_RDONLY)) == -1)
- return (NOT_OK);
- disp = 0;
- while (1) {
- if ((numrd = read (ibin, (char*) &ws[disp], 4000)) <= 0)
- break;
- disp += numrd / sizeof(short);
- }
- close (ibin);
- if (disp!=num)
- return (NOT_OK);
- return (OK);
- }
-
- /* ============================================================= */
-
- void InitTextRequest () /* initializes a string requester */
-
- {
- char *s, *t;
-
- InitRequester (&req); /* initialize the requester */
- req.LeftEdge = TLEFT;
- req.TopEdge = TTOP;
- req.Width = TWIDTH;
- req.Height = THEIGHT;
- req.ReqGadget = &gad;
- req.ReqText = &rtext;
- req.BackFill = ORANGE;
- req.Flags = 0;
- req.ReqBorder = &border_top;
-
- s = &userinput[0]; /* copy default text string */
- t = &defaulttext[0];
- while ((*s++ = *t++) != '\0') ;
- }
-
- /* ============================================================= */
-
- int HandleEvent (msg) /* processes main Intuition events */
-
- struct IntuiMessage *msg;
-
- {
-
- struct IntuiMessage *msgf;
- extern long PopChoose();
- extern void fullmap(), globe(), stars(), floodfill(), getcoord();
- extern void box(), grid(), shadow(), do_text();
- extern int getbox();
- static char title_FLAT[] = "Flat Map";
- static char title_MERCATOR[] = "Mercator";
- static char title_GLOBE[] = "Globe...view from infinitely far away";
- static char title_ORBITAL[] = " "
- " ";
- static char title_zoom[] = " "
- " ";
- static char title_GRID[] = "Grid";
- static char title_FLOOD[] = "Flood Fill";
- static char title_SHADOW[] = "Shadow";
- static char title_BOX[] = "Box";
- static char title_COLORS[] = "Colors";
- static char title_TEXT[] = "Text";
- static char title_CLEARS[] = "Clear Screen";
- static char press_prompt[] = "Press left button to select center point";
- static char drag_prompt[] = "Press and drag left button to select box";
- static char flood_wait[] = "Flood fill...press left button to select "
- "area to fill";
- static char box_error[] = "Box of zero size not allowed";
- static char grid_error[] = "Invalid map displayed for Grid option";
- static char fmt_ORBITAL[] = "Orbital...view from %.2lf kilometers";
- static char fmt_ZOOM_IN[] = "Zoom In...view from %.2lf kilometers";
- static char fmt_ZOOM_OUT[] = "Zoom Out...view from %.2lf kilometers";
- long val;
- static long oldval = -1L;
- static int fill = FILL;
- static int color_offset = 0;
- int i, x, y, x0, y0, result;
- double lat[2], lam[2];
- static double lamg, latg;
-
- switch (msg->Class) {
- case CLOSEWINDOW:
- return (NOT_OK);
- break;
- case MOUSEBUTTONS:
- switch (msg->Code) {
- case MENUDOWN:
- val = PopChoose (&map_menu, NULL);
- switch (val) {
- case COLOR_F: /* toggle color-fill flag */
- if (map_COLOR_F.Flags & CHECKED)
- fill = FILL;
- else
- fill = NOFILL;
- break;
- case FLAT: /* flat map */
- SetWindowTitles (w, title_FLAT, -1);
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- fullmap (map, FLAT, fill);
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- ModifyIDCMP (w, IDCMPFLAGS);
- oldval = val;
- break;
- case MERCATOR: /* Mercator map */
- SetWindowTitles (w, title_MERCATOR, -1);
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- fullmap (map, MERCATOR, fill);
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- ModifyIDCMP (w, IDCMPFLAGS);
- oldval = val;
- break;
- case GRID:
- if (oldval!=FLAT && oldval!=MERCATOR &&
- oldval!=GLOBE && oldval!=ORBITAL &&
- oldval!=ZOOM_IN && oldval!=ZOOM_OUT)
- SetWindowTitles (w, grid_error, -1);
- else {
- SetWindowTitles (w, title_GRID, -1);
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- grid (oldval, latg, lamg);
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- ModifyIDCMP (w, IDCMPFLAGS);
- }
- break;
- case ZOOM_IN: /* zoom views */
- case ZOOM_OUT:
- if (val==ZOOM_IN) {
- view_height /= 2.;
- if (view_height<MIN_HEIGHT)
- view_height = MIN_HEIGHT;
- sprintf (title_zoom, fmt_ZOOM_IN, view_height);
- }
- else {
- view_height *= 2.;
- sprintf (title_zoom, fmt_ZOOM_OUT, view_height);
- }
- eta = view_height/RE;
- facp = 1. + eta;
- etap = 1./facp;
- case GLOBE: /* globe views */
- case ORBITAL:
- if ( (val!=ZOOM_IN && val!=ZOOM_OUT) ||
- (oldval!=ZOOM_IN && oldval!=ZOOM_OUT &&
- oldval!=GLOBE && oldval!=ORBITAL) ) {
- SetWindowTitles (w, press_prompt, -1); /* wait for mouse button */
- if (oldval!=FLAT && oldval!=MERCATOR) {
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- fullmap (map, FLAT, fill);
- ModifyIDCMP (w, IDCMPFLAGS);
- oldval = FLAT;
- }
- SetPointer (w, cross, cross_size/4-2, 16,
- cross_x_offset, cross_y_offset);
- WaitPort (w->UserPort);
- while (1) {
- msgf = (struct IntuiMessage *) GetMsg (w->UserPort);
- if (msgf==NULL)
- WaitPort (w->UserPort);
- else
- if (msgf->Code==SELECTDOWN)
- break;
- }
- x = msgf->MouseX; /* get mouse position */
- y = msgf->MouseY;
- getcoord (x, y, oldval, &latg, &lamg);
- }
- if (val==ORBITAL) { /* re-initialize values for */
- view_height = VIEW_HEIGHT; /* orbital view */
- eta = view_height/RE;
- facp = 1. + eta;
- etap = 1./facp;
- sprintf (title_ORBITAL, fmt_ORBITAL, view_height);
- SetWindowTitles (w, title_ORBITAL, -1);
- }
- else if (val==GLOBE)
- SetWindowTitles (w, title_GLOBE, -1);
- else
- SetWindowTitles (w, title_zoom, -1);
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- Move (rp, 0, 0);
- SetBPen (rp, BLACK); /* black background */
- ClearScreen (rp);
- SetAPen (rp, BLUE); /* blue globe */
- DrawEllipse (rp, CENTERX, CENTERY, HRADIUS, VRADIUS);
- Flood (rp, 1, CENTERX, CENTERY);
- SetAPen (rp, ORANGE); /* reset colors */
- SetBPen (rp, BLUE);
- globe (map, map_trig, latg, lamg, val, fill); /* draw map */
- stars();
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- ModifyIDCMP (w, IDCMPFLAGS);
- oldval = val;
- break;
- case FLOOD: /* flood fill */
- SetWindowTitles (w, flood_wait, -1);
- SetPointer (w, cross, cross_size/4-2, 16,
- cross_x_offset, cross_y_offset);
- floodfill ();
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- SetWindowTitles (w, title_FLOOD, -1);
- break;
- case SHADOW: /* make shadows */
- SetWindowTitles (w, title_SHADOW, -1);
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- shadow ();
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- ModifyIDCMP (w, IDCMPFLAGS);
- break;
- case BOX: /* box */
- SetWindowTitles (w, drag_prompt, -1);
- if (oldval!=FLAT && oldval!=MERCATOR) {
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- fullmap (map, FLAT, fill);
- ModifyIDCMP (w, IDCMPFLAGS);
- oldval = FLAT;
- }
- SetPointer (w, cross, cross_size/4-2, 16,
- cross_x_offset, cross_y_offset);
- result = getbox (&x0, &y0, &x, &y);
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- if (result!=OK) {
- SetWindowTitles (w, box_error, -1);
- break;
- }
- SetWindowTitles (w, title_BOX, -1);
- ModifyIDCMP (w, CLOSEWINDOW);
- SetPointer (w, waiter, waiter_size/4-2, 16,
- waiter_x_offset, waiter_y_offset);
- getcoord (x0, y0, oldval, &lat[0], &lam[0]);
- getcoord (x, y, oldval, &lat[1], &lam[1]);
- Move (rp, 0, 0);
- ClearScreen (rp);
- box (map, lat, lam, fill);
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- ModifyIDCMP (w, IDCMPFLAGS);
- oldval = val;
- break;
- case COLORS: /* modify color table */
- SetWindowTitles (w, title_COLORS, -1);
- color_offset += 4;
- if (color_offset>=num_colors)
- color_offset = 0;
- LoadRGB4 (vp, &mapcolors[color_offset], 4);
- break;
- case TEXT: /* get user text */
- SetWindowTitles (w, title_TEXT, -1);
- do_text (msg, val);
- SetWindowTitles (w, title_TEXT, -1);
- break;
- case CLEARS: /* clear screen */
- SetWindowTitles (w, title_CLEARS, -1);
- Move (rp, 0, 0);
- ClearScreen (rp);
- oldval = val;
- break;
- default:
- if (map_COLOR_F.Flags & CHECKED)
- fill = FILL;
- else
- fill = NOFILL;
- break;
- }
- break;
- default:
- break;
- }
- default:
- break;
- }
- return (OK);
- }
-
- /* ============================================================= */
-
- void fullmap (ws, type, fill) /* draws flat map projections */
-
- short *ws;
- int type, fill;
-
- {
-
- extern void afill(), adraw(), plotpoint();
- int i, j, k, h1, h2, narea;
- double t;
- long pen;
- short np, xs, ys;
-
- Move (rp, 0, 0); /* clear screen */
- ClearScreen (rp);
- j = 0;
- np = 0;
- narea = 0;
- pen = ORANGE;
- SetAPen (rp, pen);
- for (i=0; i<MAXVAL; i+=2) {
- if (ws[i]==0 && ws[i+1]==0) { /* check for end of area */
- ++narea;
- pen = ORANGE;
- for (k=0; k<num_lakes; ++k) {
- if (narea==lakes[k]) {
- pen = BLUE;
- break;
- }
- }
- SetAPen (rp, pen);
- if (np<=1) {
- xs = CENTERX + area[j-2];
- ys = CENTERY + area[j-1];
- plotpoint (xs, ys);
- }
- else {
- if (fill==FILL)
- afill (np, pen);
- else
- adraw (np);
- }
- j = 0;
- np = 0;
- area[0] = 0;
- area[1] = 0;
- pen = ORANGE;
- SetAPen (rp, pen);
- }
- else { /* get coords of new point */
- t = ws[i]; /* y = latitude */
- if (type==FLAT)
- t = (t/100.) * VFACTOR;
- else if (type==MERCATOR) {
- t = (t/200. + 45.) * rad;
- t = log (tan (t)) * M_VFACTOR;
- }
- if (t<0.)
- t -= 0.5;
- else
- t += 0.5;
- h2 = -t;
- t = ws[i+1]; /* x = longitude */
- t = (t/100.) * HFACTOR;
- if (t<0.)
- t -= 0.5;
- else
- t += 0.5;
- h1 = t;
- if (np!=0) { /* disallow identical adjacent pts */
- if (h1==area[j-2] && h2==area[j-1])
- continue;
- }
- xs = CENTERX + h1;
- ys = CENTERY + h2;
- plotpoint (xs, ys);
- area[j] = h1;
- area[j+1] = h2;
- j += 2;
- ++np;
- }
- }
- if (np>0) { /* check for last area */
- pen = ORANGE;
- SetAPen (rp, pen);
- if (np==1) {
- xs = CENTERX + area[j-2];
- ys = CENTERY + area[j-1];
- plotpoint (xs, ys);
- }
- else {
- if (fill==FILL)
- afill (np, pen);
- else
- adraw (np);
- }
- }
- SetAPen (rp, ORANGE);
- }
-
- /* ============================================================= */
-
- void grid (val, lat0, lam0) /* controls drawing of grids */
-
- long val;
- double lat0, lam0;
-
- {
-
- extern void globe_grid();
- long oldpen, h1;
- double lam, lat, temp;
- static double lat_interval = 20.;
- static double lam_interval = 30.;
-
- oldpen = rp->FgPen; /* save original pen color */
- if (val!=FLAT && val!=MERCATOR) /* draw grid for globe */
- globe_grid (val, lat0, lam0);
- else { /* otherwise grid for flat */
- /* or Mercator map */
- SetAPen (rp, BLACK); /* set grid color to black */
- for (lam=-180.; lam<=+180.; lam += lam_interval) {
- h1 = lam*HFACTOR + CENTERX;
- Move (rp, h1, 0);
- Draw (rp, h1, WHEIGHT-1);
- }
- for (lat=80.; lat>=-80.; lat -= lat_interval) {
- if (val==FLAT)
- h1 = -lat*VFACTOR;
- else
- h1 = -log (tan((lat/2.+45.)*rad)) * M_VFACTOR;
- h1 += CENTERY;
- Move (rp, 0, h1);
- Draw (rp, WWIDTH-1, h1);
- }
- SetAPen (rp, WHITE); /* draw coordinate axes in white */
- Move (rp, CENTERX, 0);
- Draw (rp, CENTERX, WHEIGHT-1);
- Move (rp, 0, CENTERY);
- Draw (rp, WWIDTH-1, CENTERY);
- }
- SetAPen (rp, oldpen); /* restore pen color */
- }
-
- /* ============================================================= */
-
- void globe_grid (val, lat0, lam0) /* controls drawing globe grid */
-
- double lat0, lam0;
- long val;
-
- {
-
- extern void globe_grid_plot();
- extern int limit_lam(), limit_lat();
- double lat, lam, c0, s0, c1, s1, c2, s2, rlam, rlat;
- double hp, scale, fac3, dlat, dlam, ddelt;
- double lamp[2], latp[2];
- int k;
- long oldpen;
- char first;
- static double lat_interval = 20.;
- static double lam_interval = 30.;
- static double delta = 5.;
-
- lat0 *= rad;
- c0 = cos (lat0);
- s0 = sin (lat0);
- dlat = lat_interval;
- dlam = lam_interval;
- ddelt = delta;
- if (val==GLOBE) { /* ordinary globe view */
- hp = 0.;
- scale = 1.;
- fac3 = 1.;
- }
- else { /* orbital view */
- hp = etap;
- scale = sqrt (1.-etap*etap);
- fac3 = (facp/(facp-hp)) * scale;
- if (view_height<=1200.) {
- dlat /= 4.;
- dlam /= 4.;
- ddelt /= 5.;
- }
- }
- SetAPen (rp, BLACK); /* grid lines in black */
- for (lat=80.; lat>=-80.; lat-=dlat) { /* lines of equal latitude */
- rlat = lat*rad;
- if ((k=limit_lam (&lamp[0], rlat, lat0, hp))!=OK)
- continue; /* skip if entirely out of view */
- lamp[0] += lam0;
- lamp[1] += lam0;
- k = lamp[0]/ddelt - 1.; /* express limits as multiple */
- lamp[0] = k*ddelt; /* of ddelt */
- k = lamp[1]/ddelt + 1.;
- lamp[1] = k*ddelt;
- c1 = cos (rlat);
- s1 = sin (rlat);
- first = TRUE;
- if (lat==0.)
- SetAPen (rp, WHITE); /* draw equator in white */
- for (lam=lamp[0]; lam<=lamp[1]; lam+=ddelt) {
- rlam = (lam-lam0)*rad;
- if (rlam<-pi)
- rlam += twopi;
- if (rlam>+pi)
- rlam -= twopi;
- c2 = cos (rlam);
- s2 = sin (rlam);
- globe_grid_plot (rlat, rlam, c0, s0, c1, s1, c2, s2,
- val, hp, scale, fac3, &first);
- }
- if (lat==0.)
- SetAPen (rp, BLACK); /* reset pen to black */
- }
- for (lam=-180.; lam<+180.; lam+=dlam) { /* meridian circles */
- rlam = (lam-lam0)*rad;
- if (rlam<-pi)
- rlam += twopi;
- if (rlam>+pi)
- rlam -= twopi;
- if ((k=limit_lat (&latp[0], lat0, rlam, hp))!=OK)
- continue; /* skip if entirely out of view */
- k = latp[0]/ddelt + 1.; /* express limits as multiple */
- latp[0] = k*ddelt; /* of ddelt */
- k = latp[1]/ddelt - 1;
- latp[1] = k*ddelt;
- if (latp[0]>=90.) /* exclude North polar point */
- latp[0] = 90. - ddelt;
- if (latp[1]<=-90.) /* exclude South polar point */
- latp[1] = -90. + ddelt;
- c2 = cos (rlam);
- s2 = sin (rlam);
- first = TRUE;
- if (lam==0. || lam==-180.) /* prime meridian in white */
- SetAPen (rp, WHITE);
- for (lat=latp[0]; lat>=latp[1]; lat-=ddelt) {
- rlat = lat*rad;
- c1 = cos (rlat);
- s1 = sin (rlat);
- globe_grid_plot (rlat, rlam, c0, s0, c1, s1, c2, s2,
- val, hp, scale, fac3, &first);
- }
- if (lam==0. || lam==-180.)
- SetAPen (rp, BLACK); /* reset pen to black */
- }
- }
-
- /* ============================================================= */
-
- void globe_grid_plot (lat, lam, c0, s0, c1, s1, c2, s2,
- val, hp, scale, fac3, first)
-
- double lat, lam, c0, s0, c1, s1, c2, s2; /* draws globe grids */
- long val;
- double hp, scale, fac3;
- char *first;
-
- {
-
- extern void plotpoint(), globe_rim_fix();
- char in_view;
- short h1, h1c; /* x-dist. (pix) from center */
- short h2, h2c; /* y-dist. (pix) from center */
- short xs, ys;
- long x, y;
- double lamc, dlam; /* longitude */
- double latc, dlat; /* latitude */
- double zp, facz, h1d, h2d, fac2;
- static char prev_in_view;
- static short h1prev, h2prev;
- static double latprev, lamprev, zpprev;
-
- in_view = FALSE; /* get status of current point */
- zp = s1*s0 + c1*c0*c2;
- if (zp>=hp) { /* zp > hp => in view */
- in_view = TRUE;
- h1d = HRADIUS * c1 * s2;
- h2d = -VRADIUS * (s1*c0 - c1*s0*c2);
- if (val!=GLOBE) {
- fac2 = (facp/(facp-zp))*scale;
- h1d *= fac2;
- h2d *= fac2;
- }
- h1 = h1d;
- h2 = h2d;
- }
- if (*first==TRUE) { /* get status of first point */
- *first = FALSE;
- if (in_view==TRUE) { /* if first point is in view, */
- x = h1 + CENTERX; /* move pen to first point */
- y = h2 + CENTERY; /* and plot it */
- Move (rp, x, y);
- xs = x;
- ys = y;
- plotpoint (xs, ys);
- h1prev = h1;
- h2prev = h2;
- }
- prev_in_view = in_view; /* save status of first point */
- latprev = lat;
- lamprev = lam;
- zpprev = zp;
- return;
- }
- if (in_view==TRUE) { /* if current point is in view, */
- if (prev_in_view==FALSE) { /* but previous point was not */
- facz = zp / (zpprev-zp); /* in view, get rim point by */
- latc = lat - (latprev-lat)*facz; /* linear interpolation */
- lamc = lam - (lamprev-lam)*facz;
- dlat = fabs (lat-latprev);
- dlam = fabs (lam-lamprev);
- if ( fabs (latc-latprev)> dlat || /* if rim point not between */
- fabs (latc-lat) > dlat) /* current and previous */
- latc = (lat+latprev)/2.; /* points, use midpoint */
- if ( fabs (lamc-lamprev)> dlam ||
- fabs (lamc-lam) > dlam )
- lamc = (lam+lamprev)/2.;
- c1 = cos (latc);
- h1d = HRADIUS * c1 * sin (lamc);
- h2d = -VRADIUS * (sin (latc)*c0 - c1*s0*cos (lamc));
- if (val!=GLOBE) {
- h1d *= fac3;
- h2d *= fac3;
- }
- h1c = h1d;
- h2c = h2d;
- globe_rim_fix (&h1c, &h2c);
- x = h1c + CENTERX; /* move to rim point & plot it */
- y = h2c + CENTERY;
- Move (rp, x, y);
- xs = x;
- ys = y;
- plotpoint (xs, ys);
- h1prev = h1c;
- h2prev = h2c;
- }
- if (h1!=h1prev || h2!=h2prev) {
- x = h1 + CENTERX; /* draw to current point */
- y = h2 + CENTERY;
- Draw (rp, x, y);
- Move (rp, x, y);
- }
- h1prev = h1;
- h2prev = h2;
- }
- else { /* current point is out of view */
- if (prev_in_view==TRUE) { /* if previous point was in view, */
- facz = zp / (zpprev-zp); /* get rim point by linear */
- latc = lat - (latprev-lat)*facz; /* interpolation */
- lamc = lam - (lamprev-lam)*facz;
- dlat = fabs (lat-latprev);
- dlam = fabs (lam-lamprev);
- if ( fabs (latc-latprev)> dlat || /* if rim point not between */
- fabs (latc-lat) > dlat) /* current and previous */
- latc = (lat+latprev)/2.; /* points, use midpoint */
- if ( fabs (lamc-lamprev)> dlam ||
- fabs (lamc-lam) > dlam )
- lamc = (lam+lamprev)/2.;
- c1 = cos (latc);
- h1d = HRADIUS * c1 * sin (lamc);
- h2d = -VRADIUS * (c0*sin (latc) - c1*s0 * cos (lamc));
- if (val!=GLOBE) {
- h1d *= fac3;
- h2d *= fac3;
- }
- h1c = h1d;
- h2c = h2d;
- globe_rim_fix (&h1c, &h2c);
- x = h1c + CENTERX; /* draw to rim point */
- y = h2c + CENTERY;
- Draw (rp, x, y);
- Move (rp, x, y);
- }
- }
- prev_in_view = in_view; /* save status of current point */
- latprev = lat;
- lamprev = lam;
- zpprev = zp;
- }
-
- /* ============================================================= */
-
- int limit_lam (lam, lat, lat0, etap) /* computes limits on longitude */
- /* for constant latitude */
- double *lam, lat, lat0, etap;
-
- {
- double alpha;
-
- alpha = (etap-sin(lat)*sin(lat0)) / (cos(lat)*cos(lat0));
- if (alpha<=-1.) { /* negative => lamda covers */
- lam[0] = -180.; /* entire hemisphere */
- lam[1] = +180.;
- return (OK);
- }
- else if (alpha>=+1.) /* positive => nothing in view */
- return (NOT_OK);
- else { /* otherwise, compute limits */
- lam[0] = -acos (alpha)/rad;
- lam[1] = -lam[0];
- return (OK);
- }
- }
-
- /* ============================================================= */
-
- int limit_lat (lat, lat0, lam, etap) /* computes limits on latitude */
- /* for constant longitude */
- double *lat, lat0, lam, etap;
-
- {
- double radical, a, b, sum, fac1;
-
- a = sin (lat0);
- b = cos (lat0) * cos (lam);
- sum = a*a + b*b;
- radical = sum - etap*etap;
- if (radical<=0.) /* no real solutions */
- return (NOT_OK);
- else { /* two real solutions */
- radical = sqrt (radical); /* solve quadrtic equation */
- fac1 = (a*etap + b*radical)/sum;
- lat[0] = asin (fac1)/rad;
- fac1 = (a*etap - b*radical)/sum;
- lat[1] = asin (fac1)/rad;
- if (lat[0]<lat[1]) { /* put in correct order */
- b = lat[0];
- lat[0] = lat[1];
- lat[1] = b;
- }
- if (a>etap) /* check North pole */
- lat[0] = 90.;
- if (a<-etap) /* check South pole */
- lat[1] = -90.;
- return (OK);
- }
- }
-
- /* ============================================================= */
-
- void getcoord (x, y, val, lat, lam) /* converts screen coordinates */
- /* into latitude and longitude */
- int x, y;
- long val;
- double *lat, *lam;
-
- {
-
- (*lam) = (x - CENTERX) / HFACTOR;
- if (val==FLAT)
- (*lat) = (CENTERY - y) / VFACTOR;
- else
- (*lat) = -90. + 2.*atan(exp((CENTERY-y)/M_VFACTOR))/rad;
- }
-
- /* ============================================================= */
-
- void globe (ws, ws_trig, lat0, lam0, val, fill) /* draws globe projections */
-
- short *ws, *ws_trig;
- double lat0, lam0;
- long val;
- int fill;
-
- {
-
- extern void plotpoint(), globe_fill(), globe_rim_fix(), globe_tidy();
- char first, prev_in_view, in_view, latzero;
- short h1, h1c, h1prev; /* x-dist. (pix) from center */
- short h2, h2c, h2prev; /* y-dist. (pix) from center */
- short np, narea, nrim_in, nrim_out;
- short xs, ys;
- int i, j;
- long x, y, pen, first_color;
- double lam, lamc, lamprev; /* longitude */
- double lat, latc, latprev; /* latitude */
- double c0, s0, c1, s1, c2, zp, zpprev;
- double hp, fac2, fac3, facz, scale;
- double h1d, h2d, dlat, dlam, lat0p;
- static double fac = 1./32767.0;
-
- latzero = FALSE;
- if (val==GLOBE) { /* ordinary globe view */
- hp = 0.;
- scale = 1.;
- fac3 = 1.;
- }
- else { /* orbital globe view */
- hp = etap;
- scale = sqrt (1.-etap*etap);
- fac3 = (facp/(facp-hp)) * scale;
- }
- if (lat0==0.) {
- c0 = 1.;
- s0 = 0.;
- if (val==GLOBE)
- latzero = TRUE; /* equatorial, ordinary globe view */
- }
- else {
- lat0p = lat0 * rad;
- c0 = cos (lat0p);
- s0 = sin (lat0p);
- }
- first = TRUE;
- pen = ORANGE;
- SetAPen (rp, pen);
- first_color = BLACK;
- j = 0;
- np = 0;
- narea = 0;
- nrim_in = 0;
- nrim_out = 0;
- for (i=0; i<MAXVAL; i+=2) {
- if (ws[i]==0 && ws[i+1]==0) { /* if end of area, then */
- ++narea; /* color-fill and skip to */
- first = TRUE; /* next area */
- if (np>0 && fill==FILL)
- globe_fill (np, narea, nrim_in, nrim_out, first_color);
- j = 0;
- np = 0;
- nrim_in = 0;
- nrim_out = 0;
- first_color = BLACK;
- continue;
- }
- lat = ws[i]; /* latitude */
- lat = (lat/100.) * rad;
- lam = ws[i+1]; /* longitude */
- lam = (lam/100. - lam0) * rad;
- if (lam<-pi)
- lam += twopi;
- if (lam>pi)
- lam -= twopi;
- c1 = ws_trig[i]; /* cosine of latitude */
- c1 *= fac;
- s1 = ws_trig[i+1]; /* sine of latitude */
- s1 *= fac;
- in_view = FALSE; /* get status of current point */
- if (latzero==TRUE) { /* equatorial globe view */
- zp = c1*cos (lam);
- if (lam>=-pi2 && lam<=+pi2) {
- in_view = TRUE;
- h1 = HRADIUS * c1 * sin (lam);
- h2 = -VRADIUS * s1;
- }
- }
- else { /* oblique earth view */
- c2 = cos (lam);
- zp = s1*s0 + c1*c0*c2;
- if (zp>=hp) { /* zp > hp => in view */
- in_view = TRUE;
- h1d = HRADIUS * c1 * sin (lam);
- h2d = -VRADIUS * (s1*c0 -c1*s0*c2);
- if (val!=GLOBE) {
- fac2 = (facp/(facp-zp)) * scale;
- h1d *= fac2;
- h2d *= fac2;
- }
- h1 = h1d;
- h2 = h2d;
- }
- }
- if (first==TRUE) { /* get status of first point */
- first = FALSE;
- if (in_view==TRUE) { /* if first point is in view, */
- x = h1 + CENTERX; /* move pen to first point */
- y = h2 + CENTERY; /* and plot it */
- Move (rp, x, y);
- first_color = ReadPixel (rp, x, y);
- xs = x;
- ys = y;
- plotpoint (xs, ys);
- h1prev = h1;
- h2prev = h2;
- area[0] = h1; /* save first point for later use */
- area[1] = h2;
- j = 2;
- np = 1;
- }
- prev_in_view = in_view; /* save status of first point */
- latprev = lat;
- lamprev = lam;
- zpprev = zp;
- continue;
- }
- if (in_view==TRUE) { /* if current point is in view, */
- if (prev_in_view==FALSE) { /* but previous point was not */
- facz = zp / (zpprev-zp); /* in view, get rim point by */
- latc = lat - (latprev-lat)*facz; /* linear interpolation */
- lamc = lam - (lamprev-lam)*facz;
- dlat = fabs (lat-latprev);
- dlam = fabs (lam-lamprev);
- if ( fabs (latc-latprev)> dlat || /* if rim point not between */
- fabs (latc-lat) > dlat) /* current and previous */
- latc = (lat+latprev)/2.; /* point, use midpoint */
- if ( fabs (lamc-lamprev)> dlam ||
- fabs (lamc-lam) > dlam )
- lamc = (lam+lamprev)/2.;
- if (latzero==TRUE) {
- h1c = HRADIUS * cos (latc) * sin (lamc);
- h2c = -VRADIUS * sin (latc);
- }
- else {
- c1 = cos (latc);
- h1d = HRADIUS * c1 * sin (lamc);
- h2d = -VRADIUS * (sin (latc)*c0 - c1*s0*cos (lamc));
- if (val!=GLOBE) {
- h1d *= fac3;
- h2d *= fac3;
- }
- h1c = h1d;
- h2c = h2d;
- }
- globe_rim_fix (&h1c, &h2c); /* correct the computed rim point */
- x = h1c + CENTERX; /* move to rim point & plot it */
- y = h2c + CENTERY;
- Move (rp, x, y);
- xs = x;
- ys = y;
- plotpoint (xs, ys);
- h1prev = h1c;
- h2prev = h2c;
- area[j] = h1; /* save coords of rim point */
- area[j+1] = h2;
- j += 2;
- ++nrim_in;
- ++np;
- }
- if (h1!=h1prev || h2!=h2prev) {
- x = h1 + CENTERX; /* draw to current point */
- y = h2 + CENTERY;
- Draw (rp, x, y);
- Move (rp, x, y);
- area[j] = h1; /* save coords of current point */
- area[j+1] = h2;
- j += 2;
- ++np;
- }
- h1prev = h1;
- h2prev = h2;
- }
- else { /* current point is out of view */
- if (prev_in_view==TRUE) { /* if previous point was in view, */
- facz = zp / (zpprev-zp); /* get rim point by linear */
- latc = lat - (latprev-lat)*facz; /* interpolation */
- lamc = lam - (lamprev-lam)*facz;
- dlat = fabs (lat-latprev);
- dlam = fabs (lam-lamprev);
- if ( fabs (latc-latprev)> dlat || /* if rim point not between */
- fabs (latc-lat) > dlat) /* current and previous */
- latc = (lat+latprev)/2.; /* point, use midpoint */
- if ( fabs (lamc-lamprev)> dlam ||
- fabs (lamc-lam) > dlam )
- lamc = (lam+lamprev)/2.;
- if (latzero==TRUE) {
- h1c = HRADIUS * cos (latc) * sin (lamc);
- h2c = -VRADIUS * sin (latc);
- }
- else {
- c1 = cos (latc);
- h1d = HRADIUS * c1 * sin (lamc);
- h2d = -VRADIUS * (c0*sin(latc) - c1*s0 * cos(lamc));
- if (val!=GLOBE) {
- h1d *= fac3;
- h2d *= fac3;
- }
- h1c = h1d;
- h2c = h2d;
- }
- globe_rim_fix (&h1c, &h2c); /* correct the computed rim point */
- x = h1c + CENTERX; /* draw to rim point */
- y = h2c + CENTERY;
- Draw (rp, x, y);
- Move (rp, x, y);
- area[j] = h1; /* save coords of rim point */
- area[j+1] = h2;
- j += 2;
- ++nrim_out;
- ++np;
- }
- }
- prev_in_view = in_view; /* save status of current point */
- latprev = lat;
- lamprev = lam;
- zpprev = zp;
- }
- if (fill == FILL)
- globe_tidy (td, td_trig, lat0, lam0, val);
- }
-
- /* ============================================================= */
-
- void globe_fill (np, narea, nrim_in, nrim_out, first_color)
- /* fills area on globe */
-
- short np, narea, nrim_in, nrim_out;
- long first_color;
-
- {
-
- extern void plotpoint ();
- int k;
- long x, y;
- short xs, ys;
- char is_lake;
- static long pen = ORANGE;
-
- if (nrim_in!=nrim_out)
- return;
- if (nrim_in==0) { /* fill areas with no rim points */
- is_lake = FALSE;
- for (k=0; k<num_lakes; ++k) /* check for lake */
- if (narea==lakes[k]) {
- if (first_color==ORANGE) {
- pen = BLUE; /* make lake blue if drawn */
- is_lake = TRUE; /* into orange */
- break;
- }
- else /* don't color-fill if drawn */
- return; /* into blue */
- }
- xs = CENTERX + area[0];
- ys = CENTERY + area[1];
- if (np==1)
- plotpoint (xs, ys);
- else if (np>=GLOBE_FILL_MIN)
- afill (np, pen);
- if (is_lake==TRUE)
- pen = ORANGE;
- }
- }
-
- /* ============================================================= */
-
- void globe_rim_fix (h1, h2) /* find nearest actual rim point */
-
- short *h1, *h2;
-
- {
-
- short inc1, inc2;
- int i;
- long x, y, color;
- static int itmax = 20;
-
- if ((*h1)>=0) /* right half */
- inc1 = +1;
- else /* left half */
- inc1 = -1;
- if ((*h2)>=0) /* bottom half */
- inc2 = +1;
- else /* top half */
- inc2 = -1;
- x = (*h1) + CENTERX + 5*inc1; /* coords of test pixel */
- y = (*h2) + CENTERY + 5*inc2;
- for (i=0; i<itmax; ++i) { /* look for nearest black pixel */
- if ((color = ReadPixel (rp, x, y))==BLACK)
- break;
- x += inc1;
- y += inc2;
- }
- x -= inc1;
- y -= inc2;
- for (i=0; i<itmax; ++i) { /* look back for previous blue one */
- if ((color = ReadPixel (rp, x, y))==BLUE || color==ORANGE)
- break;
- x -= inc1;
- y -= inc2;
- }
- (*h1) = x - CENTERX;
- (*h2) = y - CENTERY;
- }
-
- /* ============================================================= */
-
- void globe_tidy (td, td_trig, lat0, lam0, val)
-
- short *td, *td_trig; /* color-fills partially-drawn */
- double lat0, lam0; /* regions */
- long val;
-
- {
-
- int i;
- double lat, lam, c0, s0, c1, s1, c2;
- double zp, hp, scale, fac2, fac3, h1d, h2d;
- short h1, h2;
- long x, y, color;
- static double fac = 1./32767.0;
-
- if (val==GLOBE) { /* ordinary globe view */
- hp = 0.;
- scale = 1.;
- fac3 = 1.;
- }
- else { /* orbital globe view */
- hp = etap;
- scale = sqrt (1.-etap*etap);
- fac3 = (facp/(facp-hp)) * scale;
- }
- lat0 *= rad;
- c0 = cos (lat0);
- s0 = sin (lat0);
- i = 0;
- while (1) {
- if (td[i]==0 && td[i+1]==0) /* check for end of array */
- break;
- lat = td[i]; /* latitude */
- lat = (lat/100.) * rad;
- lam = td[i+1]; /* longitude */
- lam = (lam/100.-lam0) * rad;
- if (lam<-pi)
- lam += twopi;
- if (lam>pi)
- lam -= twopi;
- c1 = td_trig[i];
- c1 *= fac;
- s1 = td_trig[i+1];
- s1 *= fac;
- c2 = cos (lam);
- zp = s1*s0 + c1*c0*c2;
- if (zp>=hp) { /* in view, so get screen coords */
- h1d = HRADIUS * c1 * sin (lam);
- h2d = -VRADIUS * (s1*c0-c1*s0*c2);
- if (val!=GLOBE) { /* orbital view */
- fac2 = (facp/(facp-zp)) * scale;
- h1d *= fac2;
- h2d *= fac2;
- }
- h1 = h1d; /* flood fill */
- h2 = h2d;
- x = h1 + CENTERX;
- y = h2 + CENTERY;
- if ((color = ReadPixel (rp, x, y)) == BLUE)
- Flood (rp, 1, x, y);
- }
- i += 2;
- }
- }
-
- /* ============================================================= */
-
- void stars () /* draws stars into black background */
-
- {
-
- extern double ran();
- static int nmax = 150;
- double t;
- short x, y;
- int i, nstars;
- long oldpen, color;
-
- oldpen = rp->FgPen;
- SetAPen (rp, WHITE);
- nstars = 0;
- for (i=0; ; ++i) {
- t = ran();
- x = t * WWIDTH + 0.5;
- t = ran();
- y = t * WHEIGHT + 0.5;
- if (x<0)
- x = 0;
- if (x>WWIDTH-1)
- x = WWIDTH-1;
- if (y<0)
- y = 0;
- if (y>WHEIGHT-1)
- y = WHEIGHT-1;
- if ((color = ReadPixel (rp, x, y)) == BLACK) {
- WritePixel (rp, x, y);
- ++nstars;
- if (nstars>=nmax)
- break;
- }
- }
- SetAPen (rp, oldpen);
- }
-
- /* ============================================================= */
-
- void floodfill () /* flood fills an area based */
- /* on mouse position */
- {
- struct IntuiMessage *msgf;
- short x, y;
- long color;
-
- WaitPort (w->UserPort); /* wait for message */
- while (1) {
- msgf = (struct IntuiMessage *) GetMsg (w->UserPort);
- if (msgf==NULL)
- WaitPort (w->UserPort);
- else
- if (msgf->Code==SELECTDOWN)
- break;
- }
- x = msgf->MouseX; /* get mouse coordinates */
- y = msgf->MouseY; /* and flood fill */
- if ((color = ReadPixel (rp, x, y))==BLUE)
- Flood (rp, 1, x, y);
- }
-
- /* ============================================================= */
-
- void shadow () /* makes shadowed screens */
-
- {
- int modb0, modb1, color0, color1;
- int acolor0, acolor1, bcolor0, bcolor1;
- int j, k, k1, k2, m, bitlast;
- unsigned int byte0, byte1;
- unsigned int byte0b0, byte1b0, byte0b1, byte1b1;
- long color;
- static int blackcolor0, blackcolor1, disp;
- static int bluecolor0, bluecolor1, Ocolor0, Ocolor1;
- static unsigned int bitval[] = {1, 2, 4, 8, 16, 32, 64, 128};
- static char first = NOT_OK;
-
- if (first==NOT_OK) { /* initialize color values once */
- first = OK;
- color = BLACK;
- blackcolor0 = color&1L;
- blackcolor1 = (color&2L)>>1;
- color = BLUE;
- bluecolor0 = color&1L;
- bluecolor1 = (color&2L)>>1;
- color = ORANGE;
- Ocolor0 = color&1L;
- Ocolor1 = (color&2L)>>1;
- disp = SHADOW_DISP * rowoffset; /* offset to shadowed row */
- }
- for (k=ytable[10]; k<ytable[WHEIGHT-SHADOW_DISP-1]; k+=rowoffset) {
- /* do each row */
- k2 = k + disp; /* displacement to shadowed row */
- for (j=0; j<rowoffset; ++j) { /* do each byte in row */
- byte0 = bp[0][k+j]; /* current row, planes 0 and 1 */
- byte1 = bp[1][k+j];
- byte0b0 = bp[0][k2+j]; /* shadowed row, planes 0 and 1 */
- byte1b0 = bp[1][k2+j];
- byte0b1 = bp[0][k2+j+1]; /* shadowed row, adjacent byte, */
- byte1b1 = bp[1][k2+j+1]; /* planes 0 and 1 */
- /* if last byte in row, don't */
- /* need adjacent bytes */
- ((j<rowoffset-1) ? (bitlast=0) : (bitlast=SHADOW_DISP));
- modb0 = NOT_OK;
- modb1 = NOT_OK;
- for (m=7; m>=bitlast; --m) { /* check each bit, left to right */
- color0 = BITVAL(byte0,m); /* current pixel color */
- color1 = BITVAL(byte1,m);
- if (color0==Ocolor0 && color1==Ocolor1) {
- if (m>SHADOW_DISP-1) { /* get color of pixel in */
- bcolor0 = BITVAL(byte0b0,m-SHADOW_DISP); /* shadowed row */
- bcolor1 = BITVAL(byte1b0,m-SHADOW_DISP);
- }
- else { /* use adjacent byte */
- bcolor0 = BITVAL(byte0b1,m+8-SHADOW_DISP);
- bcolor1 = BITVAL(byte1b1,m+8-SHADOW_DISP);
- }
- if (bcolor0==bluecolor0 && bcolor1==bluecolor1) {
- if (m>SHADOW_DISP-1) { /* if blue, set color to black */
- BITSTORE(byte0b0,m-SHADOW_DISP,blackcolor0);
- BITSTORE(byte1b0,m-SHADOW_DISP,blackcolor1);
- modb0 = OK;
- }
- else { /* use adjacent byte */
- BITSTORE(byte0b1,m+8-SHADOW_DISP,blackcolor0);
- BITSTORE(byte1b1,m+8-SHADOW_DISP,blackcolor1);
- modb1 = OK;
- }
- }
- }
- } /* end bit test */
- if (modb0==OK) { /* restore only modified bytes */
- bp[0][k2+j] = byte0b0;
- bp[1][k2+j] = byte1b0;
- }
- if (modb1==OK) {
- bp[0][k2+j+1] = byte0b1;
- bp[1][k2+j+1] = byte1b1;
- }
- } /* end of row */
- } /* last row */
- }
-
- /* ============================================================= */
-
- int getbox (x0, y0, x, y) /* selects a region to draw to */
- /* larger scale */
- int *x0, *y0, *x, *y;
-
- {
-
- extern void drawbox();
- struct IntuiMessage *msgf;
- int xd, yd, x1, x2, y1, y2;
- char selectbutton;
-
- selectbutton = FALSE;
- SetDrMd (rp, JAM2 | COMPLEMENT); /* turn on complement mode and */
- ModifyIDCMP (w, IDCMPFLAGS | MOUSEMOVE); /* enable mouse events */
- WaitPort (w->UserPort);
- while (1) {
- msgf = (struct IntuiMessage *) GetMsg (w->UserPort);
- if (msgf==NULL)
- WaitPort (w->UserPort);
- else if (msgf->Code==SELECTDOWN) { /* if user pressed left button, */
- x1 = msgf->MouseX; /* get initial mouse position */
- y1 = msgf->MouseY;
- xd = x1;
- yd = y1;
- selectbutton = TRUE;
- }
- else if (selectbutton==TRUE && msgf->Class==MOUSEMOVE) {
- x2 = msgf->MouseX;
- y2 = msgf->MouseY;
- drawbox (x1, y1, xd, yd); /* erase old box */
- xd = x2;
- yd = y2;
- drawbox (x1, y1, xd, yd); /* draw new box */
- }
- else if (selectbutton==TRUE && msgf->Code==SELECTUP)
- break;
- }
- x2 = msgf->MouseX; /* erase current box */
- y2 = msgf->MouseY;
- drawbox (x1, y1, xd, yd);
- SetDrMd (rp, JAM2); /* restore original drawing mode */
- ModifyIDCMP (w, IDCMPFLAGS); /* and disable mouse events */
- *x0 = x1;
- *y0 = y1;
- *x = x2;
- *y = y2;
- if (x1==x2 || y1==y2) /* error if box is of zero area */
- return (NOT_OK);
- if (x1>x2 && y1>y2) { /* ensure that the vertices of */
- *x0 = x2; /* the box are in the proper */
- *y0 = y2; /* order */
- *x = x1;
- *y = y1;
- }
- else if (x1<x2 && y1>y2) {
- *x0 = x1;
- *y0 = y2;
- *x = x2;
- *y = y1;
- }
- else if (x1>x2 && y1<y2) {
- *x0 = x2;
- *y0 = y1;
- *x = x1;
- *y = y2;
- }
- return (OK);
- }
-
- /* ============================================================= */
-
- void drawbox (x1, y1, x2, y2) /* draws a box */
-
- int x1, y1, x2, y2;
-
- {
-
- Move (rp, x1, y1);
- Draw (rp, x2, y1);
- Move (rp, x2, y1);
- Draw (rp, x2, y2);
- Move (rp, x2, y2);
- Draw (rp, x1, y2);
- Move (rp, x1, y2);
- Draw (rp, x1, y1);
- Move (rp, x1, y1);
- }
-
- /* ============================================================= */
-
- void box (ws, latp, lamp, fill) /* draws areas contained within */
- /* a rectangular region */
- short *ws;
- double *latp, *lamp;
- int fill;
-
- {
-
- extern void plotpoint(), drawbox(), box_tidy();
- char first, prev_in_view, in_view, is_lake;
- short h1, h1c, h1prev; /* x-dist. (pix) from center */
- short h2, h2c, h2prev; /* y-dist. (pix) from center */
- short np, xs, ys, nrim_in, nrim_out;
- int i, j, k, narea;
- long x, y, pen, first_color;
- double lam, lamc, lamprev; /* longitude */
- double lat, latc, latprev; /* latitude */
- double bwidth, bheight, bcx, bcy, xscale, yscale;
- double lat1, lat2, lam1, lam2;
-
- lat1 = latp[0]; /* store values for box corners */
- lat2 = latp[1]; /* locally */
- lam1 = lamp[0];
- lam2 = lamp[1];
- bwidth = lam2 - lam1; /* box width (degrees) */
- bheight = lat1 - lat2; /* box height (degrees) */
- bcx = (lam1 + lam2)/2.; /* x-coord of box center (deg) */
- bcy = (lat1 + lat2)/2.; /* y-coord of box center (deg) */
- xscale = WWIDTH / bwidth; /* horizontal scale (pix/deg) */
- yscale = (WHEIGHT-10) / bheight; /* vertical scale (pix/deg) */
- j = 0;
- np= 0;
- narea = 0;
- first = TRUE;
- pen = ORANGE;
- SetAPen (rp, pen);
- first_color = BLACK;
-
- drawbox (0, 0, WWIDTH-1, WHEIGHT-10); /* outline the box */
-
- for (i=0; i<MAXVAL; i+=2) {
- if (ws[i]==0 && ws[i+1]==0) { /* if end of area, then */
- ++narea;
- if (np>0 && fill==FILL) { /* color-fill if requested */
- if (nrim_in==0) {
- is_lake = FALSE;
- for (k=0; k<num_lakes; ++k)
- if (narea==lakes[k]) {
- is_lake = TRUE;
- if (first_color==ORANGE)
- pen = BLUE;
- break;
- }
- if (is_lake==FALSE || (is_lake==TRUE && pen==BLUE)) {
- xs = CENTERX + area[0];
- ys = CENTERY + area[1];
- if (np==1)
- plotpoint (xs, ys);
- else
- afill (np, pen);
- }
- }
- }
- j = 0;
- np = 0;
- nrim_in = 0;
- nrim_out = 0;
- pen = ORANGE;
- first_color = BLACK;
- first = TRUE;
- continue; /* skip to next point */
- }
- lat = ws[i]; /* latitude */
- lat = lat/100.;
- lam = ws[i+1]; /* longitude */
- lam = lam/100.;
- in_view = FALSE; /* get status of current point */
- if ( (lat<=lat1 && lat>=lat2)
- && (lam>=lam1 && lam<=lam2)) {
- in_view = TRUE;
- h1 = (lam-bcx) * xscale;
- h2 = - (lat-bcy) * yscale;
- }
- if (first==TRUE) { /* check first point */
- first = FALSE;
- if (in_view==TRUE) { /* if first point is in view, */
- x = h1 + CENTERX; /* move pen to first point */
- y = h2 + CENTERY; /* and plot it */
- Move (rp, x, y);
- first_color = ReadPixel (rp, x, y);
- xs = x;
- ys = y;
- plotpoint (xs, ys);
- h1prev = h1;
- h2prev = h2;
- area[0] = h1;
- area[1] = h2;
- j = 2;
- np = 1;
- }
- prev_in_view = in_view; /* save status of first point */
- latprev = lat;
- lamprev = lam;
- continue;
- }
- if (in_view==TRUE) {
- if (prev_in_view==FALSE) { /* if prev. point was not in view, */
- if (lamprev<=lam1) { /* find rim point */
- lamc = lam1;
- if (latprev<=lat2) /* lower left */
- latc = lat2;
- else if (latprev>=lat1) /* upper left */
- latc = lat1;
- else /* left center */
- latc = lat + (latprev-lat)*(lamc-lam)/(lamprev-lam);
- }
- else if (lamprev>=lam2) {
- lamc = lam2;
- if (latprev>=lat1) /* upper right */
- latc = lat1;
- else if (latprev<=lat2) /* lower right */
- latc = lat2;
- else /* right center */
- latc = lat + (latprev-lat)*(lamc-lam)/(lamprev-lam);
- }
- else {
- if (latprev>=lat1) /* top center */
- latc = lat1;
- else /* bottom center */
- latc = lat2;
- lamc = lam + (lamprev-lam)*(latc-lat)/(latprev-lat);
- }
- h1c = (lamc-bcx) * xscale;
- h2c = - (latc-bcy) * yscale;
- x = h1c + CENTERX; /* move to rim point & plot it */
- y = h2c + CENTERY;
- Move (rp, x, y);
- xs = x;
- ys = y;
- plotpoint (xs, ys);
- h1prev = h1c;
- h2prev = h2c;
- area[j] = h1;
- area[j+1] = h2;
- j += 2;
- ++nrim_in;
- ++np;
- }
- if (h1!=h1prev || h2!=h2prev) {
- x = h1 + CENTERX; /* draw to current point */
- y = h2 + CENTERY;
- Draw (rp, x, y);
- Move (rp, x, y);
- area[j] = h1;
- area[j+1] = h2;
- j += 2;
- ++np;
- }
- h1prev = h1;
- h2prev = h2;
- }
- else { /* else out of view */
- if (prev_in_view==TRUE) { /* if previous point was in view, */
- if (lam<=lam1) { /* find rim point */
- lamc = lam1;
- if (lat<=lat2) /* lower left */
- latc = lat2;
- else if (lat>=lat1) /* upper left */
- latc = lat1;
- else /* left center */
- latc = lat + (latprev-lat)*(lamc-lam)/(lamprev-lam);
- }
- else if (lam>=lam2) {
- lamc = lam2;
- if (lat>=lat1) /* upper right */
- latc = lat1;
- else if (lat<=lat2) /* lower right */
- latc = lat2;
- else /* right center */
- latc = lat + (latprev-lat)*(lamc-lam)/(lamprev-lam);
- }
- else {
- if (lat>=lat1) /* top center */
- latc = lat1;
- else /* bottom center */
- latc = lat2;
- lamc = lam + (lamprev-lam)*(latc-lat)/(latprev-lat);
- }
- h1c = (lamc-bcx) * xscale;
- h2c = - (latc-bcy) * yscale;
- x = h1c + CENTERX; /* draw to rim point */
- y = h2c + CENTERY;
- Draw (rp, x, y);
- Move (rp, x, y);
- area[j] = h1;
- area[j+1] = h2;
- j += 2;
- ++nrim_out;
- ++np;
- }
- }
- prev_in_view = in_view; /* save status of current point */
- latprev = lat;
- lamprev = lam;
- }
- if (fill==FILL)
- box_tidy (lat1, lam1, lat2, lam2, /* fill partial areas */
- bcx, bcy, xscale, yscale);
- }
-
- /* ============================================================= */
-
- void box_tidy (lat1, lam1, lat2, lam2, bcx, bcy, xscale, yscale)
- /* color-fills partially-drawn */
- /* areas in box-view */
- double lat1, lam1, lat2, lam2, bcx, bcy, xscale, yscale;
-
- {
- double lat, lam;
- int i;
- short h1, h2;
- long x, y, color;
-
- i = 0;
- while (1) { /* check each special point */
- if (td[i]==0 && td[i+1]==0) /* if end of special points, */
- break; /* then all done */
- lat = td[i];
- lat /= 100.;
- lam = td[i+1];
- lam /= 100.;
- if ((lat<=lat1 && lat>=lat2) && /* if point is in view, */
- (lam>=lam1 && lam<=lam2)) { /* then get its screen */
- h1 = (lam-bcx) * xscale; /* coordinates */
- h2 = -(lat-bcy) * yscale;
- x = h1 + CENTERX; /* color-fill if current color */
- y = h2 + CENTERY; /* is blue */
- if ((color = ReadPixel (rp, x, y)) == BLUE)
- Flood (rp, 1, x, y);
- }
- i += 2;
- }
- }
-
- /* ============================================================= */
-
- void do_text (msgin, val) /* get user text input */
-
- struct IntuiMessage *msgin;
- long val;
-
- {
- extern void drawbox();
- struct IntuiMessage *msg, *msg1;
- struct Gadget *g;
- static char title_setdown[] = "Press Select button to position text";
- int x, y, xold, yold, pixlength;
- long oldpen;
-
- x = msgin->MouseX - GAD_LEFT-8; /* position the requester */
- y = msgin->MouseY - GAD_TOP-12 + 10*val + POPTITLEHEIGHT;
- if ((x+TWIDTH) >= WWIDTH)
- x = WWIDTH-TWIDTH-15;
- if (x < 10)
- x =10;
- if ((y+THEIGHT) >= WHEIGHT)
- y = WHEIGHT-THEIGHT-15;
- if (y<5)
- y = 5;
- req.LeftEdge = x;
- req.TopEdge = y;
- Request (&req, w); /* issue the request */
- ModifyIDCMP (w, GADGETUP); /* disable all but gadgetup event */
- ActivateGadget (&gad, w, &req);
- WaitPort (w->UserPort); /* wait for gadgetup event */
- while (1) {
- msg = (struct IntuiMessage *) GetMsg (w->UserPort);
- if (msg == NULL)
- WaitPort (w->UserPort);
- else if (msg->Class == GADGETUP) { /* check for correct gadget */
- g = (struct Gadget *) (msg->IAddress);
- if (g->GadgetID != GAD_FIRST)
- continue;
- pixlength = TextLength (rp, userinput, strlen(userinput));
- SetWindowTitles (w, title_setdown, -1);
- SetDrMd (rp, JAM2 | COMPLEMENT);
- SetPointer (w, transparent, transparent_size/4-2, 16,
- transparent_x_offset, transparent_y_offset);
- xold = msg->MouseX; /* current mouse position */
- yold = msg->MouseY;
- drawbox (xold, yold, xold+pixlength, yold-10);
- ModifyIDCMP (w, IDCMPFLAGS | MOUSEMOVE);
- WaitPort (w->UserPort); /* wait for mouse button */
- while (1) {
- msg1 = (struct IntuiMessage *) GetMsg (w->UserPort);
- if (msg1 == NULL)
- WaitPort (w->UserPort);
- else {
- x = msg1->MouseX; /* get current mouse position */
- y = msg1->MouseY; /* and erase old box */
- if (msg1->Code == SELECTDOWN) {
- drawbox (xold, yold, xold+pixlength, yold-10);
- break; /* done if select button pressed */
- }
- else if (msg1->Class == MOUSEMOVE) {
- ReplyMsg (msg1); /* else draw box at current position */
- drawbox (xold, yold, xold+pixlength, yold-10);
- drawbox (x, y, x+pixlength, y-10);
- xold = x;
- yold = y;
- }
- }
- }
- ReplyMsg (msg1);
- Move (rp, x, y); /* move to current mouse position */
- SetDrMd (rp, JAM1);
- oldpen = rp->FgPen;
- SetAPen (rp, WHITE); /* draw text in WHITE */
- Text (rp, userinput, strlen(userinput));
- SetAPen (rp, oldpen);
- SetDrMd (rp, JAM2);
- ModifyIDCMP (w, IDCMPFLAGS); /* enable original event types */
- SetPointer (w, arrow, arrow_size/4-2, 16,
- arrow_x_offset, arrow_y_offset);
- break;
- }
- }
- ReplyMsg (msg);
- }
-
- /* ================================================================ */
-
- void afill (pairs, pen) /* draws and fills a region */
- /* using AreaDraw function */
- short pairs; /* how many pairs of words */
- long pen; /* pen number to use */
-
- {
-
- short i, j;
- long x, y, oldpen;
-
- oldpen = rp->FgPen;
- SetAPen (rp, pen);
- x = area[0] + CENTERX;
- y = area[1] + CENTERY;
- if (x<0)
- x = 0;
- if (x>WWIDTH-1)
- x = WWIDTH-1;
- if (y<0)
- y = 0;
- if (y>WHEIGHT-1)
- y = WHEIGHT-1;
- AreaMove (rp, x, y);
- j = 2;
- for (i=1; i<pairs; i++) {
- if (area[j]==0 && area[j+1]==0)
- break;
- x = area[j] + CENTERX;
- y = area[j+1] + CENTERY;
- if (x<0)
- x = 0;
- if (x>WWIDTH-1)
- x = WWIDTH-1;
- if (y<0)
- y = 0;
- if (y>WHEIGHT-1)
- y = WHEIGHT-1;
- AreaDraw (rp, x, y);
- j += 2;
- }
- AreaEnd (rp);
- SetAPen (rp, oldpen);
- }
-
- /* ============================================================= */
-
- void adraw (pairs) /* draws area outlines */
-
- short pairs;
-
- {
-
- short i, j;
- long x, y, oldpen;
-
- oldpen = rp->FgPen;
- SetAPen (rp, ORANGE);
- x = area[0] + CENTERX;
- y = area[1] + CENTERY;
- if (x<0)
- x = 0;
- if (x>WWIDTH-1)
- x = WWIDTH-1;
- if (y<0)
- y = 0;
- if (y>WHEIGHT-1)
- y = WHEIGHT-1;
- Move (rp, x, y);
- j = 2;
- for (i=1; i<pairs; ++i) {
- if (area[j]==0 && area[j+1]==0)
- break;
- x = area[j] + CENTERX;
- y = area[j+1] + CENTERY;
- if (x<0)
- x = 0;
- if (x>WWIDTH-1)
- x = WWIDTH-1;
- if (y<0)
- y = 0;
- if (y>WHEIGHT-1)
- y = WHEIGHT-1;
- Draw (rp, x, y);
- Move (rp, x, y);
- j += 2;
- }
- SetAPen (rp, oldpen);
- }
-
- /* ============================================================= */
-
- void plotpoint (x, y) /* plots a single point */
-
- short x, y;
-
- {
-
- if (x<0)
- x = 0;
- if (x>WWIDTH-1)
- x = WWIDTH-1;
- if (y<0)
- y = 0;
- if (y>WHEIGHT-1)
- y = WHEIGHT-1;
- WritePixel (rp, x, y);
- }
-
- /* ============================================================= */
-
- short *svector (nl,nh) /* Allocates a short vector */
- /* with range [nl..nh] */
- int nl, nh;
-
- {
- extern char *calloc();
- extern void errors();
- short *v;
-
- v = (short*) calloc (1, (unsigned) (nh-nl+1)*sizeof(short));
- if (v==NULL)
- return (NULL);
- else
- return v-nl;
- }
-
- /* ============================================================= */
-
- void free_svector (v,nl,nh) /* Frees a short vector */
- /* allocated by svector */
- short *v;
- int nl, nh;
-
- {
-
- free ((char*) (v+nl));
- }
-