Actual source code: axisc.c
petsc-3.7.7 2017-09-25
1: #include <../src/sys/classes/draw/utils/axisimpl.h> /*I "petscdraw.h" I*/
3: PetscClassId PETSC_DRAWAXIS_CLASSID = 0;
7: /*@
8: PetscDrawAxisCreate - Generate the axis data structure.
10: Collective on PetscDraw
12: Input Parameters:
13: . win - PetscDraw object where axis to to be made
15: Ouput Parameters:
16: . axis - the axis datastructure
18: Level: advanced
20: @*/
21: PetscErrorCode PetscDrawAxisCreate(PetscDraw draw,PetscDrawAxis *axis)
22: {
23: PetscDrawAxis ad;
30: PetscHeaderCreate(ad,PETSC_DRAWAXIS_CLASSID,"DrawAxis","Draw Axis","Draw",PetscObjectComm((PetscObject)draw),PetscDrawAxisDestroy,NULL);
31: PetscLogObjectParent((PetscObject)draw,(PetscObject)ad);
33: PetscObjectReference((PetscObject)draw);
34: ad->win = draw;
36: ad->xticks = PetscADefTicks;
37: ad->yticks = PetscADefTicks;
38: ad->xlabelstr = PetscADefLabel;
39: ad->ylabelstr = PetscADefLabel;
40: ad->ac = PETSC_DRAW_BLACK;
41: ad->tc = PETSC_DRAW_BLACK;
42: ad->cc = PETSC_DRAW_BLACK;
43: ad->xlabel = NULL;
44: ad->ylabel = NULL;
45: ad->toplabel = NULL;
47: *axis = ad;
48: return(0);
49: }
53: /*@
54: PetscDrawAxisDestroy - Frees the space used by an axis structure.
56: Collective on PetscDrawAxis
58: Input Parameters:
59: . axis - the axis context
61: Level: advanced
63: @*/
64: PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis)
65: {
69: if (!*axis) return(0);
71: if (--((PetscObject)(*axis))->refct > 0) {*axis = NULL; return(0);}
73: PetscFree((*axis)->toplabel);
74: PetscFree((*axis)->xlabel);
75: PetscFree((*axis)->ylabel);
76: PetscDrawDestroy(&(*axis)->win);
77: PetscHeaderDestroy(axis);
78: return(0);
79: }
83: /*@
84: PetscDrawAxisSetColors - Sets the colors to be used for the axis,
85: tickmarks, and text.
87: Logically Collective on PetscDrawAxis
89: Input Parameters:
90: + axis - the axis
91: . ac - the color of the axis lines
92: . tc - the color of the tick marks
93: - cc - the color of the text strings
95: Level: advanced
97: @*/
98: PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis,int ac,int tc,int cc)
99: {
105: axis->ac = ac; axis->tc = tc; axis->cc = cc;
106: return(0);
107: }
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: @*/
127: PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis,const char top[],const char xlabel[],const char ylabel[])
128: {
133: PetscFree(axis->xlabel);
134: PetscFree(axis->ylabel);
135: PetscFree(axis->toplabel);
136: PetscStrallocpy(xlabel,&axis->xlabel);
137: PetscStrallocpy(ylabel,&axis->ylabel);
138: PetscStrallocpy(top,&axis->toplabel);
139: return(0);
140: }
144: /*@
145: PetscDrawAxisSetLimits - Sets the limits (in user coords) of the axis
147: Logically Collective on PetscDrawAxis
149: Input Parameters:
150: + axis - the axis
151: . xmin,xmax - limits in x
152: - ymin,ymax - limits in y
154: Options Database:
155: . -drawaxis_hold - hold the initial set of axis limits for future plotting
157: Level: advanced
159: .seealso: PetscDrawAxisSetHoldLimits()
161: @*/
162: PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
163: {
168: if (axis->hold) return(0);
169: axis->xlow = xmin;
170: axis->xhigh= xmax;
171: axis->ylow = ymin;
172: axis->yhigh= ymax;
173: PetscOptionsHasName(((PetscObject)axis)->options,((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);
174: return(0);
175: }
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: PetscDrawAxisSetLimits()
193: @*/
194: PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
195: {
198: *xmin = axis->xlow;
199: *xmax = axis->xhigh;
200: *ymin = axis->ylow;
201: *ymax = axis->yhigh;
202: return(0);
203: }
207: /*@
208: PetscDrawAxisSetHoldLimits - Causes an axis to keep the same limits until this is called
209: again
211: Logically Collective on PetscDrawAxis
213: Input Parameters:
214: + axis - the axis
215: - hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed
217: Level: advanced
219: Notes:
220: Once this has been called with PETSC_TRUE the limits will not change if you call
221: PetscDrawAxisSetLimits() until you call this with PETSC_FALSE
223: .seealso: PetscDrawAxisSetLimits()
225: @*/
226: PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold)
227: {
231: axis->hold = hold;
232: return(0);
233: }
237: /*@
238: PetscDrawAxisDraw - PetscDraws an axis.
240: Collective on PetscDrawAxis
242: Input Parameter:
243: . axis - Axis structure
245: Level: advanced
247: Note:
248: This draws the actual axis. The limits etc have already been set.
249: By picking special routines for the ticks and labels, special
250: effects may be generated. These routines are part of the Axis
251: structure (axis).
252: @*/
253: PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis)
254: {
255: int i,ntick,numx,numy,ac,tc,cc;
256: PetscMPIInt rank;
257: size_t len,ytlen=0;
258: PetscReal coors[4],tickloc[MAXSEGS],sep,tw,th;
259: PetscReal xl,xr,yl,yr,dxl=0,dyl=0,dxr=0,dyr=0;
260: char *p;
261: PetscDraw draw;
262: PetscBool isnull;
267: PetscDrawIsNull(axis->win,&isnull);
268: if (isnull) return(0);
269: MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);
271: draw = axis->win;
273: ac = axis->ac; tc = axis->tc; cc = axis->cc;
274: if (axis->xlow == axis->xhigh) {axis->xlow -= .5; axis->xhigh += .5;}
275: if (axis->ylow == axis->yhigh) {axis->ylow -= .5; axis->yhigh += .5;}
277: PetscDrawCollectiveBegin(draw);
278: if (rank) goto finally;
280: /* get cannonical string size */
281: PetscDrawSetCoordinates(draw,0,0,1,1);
282: PetscDrawStringGetSize(draw,&tw,&th);
283: /* lower spacing */
284: if (axis->xlabelstr) dyl += 1.5*th;
285: if (axis->xlabel) dyl += 1.5*th;
286: /* left spacing */
287: if (axis->ylabelstr) dxl += 7.5*tw;
288: if (axis->ylabel) dxl += 2.0*tw;
289: /* right and top spacing */
290: if (axis->xlabelstr) dxr = 2.5*tw;
291: if (axis->ylabelstr) dyr = 0.5*th;
292: if (axis->toplabel) dyr = 1.5*th;
293: /* extra spacing */
294: dxl += 0.7*tw; dxr += 0.5*tw;
295: dyl += 0.2*th; dyr += 0.2*th;
296: /* determine coordinates */
297: xl = (dxl*axis->xhigh + dxr*axis->xlow - axis->xlow) / (dxl + dxr - 1);
298: xr = (dxl*axis->xhigh + dxr*axis->xlow - axis->xhigh) / (dxl + dxr - 1);
299: yl = (dyl*axis->yhigh + dyr*axis->ylow - axis->ylow) / (dyl + dyr - 1);
300: yr = (dyl*axis->yhigh + dyr*axis->ylow - axis->yhigh) / (dyl + dyr - 1);
301: PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
302: PetscDrawStringGetSize(draw,&tw,&th);
304: /* PetscDraw the axis lines */
305: PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);
306: PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);
307: PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);
308: PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);
310: /* PetscDraw the top label */
311: if (axis->toplabel) {
312: PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th;
313: PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);
314: }
316: /* PetscDraw the X ticks and labels */
317: if (axis->xticks) {
318: numx = (int)(.15*(axis->xhigh-axis->xlow)/tw); numx = PetscClipInterval(numx,2,6);
319: (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);
320: /* PetscDraw in tick marks */
321: for (i=0; i<ntick; i++) {
322: PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);
323: PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);
324: }
325: /* label ticks */
326: if (axis->xlabelstr) {
327: for (i=0; i<ntick; i++) {
328: if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
329: else if (i > 0) sep = tickloc[i] - tickloc[i-1];
330: else sep = 0.0;
331: (*axis->xlabelstr)(tickloc[i],sep,&p);
332: PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);
333: }
334: }
335: }
336: if (axis->xlabel) {
337: PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->ylow - 1.5*th;
338: if (axis->xlabelstr) y -= 1.5*th;
339: PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);
340: }
342: /* PetscDraw the Y ticks and labels */
343: if (axis->yticks) {
344: numy = (int)(.50*(axis->yhigh-axis->ylow)/th); numy = PetscClipInterval(numy,2,6);
345: (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);
346: /* PetscDraw in tick marks */
347: for (i=0; i<ntick; i++) {
348: PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);
349: PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);
350: }
351: /* label ticks */
352: if (axis->ylabelstr) {
353: for (i=0; i<ntick; i++) {
354: if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
355: else if (i > 0) sep = tickloc[i] - tickloc[i-1];
356: else sep = 0.0;
357: (*axis->ylabelstr)(tickloc[i],sep,&p);
358: PetscStrlen(p,&len); ytlen = PetscMax(ytlen,len);
359: PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);
360: }
361: }
362: }
363: if (axis->ylabel) {
364: PetscReal x = axis->xlow - 2.0*tw, y = (axis->ylow + axis->yhigh)/2;
365: if (axis->ylabelstr) x -= (ytlen+.5)*tw;
366: PetscStrlen(axis->ylabel,&len);
367: PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);
368: }
370: PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);
371: finally:
372: PetscDrawCollectiveEnd(draw);
373: MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));
374: PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);
375: return(0);
376: }
380: /*
381: Removes all zeros but one from .0000
382: */
383: PetscErrorCode PetscStripe0(char *buf)
384: {
386: size_t n;
387: PetscBool flg;
388: char *str;
391: PetscStrlen(buf,&n);
392: PetscStrendswith(buf,"e00",&flg);
393: if (flg) buf[n-3] = 0;
394: PetscStrstr(buf,"e0",&str);
395: if (str) {
396: buf[n-2] = buf[n-1];
397: buf[n-1] = 0;
398: }
399: PetscStrstr(buf,"e-0",&str);
400: if (str) {
401: buf[n-2] = buf[n-1];
402: buf[n-1] = 0;
403: }
404: return(0);
405: }
409: /*
410: Removes all zeros but one from .0000
411: */
412: PetscErrorCode PetscStripAllZeros(char *buf)
413: {
415: size_t i,n;
418: PetscStrlen(buf,&n);
419: if (buf[0] != '.') return(0);
420: for (i=1; i<n; i++) {
421: if (buf[i] != '0') return(0);
422: }
423: buf[0] = '0';
424: buf[1] = 0;
425: return(0);
426: }
430: /*
431: Removes trailing zeros
432: */
433: PetscErrorCode PetscStripTrailingZeros(char *buf)
434: {
436: char *found;
437: size_t i,n,m = PETSC_MAX_INT;
440: /* if there is an e in string DO NOT strip trailing zeros */
441: PetscStrchr(buf,'e',&found);
442: if (found) return(0);
444: PetscStrlen(buf,&n);
445: /* locate decimal point */
446: for (i=0; i<n; i++) {
447: if (buf[i] == '.') {m = i; break;}
448: }
449: /* if not decimal point then no zeros to remove */
450: if (m == PETSC_MAX_INT) return(0);
451: /* start at right end of string removing 0s */
452: for (i=n-1; i>m; i++) {
453: if (buf[i] != '0') return(0);
454: buf[i] = 0;
455: }
456: return(0);
457: }
461: /*
462: Removes leading 0 from 0.22 or -0.22
463: */
464: PetscErrorCode PetscStripInitialZero(char *buf)
465: {
467: size_t i,n;
470: PetscStrlen(buf,&n);
471: if (buf[0] == '0') {
472: for (i=0; i<n; i++) buf[i] = buf[i+1];
473: } else if (buf[0] == '-' && buf[1] == '0') {
474: for (i=1; i<n; i++) buf[i] = buf[i+1];
475: }
476: return(0);
477: }
481: /*
482: Removes the extraneous zeros in numbers like 1.10000e6
483: */
484: PetscErrorCode PetscStripZeros(char *buf)
485: {
487: size_t i,j,n;
490: PetscStrlen(buf,&n);
491: if (n<5) return(0);
492: for (i=1; i<n-1; i++) {
493: if (buf[i] == 'e' && buf[i-1] == '0') {
494: for (j=i; j<n+1; j++) buf[j-1] = buf[j];
495: PetscStripZeros(buf);
496: return(0);
497: }
498: }
499: return(0);
500: }
504: /*
505: Removes the plus in something like 1.1e+2 or 1.1e+02
506: */
507: PetscErrorCode PetscStripZerosPlus(char *buf)
508: {
510: size_t i,j,n;
513: PetscStrlen(buf,&n);
514: if (n<5) return(0);
515: for (i=1; i<n-2; i++) {
516: if (buf[i] == '+') {
517: if (buf[i+1] == '0') {
518: for (j=i+1; j<n; j++) buf[j-1] = buf[j+1];
519: return(0);
520: } else {
521: for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
522: return(0);
523: }
524: } else if (buf[i] == '-') {
525: if (buf[i+1] == '0') {
526: for (j=i+1; j<n; j++) buf[j] = buf[j+1];
527: return(0);
528: }
529: }
530: }
531: return(0);
532: }