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

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    csrarea.c (Cursor Area)
  6.  * Purpose:    Calculate areas of cursors
  7.  * Subroutine:    cursor_area();                returns: double
  8.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  9.  *        You may do anything you like with this file except remove
  10.  *        this copyright.  The Smithsonian Astrophysical Observatory
  11.  *        makes no representations about the suitability of this
  12.  *        software for any purpose.  It is provided "as is" without
  13.  *        express or implied warranty.
  14.  * Modified:    {0} Michael VanHilst    initial version          4 June 1989
  15.  *        {n} <who> -- <does what> -- <when>
  16.  */
  17.  
  18. #include <X11/Xlib.h>        /* X window stuff */
  19. #include <X11/Xutil.h>        /* X window manager stuff */
  20. #include "hfiles/color.h"    /* cursor colors needed by Cursor.h */
  21. #include "hfiles/constant.h"    /* define codes */
  22. #include "hfiles/cursor.h"    /* define cursor parameter structures */
  23.  
  24. #define PI 3.14159265358979323846
  25.  
  26. /*
  27.  * Subroutine:    cursor_area
  28.  * Purpose:    Calculate area, in float units file pixels, enclosed by cursor
  29.  * Method:    Use mathematical formula appropriate to cursor type
  30.  */
  31. double cursor_area ( cursor, user_info )
  32.      struct cursorRec *cursor;
  33.      int user_info;        /* flag, data is for user info */
  34. {
  35.   double area;
  36.   int i, j;
  37.   static int test_cross();
  38.  
  39.   switch( cursor->type ) {
  40.   case COP_Circle:
  41.     area = PI * cursor->file.Xdim * cursor->file.Xdim;
  42.     break;
  43.   case COP_Ellipse:
  44.     area = PI * cursor->file.Xdim * cursor->file.Ydim;
  45.     break;
  46.   case COP_Box:
  47.     area = cursor->file.Xdim * cursor->file.Ydim * 4.0;
  48.     break;
  49.   case COP_Point:
  50.     area = 0.0;
  51.     break;
  52.   case COP_Polygon:
  53.     /* polygon area is sum of signed areas between each edge and x axis */
  54.     /* (except when polygon edges cross one another) */
  55.     area = 0;
  56.     if( user_info &&
  57.     test_cross(cursor->poly, cursor->poly_cnt, cursor->poly_cnt - 1, 0) )
  58.       return( -1.0 );
  59.     j = cursor->poly_cnt - 1;
  60.     /* each area is (x1-x2)*(y1+y2)/2, /2 will be done once at end */
  61.     for( i=0; i<cursor->poly_cnt; i++ ) {
  62.       area += (cursor->poly[i].fileX - cursor->poly[j].fileX) *
  63.     (cursor->poly[i].fileY + cursor->poly[j].fileY);
  64.       j = i;
  65.     }
  66.     /* sign of area depends on clockwise or counter-clockwise ordering */
  67.     if( area < 0.0 ) area *= -0.5;
  68.     else area *= 0.5;
  69.   default:
  70.     break;
  71.   }
  72.   return( area );
  73. }
  74.  
  75. /* end points of a polygon edge against which to test others for crossing */
  76. static double x11, y11, x12, y12;
  77.  
  78. /*
  79.  * Subroutine:    test_cross
  80.  * Purpose:    Test the edges of a polygon to see if any cross each other
  81.  * method:    Starting with last edge, test each edge against subsequent
  82.  *        edges.  Routine recurses with for next edge.  Adjacent edges
  83.  *        are not tested since neighbors cannot cross but neighbors do
  84.  *        share a common point.
  85.  */
  86. static int test_cross ( pt, cnt, j, i )
  87.      PolyPoint *pt;    /* list of vertices */
  88.      int cnt;        /* number of vertices */
  89.      int j, i;        /* two vertices at ends of edge being tested */
  90. {
  91.   int k;
  92.   static int intercept();
  93.  
  94.   if( (i+2) >= cnt ) {
  95.     return( 0 );
  96.   } else {
  97.     x11 = pt[j].fileX;
  98.     y11 = pt[j].fileY;
  99.     x12 = pt[i].fileX;
  100.     y12 = pt[i].fileY;
  101.     /* test each subsequent edge against this edge (but not adjacent edges) */
  102.     for( k=i+2; k<cnt; k++ ) {
  103.       if( ((k+1) != j) &&
  104.           intercept(pt[k-1].fileX, pt[k-1].fileY, pt[k].fileX, pt[k].fileY) )
  105.     return(1);
  106.     }
  107.     /* recurse on to test next edge */
  108.     return( test_cross(pt, cnt, i, i+1) );
  109.   }
  110. }
  111.  
  112. /*
  113.  * Subroutine:    intercept
  114.  * Purpose:    Test this edge against the reference edge
  115.  * Method:    A) Minmax test if two edges have overlapping coordinates.
  116.  *        B) Calculate the intercept of the two lines.
  117.  *        C) Test if intercept is within both edges.
  118.  */
  119. static int intercept ( x21, y21, x22, y22 )
  120.      double x21, y21, x22, y22;
  121. {
  122.   double xpt, ypt, m1, m2;
  123.  
  124.   /* try minmax test */
  125.   if( x11 > x12 ) {
  126.     if( ((x12 >= x21) && (x12 >= x22)) || ((x11 <= x21) && (x11 <= x22)) )
  127.       return( 0 );
  128.   } else {
  129.     if( ((x11 >= x21) && (x11 >= x22)) || ((x12 <= x21) && (x12 <= x22)) )
  130.       return( 0 );
  131.   }
  132.   if( y11 > y21 ) {
  133.     if( ((y12 >= y21) && (y12 >= y22)) || ((y11 <= y21) && (y11 <= y22)) )
  134.       return( 0 );
  135.   } else {
  136.     if( ((y11 >= y21) && (y11 >= y22)) || ((y12 <= y21) && (y12 <= y22)) )
  137.       return( 0 );
  138.   }
  139.   /* compute intercept of line */
  140.   if( x12 == x11 ) {
  141.     xpt = x12;
  142.     ypt = y21 + ((xpt - x21) * (y22 - y21) / (x22 - x21));
  143.   } else if( x22 == x21 ) {
  144.     xpt = x21;
  145.     ypt = y11 + ((xpt - x11) * (y12 - y11) / (x12 - x11));
  146.   } else {
  147.     m1 = (y12 - y11) / (x12 - x11);
  148.     m2 = (y22 - y21) / (x22 - x21);
  149.     xpt = ((x11 * m1) - (x21 * m2) + (y21 - y11)) / (m1 - m2);
  150.     ypt = y11 + (m1 * (xpt - x11));
  151.   }
  152.   /* check for being on both edges */
  153.   /* intercept x within x's of reference edge */
  154.   if( x11 > x12 ) {
  155.     if( (x12 > xpt) || (xpt > x11) )
  156.       return( 0 );
  157.   } else {
  158.     if( (x12 < xpt) || (xpt < x11) )
  159.       return( 0 );
  160.   }
  161.   /* intercept y within y's of reference edge */
  162.   if( y11 > y12 ) {
  163.     if( (y12 > ypt) || (ypt > y11) )
  164.       return( 0 );
  165.   } else {
  166.     if( (y12 < ypt) || (ypt < y11) )
  167.       return( 0 );
  168.   }
  169.   /* intercept x within x's of test edge */
  170.   if( x21 > x22 ) {
  171.     if( (x22 > xpt) || (xpt > x21) )
  172.       return( 0 );
  173.   } else {
  174.     if( (x22 < xpt) || (xpt < x21) )
  175.       return( 0 );
  176.   }
  177.   /* intercept y within y's of test edge */
  178.   if( y21 > y22 ) {
  179.     if( (y22 > ypt) || (ypt > y21) )
  180.       return( 0 );
  181.   } else {
  182.     if( (y22 < ypt) || (ypt < y21) )
  183.       return( 0 );
  184.   }
  185.   return( 1 );
  186. }
  187.