Actual source code: axisc.c

  1: #include <petsc/private/drawimpl.h>

  3: #define PETSC_DRAW_AXIS_MAX_SEGMENTS 20
  4: PetscClassId PETSC_DRAWAXIS_CLASSID = 0;

  6: /*@
  7:    PetscDrawAxisCreate - Generate the axis data structure.

  9:    Collective on PetscDraw

 11:    Input Parameters:
 12: .  win - PetscDraw object where axis to to be made

 14:    Output Parameter:
 15: .  axis - the axis datastructure

 17:    Notes:
 18:     the MPI communicator that owns the underlying draw object owns the PetscDrawAxis object, but calls to set PetscDrawAxis options are ignored by all processes
 19:           except the first MPI process in the communicator

 21:    Level: advanced

 23: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawLGGetAxis(), PetscDrawSPGetAxis(),
 24:           PetscDrawHGGetAxis(), PetscDrawBarGetAxis(), PetscDrawAxis, PetscDrawAxisDestroy(), PetscDrawAxisSetColors(), PetscDrawAxisSetLabels(), PetscDrawAxisSetLimits(), PetscDrawAxisGetLimits(), PetscDrawAxisSetHoldLimits(),
 25:           PetscDrawAxisDraw()
 26: @*/
 27: PetscErrorCode  PetscDrawAxisCreate(PetscDraw draw,PetscDrawAxis *axis)
 28: {
 29:   PetscDrawAxis  ad;


 36:   PetscHeaderCreate(ad,PETSC_DRAWAXIS_CLASSID,"DrawAxis","Draw Axis","Draw",PetscObjectComm((PetscObject)draw),PetscDrawAxisDestroy,NULL);
 37:   PetscLogObjectParent((PetscObject)draw,(PetscObject)ad);

 39:   PetscObjectReference((PetscObject)draw);
 40:   ad->win = draw;

 42:   ad->xticks    = PetscADefTicks;
 43:   ad->yticks    = PetscADefTicks;
 44:   ad->xlabelstr = PetscADefLabel;
 45:   ad->ylabelstr = PetscADefLabel;
 46:   ad->ac        = PETSC_DRAW_BLACK;
 47:   ad->tc        = PETSC_DRAW_BLACK;
 48:   ad->cc        = PETSC_DRAW_BLACK;
 49:   ad->xlabel    = NULL;
 50:   ad->ylabel    = NULL;
 51:   ad->toplabel  = NULL;

 53:   *axis = ad;
 54:   return(0);
 55: }

 57: /*@
 58:     PetscDrawAxisDestroy - Frees the space used by an axis structure.

 60:     Collective on PetscDrawAxis

 62:     Input Parameters:
 63: .   axis - the axis context

 65:     Level: advanced

 67: .seealso: PetscDrawAxisCreate(), PetscDrawAxis
 68: @*/
 69: PetscErrorCode  PetscDrawAxisDestroy(PetscDrawAxis *axis)
 70: {

 74:   if (!*axis) return(0);
 76:   if (--((PetscObject)(*axis))->refct > 0) {*axis = NULL; return(0);}

 78:   PetscFree((*axis)->toplabel);
 79:   PetscFree((*axis)->xlabel);
 80:   PetscFree((*axis)->ylabel);
 81:   PetscDrawDestroy(&(*axis)->win);
 82:   PetscHeaderDestroy(axis);
 83:   return(0);
 84: }

 86: /*@
 87:     PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
 88:                          tickmarks, and text.

 90:     Logically Collective on PetscDrawAxis

 92:     Input Parameters:
 93: +   axis - the axis
 94: .   ac - the color of the axis lines
 95: .   tc - the color of the tick marks
 96: -   cc - the color of the text strings

 98:     Level: advanced

100: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetLabels(), PetscDrawAxisDraw(), PetscDrawAxisSetLimits()
101: @*/
102: PetscErrorCode  PetscDrawAxisSetColors(PetscDrawAxis axis,int ac,int tc,int cc)
103: {
109:   axis->ac = ac; axis->tc = tc; axis->cc = cc;
110:   return(0);
111: }

113: /*@C
114:     PetscDrawAxisSetLabels -  Sets the x and y axis labels.

116:     Logically Collective on PetscDrawAxis

118:     Input Parameters:
119: +   axis - the axis
120: .   top - the label at the top of the image
121: -   xlabel,ylabel - the labes for the x and y axis

123:     Notes:
124:     Must be called before PetscDrawAxisDraw() or PetscDrawLGDraw()
125:            There should be no newlines in the arguments

127:     Level: advanced

129: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetColors(), PetscDrawAxisDraw(), PetscDrawAxisSetLimits()
130: @*/
131: PetscErrorCode  PetscDrawAxisSetLabels(PetscDrawAxis axis,const char top[],const char xlabel[],const char ylabel[])
132: {

137:   PetscFree(axis->xlabel);
138:   PetscFree(axis->ylabel);
139:   PetscFree(axis->toplabel);
140:   PetscStrallocpy(xlabel,&axis->xlabel);
141:   PetscStrallocpy(ylabel,&axis->ylabel);
142:   PetscStrallocpy(top,&axis->toplabel);
143:   return(0);
144: }

146: /*@
147:     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis

149:     Logically Collective on PetscDrawAxis

151:     Input Parameters:
152: +   axis - the axis
153: .   xmin,xmax - limits in x
154: -   ymin,ymax - limits in y

156:     Options Database:
157: .   -drawaxis_hold - hold the initial set of axis limits for future plotting

159:     Level: advanced

161: .seealso:  PetscDrawAxisSetHoldLimits(), PetscDrawAxisGetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()

163: @*/
164: PetscErrorCode  PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
165: {

170:   if (axis->hold) return(0);
171:   axis->xlow = xmin;
172:   axis->xhigh= xmax;
173:   axis->ylow = ymin;
174:   axis->yhigh= ymax;
175:   PetscOptionsHasName(((PetscObject)axis)->options,((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);
176:   return(0);
177: }

179: /*@
180:     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis

182:     Not Collective

184:     Input Parameters:
185: +   axis - the axis
186: .   xmin,xmax - limits in x
187: -   ymin,ymax - limits in y

189:     Level: advanced

191: .seealso:  PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetHoldLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()

193: @*/
194: PetscErrorCode  PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
195: {
198:   if (xmin) *xmin = axis->xlow;
199:   if (xmax) *xmax = axis->xhigh;
200:   if (ymin) *ymin = axis->ylow;
201:   if (ymax) *ymax = axis->yhigh;
202:   return(0);
203: }

205: /*@
206:     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
207:         again

209:     Logically Collective on PetscDrawAxis

211:     Input Parameters:
212: +   axis - the axis
213: -   hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed

215:     Level: advanced

217:     Notes:
218:         Once this has been called with PETSC_TRUE the limits will not change if you call
219:      PetscDrawAxisSetLimits() until you call this with PETSC_FALSE

221: .seealso:  PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisGetLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()

223: @*/
224: PetscErrorCode  PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold)
225: {
229:   axis->hold = hold;
230:   return(0);
231: }

233: /*@
234:     PetscDrawAxisDraw - PetscDraws an axis.

236:     Collective on PetscDrawAxis

238:     Input Parameter:
239: .   axis - Axis structure

241:     Level: advanced

243:     Note:
244:     This draws the actual axis.  The limits etc have already been set.
245:     By picking special routines for the ticks and labels, special
246:     effects may be generated.  These routines are part of the Axis
247:     structure (axis).

249: .seealso:  PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisGetLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()

251: @*/
252: PetscErrorCode  PetscDrawAxisDraw(PetscDrawAxis axis)
253: {
254:   int            i,ntick,numx,numy,ac,tc,cc;
255:   PetscMPIInt    rank;
256:   size_t         len,ytlen=0;
257:   PetscReal      coors[4],tickloc[PETSC_DRAW_AXIS_MAX_SEGMENTS],sep,tw,th;
258:   PetscReal      xl,xr,yl,yr,dxl=0,dyl=0,dxr=0,dyr=0;
259:   char           *p;
260:   PetscDraw      draw;
261:   PetscBool      isnull;

266:   PetscDrawIsNull(axis->win,&isnull);
267:   if (isnull) return(0);
268:   MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);

270:   draw = axis->win;

272:   ac = axis->ac; tc = axis->tc; cc = axis->cc;
273:   if (axis->xlow == axis->xhigh) {axis->xlow -= .5; axis->xhigh += .5;}
274:   if (axis->ylow == axis->yhigh) {axis->ylow -= .5; axis->yhigh += .5;}

276:   PetscDrawCollectiveBegin(draw);
277:   if (rank) goto finally;

279:   /* get cannonical string size */
280:   PetscDrawSetCoordinates(draw,0,0,1,1);
281:   PetscDrawStringGetSize(draw,&tw,&th);
282:   /* lower spacing */
283:   if (axis->xlabelstr) dyl += 1.5*th;
284:   if (axis->xlabel)    dyl += 1.5*th;
285:   /* left spacing */
286:   if (axis->ylabelstr) dxl += 7.5*tw;
287:   if (axis->ylabel)    dxl += 2.0*tw;
288:   /* right and top spacing */
289:   if (axis->xlabelstr) dxr = 2.5*tw;
290:   if (axis->ylabelstr) dyr = 0.5*th;
291:   if (axis->toplabel)  dyr = 1.5*th;
292:   /* extra spacing */
293:   dxl += 0.7*tw; dxr += 0.5*tw;
294:   dyl += 0.2*th; dyr += 0.2*th;
295:   /* determine coordinates */
296:   xl = (dxl*axis->xhigh + dxr*axis->xlow - axis->xlow)  / (dxl + dxr - 1);
297:   xr = (dxl*axis->xhigh + dxr*axis->xlow - axis->xhigh) / (dxl + dxr - 1);
298:   yl = (dyl*axis->yhigh + dyr*axis->ylow - axis->ylow)  / (dyl + dyr - 1);
299:   yr = (dyl*axis->yhigh + dyr*axis->ylow - axis->yhigh) / (dyl + dyr - 1);
300:   PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
301:   PetscDrawStringGetSize(draw,&tw,&th);

303:   /* PetscDraw the axis lines */
304:   PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);
305:   PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);
306:   PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);
307:   PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);

309:   /* PetscDraw the top label */
310:   if (axis->toplabel) {
311:     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th;
312:     PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);
313:   }

315:   /* PetscDraw the X ticks and labels */
316:   if (axis->xticks) {
317:     numx = (int)(.15*(axis->xhigh-axis->xlow)/tw); numx = PetscClipInterval(numx,2,6);
318:     (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,PETSC_DRAW_AXIS_MAX_SEGMENTS);
319:     /* PetscDraw in tick marks */
320:     for (i=0; i<ntick; i++) {
321:       PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);
322:       PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);
323:     }
324:     /* label ticks */
325:     if (axis->xlabelstr) {
326:       for (i=0; i<ntick; i++) {
327:         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
328:         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
329:         else               sep = 0.0;
330:         (*axis->xlabelstr)(tickloc[i],sep,&p);
331:         PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);
332:       }
333:     }
334:   }
335:   if (axis->xlabel) {
336:     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->ylow - 1.5*th;
337:     if (axis->xlabelstr) y -= 1.5*th;
338:     PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);
339:   }

341:   /* PetscDraw the Y ticks and labels */
342:   if (axis->yticks) {
343:     numy = (int)(.50*(axis->yhigh-axis->ylow)/th); numy = PetscClipInterval(numy,2,6);
344:     (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,PETSC_DRAW_AXIS_MAX_SEGMENTS);
345:     /* PetscDraw in tick marks */
346:     for (i=0; i<ntick; i++) {
347:       PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);
348:       PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);
349:     }
350:     /* label ticks */
351:     if (axis->ylabelstr) {
352:       for (i=0; i<ntick; i++) {
353:         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
354:         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
355:         else               sep = 0.0;
356:         (*axis->ylabelstr)(tickloc[i],sep,&p);
357:         PetscStrlen(p,&len); ytlen = PetscMax(ytlen,len);
358:         PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);
359:       }
360:     }
361:   }
362:   if (axis->ylabel) {
363:     PetscReal x = axis->xlow - 2.0*tw, y = (axis->ylow + axis->yhigh)/2;
364:     if (axis->ylabelstr) x -= (ytlen+.5)*tw;
365:     PetscStrlen(axis->ylabel,&len);
366:     PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);
367:   }

369:   PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);
370: finally:
371:   PetscDrawCollectiveEnd(draw);
372:   MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));
373:   PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);
374:   return(0);
375: }

377: /*
378:     Removes all zeros but one from .0000
379: */
380: PetscErrorCode PetscStripe0(char *buf)
381: {
383:   size_t         n;
384:   PetscBool      flg;
385:   char           *str;

388:   PetscStrlen(buf,&n);
389:   PetscStrendswith(buf,"e00",&flg);
390:   if (flg) buf[n-3] = 0;
391:   PetscStrstr(buf,"e0",&str);
392:   if (str) {
393:     buf[n-2] = buf[n-1];
394:     buf[n-1] = 0;
395:   }
396:   PetscStrstr(buf,"e-0",&str);
397:   if (str) {
398:     buf[n-2] = buf[n-1];
399:     buf[n-1] = 0;
400:   }
401:   return(0);
402: }

404: /*
405:     Removes all zeros but one from .0000
406: */
407: PetscErrorCode PetscStripAllZeros(char *buf)
408: {
410:   size_t         i,n;

413:   PetscStrlen(buf,&n);
414:   if (buf[0] != '.') return(0);
415:   for (i=1; i<n; i++) {
416:     if (buf[i] != '0') return(0);
417:   }
418:   buf[0] = '0';
419:   buf[1] = 0;
420:   return(0);
421: }

423: /*
424:     Removes trailing zeros
425: */
426: PetscErrorCode PetscStripTrailingZeros(char *buf)
427: {
429:   char           *found;
430:   size_t         i,n,m = PETSC_MAX_INT;

433:   /* if there is an e in string DO NOT strip trailing zeros */
434:   PetscStrchr(buf,'e',&found);
435:   if (found) return(0);

437:   PetscStrlen(buf,&n);
438:   /* locate decimal point */
439:   for (i=0; i<n; i++) {
440:     if (buf[i] == '.') {m = i; break;}
441:   }
442:   /* if not decimal point then no zeros to remove */
443:   if (m == PETSC_MAX_INT) return(0);
444:   /* start at right end of string removing 0s */
445:   for (i=n-1; i>m; i++) {
446:     if (buf[i] != '0') return(0);
447:     buf[i] = 0;
448:   }
449:   return(0);
450: }

452: /*
453:     Removes leading 0 from 0.22 or -0.22
454: */
455: PetscErrorCode PetscStripInitialZero(char *buf)
456: {
458:   size_t         i,n;

461:   PetscStrlen(buf,&n);
462:   if (buf[0] == '0') {
463:     for (i=0; i<n; i++) buf[i] = buf[i+1];
464:   } else if (buf[0] == '-' && buf[1] == '0') {
465:     for (i=1; i<n; i++) buf[i] = buf[i+1];
466:   }
467:   return(0);
468: }

470: /*
471:      Removes the extraneous zeros in numbers like 1.10000e6
472: */
473: PetscErrorCode PetscStripZeros(char *buf)
474: {
476:   size_t         i,j,n;

479:   PetscStrlen(buf,&n);
480:   if (n<5) return(0);
481:   for (i=1; i<n-1; i++) {
482:     if (buf[i] == 'e' && buf[i-1] == '0') {
483:       for (j=i; j<n+1; j++) buf[j-1] = buf[j];
484:       PetscStripZeros(buf);
485:       return(0);
486:     }
487:   }
488:   return(0);
489: }

491: /*
492:       Removes the plus in something like 1.1e+2 or 1.1e+02
493: */
494: PetscErrorCode PetscStripZerosPlus(char *buf)
495: {
497:   size_t         i,j,n;

500:   PetscStrlen(buf,&n);
501:   if (n<5) return(0);
502:   for (i=1; i<n-2; i++) {
503:     if (buf[i] == '+') {
504:       if (buf[i+1] == '0') {
505:         for (j=i+1; j<n; j++) buf[j-1] = buf[j+1];
506:         return(0);
507:       } else {
508:         for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
509:         return(0);
510:       }
511:     } else if (buf[i] == '-') {
512:       if (buf[i+1] == '0') {
513:         for (j=i+1; j<n; j++) buf[j] = buf[j+1];
514:         return(0);
515:       }
516:     }
517:   }
518:   return(0);
519: }