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: }