Actual source code: axisc.c

petsc-3.13.6 2020-09-29
Report Typos and Errors
  1:  #include <../src/sys/classes/draw/utils/axisimpl.h>

  3: PetscClassId PETSC_DRAWAXIS_CLASSID = 0;

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

  8:    Collective on PetscDraw

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

 13:    Ouput Parameters:
 14: .  axis - the axis datastructure

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

 20:    Level: advanced

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


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

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

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

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

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

 59:     Collective on PetscDrawAxis

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

 64:     Level: advanced

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

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

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

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

 89:     Logically Collective on PetscDrawAxis

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

 97:     Level: advanced

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

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

115:     Logically Collective on PetscDrawAxis

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

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

126:     Level: advanced

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

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

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

148:     Logically Collective on PetscDrawAxis

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

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

158:     Level: advanced

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

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

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

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

181:     Not Collective

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

188:     Level: advanced

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

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

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

208:     Logically Collective on PetscDrawAxis

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

214:     Level: advanced

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

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

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

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

235:     Collective on PetscDrawAxis

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

240:     Level: advanced

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

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

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

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

269:   draw = axis->win;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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