IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 8, 2019, 9:11:38 PM (7 years ago)
Author:
eugene
Message:

add general polygon and polyfill functions

Location:
branches/eam_branches/ohana.20190329/src/libkapa
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ohana.20190329/src/libkapa/include/kapa.h

    r40783 r40926  
    4545  KAPA_PLOT_BARS_OUTLINE =  4,
    4646  KAPA_PLOT_BARS_OUTFILL =  5,
    47   KAPA_PLOT_INVALID_MAX  =  6,
     47  KAPA_PLOT_POLYGON      =  6,
     48  KAPA_PLOT_POLYFILL     =  7,
     49  KAPA_PLOT_INVALID_MAX  =  8,
    4850} KapaPlotStyle;
    4951
     
    320322void bDrawTriOpen  (bDrawBuffer *buffer, double x1, double y1, double x2, double y2, double x3, double y3);
    321323void bDrawTriFill  (bDrawBuffer *buffer, double x1, double y1, double dx, double dy);
     324void bDrawPolyFill (bDrawBuffer *buffer, double *x, double *y, int Npoints);
    322325
    323326void bDrawSmooth (bDrawBuffer *buffer, float sigma);
  • branches/eam_branches/ohana.20190329/src/libkapa/src/KapaStyles.c

    r40106 r40926  
    5454  if (!strcasecmp (string,  "outline")) return KAPA_PLOT_BARS_OUTLINE;
    5555  if (!strcasecmp (string,  "outfill")) return KAPA_PLOT_BARS_OUTFILL;
     56
     57  if (!strcasecmp (string,  "polygon"))   return KAPA_PLOT_POLYGON;
     58  if (!strcasecmp (string,  "polyfill"))  return KAPA_PLOT_POLYFILL;
    5659
    5760  if (strlen(string) > 2) {
  • branches/eam_branches/ohana.20190329/src/libkapa/src/bDrawFuncs.c

    r40730 r40926  
    173173void bDrawRectOpen (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
    174174
    175   int X1, Y1, X2, Y2;
    176 
    177175  if (x1 > x2) SWAP (x1, x2);
    178176  if (y1 > y2) SWAP (y1, y2);
    179177
     178  int X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1);
     179  int X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1);
     180
     181  int Y1 = MIN (MAX (ROUND (y1), 0), buffer[0].Ny - 1);
     182  int Y2 = MIN (MAX (ROUND (y2), 1), buffer[0].Ny - 1);
     183
     184  int dNs = -0.5*(buffer->bWeight - 1);
     185  /* 0, 0, 0, -1, -1, -2, -2 */
     186
     187  int dNe = +0.5*buffer->bWeight + 1;
     188  /* 1, 1, 2, 2, 2, 3, 3 */
     189
     190  for (int dN = dNs; dN < dNe; dN ++) {
     191    // line on the bottom needs to run longer for the negative dN values
     192    bDrawLineHorizontal (buffer, X1 + dN, X2 + 1 - dN, Y1 + dN);
     193
     194    // line on the top needs to run longer for the positive dN values
     195    bDrawLineHorizontal (buffer, X1 + dN, X2 + 1 - dN, Y2 - dN);
     196
     197    // line on the left needs to run longer for the negative dN values
     198    bDrawLineVertical   (buffer, X1 + dN, Y1 + dN, Y2 - dN);
     199
     200    // line on the right needs to run longer for the positive dN values
     201    bDrawLineVertical   (buffer, X2 - dN, Y1 + dN, Y2 - dN);
     202  }
     203  return;
     204}
     205
     206void bDrawRectFill (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
     207
     208  int i;
     209  int X1, Y1, X2, Y2;
     210
     211  if (x1 > x2) SWAP (x1, x2);
     212  if (y1 > y2) SWAP (y1, y2);
     213
    180214  X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1);
    181215  X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1);
    182216
    183217  Y1 = MIN (MAX (ROUND (y1), 0), buffer[0].Ny - 1);
    184   Y2 = MIN (MAX (ROUND (y2), 1), buffer[0].Ny - 1);
    185 
    186   bDrawLineHorizontal (buffer, X1, X2 + 1, Y1);
    187   bDrawLineHorizontal (buffer, X1, X2 + 1, Y2);
    188   bDrawLineVertical   (buffer, X1, Y1, Y2);
    189   bDrawLineVertical   (buffer, X2, Y1, Y2);
    190   return;
    191 }
    192 
    193 void bDrawRectFill (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
    194 
    195   int i;
    196   int X1, Y1, X2, Y2;
    197 
    198   if (x1 > x2) SWAP (x1, x2);
    199   if (y1 > y2) SWAP (y1, y2);
    200 
    201   X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1);
    202   X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1);
    203 
    204   Y1 = MIN (MAX (ROUND (y1), 0), buffer[0].Ny - 1);
    205218  Y2 = MIN (MAX (ROUND (y2), 0), buffer[0].Ny - 1);
    206219
    207220  for (i = Y1; i < Y2; i++) {
     221    // this should must be a line or width 1 or we duplicate pixels
    208222    bDrawLineHorizontal (buffer, X1, X2, i);
    209223  }
     
    258272// use the Bresenham line drawing technique
    259273// integer-only Bresenham line-draw version which is fast
     274// bresenham assumes x1 < x2 and (y2 - y1) < (x2 - x1)
    260275void bDrawLineBresen (bDrawBuffer *buffer, int X1, int Y1, int X2, int Y2, int swapcoords) {
    261276
     
    405420}
    406421
     422# define BOT_LEFT 0
     423# define BOT_RGHT 1
     424# define TOP_LEFT 2
     425# define TOP_RGHT 3
     426
     427// I should probably look up an appropriate recipe for this
     428// source code for XDrawPolyFill?
     429
     430int GetNextSeqNumber (int seq, int Npoint, int Clockwise, int LeftSide);
     431int bDrawFillBetweenSegments (bDrawBuffer *buffer, int *x, int *y, int ystart);
     432
     433void bDrawPolyFill (bDrawBuffer *buffer, double *x, double *y, int Npoints) {
     434
     435  // The coord list which is passed in (x,y) must be in order around the contour
     436  for (int i = 0; i < Npoints; i++) {
     437    fprintf (stderr, "%d : %f,%f\n", i, x[i], y[i]);
     438  }
     439
     440  // First, find the lowest point and start at that sequence number
     441  int iMin = 0;
     442  double yMin = y[iMin];
     443  for (int i = 1; i < Npoints; i++) {
     444    if (y[i] < yMin) { iMin = i; yMin = y[iMin]; }
     445  }
     446
     447  // we generate two line segments and will fill between them
     448  int xval[4];
     449  int yval[4];
     450
     451  // the starting point is a vertex
     452  xval[BOT_LEFT] = x[iMin];  yval[BOT_LEFT] = y[iMin];
     453  xval[BOT_RGHT] = x[iMin];  yval[BOT_RGHT] = y[iMin];
     454
     455  // get iNext, iPrev assuming ClockWise, then test
     456  int isCW = TRUE;
     457  int iNextLeft = GetNextSeqNumber (iMin, Npoints, isCW, TRUE); // TRUE => left-side
     458  int iNextRght = GetNextSeqNumber (iMin, Npoints, isCW, FALSE);
     459
     460  // if this is true, the points are not clockwise
     461  if (x[iNextLeft] > x[iNextRght]) {
     462    isCW = FALSE;
     463    int tmp = iNextLeft;
     464    iNextLeft = iNextRght;
     465    iNextRght = tmp;
     466  }
     467
     468  int iTL = iNextLeft; // sequence number of the top,left point
     469  int iTR = iNextRght; // sequence number of the top,right point
     470  xval[TOP_LEFT] = x[iTL]; yval[TOP_LEFT] = y[iTL];
     471  xval[TOP_RGHT] = x[iTR]; yval[TOP_RGHT] = y[iTR];
     472
     473  // we need to track the starting row, start at the bottom
     474  int ystart = yval[BOT_LEFT];
     475
     476  while (TRUE) {
     477    int isLeft = bDrawFillBetweenSegments (buffer, xval, yval, ystart);
     478
     479    // the last pair of segments in the sequence end at the same top point:
     480    if (iTL == iTR) break;
     481
     482    // after one pass, if isLeft is true, then cycle the points on the left
     483    // segment, otherwise cycle the right segment:
     484
     485    if (isLeft) {
     486      iTL = GetNextSeqNumber (iTL, Npoints, isCW, TRUE);
     487      xval[BOT_LEFT] = xval[TOP_LEFT]; yval[BOT_LEFT] = yval[TOP_LEFT];
     488      xval[TOP_LEFT] = x[iTL];         yval[TOP_LEFT] = y[iTL];
     489      ystart = yval[BOT_LEFT];
     490    } else {
     491      iTR = GetNextSeqNumber (iTR, Npoints, isCW, FALSE);
     492      xval[BOT_RGHT] = xval[TOP_RGHT]; yval[BOT_RGHT] = yval[TOP_RGHT];
     493      xval[TOP_RGHT] = x[iTR];         yval[TOP_RGHT] = y[iTR];
     494      ystart = yval[BOT_RGHT];
     495    }
     496  }
     497  return;
     498}
     499
     500// we have two line segments defined by x[],y[]. 
     501
     502// [0],[1] is the left-side segment
     503// [2],[3] is the right-side segment
     504
     505// Fill the region between the two segments until
     506// the lower of the two y coordinates y[1], y[3]
     507
     508// return which of y[1] or y[3] was the ending row
     509
     510int bDrawFillBetweenSegments_BresenBroken (bDrawBuffer *buffer, int *x, int *y, int ystart) {
     511
     512  fprintf (stderr, "%d, %d - %d, %d : %d, %d - %d, %d @ %d\n",
     513           x[BOT_LEFT], y[BOT_LEFT], x[TOP_LEFT], y[TOP_LEFT],
     514           x[BOT_RGHT], y[BOT_RGHT], x[TOP_RGHT], y[TOP_RGHT], ystart);
     515
     516  int dY_L = y[TOP_LEFT] - y[BOT_LEFT];
     517  int dX_L = x[TOP_LEFT] - x[BOT_LEFT];
     518
     519  int dY_R = y[TOP_RGHT] - y[BOT_RGHT];
     520  int dX_R = x[TOP_RGHT] - x[BOT_RGHT];
     521   
     522  // I need to calculate x_L & x_R from the two line segements given ystart.
     523
     524  // I cannot assume X_L,X_R correspond to x[BOT_LEFT],x[BOT_RGHT]?
     525
     526  int X_L = (dY_L == 0) ? x[BOT_LEFT] : (ystart - y[BOT_LEFT]) * dX_L / dY_L + x[BOT_LEFT];
     527  int X_R = (dY_R == 0) ? x[BOT_RGHT] : (ystart - y[BOT_RGHT]) * dX_R / dY_R + x[BOT_RGHT];
     528  int e_L = 0;
     529  int e_R = 0;
     530
     531  fprintf (stderr, "start: %d - %d @ %d\n", X_L, X_R, ystart);
     532
     533  // stop at whichever comes first
     534  // XXX not sure if I need to use < or <= here:
     535  // with <=, the value of Y after the loop will be one too high.
     536  int Y;
     537  for (Y = ystart; (Y < y[TOP_LEFT]) && (Y < y[TOP_RGHT]); Y++) {
     538     
     539    // draw horizontal line from X_L to X_R at Y
     540    bDrawLineHorizontal (buffer, X_L, X_R, Y);
     541
     542    e_L += dX_L;
     543    int e_L2 = 2*e_L;
     544    if (e_L2 > dY_L) {
     545      X_L ++;
     546      e_L -= dY_L;
     547    }
     548    if (e_L2 < -dY_L) {
     549      X_L --;
     550      e_L += dY_L;
     551    }
     552
     553    e_R += dX_R;
     554    int e_R2 = 2*e_R;
     555    if (e_R2 > dY_R) {
     556      X_R ++;
     557      e_R -= dY_R;
     558    }
     559    if (e_R2 < -dY_R) {
     560      X_R --;
     561      e_R += dY_R;
     562    }
     563  }
     564
     565  fprintf (stderr, "end: %d - %d @ %d\n", X_L, X_R, Y);
     566
     567  if (Y == y[TOP_LEFT]) {
     568    return TRUE; // TRUE is LEFT SIDE
     569  } else {
     570    return FALSE;
     571  }
     572}
     573
     574int bDrawFillBetweenSegments (bDrawBuffer *buffer, int *x, int *y, int ystart) {
     575
     576  int dY_L = y[TOP_LEFT] - y[BOT_LEFT];
     577  int dX_L = x[TOP_LEFT] - x[BOT_LEFT];
     578
     579  int dY_R = y[TOP_RGHT] - y[BOT_RGHT];
     580  int dX_R = x[TOP_RGHT] - x[BOT_RGHT];
     581   
     582  double Slope_L = (dY_L == 0) ? NAN : dX_L / (double) dY_L;
     583  double Slope_R = (dY_R == 0) ? NAN : dX_R / (double) dY_R;
     584
     585  // stop at whichever comes first
     586  // XXX not sure if I need to use < or <= here:
     587  // with <=, the value of Y after the loop will be one too high.
     588  int Y;
     589  for (Y = ystart; (Y < y[TOP_LEFT]) && (Y < y[TOP_RGHT]); Y++) {
     590
     591    // calculating X_L, X_R based on the slope and current y point
     592    int X_L = (dY_L == 0) ? x[BOT_LEFT] : (Y - y[BOT_LEFT]) * Slope_L + x[BOT_LEFT];
     593    int X_R = (dY_R == 0) ? x[BOT_RGHT] : (Y - y[BOT_RGHT]) * Slope_R + x[BOT_RGHT];
     594     
     595    // draw horizontal line from X_L to X_R at Y
     596    bDrawLineHorizontal (buffer, X_L, X_R, Y);
     597  }
     598
     599  if (Y == y[TOP_LEFT]) {
     600    return TRUE; // TRUE is LEFT SIDE
     601  } else {
     602    return FALSE;
     603  }
     604}
     605
     606int GetNextSeqNumber (int seq, int Npoints, int Clockwise, int LeftSide) {
     607
     608  int iNext;
     609
     610  if (Clockwise) {
     611    if (LeftSide) {
     612      // next point is next in sequence
     613      iNext = (seq < Npoints - 1) ? seq + 1 : 0;
     614    } else {
     615      // next point is prev in sequence
     616      iNext = (seq > 0) ? seq - 1 : Npoints - 1;
     617    }
     618  } else {
     619    if (LeftSide) {
     620      // next point is prev in sequence
     621      iNext = (seq > 0) ? seq - 1 : Npoints - 1;
     622    } else {
     623      // next point is next in sequence
     624      iNext = (seq < Npoints - 1) ? seq + 1 : 0;
     625    }
     626  }
     627  return iNext;
     628}
     629
    407630void bDrawArc (bDrawBuffer *buffer, double Xc, double Yc, double Xr, double Yr, double Ts, double Te) {
    408631
     
    604827  if (x == 0) {
    605828    if (decrementY) {
     829      // this should must be a line or width 1 or we duplicate pixels
    606830      bDrawLineHorizontal (buffer, Xc    , Xc + 1, Yc + y);
    607831      bDrawLineHorizontal (buffer, Xc    , Xc + 1, Yc - y);
     
    609833
    610834    // center line
     835    // this should must be a line or width 1 or we duplicate pixels
    611836    bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc    );
    612837    return;
     
    614839
    615840  if (x == y) {
     841    // this should must be a line or width 1 or we duplicate pixels
    616842    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc + y);
    617843    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc - y);
     
    621847  // only draw these two lines if we decrement y
    622848  if (decrementY) {
     849    // this must be a line or width 1 or we duplicate pixels
    623850    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc + y);
    624851    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc - y);
     
    626853
    627854  // always draw these two lines:
     855  // this must be a line or width 1 or we duplicate pixels
    628856  bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc + x);
    629857  bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc - x);
Note: See TracChangeset for help on using the changeset viewer.