IFillPol.c
资源名称:ilib [点击查看]
上传用户:changbiao
上传日期:2007-01-13
资源大小:141k
文件大小:5k
源码类别:

图片显示

开发平台:

C/C++

  1. /*
  2.  * IFillPol.c
  3.  *
  4.  * Image library
  5.  *
  6.  * Description:
  7.  * Portable routines to manipulate raster images.
  8.  *
  9.  * Limitations:
  10.  * This function only handles CONVEX non-intersecting polygons.
  11.  * That means if you scan from left to right, you will pass through
  12.  * the polygon once.  This make this algorith (1) faster and
  13.  * (2) easier.  We also assume this is _closed_ polygon.
  14.  *
  15.  * History:
  16.  * 22-Nov-99 Craig Knudsen cknudsen@radix.net
  17.  * Created
  18.  *
  19.  ****************************************************************************/
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <ctype.h>
  23. #include <memory.h>
  24. #include <math.h>
  25. #include "Ilib.h"
  26. #include "IlibP.h"
  27. typedef struct {
  28.   int x1, y1, x2, y2;
  29.   double slope;
  30. } linetype;
  31. #undef max
  32. #define max(a,b) ( a > b ) ? a : b
  33. #undef min
  34. #define min(a,b) ( a < b ) ? a : b
  35. /*
  36. ** Calculate slope.  Keep in mind that our y coordinate is reverse
  37. ** compared to the standard math coordinate system.
  38. */
  39. static void set_line_slope ( line )
  40. linetype *line;
  41. {
  42.   if ( abs ( line->x2 - line->x1 ) < 0.01 )
  43.     line->slope = 0;
  44.   else
  45.     line->slope = ( (double)line->y2 - (double)line->y1 ) /
  46.       ( (double) line->x2 - (double) line->x1 );
  47. }
  48. /*
  49. ** Does a line include the specified y value?
  50. */
  51. static int line_includes_y_value ( line, yval )
  52. linetype line;
  53. int yval;
  54. {
  55.   if ( line.y1 <= yval && line.y2 >= yval )
  56.     return 1;
  57.   if ( line.y2 <= yval && line.y1 >= yval )
  58.     return 1;
  59.   return 0;
  60. }
  61. static int get_intersection_x_value ( line, yval )
  62. linetype line;
  63. int yval;
  64. {
  65.   double b, ret;
  66.   if ( line.x1 == line.x2 )
  67.     ret = (double) line.x1;
  68.   else if ( line.y1 == line.y2 )
  69.     ret = (double) line.x1;
  70.   else {
  71.     /* calc b now
  72.     ** y = mx + b
  73.     ** b = y - mx
  74.     */
  75.     b = line.y2 - ( line.slope * (double) line.x2 );
  76.     /*
  77.     ** now determine x value
  78.     ** x = (y - b) / m)
  79.     */
  80.     ret = ( ( (double)yval - b ) / line.slope );
  81.   }
  82.   return (int) ret;
  83. }
  84. IError IFillPolygon ( image, gc, points, npoints )
  85. IImage image;
  86. IGC gc;
  87. IPoint *points;
  88. int npoints;
  89. {
  90.   IGCP *gcp = (IGCP *)gc;
  91.   IImageP *imagep = (IImageP *)image;
  92.   int loop;
  93.   int maxY, minY;
  94.   IPoint *pts;
  95.   int left, right, xval;
  96.   int npts, yloop;
  97.   linetype *lines;
  98.   int nlines;
  99.   int found;
  100.   int save_line_width;
  101.   if ( ! gcp )
  102.     return ( IInvalidGC );
  103.   if ( gcp->magic != IMAGIC_GC )
  104.     return ( IInvalidGC );
  105.   if ( ! imagep )
  106.     return ( IInvalidImage );
  107.   if ( imagep->magic != IMAGIC_IMAGE )
  108.     return ( IInvalidImage );
  109.   if ( npoints < 2 )
  110.     return ( INoError );
  111.   save_line_width = gcp->line_width;
  112.   gcp->line_width = 1;
  113.   /* create an array of lines */
  114.   nlines = npoints;
  115.   lines = (linetype *) malloc ( sizeof ( linetype ) * nlines );
  116.   for ( loop = 1; loop < npoints; loop++ ) {
  117.     lines[loop].x1 = points[loop-1].x;
  118.     lines[loop].y1 = points[loop-1].y;
  119.     lines[loop].x2 = points[loop].x;
  120.     lines[loop].y2 = points[loop].y;
  121.     set_line_slope ( &lines[loop] );
  122.   }
  123.   /* last line connects first and last points */
  124.   lines[0].x1 = points[npoints-1].x;
  125.   lines[0].y1 = points[npoints-1].y;
  126.   lines[0].x2 = points[0].x;
  127.   lines[0].y2 = points[0].y;
  128.   set_line_slope ( &lines[0] );
  129. /* debugging code
  130.   for ( loop = 0; loop < nlines; loop++ ) {
  131.     printf ( "Line %d: (%d,%d) to (%d,%d) with slope = %.2fn",
  132.       loop, lines[loop].x1, lines[loop].y1, lines[loop].x2, lines[loop].y2,
  133.       (float)lines[loop].slope );
  134.   }
  135. */
  136.   /* calculate the min and max y values */
  137.   minY = maxY = points[0].y;
  138.   for ( loop = 1; loop < npoints; loop++ ) {
  139.     minY = points[loop].y < minY ? points[loop].y : minY;
  140.     maxY = points[loop].y > maxY ? points[loop].y : maxY;
  141.   }
  142.   npts = maxY - minY + 1;
  143.   pts = (IPoint *) malloc ( sizeof ( IPoint ) * npts );
  144.   memset ( pts, '', sizeof ( IPoint ) * npts );
  145.   /* now loop through from lowest y to top y */
  146.   for ( yloop = minY; yloop <= maxY; yloop++ ) {
  147.     /* now determine which lines of this polygon intersect this y value */
  148.     found = 0;
  149.     for ( loop = 0; loop < nlines; loop++ ) {
  150.       if ( line_includes_y_value ( lines[loop], yloop ) ) {
  151.         /* don't know if this is the left-most or right-most if this is
  152.         ** first point found...
  153.         */
  154.         if ( ! found ) {
  155.           /* get intersection of this line and y */
  156.           if ( lines[loop].y1 == lines[loop].y2 ) {
  157.             left = min ( lines[loop].x1, lines[loop].x2 );
  158.             right = max ( lines[loop].x1, lines[loop].x2 );
  159.           } else {
  160.             left = right = get_intersection_x_value ( lines[loop], yloop );
  161.           }
  162.           found++;
  163.         } else {
  164.           if ( lines[loop].y1 == lines[loop].y2 ) {
  165.             left = min ( left, lines[loop].x1 );
  166.             left = min ( left, lines[loop].x2 );
  167.             right = max ( right, lines[loop].x1 );
  168.             right = max ( right, lines[loop].x2 );
  169.           } else {
  170.             xval = get_intersection_x_value ( lines[loop], yloop );
  171.             left = min ( left, xval );
  172.             right = max ( right, xval );
  173.           }
  174.           found++;
  175.           /* printf ( "left = %d, right = %dn", left, right ); */
  176.         }
  177.       }
  178.     }
  179.     if ( found >= 2 ) {
  180.       IDrawLine ( image, gc, left, yloop, right, yloop );
  181.     } else if ( found == 1 && left == right ) {
  182.       IDrawLine ( image, gc, left, yloop, right, yloop );
  183.     } else if ( found == 1 && left != right ) {
  184.       /* Eek.  This really shouldn't happen */
  185.       fprintf ( stderr, "Ilib bug no. 34534345n" );
  186.     }
  187.   }
  188.   free ( lines );
  189.   free ( pts );
  190.   gcp->line_width = save_line_width;
  191.  
  192.   return ( INoError );
  193. }