Actual source code: pops.c

      1: #define PETSC_DLL

      3: /*
      4:     Defines the operations for the Postscript PetscDraw implementation.
      5: */

     7:  #include src/sys/src/draw/impls/ps/psimpl.h

     11: /*@C
     12:       PetscDrawOpenPS - Opens a PetscViewer that generates Postscript

     14:   Collective on MPI_Comm

     16:   Input Parameters:
     17: +   comm - communicator that shares the PetscViewer
     18: -   file - name of file where Postscript is to be stored

     20:   Output Parameter:
     21: .  viewer - the PetscViewer object

     23:   Level: beginner

     25: .seealso: PetscDrawDestroy(), PetscDrawOpenX(), PetscDrawCreate(), PetscViewerDrawOpen(), PetscViewerDrawGetDraw()
     26: @*/
     27: PetscErrorCode PETSC_DLLEXPORT PetscDrawOpenPS(MPI_Comm comm,char *filename,PetscDraw *draw)
     28: {

     32:   PetscDrawCreate(comm,filename,0,0,0,0,0,draw);
     33:   PetscDrawSetType(*draw,PETSC_DRAW_PS);
     34:   return(0);
     35: }

     37: /*
     38:      These macros transform from the users coordinates to the Postscript
     39: */
     40: #define WIDTH  8.5*72
     41: #define HEIGHT 11*72
     42: #define XTRANS(win,x) \
     43:    ((WIDTH)*((win)->port_xl+(((x-(win)->coor_xl)*((win)->port_xr-(win)->port_xl))/((win)->coor_xr-(win)->coor_xl))))
     44: #define YTRANS(win,y) \
     45:    ((HEIGHT)*((win)->port_yl+(((y-(win)->coor_yl)*((win)->port_yr-(win)->port_yl))/((win)->coor_yr-(win)->coor_yl))))

     47: /*
     48:     Contains the RGB colors for the PETSc defined colors
     49: */
     50: static PetscReal  rgb[3][256];
     51: static PetscTruth rgbfilled = PETSC_FALSE;

     53: #define PSSetColor(ps,c)   (((c) == ps->currentcolor) ? 0 : \
     54: (ps->currentcolor = (c),PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g setrgbcolor\n",rgb[0][c],rgb[1][c],rgb[2][c])))

     58: static PetscErrorCode PetscDrawPoint_PS(PetscDraw draw,PetscReal x,PetscReal  y,int c)
     59: {
     60:   PetscReal      xx,yy;
     62:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;

     65:   xx = XTRANS(draw,x);  yy = YTRANS(draw,y);
     66:   PSSetColor(ps,c);
     67:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g moveto %g %g lineto stroke\n",xx,yy,xx+1,yy);
     68:   return(0);
     69: }

     73: static PetscErrorCode PetscDrawLine_PS(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c)
     74: {
     75:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;
     76:   PetscReal      x1,y_1,x2,y2;

     80:   x1 = XTRANS(draw,xl);   x2  = XTRANS(draw,xr);
     81:   y_1 = YTRANS(draw,yl);   y2  = YTRANS(draw,yr);
     82:   PSSetColor(ps,c);
     83:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g moveto %g %g lineto stroke\n",x1,y_1,x2,y2);
     84:   return(0);
     85: }

     89: static PetscErrorCode PetscDrawStringSetSize_PS(PetscDraw draw,PetscReal x,PetscReal  y)
     90: {
     91:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;
     93:   int            w,h;

     96:   w = (int)((WIDTH)*x*(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
     97:   h = (int)((HEIGHT)*y*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
     98:   PetscViewerASCIIPrintf(ps->ps_file,"/Helvetica-normal findfont %g scalefont setfont\n",(w+h)/2.0);
     99:   return(0);
    100: }

    104: static PetscErrorCode PetscDrawStringGetSize_PS(PetscDraw draw,PetscReal *x,PetscReal  *y)
    105: {
    106:   PetscReal   w = 9,h = 9;

    109:   *x = w*(draw->coor_xr - draw->coor_xl)/(WIDTH)*(draw->port_xr - draw->port_xl);
    110:   *y = h*(draw->coor_yr - draw->coor_yl)/(HEIGHT)*(draw->port_yr - draw->port_yl);
    111:   return(0);
    112: }

    116: static PetscErrorCode PetscDrawString_PS(PetscDraw draw,PetscReal x,PetscReal  y,int c,const char chrs[])
    117: {
    118:   PetscDraw_PS* ps = (PetscDraw_PS*)draw->data;
    119:   PetscReal     x1,y_1;

    123:   PSSetColor(ps,c);
    124:   x1 = XTRANS(draw,x);
    125:   y_1 = YTRANS(draw,y);
    126:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g moveto (%s) show\n",x1,y_1,chrs);
    127:   return(0);
    128: }

    132: static PetscErrorCode PetscDrawStringVertical_PS(PetscDraw draw,PetscReal x,PetscReal  y,int c,const char chrs[])
    133: {
    134:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;
    135:   PetscReal      x1,y_1;

    139:   PSSetColor(ps,c);
    140:   x1 = XTRANS(draw,x);
    141:   y_1 = YTRANS(draw,y);
    142:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"gsave %g %g moveto 90 rotate (%s) show grestore\n",x1,y_1,chrs);
    143:   return(0);
    144: }

    146: static PetscErrorCode PetscDrawInterpolatedTriangle_PS(PetscDraw_PS*,PetscReal,PetscReal,int,PetscReal,PetscReal,int,PetscReal,PetscReal,int);

    150: static PetscErrorCode PetscDrawTriangle_PS(PetscDraw draw,PetscReal X1,PetscReal Y_1,PetscReal X2,
    151:                           PetscReal Y2,PetscReal X3,PetscReal Y3,int c1,int c2,int c3)
    152: {
    153:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;
    155:   PetscReal      x1,y_1,x2,y2,x3,y3;

    158:   x1   = XTRANS(draw,X1);
    159:   y_1  = YTRANS(draw,Y_1);
    160:   x2   = XTRANS(draw,X2);
    161:   y2   = YTRANS(draw,Y2);
    162:   x3   = XTRANS(draw,X3);
    163:   y3   = YTRANS(draw,Y3);

    165:   if (c1 == c2 && c2 == c3) {
    166:     PSSetColor(ps,c1);
    167:     PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g moveto %g %g lineto %g %g lineto fill\n",x1,y_1,x2,y2,x3,y3);
    168:   } else {
    169:     PetscDrawInterpolatedTriangle_PS(ps,x1,y_1,c1,x2,y2,c2,x3,y3,c3);
    170:   }
    171:   return(0);
    172: }

    176: static PetscErrorCode PetscDrawRectangle_PS(PetscDraw draw,PetscReal X1,PetscReal Y_1,PetscReal X2,
    177:                           PetscReal Y2,int c1,int c2,int c3,int c4)
    178: {
    179:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;
    181:   PetscReal      x1,y_1,x2,y2,x3,y3,x4,y4;

    184:   x1   = XTRANS(draw,X1);
    185:   y_1  = YTRANS(draw,Y_1);
    186:   x2   = XTRANS(draw,X2);
    187:   y2   = YTRANS(draw,Y_1);
    188:   x3   = XTRANS(draw,X2);
    189:   y3   = YTRANS(draw,Y2);
    190:   x4   = XTRANS(draw,X1);
    191:   y4   = YTRANS(draw,Y2);

    193:   PSSetColor(ps,(c1+c2+c3+c4)/4);
    194:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g moveto %g %g lineto %g %g lineto %g %g lineto %g %g lineto fill\n",x1,y_1,x2,y2,x3,y3,x4,y4,x1,y_1);
    195:   return(0);
    196: }

    200: static PetscErrorCode PetscDrawDestroy_PS(PetscDraw draw)
    201: {
    202:   PetscDraw_PS   *ps = (PetscDraw_PS*)draw->data;
    204:   PetscTruth     show;
    205:   char           *filename,par[PETSC_MAX_PATH_LEN];
    206:
    208:   PetscViewerASCIIPrintf(ps->ps_file,"\nshowpage\n");
    209:   PetscOptionsHasName(draw->prefix,"-draw_ps_show",&show);
    210:   if (show) {
    211:     PetscViewerGetFilename(ps->ps_file,&filename);
    212:     PetscStrcpy(par,"ghostview ");
    213:     PetscStrcat(par,filename);
    214: #if defined(PETSC_HAVE_POPEN)
    215:     PetscPOpen(draw->comm,PETSC_NULL,par,"r",PETSC_NULL);
    216: #else
    217:     SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
    218: #endif
    219:   }
    220:   PetscViewerDestroy(ps->ps_file);
    221:   PetscFree(ps);
    222:   return(0);
    223: }

    227: static PetscErrorCode PetscDrawSynchronizedFlush_PS(PetscDraw draw)
    228: {
    230:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;

    233:   PetscViewerFlush(ps->ps_file);
    234:   return(0);
    235: }

    239: static PetscErrorCode PetscDrawSynchronizedClear_PS(PetscDraw draw)
    240: {
    242:   PetscDraw_PS*  ps = (PetscDraw_PS*)draw->data;

    245:   PetscViewerFlush(ps->ps_file);
    246:   PetscViewerASCIIPrintf(ps->ps_file,"\nshowpage\n");
    247:   return(0);
    248: }

    250: static struct _PetscDrawOps DvOps = { 0,
    251:                                  0,
    252:                                  PetscDrawLine_PS,
    253:                                  0,
    254:                                  0,
    255:                                  PetscDrawPoint_PS,
    256:                                  0,
    257:                                  PetscDrawString_PS,
    258:                                  PetscDrawStringVertical_PS,
    259:                                  PetscDrawStringSetSize_PS,
    260:                                  PetscDrawStringGetSize_PS,
    261:                                  0,
    262:                                  0,
    263:                                  PetscDrawSynchronizedFlush_PS,
    264:                                  PetscDrawRectangle_PS,
    265:                                  PetscDrawTriangle_PS,
    266:                                  0,
    267:                                  0,
    268:                                  0,
    269:                                  PetscDrawSynchronizedClear_PS,
    270:                                  0,
    271:                                  0,
    272:                                  0,
    273:                                  0,
    274:                                  0,
    275:                                  0,
    276:                                  PetscDrawDestroy_PS,
    277:                                  0,
    278:                                  0,
    279:                                  0 };

    284: PetscErrorCode PETSC_DLLEXPORT PetscDrawCreate_PS(PetscDraw draw)
    285: {
    286:   PetscDraw_PS  *ps;
    288:   int           ncolors,i;
    289:   unsigned char *red,*green,*blue;
    290:   static int    filecount = 0;
    291:   char          buff[32];
    292:   char          version[256];

    295:   if (!draw->display) {
    296:     sprintf(buff,"defaultps%d.ps",filecount++);
    297:     PetscStrallocpy(buff,&draw->display);
    298:   }

    300:   PetscGetVersion(&version);
    301:   PetscNew(PetscDraw_PS,&ps);
    302:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
    303:   PetscViewerASCIIOpen(draw->comm,draw->display,&ps->ps_file);
    304:   PetscViewerASCIIPrintf(ps->ps_file,"%%!PS-Adobe-2.0\n");
    305:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%Creator: PETSc %s\n",version);
    306:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%Title: %s\n",draw->display);
    307:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%Pages: 1\n");
    308:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%PageOrder: Ascend\n");
    309:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%BoundingBox: 0 0 612 792\n");
    310:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%DocumentFonts: Helvetica-normal Symbol\n");
    311:   PetscViewerASCIIPrintf(ps->ps_file,"%%%%EndComments\n");
    312:   PetscViewerASCIIPrintf(ps->ps_file,"/Helvetica-normal findfont 10 scalefont setfont\n");
    313:   PetscViewerASCIIPrintf(ps->ps_file,"/c {setrgbcolor} def\n");
    314:   PetscViewerASCIIPrintf(ps->ps_file,"/l {lineto stroke} def\n");
    315:   PetscViewerASCIIPrintf(ps->ps_file,"/m {moveto} def\n");

    317:   ps->currentcolor = PETSC_DRAW_BLACK;

    319:   if (!rgbfilled) {
    320:     rgbfilled = PETSC_TRUE;
    321:     rgb[0][PETSC_DRAW_WHITE]       = 255/255;
    322:     rgb[1][PETSC_DRAW_WHITE]       = 255/255;
    323:     rgb[2][PETSC_DRAW_WHITE]       = 255/255;
    324:     rgb[0][PETSC_DRAW_BLACK]       = 0;
    325:     rgb[1][PETSC_DRAW_BLACK]       = 0;
    326:     rgb[2][PETSC_DRAW_BLACK]       = 0;
    327:     rgb[0][PETSC_DRAW_RED]         = 255/255;
    328:     rgb[1][PETSC_DRAW_RED]         = 0;
    329:     rgb[2][PETSC_DRAW_RED]         = 0;
    330:     rgb[0][PETSC_DRAW_GREEN]       = 0;
    331:     rgb[1][PETSC_DRAW_GREEN]       = 255./255;
    332:     rgb[2][PETSC_DRAW_GREEN]       = 0;
    333:     rgb[0][PETSC_DRAW_CYAN]        = 0;
    334:     rgb[1][PETSC_DRAW_CYAN]        = 255./255;
    335:     rgb[2][PETSC_DRAW_CYAN]        = 255./255;
    336:     rgb[0][PETSC_DRAW_BLUE]        = 0;
    337:     rgb[1][PETSC_DRAW_BLUE]        = 0;
    338:     rgb[2][PETSC_DRAW_BLUE]        = 255./255;
    339:     rgb[0][PETSC_DRAW_MAGENTA]     = 255./255;
    340:     rgb[1][PETSC_DRAW_MAGENTA]     = 0;
    341:     rgb[2][PETSC_DRAW_MAGENTA]     = 255./255;
    342:     rgb[0][PETSC_DRAW_AQUAMARINE]  = 127./255;
    343:     rgb[1][PETSC_DRAW_AQUAMARINE]  = 255./255;
    344:     rgb[2][PETSC_DRAW_AQUAMARINE]  = 212./255;
    345:     rgb[0][PETSC_DRAW_FORESTGREEN] = 34./255   ;
    346:     rgb[1][PETSC_DRAW_FORESTGREEN] = 139./255.;
    347:     rgb[2][PETSC_DRAW_FORESTGREEN] = 34./255. ;
    348:     rgb[0][PETSC_DRAW_ORANGE]      = 255./255.    ;
    349:     rgb[1][PETSC_DRAW_ORANGE]      = 165./255.;
    350:     rgb[2][PETSC_DRAW_ORANGE]      = 0 ;
    351:     rgb[0][PETSC_DRAW_VIOLET]      = 238./255.  ;
    352:     rgb[1][PETSC_DRAW_VIOLET]      = 130./255.;
    353:     rgb[2][PETSC_DRAW_VIOLET]      = 238./255.;
    354:     rgb[0][PETSC_DRAW_BROWN]       = 165./255.   ;
    355:     rgb[1][PETSC_DRAW_BROWN]       =  42./255.;
    356:     rgb[2][PETSC_DRAW_BROWN]       = 42./255.;
    357:     rgb[0][PETSC_DRAW_PINK]        = 255./255. ;
    358:     rgb[1][PETSC_DRAW_PINK]        = 192./255. ;
    359:     rgb[2][PETSC_DRAW_PINK]        = 203./255.;
    360:     rgb[0][PETSC_DRAW_CORAL]       = 255./255.;
    361:     rgb[1][PETSC_DRAW_CORAL]       = 127./255.;
    362:     rgb[2][PETSC_DRAW_CORAL]       = 80./255.;
    363:     rgb[0][PETSC_DRAW_GRAY]        = 190./255.  ;
    364:     rgb[1][PETSC_DRAW_GRAY]        = 190./255.;
    365:     rgb[2][PETSC_DRAW_GRAY]        = 190./255.;
    366:     rgb[0][PETSC_DRAW_YELLOW]      = 255./255.    ;
    367:     rgb[1][PETSC_DRAW_YELLOW]      = 255./255.;
    368:     rgb[2][PETSC_DRAW_YELLOW]      = 0/255.;
    369:     rgb[0][PETSC_DRAW_GOLD]        = 255./255.  ;
    370:     rgb[1][PETSC_DRAW_GOLD]        =  215./255.;
    371:     rgb[2][PETSC_DRAW_GOLD]        =  0;
    372:     rgb[0][PETSC_DRAW_LIGHTPINK]   = 255./255.  ;
    373:     rgb[1][PETSC_DRAW_LIGHTPINK]   = 182./255.;
    374:     rgb[2][PETSC_DRAW_LIGHTPINK]   = 193./255.;
    375:     rgb[0][PETSC_DRAW_MEDIUMTURQUOISE] = 72./255.;
    376:     rgb[1][PETSC_DRAW_MEDIUMTURQUOISE] =  209./255.;
    377:     rgb[2][PETSC_DRAW_MEDIUMTURQUOISE] =  204./255.;
    378:     rgb[0][PETSC_DRAW_KHAKI]           = 240./255.  ;
    379:     rgb[1][PETSC_DRAW_KHAKI]           = 230./255.;
    380:     rgb[2][PETSC_DRAW_KHAKI]           = 140./255.;
    381:     rgb[0][PETSC_DRAW_DIMGRAY]         = 105./255.  ;
    382:     rgb[1][PETSC_DRAW_DIMGRAY]         = 105./255.;
    383:     rgb[2][PETSC_DRAW_DIMGRAY]         = 105./255.;
    384:     rgb[0][PETSC_DRAW_YELLOWGREEN]     = 154./255.   ;
    385:     rgb[1][PETSC_DRAW_YELLOWGREEN]     = 205./255.;
    386:     rgb[2][PETSC_DRAW_YELLOWGREEN]     =  50./255.;
    387:     rgb[0][PETSC_DRAW_SKYBLUE]         = 135./255.  ;
    388:     rgb[1][PETSC_DRAW_SKYBLUE]         = 206./255.;
    389:     rgb[2][PETSC_DRAW_SKYBLUE]         = 235./255.;
    390:     rgb[0][PETSC_DRAW_DARKGREEN]       = 0    ;
    391:     rgb[1][PETSC_DRAW_DARKGREEN]       = 100./255.;
    392:     rgb[2][PETSC_DRAW_DARKGREEN]       = 0;
    393:     rgb[0][PETSC_DRAW_NAVYBLUE]        = 0   ;
    394:     rgb[1][PETSC_DRAW_NAVYBLUE]        =  0;
    395:     rgb[2][PETSC_DRAW_NAVYBLUE]        = 128./255.;
    396:     rgb[0][PETSC_DRAW_SANDYBROWN]      = 244./255.   ;
    397:     rgb[1][PETSC_DRAW_SANDYBROWN]      = 164./255.;
    398:     rgb[2][PETSC_DRAW_SANDYBROWN]      = 96./255.;
    399:     rgb[0][PETSC_DRAW_CADETBLUE]       =  95./255.  ;
    400:     rgb[1][PETSC_DRAW_CADETBLUE]       = 158./255.;
    401:     rgb[2][PETSC_DRAW_CADETBLUE]       = 160./255.;
    402:     rgb[0][PETSC_DRAW_POWDERBLUE]      = 176./255.  ;
    403:     rgb[1][PETSC_DRAW_POWDERBLUE]      = 224./255.;
    404:     rgb[2][PETSC_DRAW_POWDERBLUE]      = 230./255.;
    405:     rgb[0][PETSC_DRAW_DEEPPINK]        = 255./255. ;
    406:     rgb[1][PETSC_DRAW_DEEPPINK]        =  20./255.;
    407:     rgb[2][PETSC_DRAW_DEEPPINK]        = 147./255.;
    408:     rgb[0][PETSC_DRAW_THISTLE]         = 216./255.  ;
    409:     rgb[1][PETSC_DRAW_THISTLE]         = 191./255.;
    410:     rgb[2][PETSC_DRAW_THISTLE]         = 216./255.;
    411:     rgb[0][PETSC_DRAW_LIMEGREEN]       = 50./255.  ;
    412:     rgb[1][PETSC_DRAW_LIMEGREEN]       = 205./255.;
    413:     rgb[2][PETSC_DRAW_LIMEGREEN]       =  50./255.;
    414:     rgb[0][PETSC_DRAW_LAVENDERBLUSH]   = 255./255.  ;
    415:     rgb[1][PETSC_DRAW_LAVENDERBLUSH]   = 240./255.;
    416:     rgb[2][PETSC_DRAW_LAVENDERBLUSH]   = 245./255.;

    418:     /* now do the uniform hue part of the colors */
    419:     ncolors = 256-PETSC_DRAW_BASIC_COLORS;
    420:     PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
    421:     green   = red   + ncolors;
    422:     blue    = green + ncolors;
    423:     PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
    424:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
    425:       rgb[0][i]  = ((double)red[i-PETSC_DRAW_BASIC_COLORS])/255.;
    426:       rgb[1][i]  = ((double)green[i-PETSC_DRAW_BASIC_COLORS])/255.;
    427:       rgb[2][i]  = ((double)blue[i-PETSC_DRAW_BASIC_COLORS])/255.;
    428:     }
    429:     PetscFree(red);
    430:   }

    432:   draw->data    = (void*)ps;
    433:   return(0);
    434: }

    439: /*
    440:          This works in Postscript coordinates
    441: */
    442: /*

    444:    this kind of thing should do contour triangles with Postscript level 3
    445: 1000 dict begin
    446:   /ShadingType 4 def
    447:   /ColorSpace /DeviceRGB def
    448:   /DataSource [0 10 10 255 255 255 0 400 10 0 0 0 0 200 400 255 0 0] def
    449:   shfill

    451:    once we have Postscript level 3 we should put this in as an option
    452: */

    457: static PetscErrorCode PetscDrawInterpolatedTriangle_PS(PetscDraw_PS* ps,PetscReal x1,PetscReal y_1,int t1,
    458:                                 PetscReal x2,PetscReal y2,int t2,PetscReal x3,PetscReal y3,int t3)
    459: {
    460:   PetscReal      rfrac,lfrac;
    461:   PetscReal      lc,rc = 0.0,lx,rx = 0.0,xx,y;
    462:   PetscReal      rc_lc,rx_lx,t2_t1,x2_x1,t3_t1,x3_x1,t3_t2,x3_x2;
    463:   PetscReal      R_y2_y_1,R_y3_y_1,R_y3_y2;
    465:   int            c;

    468:   /*
    469:         Is triangle even visible in window?
    470:   */
    471:   if (x1 < 0 && x2 < 0 && x3 < 0) return(0);
    472:   if (y_1 < 0 && y2 < 0 && y3 < 0) return(0);
    473:   if (x1 > 72*8.5 && x2 > 72*8.5 && x3 > 72*8.5) return(0);
    474:   if (y_1 > 72*11 && y2 > 72*11 && y3 > 72*11) return(0);

    476:   /* scale everything by two to reduce the huge file; note this reduces the quality */
    477:   x1  /= 2.0;
    478:   x2  /= 2.0;
    479:   x3  /= 2.0;
    480:   y_1 /= 2.0;
    481:   y2  /= 2.0;
    482:   y3  /= 2.0;
    483:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"gsave 2 2 scale\n");

    486:   /* Sort the vertices */
    487: #define SWAP(a,b) {PetscReal _a; _a=a; a=b; b=_a;}
    488: #define ISWAP(a,b) {int _a; _a=a; a=b; b=_a;}
    489:   if (y_1 > y2) {
    490:     SWAP(y_1,y2);ISWAP(t1,t2); SWAP(x1,x2);
    491:   }
    492:   if (y_1 > y3) {
    493:     SWAP(y_1,y3);ISWAP(t1,t3); SWAP(x1,x3);
    494:   }
    495:   if (y2 > y3) {
    496:     SWAP(y2,y3);ISWAP(t2,t3); SWAP(x2,x3);
    497:   }
    498:   /* This code is decidely non-optimal; it is intended to be a start at
    499:    an implementation */

    501:   if (y2 != y_1) R_y2_y_1 = 1.0/((y2-y_1)); else R_y2_y_1 = 0.0;
    502:   if (y3 != y_1) R_y3_y_1 = 1.0/((y3-y_1)); else R_y3_y_1 = 0.0;
    503:   t2_t1   = t2 - t1;
    504:   x2_x1   = x2 - x1;
    505:   t3_t1   = t3 - t1;
    506:   x3_x1   = x3 - x1;
    507:   for (y=y_1; y<=y2; y++) {
    508:     /* PetscDraw a line with the correct color from t1-t2 to t1-t3 */
    509:     /* Left color is (y-y_1)/(y2-y_1) * (t2-t1) + t1 */
    510:     lfrac = ((y-y_1)) * R_y2_y_1;
    511:     lc    = (lfrac * (t2_t1) + t1);
    512:     lx    = (lfrac * (x2_x1) + x1);
    513:     /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */
    514:     rfrac = ((y - y_1)) * R_y3_y_1;
    515:     rc    = (rfrac * (t3_t1) + t1);
    516:     rx    = (rfrac * (x3_x1) + x1);
    517:     /* PetscDraw the line */
    518:     rc_lc = rc - lc;
    519:     rx_lx = rx - lx;
    520:     if (rx > lx) {
    521:       for (xx=lx; xx<=rx; xx++) {
    522:         c = (int)(((xx-lx) * (rc_lc)) / (rx_lx) + lc);
    523:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g c\n",rgb[0][c],rgb[1][c],rgb[2][c]);
    524:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g m %g %g l\n",xx,y,xx+1,y);
    525:       }
    526:     } else if (rx < lx) {
    527:       for (xx=lx; xx>=rx; xx--) {
    528:         c = (int)(((xx-lx) * (rc_lc)) / (rx_lx) + lc);
    529:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g c\n",rgb[0][c],rgb[1][c],rgb[2][c]);
    530:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g m %g %g l\n",xx,y,xx+1,y);
    531:       }
    532:     } else {
    533:       c = (int)lc;
    534:       PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g c\n",rgb[0][c],rgb[1][c],rgb[2][c]);
    535:       PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g m %g %g l\n",lx,y,lx+1,y);
    536:     }
    537:   }

    539:   /* For simplicity,"move" t1 to the intersection of t1-t3 with the line y=y2.
    540:      We take advantage of the previous iteration. */
    541:   if (y2 >= y3) {
    542:     PetscViewerASCIISynchronizedPrintf(ps->ps_file,"grestore\n");
    543:     return(0);
    544:   }
    545:   if (y_1 < y2) {
    546:     t1  = (int)rc;
    547:     y_1 = y2;
    548:     x1  = rx;

    550:     t3_t1   = t3 - t1;
    551:     x3_x1   = x3 - x1;
    552:   }
    553:   t3_t2 = t3 - t2;
    554:   x3_x2 = x3 - x2;
    555:   if (y3 != y2) R_y3_y2 = 1.0/((y3-y2)); else R_y3_y2 = 0.0;
    556:   if (y3 != y_1) R_y3_y_1 = 1.0/((y3-y_1)); else R_y3_y_1 = 0.0;
    557:   for (y=y2; y<=y3; y++) {
    558:     /* PetscDraw a line with the correct color from t2-t3 to t1-t3 */
    559:     /* Left color is (y-y_1)/(y2-y_1) * (t2-t1) + t1 */
    560:     lfrac = ((y-y2)) * R_y3_y2;
    561:     lc    = (lfrac * (t3_t2) + t2);
    562:     lx    = (lfrac * (x3_x2) + x2);
    563:     /* Right color is (y-y_1)/(y3-y_1) * (t3-t1) + t1 */
    564:     rfrac = ((y - y_1)) * R_y3_y_1;
    565:     rc    = (rfrac * (t3_t1) + t1);
    566:     rx    = (rfrac * (x3_x1) + x1);
    567:     /* PetscDraw the line */
    568:     rc_lc = rc - lc;
    569:     rx_lx = rx - lx;
    570:     if (rx > lx) {
    571:       for (xx=lx; xx<=rx; xx++) {
    572:         c = (int)(((xx-lx) * (rc_lc)) / (rx_lx) + lc);
    573:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g c\n",rgb[0][c],rgb[1][c],rgb[2][c]);
    574:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g m %g %g l\n",xx,y,xx+1,y);
    575:       }
    576:     } else if (rx < lx) {
    577:       for (xx=lx; xx>=rx; xx--) {
    578:         c = (int)(((xx-lx) * (rc_lc)) / (rx_lx) + lc);
    579:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g c\n",rgb[0][c],rgb[1][c],rgb[2][c]);
    580:         PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g m %g %g l\n",xx,y,xx+1,y);
    581:       }
    582:     } else {
    583:       c = (int)lc;
    584:       PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g %g c\n",rgb[0][c],rgb[1][c],rgb[2][c]);
    585:       PetscViewerASCIISynchronizedPrintf(ps->ps_file,"%g %g m %g %g l\n",lx,y,lx+1,y);
    586:     }
    587:   }
    588:   PetscViewerASCIISynchronizedPrintf(ps->ps_file,"grestore\n");
    589:   return(0);
    590: }