home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / csrpoly1.c < prev    next >
C/C++ Source or Header  |  1990-04-20  |  7KB  |  232 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    csrpoly1.c (Cursor Polygon)
  6.  * Purpose:    Manipulate vertex lists for drawing polygon cursor
  7.  * Subroutine:    grab_polygon_vertex()            returns: void
  8.  * Subroutine:    size_polygon()                returns: void
  9.  * Subroutine:    request_delete_polygon_vertex()        returns: int
  10.  * Subroutine:    size_polygon_from_file_coords()        returns: void
  11.  * Subroutine:    set_polygon_file_coords()        returns: void
  12.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  13.  *        You may do anything you like with this file except remove
  14.  *        this copyright.  The Smithsonian Astrophysical Observatory
  15.  *        makes no representations about the suitability of this
  16.  *        software for any purpose.  It is provided "as is" without
  17.  *        express or implied warranty.
  18.  * Modified:    {0} Michael VanHilst    initial version          4 June 1989
  19.  *        {n} <who> -- <does what> -- <when>
  20.  */
  21.  
  22. #include <X11/Xlib.h>        /* X window stuff */
  23. #include <X11/Xutil.h>        /* X window manager stuff */
  24. #include "hfiles/color.h"    /* cursor colors needed by Cursor.h */
  25. #include "hfiles/coord.h"    /* coord structs */
  26. #include "hfiles/cursor.h"    /* define cursor parameter structures */
  27. #include "hfiles/define.h"    /* define SQR, etc */
  28.  
  29. extern struct colorRec color;    /* need to know color.gcset */
  30.  
  31. #define GRAB_RANGE 8
  32.  
  33. /*
  34.  * Subroutine:    grab_polygon_vertex
  35.  * Purpose:    Identify or create polygon vertex for manipulation
  36.  *        Used when initiating a move or size action
  37.  * Called by:    control_cursor() in CursorCtrl.c
  38.  */
  39. void grab_polygon_vertex ( cursor, event, size )
  40.      struct cursorRec *cursor;
  41.      XEvent *event;        /* i: XbuttonEvent (ButtonPress) for x & y */
  42.      int size;            /* i: distinguish size action from move */
  43. {
  44.   int x, y;            /* l: coordinates of event */
  45.   int pt;            /* l: index of polygon vertex */
  46.   int closest_polygon_line();
  47.   void draw_cursor(), add_polygon_vertex();
  48.   static int on_polygon_vertex();
  49.  
  50.   /* erase existing cursor */
  51.   draw_cursor(cursor, &color.gcset.undraw);
  52.   x = event->xbutton.x;
  53.   y = event->xbutton.y;
  54.   /* close enough to grab and existing vertex? */
  55.   pt = on_polygon_vertex(x, y, cursor->points, cursor->poly_cnt);
  56.   if( pt >= 0 ) {
  57.     cursor->ctrl.active_vertex = pt;
  58.   } else {
  59.     if( size ) {
  60.       /* decide in which line to add new point */
  61.       cursor->ctrl.active_vertex =
  62.     closest_polygon_line(x, y, cursor->points, cursor->poly_cnt);
  63.       add_polygon_vertex(cursor, cursor->ctrl.active_vertex, x, y);
  64.     }
  65.   }
  66.   if( size ) {
  67.     /* size displaces one vertex */
  68.     cursor->poly[cursor->ctrl.active_vertex].unset = 1;
  69.   } else {
  70.     /* move displaces all vertices */
  71.     for( pt=0; pt<cursor->poly_cnt; pt++ )
  72.       cursor->poly[pt].unset = 1;
  73.   }
  74.   /* make cursor coordinates those of the active vertex */
  75.   cursor->win.x = cursor->points[cursor->ctrl.active_vertex].x;
  76.   cursor->win.y = cursor->points[cursor->ctrl.active_vertex].y;
  77.   cursor->win.X = (float)cursor->win.x + 0.5;
  78.   cursor->win.Y = (float)cursor->win.y + 0.5;
  79. }
  80.  
  81. /*
  82.  * Subroutine:    request_delete_polygon_vertex
  83.  * Purpose:    Remove a polygon vertex if mouse is close enough to grab it
  84.  * Returns:    1 if image must be redrawn, else 0
  85.  * Called by:    control_cursor() in CursorCtrl.c
  86.  */
  87. int request_delete_polygon_vertex ( cursor, event )
  88.      struct cursorRec *cursor;
  89.      XEvent *event;        /* i: XbuttonEvent (ButtonPress) for x & y */
  90. {
  91.   int i;
  92.   void delete_polygon_vertex(), draw_cursor();
  93.   static int on_polygon_vertex();
  94.  
  95.   i = on_polygon_vertex((int)event->xbutton.x, (int)event->xbutton.y,
  96.             cursor->points, cursor->poly_cnt);
  97.   if( i >= 0 ) {
  98.     /* if changing cursor messes up image, request repainted image */ 
  99.     if( cursor->overwrites_image_data ) {
  100.       delete_polygon_vertex(cursor, i);
  101.       return( 1 );
  102.     }
  103.     /* erase existing cursor */
  104.     draw_cursor(cursor, &color.gcset.undraw);
  105.     delete_polygon_vertex(cursor, i);
  106.     /* draw new cursor */
  107.     draw_cursor(cursor, cursor->draw);
  108.   }
  109.   return( 0 );
  110. }
  111.  
  112. /*
  113.  * Subroutine:    size_polygon
  114.  * Purpose:    Move the tracked vertex of the polygon
  115.  * Called by:    size_cursor() in CursorMove.c
  116.  */
  117. void size_polygon ( cursor, x, y )
  118.      struct cursorRec *cursor;
  119.      int x, y;
  120. {
  121.   void set_active_polygon_hashmark();
  122.  
  123.   cursor->points[cursor->ctrl.active_vertex].x = x;
  124.   cursor->points[cursor->ctrl.active_vertex].y = y;
  125.   if( cursor->ctrl.active_vertex == 0 ) {
  126.     /* if moving first point, don't forget that last point returns here */
  127.     cursor->points[cursor->poly_cnt].x = x;
  128.     cursor->points[cursor->poly_cnt].y = y;
  129.   }
  130.   set_active_polygon_hashmark(cursor);
  131. }
  132.  
  133. /*
  134.  * Subroutine:    set_polygon_file_coords
  135.  * Purpose:    Update all display coordinates and then the file coordinates
  136.  *        for vertices
  137.  * Called by:    control_cursor() in CursorCtrl.c
  138.  */
  139. void set_polygon_file_coords ( cursor, disptofile )
  140.      struct cursorRec *cursor;
  141.      Transform *disptofile;
  142. {
  143.   int i;
  144.   PolyPoint *poly;
  145.   void d_transform();
  146.  
  147.   /* update the cursor file coords */
  148.   d_transform(disptofile, cursor->win.X, cursor->win.Y,
  149.           &cursor->file.X, &cursor->file.Y);
  150.   /* update poly vertex file coords */
  151.   for( i=0; i<cursor->poly_cnt; i++ ) {
  152.     poly = &cursor->poly[i];
  153.     /* update any poly coords if they have changed since last noted */
  154.     if( poly->unset ) {
  155.       poly->winX = 0.5 + (float)cursor->points[i].x;
  156.       poly->winY = 0.5 + (float)cursor->points[i].y;
  157.       poly->unset = 0;
  158.     }
  159.     d_transform(disptofile, (double)poly->winX, (double)poly->winY,
  160.         &poly->fileX, &poly->fileY);
  161.   }
  162. }
  163.  
  164. /*
  165.  * Subroutine:    set_polygon_from_file_coords
  166.  * Purpose:    Update polygon coordinates from file coordinates for
  167.  *        current display window
  168.  * Called by:    adjust_cursor() in CursorCoord.c
  169.  * Called by:    start_polygon() in CursorPolyPt.c
  170.  * Called by:    make_polygon() in RegionMake.c
  171.  */
  172. void set_polygon_from_file_coords ( cursor, filetodisp, hash )
  173.      struct cursorRec *cursor;
  174.      Transform *filetodisp;
  175.      int hash;
  176. {
  177.   int i;
  178.   PolyPoint *poly;
  179.   float X, Y;
  180.   void d_transform(), set_polygon_hashmarks();
  181.  
  182.   for( i=0; i<cursor->poly_cnt; i++ ) {
  183.     poly = &cursor->poly[i];
  184.     d_transform(filetodisp, (double)poly->fileX, (double)poly->fileY,
  185.         &poly->winX, &poly->winY);
  186.     cursor->points[i].x = (short)poly->winX;
  187.     cursor->points[i].y = (short)poly->winY;
  188.     poly->unset = 0;
  189.   }
  190.   cursor->points[i].x = cursor->points[0].x;
  191.   cursor->points[i].y = cursor->points[0].y;
  192.   /* update vertex hash mark centers */
  193.   if( hash )
  194.     set_polygon_hashmarks(cursor);
  195.   /* update the cursor coords as well */
  196.   d_transform(filetodisp, (double)cursor->file.X, (double)cursor->file.Y,
  197.           &X, &Y);
  198.   cursor->win.X = X;
  199.   cursor->win.Y = Y;
  200.   cursor->win.x = (int)X;
  201.   cursor->win.y = (int)Y;
  202. }
  203.  
  204. /*
  205.  * Subroutine:    on_polygon_vertex
  206.  * Purpose:    Test for being on a polygon point, return its index
  207.  * Note:    If more than one vertex are within range, choose closest
  208.  * Note:    (if ambiguity, favor point towards end - top down search)
  209.  */
  210. static int on_polygon_vertex ( x, y, vertex, cnt )
  211.      int x, y;
  212.      XPoint *vertex;
  213.      int cnt;
  214. {
  215.   register int i;
  216.   int match = -1;
  217.  
  218.   for( i=cnt-1; i>=0; i-- ) {
  219.     if( (abs(x - vertex[i].x) < GRAB_RANGE) &&
  220.         (abs(y - vertex[i].y) < GRAB_RANGE) ) {
  221.       if( match >= 0 ) {
  222.     /* if not only point within range, compare */
  223.     if( (SQR(vertex[match].x - x) + SQR(vertex[match].y - y)) >
  224.         (SQR(vertex[i].x - x) + SQR(vertex[i].y - y)) )
  225.       match = i;
  226.       } else
  227.     match = i;
  228.     }
  229.   }
  230.   return( match );
  231. }
  232.