Actual source code: axisc.c
petsc-3.9.4 2018-09-11
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: the MPI communicator that owns the underlying draw object owns the PetscDrawAxis object, but calls to set PetscDrawAxis options are ignored by all processes
17: except the first MPI process in the communicator
19: Level: advanced
21: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawLGGetAxis(), PetscDrawSPGetAxis(),
22: PetscDrawHGGetAxis(), PetscDrawBarGetAxis(), PetscDrawAxis, PetscDrawAxisDestroy(), PetscDrawAxisSetColors(), PetscDrawAxisSetLabels(), PetscDrawAxisSetLimits(), PetscDrawAxisGetLimits(), PetscDrawAxisSetHoldLimits(),
23: PetscDrawAxisDraw()
24: @*/
25: PetscErrorCode PetscDrawAxisCreate(PetscDraw draw,PetscDrawAxis *axis)
26: {
27: PetscDrawAxis ad;
34: PetscHeaderCreate(ad,PETSC_DRAWAXIS_CLASSID,"DrawAxis","Draw Axis","Draw",PetscObjectComm((PetscObject)draw),PetscDrawAxisDestroy,NULL);
35: PetscLogObjectParent((PetscObject)draw,(PetscObject)ad);
37: PetscObjectReference((PetscObject)draw);
38: ad->win = draw;
40: ad->xticks = PetscADefTicks;
41: ad->yticks = PetscADefTicks;
42: ad->xlabelstr = PetscADefLabel;
43: ad->ylabelstr = PetscADefLabel;
44: ad->ac = PETSC_DRAW_BLACK;
45: ad->tc = PETSC_DRAW_BLACK;
46: ad->cc = PETSC_DRAW_BLACK;
47: ad->xlabel = NULL;
48: ad->ylabel = NULL;
49: ad->toplabel = NULL;
51: *axis = ad;
52: return(0);
53: }
55: /*@
56: PetscDrawAxisDestroy - Frees the space used by an axis structure.
58: Collective on PetscDrawAxis
60: Input Parameters:
61: . axis - the axis context
63: Level: advanced
65: .seealso: PetscDrawAxisCreate(), PetscDrawAxis
66: @*/
67: PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis)
68: {
72: if (!*axis) return(0);
74: if (--((PetscObject)(*axis))->refct > 0) {*axis = NULL; return(0);}
76: PetscFree((*axis)->toplabel);
77: PetscFree((*axis)->xlabel);
78: PetscFree((*axis)->ylabel);
79: PetscDrawDestroy(&(*axis)->win);
80: PetscHeaderDestroy(axis);
81: return(0);
82: }
84: /*@
85: PetscDrawAxisSetColors - Sets the colors to be used for the axis,
86: tickmarks, and text.
88: Logically Collective on PetscDrawAxis
90: Input Parameters:
91: + axis - the axis
92: . ac - the color of the axis lines
93: . tc - the color of the tick marks
94: - cc - the color of the text strings
96: Level: advanced
98: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetLabels(), PetscDrawAxisDraw(), PetscDrawAxisSetLimits()
99: @*/
100: PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis,int ac,int tc,int cc)
101: {
107: axis->ac = ac; axis->tc = tc; axis->cc = cc;
108: return(0);
109: }
111: /*@C
112: PetscDrawAxisSetLabels - Sets the x and y axis labels.
114: Logically Collective on PetscDrawAxis
116: Input Parameters:
117: + axis - the axis
118: . top - the label at the top of the image
119: - xlabel,ylabel - the labes for the x and y axis
121: Notes: Must be called before PetscDrawAxisDraw() or PetscDrawLGDraw()
122: There should be no newlines in the arguments
124: Level: advanced
126: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetColors(), PetscDrawAxisDraw(), PetscDrawAxisSetLimits()
127: @*/
128: PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis,const char top[],const char xlabel[],const char ylabel[])
129: {
134: PetscFree(axis->xlabel);
135: PetscFree(axis->ylabel);
136: PetscFree(axis->toplabel);
137: PetscStrallocpy(xlabel,&axis->xlabel);
138: PetscStrallocpy(ylabel,&axis->ylabel);
139: PetscStrallocpy(top,&axis->toplabel);
140: return(0);
141: }
143: /*@
144: PetscDrawAxisSetLimits - Sets the limits (in user coords) of the axis
146: Logically Collective on PetscDrawAxis
148: Input Parameters:
149: + axis - the axis
150: . xmin,xmax - limits in x
151: - ymin,ymax - limits in y
153: Options Database:
154: . -drawaxis_hold - hold the initial set of axis limits for future plotting
156: Level: advanced
158: .seealso: PetscDrawAxisSetHoldLimits(), PetscDrawAxisGetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
160: @*/
161: PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
162: {
167: if (axis->hold) return(0);
168: axis->xlow = xmin;
169: axis->xhigh= xmax;
170: axis->ylow = ymin;
171: axis->yhigh= ymax;
172: PetscOptionsHasName(((PetscObject)axis)->options,((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);
173: return(0);
174: }
176: /*@
177: PetscDrawAxisGetLimits - Gets the limits (in user coords) of the axis
179: Not Collective
181: Input Parameters:
182: + axis - the axis
183: . xmin,xmax - limits in x
184: - ymin,ymax - limits in y
186: Level: advanced
188: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetHoldLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
190: @*/
191: PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
192: {
195: *xmin = axis->xlow;
196: *xmax = axis->xhigh;
197: *ymin = axis->ylow;
198: *ymax = axis->yhigh;
199: return(0);
200: }
202: /*@
203: PetscDrawAxisSetHoldLimits - Causes an axis to keep the same limits until this is called
204: again
206: Logically Collective on PetscDrawAxis
208: Input Parameters:
209: + axis - the axis
210: - hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed
212: Level: advanced
214: Notes:
215: Once this has been called with PETSC_TRUE the limits will not change if you call
216: PetscDrawAxisSetLimits() until you call this with PETSC_FALSE
218: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisGetLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
220: @*/
221: PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold)
222: {
226: axis->hold = hold;
227: return(0);
228: }
230: /*@
231: PetscDrawAxisDraw - PetscDraws an axis.
233: Collective on PetscDrawAxis
235: Input Parameter:
236: . axis - Axis structure
238: Level: advanced
240: Note:
241: This draws the actual axis. The limits etc have already been set.
242: By picking special routines for the ticks and labels, special
243: effects may be generated. These routines are part of the Axis
244: structure (axis).
246: .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisGetLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
248: @*/
249: PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis)
250: {
251: int i,ntick,numx,numy,ac,tc,cc;
252: PetscMPIInt rank;
253: size_t len,ytlen=0;
254: PetscReal coors[4],tickloc[MAXSEGS],sep,tw,th;
255: PetscReal xl,xr,yl,yr,dxl=0,dyl=0,dxr=0,dyr=0;
256: char *p;
257: PetscDraw draw;
258: PetscBool isnull;
263: PetscDrawIsNull(axis->win,&isnull);
264: if (isnull) return(0);
265: MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);
267: draw = axis->win;
269: ac = axis->ac; tc = axis->tc; cc = axis->cc;
270: if (axis->xlow == axis->xhigh) {axis->xlow -= .5; axis->xhigh += .5;}
271: if (axis->ylow == axis->yhigh) {axis->ylow -= .5; axis->yhigh += .5;}
273: PetscDrawCollectiveBegin(draw);
274: if (rank) goto finally;
276: /* get cannonical string size */
277: PetscDrawSetCoordinates(draw,0,0,1,1);
278: PetscDrawStringGetSize(draw,&tw,&th);
279: /* lower spacing */
280: if (axis->xlabelstr) dyl += 1.5*th;
281: if (axis->xlabel) dyl += 1.5*th;
282: /* left spacing */
283: if (axis->ylabelstr) dxl += 7.5*tw;
284: if (axis->ylabel) dxl += 2.0*tw;
285: /* right and top spacing */
286: if (axis->xlabelstr) dxr = 2.5*tw;
287: if (axis->ylabelstr) dyr = 0.5*th;
288: if (axis->toplabel) dyr = 1.5*th;
289: /* extra spacing */
290: dxl += 0.7*tw; dxr += 0.5*tw;
291: dyl += 0.2*th; dyr += 0.2*th;
292: /* determine coordinates */
293: xl = (dxl*axis->xhigh + dxr*axis->xlow - axis->xlow) / (dxl + dxr - 1);
294: xr = (dxl*axis->xhigh + dxr*axis->xlow - axis->xhigh) / (dxl + dxr - 1);
295: yl = (dyl*axis->yhigh + dyr*axis->ylow - axis->ylow) / (dyl + dyr - 1);
296: yr = (dyl*axis->yhigh + dyr*axis->ylow - axis->yhigh) / (dyl + dyr - 1);
297: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
298: PetscDrawStringGetSize(draw,&tw,&th);
300: /* PetscDraw the axis lines */
301: PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);
302: PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);
303: PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);
304: PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);
306: /* PetscDraw the top label */
307: if (axis->toplabel) {
308: PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th;
309: PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);
310: }
312: /* PetscDraw the X ticks and labels */
313: if (axis->xticks) {
314: numx = (int)(.15*(axis->xhigh-axis->xlow)/tw); numx = PetscClipInterval(numx,2,6);
315: (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);
316: /* PetscDraw in tick marks */
317: for (i=0; i<ntick; i++) {
318: PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);
319: PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);
320: }
321: /* label ticks */
322: if (axis->xlabelstr) {
323: for (i=0; i<ntick; i++) {
324: if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
325: else if (i > 0) sep = tickloc[i] - tickloc[i-1];
326: else sep = 0.0;
327: (*axis->xlabelstr)(tickloc[i],sep,&p);
328: PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);
329: }
330: }
331: }
332: if (axis->xlabel) {
333: PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->ylow - 1.5*th;
334: if (axis->xlabelstr) y -= 1.5*th;
335: PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);
336: }
338: /* PetscDraw the Y ticks and labels */
339: if (axis->yticks) {
340: numy = (int)(.50*(axis->yhigh-axis->ylow)/th); numy = PetscClipInterval(numy,2,6);
341: (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);
342: /* PetscDraw in tick marks */
343: for (i=0; i<ntick; i++) {
344: PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);
345: PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);
346: }
347: /* label ticks */
348: if (axis->ylabelstr) {
349: for (i=0; i<ntick; i++) {
350: if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
351: else if (i > 0) sep = tickloc[i] - tickloc[i-1];
352: else sep = 0.0;
353: (*axis->ylabelstr)(tickloc[i],sep,&p);
354: PetscStrlen(p,&len); ytlen = PetscMax(ytlen,len);
355: PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);
356: }
357: }
358: }
359: if (axis->ylabel) {
360: PetscReal x = axis->xlow - 2.0*tw, y = (axis->ylow + axis->yhigh)/2;
361: if (axis->ylabelstr) x -= (ytlen+.5)*tw;
362: PetscStrlen(axis->ylabel,&len);
363: PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);
364: }
366: PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);
367: finally:
368: PetscDrawCollectiveEnd(draw);
369: MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));
370: PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);
371: return(0);
372: }
374: /*
375: Removes all zeros but one from .0000
376: */
377: PetscErrorCode PetscStripe0(char *buf)
378: {
380: size_t n;
381: PetscBool flg;
382: char *str;
385: PetscStrlen(buf,&n);
386: PetscStrendswith(buf,"e00",&flg);
387: if (flg) buf[n-3] = 0;
388: PetscStrstr(buf,"e0",&str);
389: if (str) {
390: buf[n-2] = buf[n-1];
391: buf[n-1] = 0;
392: }
393: PetscStrstr(buf,"e-0",&str);
394: if (str) {
395: buf[n-2] = buf[n-1];
396: buf[n-1] = 0;
397: }
398: return(0);
399: }
401: /*
402: Removes all zeros but one from .0000
403: */
404: PetscErrorCode PetscStripAllZeros(char *buf)
405: {
407: size_t i,n;
410: PetscStrlen(buf,&n);
411: if (buf[0] != '.') return(0);
412: for (i=1; i<n; i++) {
413: if (buf[i] != '0') return(0);
414: }
415: buf[0] = '0';
416: buf[1] = 0;
417: return(0);
418: }
420: /*
421: Removes trailing zeros
422: */
423: PetscErrorCode PetscStripTrailingZeros(char *buf)
424: {
426: char *found;
427: size_t i,n,m = PETSC_MAX_INT;
430: /* if there is an e in string DO NOT strip trailing zeros */
431: PetscStrchr(buf,'e',&found);
432: if (found) return(0);
434: PetscStrlen(buf,&n);
435: /* locate decimal point */
436: for (i=0; i<n; i++) {
437: if (buf[i] == '.') {m = i; break;}
438: }
439: /* if not decimal point then no zeros to remove */
440: if (m == PETSC_MAX_INT) return(0);
441: /* start at right end of string removing 0s */
442: for (i=n-1; i>m; i++) {
443: if (buf[i] != '0') return(0);
444: buf[i] = 0;
445: }
446: return(0);
447: }
449: /*
450: Removes leading 0 from 0.22 or -0.22
451: */
452: PetscErrorCode PetscStripInitialZero(char *buf)
453: {
455: size_t i,n;
458: PetscStrlen(buf,&n);
459: if (buf[0] == '0') {
460: for (i=0; i<n; i++) buf[i] = buf[i+1];
461: } else if (buf[0] == '-' && buf[1] == '0') {
462: for (i=1; i<n; i++) buf[i] = buf[i+1];
463: }
464: return(0);
465: }
467: /*
468: Removes the extraneous zeros in numbers like 1.10000e6
469: */
470: PetscErrorCode PetscStripZeros(char *buf)
471: {
473: size_t i,j,n;
476: PetscStrlen(buf,&n);
477: if (n<5) return(0);
478: for (i=1; i<n-1; i++) {
479: if (buf[i] == 'e' && buf[i-1] == '0') {
480: for (j=i; j<n+1; j++) buf[j-1] = buf[j];
481: PetscStripZeros(buf);
482: return(0);
483: }
484: }
485: return(0);
486: }
488: /*
489: Removes the plus in something like 1.1e+2 or 1.1e+02
490: */
491: PetscErrorCode PetscStripZerosPlus(char *buf)
492: {
494: size_t i,j,n;
497: PetscStrlen(buf,&n);
498: if (n<5) return(0);
499: for (i=1; i<n-2; i++) {
500: if (buf[i] == '+') {
501: if (buf[i+1] == '0') {
502: for (j=i+1; j<n; j++) buf[j-1] = buf[j+1];
503: return(0);
504: } else {
505: for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
506: return(0);
507: }
508: } else if (buf[i] == '-') {
509: if (buf[i+1] == '0') {
510: for (j=i+1; j<n; j++) buf[j] = buf[j+1];
511: return(0);
512: }
513: }
514: }
515: return(0);
516: }