Draw Diagonal Hatch-lines Inside A Set of Polygons, With C Code Sample
© 2009 Darel Rex Finley.  This complete article, unmodified, may be freely distributed for educational purposes.



Suppose you have a set of polygons, like this:



And you want to draw diagonal hatch lines at a 45° angle (or some other angle), like this:



How do you do it?

First, rotate the whole coordinate system so that the hatch-lines will be horizontal, like so:



Then, use the previously described efficient polygon fill technique to create horizontal rows of nodes, and connect them with line segments, which gives you this:



Finally, rotate the hatch lines back to the original coordinate system to get the desired effect:




C Code Sample

//  public-domain code by Darel Rex Finley, 2009
//  See diagrams at http://alienryderflex.com/polygon_hatchline_fill



//  This function returns NO if MAX_NODES is exceeded, in which case some
//  of the stripes may have been drawn, but not all of them.


bool drawDiagonalStripes(long polygonCount, long *polygonCorners,
double **polygons, double spacing) {

  #define  MAX_NODES          1000
  #define  FAR_FAR_AWAY  999999999.

  double  spanMin= FAR_FAR_AWAY, theCos, theSin, nodeX[MAX_NODES] ;
  double  spanMax=-FAR_FAR_AWAY, x, y, a, b, newX, stripeY, swap  ;
  long    i, j, k, spanStart, spanEnd, nodeCount, step ;

  //  Create a 45-degree angle for stripes.
  theCos=sqrt(.5);
  theSin=sqrt(.5);

  //  Loop to determine the span over which diagonal lines must be drawn.
  for   (i=0; i<polygonCount     ; i++) {
    for (j=0; j<polygonCorners[i]; j++) {
      x=polygons[i][j*2  ];
      y=polygons[i][j*2+1];

      //  Rotate the point, since the stripes may be at an angle.
      y=y*theCos-x*theSin;

      //  Adjust the span.
      if (spanMin>y) spanMin=y;
      if (spanMax<y) spanMax=y; }}

  //  Turn the span into a discrete step range.
  spanStart=(long) floor(spanMin/spacing)-1;
  spanEnd  =(long) floor(spanMax/spacing)+1;

  //  Loop to create all stripes.
  for (step=spanStart; step<=spanEnd; step++) {
    nodeCount=0; stripeY=spacing*(double) step;

    //  Loop to build a node list for one row of stripes.
    for   (i=0; i<polygonCount     ; i++) {
      k=polygonCorners[i]-1;
      for (j=0; j<polygonCorners[i]; j++) {
        a=polygons[i][k*2  ];
        b=polygons[i][k*2+1];
        x=polygons[i][j*2  ];
        y=polygons[i][j*2+1];

        //  Rotate the points, since the stripes may be at an angle.
        newX=a*theCos+b*theSin;
        b   =b*theCos-a*theSin; a=newX;
        newX=x*theCos+y*theSin;
        y   =y*theCos-x*theSin; x=newX;

        //  Find the node, if any.
        if (b<stripeY && y>=stripeY
        ||  y<stripeY && b>=stripeY) {
          if (nodeCount>=MAX_NODES) return NO;
          nodeX[nodeCount++]=a+(x-a)*(stripeY-b)/(y-b); }

        k=j; }}

    //  Sort the node list.
    i=0;
    while (i<nodeCount-1) {
      if (nodeX[i]<=nodeX[i+1]) i++;
      else {
        swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--; }}

    //  Loop to draw one row of stripe segments.
    for (i=0; i<nodeCount; i+=2) {

      //  Rotate the points back to their original coordinate system.
      a=nodeX[i  ]*theCos-   stripeY*theSin;
      b=   stripeY*theCos+nodeX[i  ]*theSin;
      x=nodeX[i+1]*theCos-   stripeY*theSin;
      y=   stripeY*theCos+nodeX[i+1]*theSin;

      //  Draw a single stripe segment.
      drawLineSegmentABtoXY(a,b,x,y); }}

  //  Success.
  return YES; }


In the above code, the function drawLineSegmentABtoXY() has not been defined.  You should substitute in whatever line-segment-drawing function you actually plan to use.


Send me an e-mail!

Does the brace style in the above code sample freak you out?  Click here to see it explained in a new window.

Back to tutorials.