IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40107


Ignore:
Timestamp:
Aug 7, 2017, 9:32:12 AM (9 years ago)
Author:
eugene
Message:

add functions to draw histogram bars

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/kapa2/src/DrawObjects.c

    r40018 r40107  
    11# include "Ximage.h"
     2
     3void DrawBars (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object, int mode);
    24
    35# define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X1), (int)(Y1), (int)(X2), (int)(Y2)))
     
    3638}
    3739
    38 /* Draw a specific object in the graph */
    39 int DrawObjectN (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object) {
    40  
     40void DrawLineStyle (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object) {
     41
    4142  static char dot[2] = {2,3};
    4243  static char short_dash[2] = {4,4};
     
    8586    XSetForeground (graphic->display, graphic->gc, graphic->color[object[0].color]);
    8687  }
     88  return;
     89}
     90
     91/* Draw a specific object in the graph */
     92int DrawObjectN (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object) {
     93 
     94  DrawLineStyle (graphic, graph, object);
    8795
    8896  switch (object[0].style) {
     
    92100    case KAPA_PLOT_HISTOGRAM:
    93101      DrawHistogram (graphic, graph, object);
     102      break;
     103    case KAPA_PLOT_BARS_SOLID:
     104      DrawBars (graphic, graph, object, KAPA_PLOT_BARS_SOLID);
     105      break;
     106    case KAPA_PLOT_BARS_OUTLINE:
     107      DrawBars (graphic, graph, object, KAPA_PLOT_BARS_OUTLINE);
     108      break;
     109    case KAPA_PLOT_BARS_OUTFILL:
     110      DrawBars (graphic, graph, object, KAPA_PLOT_BARS_OUTFILL);
    94111      break;
    95112    case KAPA_PLOT_POINTS:
     
    402419}
    403420# endif
     421
     422// uses object->color
     423# define HISTOGRAM_SOLID(X_VALUE, Y_VALUE, DX_VAL) {                    \
     424  /* histogram bar corners */                                           \
     425  double sxmin = (X_VALUE) - 0.5*(DX_VAL);                              \
     426  double sxmax = (X_VALUE) + 0.5*(DX_VAL);                              \
     427  double symin = Xaxis;                                                 \
     428  double symax = (Y_VALUE);                                             \
     429  /* saturated values for corner coords: */                             \
     430  sxmin = MIN (MAX (sxmin, X0), X1);                                    \
     431  sxmax = MIN (MAX (sxmax, X0), X1);                                    \
     432  symin = MAX (MIN (symin, Y0), Y1);                                    \
     433  symax = MAX (MIN (symax, Y0), Y1);                                    \
     434  double dy = fabs(symax - symin);                                      \
     435  double ylow = MIN(symin, symax);                                      \
     436  FillRectangle (sxmin, ylow, (DX_VAL), dy); }
     437
     438// uses object->color
     439# define HISTOGRAM_OUTLINE(X_VALUE, Y_VALUE, DX_VAL) {                  \
     440  /* histogram bar corners */                                           \
     441  double sxmin = (X_VALUE) - 0.5*(DX_VAL);                              \
     442  double sxmax = (X_VALUE) + 0.5*(DX_VAL);                              \
     443  double symin = Xaxis;                                                 \
     444  double symax = (Y_VALUE);                                             \
     445  /* saturated values for corner coords: */                             \
     446  sxmin = MIN (MAX (sxmin, X0), X1);                                    \
     447  sxmax = MIN (MAX (sxmax, X0), X1);                                    \
     448  symin = MAX (MIN (symin, Y0), Y1);                                    \
     449  symax = MAX (MIN (symax, Y0), Y1);                                    \
     450  double dy = fabs(symax - symin);                                      \
     451  double ylow = MIN(symin, symax);                                      \
     452  DrawRectangle (sxmin, ylow, (DX_VAL), dy); }
     453
     454# define HISTOGRAM_OUTFILL(X_VALUE, Y_VALUE, DX_VAL) {                  \
     455  /* histogram bar corners */                                           \
     456  double sxmin = (X_VALUE) - 0.5*(DX_VAL);                              \
     457  double sxmax = (X_VALUE) + 0.5*(DX_VAL);                              \
     458  double symin = Xaxis;                                                 \
     459  double symax = (Y_VALUE);                                             \
     460  /* saturated values for corner coords: */                             \
     461  sxmin = MIN (MAX (sxmin, X0), X1);                                    \
     462  sxmax = MIN (MAX (sxmax, X0), X1);                                    \
     463  symin = MAX (MIN (symin, Y0), Y1);                                    \
     464  symax = MAX (MIN (symax, Y0), Y1);                                    \
     465  double dy = fabs(symax - symin);                                      \
     466  double ylow = MIN(symin, symax);                                      \
     467  FillRectangle (sxmin, ylow, (DX_VAL), dy);                            \
     468  XSetForeground (graphic->display, graphic->gc, graphic->fore);        \
     469  DrawRectangle (sxmin, ylow, (DX_VAL), dy);                            \
     470  XSetForeground (graphic->display, graphic->gc, graphic->color[object[0].color]); }
     471
     472void DrawBars (Graphic *graphic, KapaGraphWidget *graph, Gobjects *object, int mode) {
     473
     474  double mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels
     475  double mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0); // slope of the x-axis in y-pixels (always 0 for now)
     476  double myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0); // slope of the x-axis in x-pixels (always 0 for now)
     477  double myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); // slope of the x-axis in x-pixels
     478 
     479  // intercepts of axes
     480  double bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
     481  double bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
     482  double byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
     483  double byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
     484 
     485  double bx = bxi + bxj;
     486  double by = byi + byj;
     487 
     488  // corner coords
     489  double X0 = graph[0].axis[0].fx;
     490  double X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
     491  double Y0 = graph[0].axis[1].fy;
     492  double Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
     493
     494  /* find the first valid datapoint */
     495  float *x = object[0].x;
     496  float *y = object[0].y;
     497 
     498  /* we are drawing bars which are filled rectangles of height y[i] and width 0.5*dx
     499     one point at a time
     500  */
     501
     502  // I need to know the distance to the next and prev points to calculate dx
     503  // for the first point, dx is x[1] - x[0]
     504  // for the last point, dx is x[-1] - x[-2] (x[-1] is the last point)
     505  // for the rest, dx is 0.5*(x[i+1] - x[i-1])
     506
     507  // rather than working out complex on-the-fly logic, I want to find the first and last
     508  // valid point in an initial pass, the calculate the above for the remainder.
     509  // or make an index vector of only valid points?
     510
     511  int Ngood = 0;
     512  ALLOCATE_PTR (goodPoint, int, object[0].Npts);
     513
     514  // x = ??, y = 0: this assumes the xaxis is parallel to the plot window (myi = 0)
     515  // since y runs from large on bottom to small on top, this is slightly backwards
     516  float Xaxis = by + YCENTER;
     517  Xaxis = MAX (Y1, MIN (Xaxis, Y0)); // MIN & MAX reversed for neg y dir
     518
     519  for (int i = 0; i < object[0].Npts; i++) {
     520    if (!(finite(x[i]) && finite(y[i]))) continue;
     521
     522    // coordinate on the screen of the point:
     523    double sx1r = x[i]*mxi + y[i]*mxj + bx + XCENTER;
     524    double sy1r = x[i]*myi + y[i]*myj + by + YCENTER;
     525
     526    if (sx1r < X0) {
     527      // point to the left, skip it
     528      continue;
     529    }
     530    if (sx1r > X1) {
     531      // point to the right, skip it
     532      continue;
     533    }
     534
     535    goodPoint[Ngood] = i;
     536    Ngood ++;
     537  }
     538   
     539  if (Ngood == 0) {
     540    free (goodPoint);
     541    return;
     542  }
     543
     544  // if we only have 1 point, draw bar half the width of the screen
     545  // this works fine, but the auto limits for 1 value are somewhat silly
     546  if (Ngood == 1) {
     547    // coordinate on the screen of the point:
     548    int n = goodPoint[0];
     549    double sx1r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     550    double sy1r = x[n]*myi + y[n]*myj + by + YCENTER;
     551
     552    float dx = 0.5*object->size*(X1 - X0);
     553   
     554    switch (mode) {
     555      case KAPA_PLOT_BARS_SOLID:
     556        HISTOGRAM_SOLID(sx1r, sy1r, dx);
     557        break;
     558      case KAPA_PLOT_BARS_OUTLINE:
     559        HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
     560        break;
     561      case KAPA_PLOT_BARS_OUTFILL:
     562        HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
     563        break;
     564      default:
     565        HISTOGRAM_SOLID(sx1r, sy1r, dx);
     566        break;
     567    }
     568
     569    free (goodPoint);
     570    return;
     571  }
     572
     573  // first point:
     574  {
     575    int n;
     576    n = goodPoint[1];
     577    double sx1r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     578//  double sy1r = x[n]*myi + y[n]*myj + by + YCENTER;
     579
     580    n = goodPoint[0];
     581    double sx0r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     582    double sy0r = x[n]*myi + y[n]*myj + by + YCENTER;
     583
     584    double dx = 0.5*object->size*(sx1r - sx0r);
     585   
     586    switch (mode) {
     587      case KAPA_PLOT_BARS_SOLID:
     588        HISTOGRAM_SOLID(sx0r, sy0r, dx);
     589        break;
     590      case KAPA_PLOT_BARS_OUTLINE:
     591        HISTOGRAM_OUTLINE(sx0r, sy0r, dx);
     592        break;
     593      case KAPA_PLOT_BARS_OUTFILL:
     594        HISTOGRAM_OUTFILL(sx0r, sy0r, dx);
     595        break;
     596      default:
     597        HISTOGRAM_SOLID(sx0r, sy0r, dx);
     598        break;
     599    }
     600  }
     601
     602  for (int i = 1; i < Ngood - 1; i++) {
     603
     604    int n;
     605    n = goodPoint[i + 1];
     606    double sx2r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     607    double sy2r = x[n]*myi + y[n]*myj + by + YCENTER;
     608
     609    n = goodPoint[i - 1];
     610    double sx0r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     611    double sy0r = x[n]*myi + y[n]*myj + by + YCENTER;
     612
     613    double dx = 0.5*0.5*object->size*(sx2r - sx0r); // 2 factors of 0.5 (we want half of the average spacing)
     614
     615    n = goodPoint[i];
     616    double sx1r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     617    double sy1r = x[n]*myi + y[n]*myj + by + YCENTER;
     618
     619    switch (mode) {
     620      case KAPA_PLOT_BARS_SOLID:
     621        HISTOGRAM_SOLID(sx1r, sy1r, dx);
     622        break;
     623      case KAPA_PLOT_BARS_OUTLINE:
     624        HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
     625        break;
     626      case KAPA_PLOT_BARS_OUTFILL:
     627        HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
     628        break;
     629      default:
     630        HISTOGRAM_SOLID(sx1r, sy1r, dx);
     631        break;
     632    }
     633  }
     634 
     635  // last point:
     636  {
     637    int n;
     638    n = goodPoint[Ngood - 1];
     639    double sx1r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     640    double sy1r = x[n]*myi + y[n]*myj + by + YCENTER;
     641
     642    n = goodPoint[Ngood - 2];
     643    double sx0r = x[n]*mxi + y[n]*mxj + bx + XCENTER;
     644//  double sy0r = x[n]*myi + y[n]*myj + by + YCENTER;
     645
     646    double dx = 0.5*object->size*(sx1r - sx0r);
     647
     648    switch (mode) {
     649      case KAPA_PLOT_BARS_SOLID:
     650        HISTOGRAM_SOLID(sx1r, sy1r, dx);
     651        break;
     652      case KAPA_PLOT_BARS_OUTLINE:
     653        HISTOGRAM_OUTLINE(sx1r, sy1r, dx);
     654        break;
     655      case KAPA_PLOT_BARS_OUTFILL:
     656        HISTOGRAM_OUTFILL(sx1r, sy1r, dx);
     657        break;
     658      default:
     659        HISTOGRAM_SOLID(sx1r, sy1r, dx);
     660        break;
     661    }
     662  }
     663  free (goodPoint);
     664  return;
     665}
    404666
    405667/******/
Note: See TracChangeset for help on using the changeset viewer.