Actual source code: axisc.c
petsc-3.11.4 2019-09-28
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: *xmin = axis->xlow;
198: *xmax = axis->xhigh;
199: *ymin = axis->ylow;
200: *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: }