home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / rgnmake.c < prev    next >
C/C++ Source or Header  |  1991-08-03  |  10KB  |  332 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    rgnmake.c (Region Make)
  6.  * Purpose:    Create cursor regions given sets of parameters
  7.  * Subroutine:    make_next_region()        returns: void
  8.  * Xlib calls:    none
  9.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  10.  *        You may do anything you like with this file except remove
  11.  *        this copyright.  The Smithsonian Astrophysical Observatory
  12.  *        makes no representations about the suitability of this
  13.  *        software for any purpose.  It is provided "as is" without
  14.  *        express or implied warranty.
  15.  * Modified:    {0} Michael VanHilst    initial version          11 May 1989
  16.  *        {1} MVH box dims are read as diameters           7 Dec 1989
  17.  *        {2} MVH support for text and arrow label cursors   1 Jan 1991
  18.  *        {n} <who> -- <does what> -- <when>
  19.  */
  20.  
  21. #ifndef VMS
  22. #ifdef SYSV
  23. #include <string.h>        /*  strlen, strcat, strcpy, strrchr  */
  24. #else
  25. #include <strings.h>        /*  strlen, strcat, strcpy, rindex  */
  26. #define strchr index
  27. #endif
  28. #else
  29. #include <string.h>        /*  strlen, strcat, strcpy, strrchr  */
  30. #endif
  31.  
  32. #include <stdio.h>        /* get stderr, define sscanf */
  33. #include <math.h>        /* sin, cos, etc */
  34. #include <X11/Xlib.h>        /* X window stuff */
  35. #include <X11/Xutil.h>        /* X window manager stuff */
  36. #include "hfiles/constant.h"    /* define codes */
  37. #include "hfiles/define.h"    /* TWO_PI */
  38. #include "hfiles/struct.h"    /* declare structure types */
  39. #include "hfiles/extern.h"    /* extern main SAOimage parameter structures */
  40.  
  41.  
  42. /*  Amount of space for string is actually (CURSOR_MAX - 1)*sizeof(XPoint)  */
  43. struct curText {
  44.   int char_cnt;
  45.   char string[CURSOR_MAX*2];
  46. };
  47.  
  48.  
  49. #ifdef ANSIC
  50.  
  51. void        make_next_region(    int type, char *line, int exclude,
  52.                 int draw, float *scratch, int scratch_max);
  53. static void parse_error(    char* line);
  54. static void make_annuli(    struct cursorRec *region, char *line,
  55.                 float *radii, int radii_max);
  56. void        make_polygon(    char *line, int exclude, int draw,
  57.                 float *vertex_coord, int coord_max);
  58. void        make_polygon(    char *line, int exclude, int draw,
  59.                 float *vertex_coord, int coord_max);
  60. static int  parse_coords(    char *line, float *coord, int maxcnt);
  61.  
  62. #else
  63.  
  64.   static void make_annuli(), parse_error();
  65.   static int parse_coords();
  66.   struct cursorRec *get_new_cursor();
  67.   char *next_token();
  68.   void set_cursor_from_file_coords(), disp_cursor();
  69.   void make_polygon(), free_cursor();
  70.   int parse_radii();
  71.   void set_cursor_from_file_coords(), make_new_annulus();
  72.   void set_polygon_from_file_coords();
  73.  
  74. #endif
  75.  
  76.  
  77. #define DEG(r) ((360.0 / TWO_PI) * (r))
  78. #define RAD(d) ((TWO_PI / 360.0) * (d))
  79.  
  80. extern int CircleCnt;
  81. extern int EllipseCnt;
  82.  
  83.  
  84. /*  Subroutine:    make_next_region
  85.  *  Purpose:    Make and install a region given basic file coord parameters
  86.  */
  87. #ifdef ANSIC
  88. void make_next_region( int type, char *line, int exclude,
  89.                int draw, float *scratch, int scratch_max )
  90. #else
  91. void make_next_region( type, line, exclude, draw, scratch, scratch_max )
  92.      int type;        /* i: cursor type */
  93.      char *line;    /* i: ascii string with parameters */
  94.      int exclude;    /* i: region-is-exclude_region */
  95.      int draw;        /* i: draw-region-after-making-it */
  96.      float *scratch;    /* i: scratch space for list of floats */
  97.      int scratch_max;    /* i: size of scratch space */
  98. #endif
  99. {
  100.   struct cursorRec *region;
  101.   float angle, tempX, tempY;
  102.   int point_cnt, tokens, char_cnt;
  103.   int annuli = 0;
  104.  
  105.   switch( type ) {
  106.   case COP_Point:
  107.     point_cnt = 0;
  108.     break;
  109.   case COP_Box:
  110.     point_cnt = 5;
  111.     break;
  112.   case COP_Annuli:
  113.     annuli = 1;
  114.     type = COP_Circle;
  115.   case COP_Circle:
  116.     point_cnt = CircleCnt + 1;
  117.     break;
  118.   case COP_Ellipse:
  119.     point_cnt = EllipseCnt + 1;
  120.     break;
  121.   case COP_Arrow:
  122.     point_cnt = 6;
  123.     break;
  124.   case COP_Text:
  125.     if( 3 != sscanf(line, "%f%f%d", &tempX, &tempY, &char_cnt) ) {
  126.       parse_error(line);
  127.       return;
  128.     }
  129.     point_cnt = ((char_cnt + 1) / sizeof(XPoint)) + 2;
  130.     break;
  131.   case COP_Polygon:
  132.     make_polygon(line, exclude, draw, scratch, scratch_max);
  133.   default:
  134.     return;
  135.   }
  136.   region = get_new_cursor(point_cnt, 0);
  137.   region->type = type;
  138.   region->point_cnt = point_cnt;
  139.   if( (region->next_region = cursor.next_region) != NULL )
  140.     region->index = cursor.next_region->index + 1;
  141.   else
  142.     region->index = 1;
  143.   cursor.next_region = region;
  144.   /*  Put in text cursor info  */
  145.   if( type == COP_Text ) {
  146.     struct curText *curtext = (struct curText *)cursor.next_region->points;
  147.     curtext->char_cnt = char_cnt;
  148.     line = strchr(line, '\"');
  149.     (void)strncpy(curtext->string, &line[1], char_cnt);
  150.     region->file.X = tempX;
  151.     region->file.Y = tempY;
  152.   } else {
  153.     tokens = sscanf(line, "%f%f%f%f%f", ®ion->file.X, ®ion->file.Y,
  154.             ®ion->file.Xdim, ®ion->file.Ydim, &angle);
  155.     if( type == COP_Box ) {
  156.       /*  Boxes in PROS use diameter, internally they use radius  */
  157.       region->file.Xdim *= 0.5;
  158.       region->file.Ydim *= 0.5;
  159.     }
  160.     if( (tokens > 4) && (type != COP_Circle) && (type != COP_Point) ) {
  161.       region->rot.angle = RAD((double)angle);
  162.       region->rot.cos = cos(PI - region->rot.angle);
  163.       region->rot.sin = sin(PI - region->rot.angle);
  164.     } else {
  165.       region->rot.angle = 0.0;
  166.       region->rot.cos = -1.0;
  167.       region->rot.sin = 0.0;
  168.       if( (tokens < 3) || (type == COP_Point) ) {
  169.     if( type != COP_Point ) {
  170.       parse_error(line);
  171.       cursor.next_region = region->next_region;
  172.       free_cursor (region);
  173.       return;
  174.     } else {
  175.       region->file.Xdim = 0.0;
  176.       /*  Recurse on a list of points  */
  177.       if( tokens >= 4 ) {
  178.         /*  Advance to next coordinate pair  */
  179.         line = next_token (line, 2);
  180.         make_next_region(type, line, exclude, draw, scratch, scratch_max);
  181.       }
  182.     }
  183.     if( (tokens < 4) || (type == COP_Circle) )
  184.       region->file.Ydim = region->file.Xdim;
  185.       }
  186.     }
  187.   }
  188.   if( (region->exclude_region = exclude) )
  189.     region->draw = &color.gcset.excl;
  190.   else
  191.     region->draw = &color.gcset.incl;
  192.   region->win.display = dispbox.display;
  193.   region->win.ID = dispbox.ID;
  194.   region->overwrites_image_data = 1;
  195.   /* in case of circular annuli, this was just the beginning */
  196.   if( annuli ) {
  197.     region->annuli = 1;
  198.     make_annuli(region, line, scratch, scratch_max);
  199.   } else {
  200.     set_cursor_from_file_coords(region, &coord.filetodisp);
  201.   }
  202.   if( draw )
  203.     disp_cursor(region);
  204. }
  205.  
  206.  
  207. /*  Subroutine:    parse_error
  208.  *  Purpose:    Print parsing error message
  209.  */
  210. #ifdef ANSIC
  211. static void parse_error( char* line )
  212. #else
  213. static void parse_error( line )
  214.   char* line;
  215. #endif
  216. {
  217.   (void)fprintf(stderr, "Parse error: too few parameters parsed\n");
  218.   (void)fprintf(stderr, "-> %s\n", line);
  219. }
  220.  
  221.  
  222. /*  Subroutine:    make_annuli
  223.  *  Purpose:    Make circular annuli given base region and string of radii
  224.  *  Note:    Base region is circle of first radius
  225.  *  Method:    Make base region as each ring, then copy as one of its annuli
  226.  *        (mimics procedure user would take).
  227.  *  Called by:    make_region() above
  228.  */
  229. #ifdef ANSIC
  230. static void make_annuli ( struct cursorRec *region, char *line,
  231.               float *radii, int radii_max )
  232. #else
  233. static void make_annuli ( region, line, radii, radii_max )
  234.      struct cursorRec *region;
  235.      char *line;
  236.      float *radii;
  237.      int radii_max;
  238. #endif
  239. {
  240.   int i, cnt;
  241.  
  242.   /*  Advance beyond center coords  */
  243.   line = next_token(line, 2);
  244.   cnt = parse_radii(line, radii, radii_max);
  245.   /*  Reverse order for ascending insert sort from list in ascending order  */
  246.   for( i = cnt - 1; i >= 0; i-- ) {
  247.     region->file.Xdim = radii[i];
  248.     region->file.Ydim = region->file.Xdim;
  249.     set_cursor_from_file_coords(region, &coord.filetodisp);
  250.     make_new_annulus(region);
  251.   }
  252. }
  253.  
  254.  
  255. /*  Subroutine:    parse_coords
  256.  *  Purpose:    Parse coordinate pairs off the line
  257.  *  Called by:    make_polygon() below
  258.  */
  259. #ifdef ANSIC
  260. static int parse_coords ( char *line, float *coord, int maxcnt )
  261. #else
  262. static int parse_coords ( line, coord, maxcnt )
  263.      char *line;
  264.      float *coord;
  265.      int maxcnt;
  266. #endif
  267. {
  268.   int i;
  269.  
  270.   /*  Keep reading while there are tokens on the line  */
  271.   for( i=0; (line != NULL) && (i < maxcnt); i+= 2 ) {
  272.     if( sscanf(line, "%f%f", &coord[i], &coord[i+1]) != 2 )
  273.       return( 0 );
  274.     line = next_token(line, 2);
  275.   }
  276.   return( i );
  277. }
  278.  
  279.  
  280. /*  Subroutine:    make_polygon
  281.  *  Purpose:    Parse line and make a polygon region
  282.  */
  283. #ifdef ANSIC
  284. void make_polygon ( char *line, int exclude, int draw, float *vertex_coord,
  285.             int coord_max )
  286. #else
  287. void make_polygon ( line, exclude, draw, vertex_coord, coord_max )
  288.      char *line;
  289.      int exclude;
  290.      int draw;
  291.      float *vertex_coord;
  292.      int coord_max;
  293. #endif
  294. {
  295.   int i, j;
  296.   int cnt;
  297.   struct cursorRec *region;
  298.  
  299.   cnt = parse_coords(line, vertex_coord, coord_max);
  300.   if( cnt % 2 ) {
  301.     (void)fprintf(stderr, "Parse error: odd number for pairs: %d\n", cnt);
  302.     (void)fprintf(stderr, "-> %s\n", line);
  303.     return;
  304.   }
  305.   cnt /= 2;
  306.   region = get_new_cursor(cnt + 1, cnt);
  307.   region->type = COP_Polygon;
  308.   region->poly_cnt = cnt;
  309.   region->point_cnt = cnt + 1;
  310.   for( j=0, i=0; i<cnt; i++ ) {
  311.     region->poly[i].fileX = vertex_coord[j++];
  312.     region->poly[i].fileY = vertex_coord[j++];
  313.   }
  314.   region->file.X = vertex_coord[0];
  315.   region->file.Y = vertex_coord[1];
  316.   set_polygon_from_file_coords(region, &coord.filetodisp, 0);
  317.   if( (region->next_region = cursor.next_region) != NULL )
  318.     region->index = cursor.next_region->index + 1;
  319.   else
  320.     region->index = 1;
  321.   cursor.next_region = region;
  322.   if( (region->exclude_region = exclude) )
  323.     region->draw = &color.gcset.excl;
  324.   else
  325.     region->draw = &color.gcset.incl;
  326.   region->win.display = dispbox.display;
  327.   region->win.ID = dispbox.ID;
  328.   region->overwrites_image_data = 1;
  329.   if( draw )
  330.     disp_cursor(region);
  331. }
  332.