xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision 71917b759519de482e858f2e8a03b977bf09ff31)
1 #include <../src/sys/classes/draw/utils/axisimpl.h>  /*I   "petscdraw.h"  I*/
2 
3 PetscClassId PETSC_DRAWAXIS_CLASSID = 0;
4 
5 #undef __FUNCT__
6 #define __FUNCT__ "PetscDrawAxisCreate"
7 /*@
8    PetscDrawAxisCreate - Generate the axis data structure.
9 
10    Collective on PetscDraw
11 
12    Input Parameters:
13 .  win - PetscDraw object where axis to to be made
14 
15    Ouput Parameters:
16 .  axis - the axis datastructure
17 
18    Level: advanced
19 
20 @*/
21 PetscErrorCode  PetscDrawAxisCreate(PetscDraw draw,PetscDrawAxis *axis)
22 {
23   PetscDrawAxis  ad;
24   PetscErrorCode ierr;
25 
26   PetscFunctionBegin;
27   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
28   PetscValidPointer(axis,2);
29 
30   ierr = PetscHeaderCreate(ad,PETSC_DRAWAXIS_CLASSID,"DrawAxis","Draw Axis","Draw",PetscObjectComm((PetscObject)draw),PetscDrawAxisDestroy,NULL);CHKERRQ(ierr);
31   ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)ad);CHKERRQ(ierr);
32 
33   ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr);
34   ad->win = draw;
35 
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;
46 
47   *axis = ad;
48   PetscFunctionReturn(0);
49 }
50 
51 #undef __FUNCT__
52 #define __FUNCT__ "PetscDrawAxisDestroy"
53 /*@
54     PetscDrawAxisDestroy - Frees the space used by an axis structure.
55 
56     Collective on PetscDrawAxis
57 
58     Input Parameters:
59 .   axis - the axis context
60 
61     Level: advanced
62 
63 @*/
64 PetscErrorCode  PetscDrawAxisDestroy(PetscDrawAxis *axis)
65 {
66   PetscErrorCode ierr;
67 
68   PetscFunctionBegin;
69   if (!*axis) PetscFunctionReturn(0);
70   PetscValidHeaderSpecific(*axis,PETSC_DRAWAXIS_CLASSID,1);
71   if (--((PetscObject)(*axis))->refct > 0) {*axis = NULL; PetscFunctionReturn(0);}
72 
73   ierr = PetscFree((*axis)->toplabel);CHKERRQ(ierr);
74   ierr = PetscFree((*axis)->xlabel);CHKERRQ(ierr);
75   ierr = PetscFree((*axis)->ylabel);CHKERRQ(ierr);
76   ierr = PetscDrawDestroy(&(*axis)->win);CHKERRQ(ierr);
77   ierr = PetscHeaderDestroy(axis);CHKERRQ(ierr);
78   PetscFunctionReturn(0);
79 }
80 
81 #undef __FUNCT__
82 #define __FUNCT__ "PetscDrawAxisSetColors"
83 /*@
84     PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
85                          tickmarks, and text.
86 
87     Logically Collective on PetscDrawAxis
88 
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
94 
95     Level: advanced
96 
97 @*/
98 PetscErrorCode  PetscDrawAxisSetColors(PetscDrawAxis axis,int ac,int tc,int cc)
99 {
100   PetscFunctionBegin;
101   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
102   PetscValidLogicalCollectiveInt(axis,ac,2);
103   PetscValidLogicalCollectiveInt(axis,tc,3);
104   PetscValidLogicalCollectiveInt(axis,cc,4);
105   axis->ac = ac; axis->tc = tc; axis->cc = cc;
106   PetscFunctionReturn(0);
107 }
108 
109 #undef __FUNCT__
110 #define __FUNCT__ "PetscDrawAxisSetLabels"
111 /*@C
112     PetscDrawAxisSetLabels -  Sets the x and y axis labels.
113 
114     Logically Collective on PetscDrawAxis
115 
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
120 
121     Notes: Must be called before PetscDrawAxisDraw() or PetscDrawLGDraw()
122            There should be no newlines in the arguments
123 
124     Level: advanced
125 
126 @*/
127 PetscErrorCode  PetscDrawAxisSetLabels(PetscDrawAxis axis,const char top[],const char xlabel[],const char ylabel[])
128 {
129   PetscErrorCode ierr;
130 
131   PetscFunctionBegin;
132   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
133   ierr = PetscFree(axis->xlabel);CHKERRQ(ierr);
134   ierr = PetscFree(axis->ylabel);CHKERRQ(ierr);
135   ierr = PetscFree(axis->toplabel);CHKERRQ(ierr);
136   ierr = PetscStrallocpy(xlabel,&axis->xlabel);CHKERRQ(ierr);
137   ierr = PetscStrallocpy(ylabel,&axis->ylabel);CHKERRQ(ierr);
138   ierr = PetscStrallocpy(top,&axis->toplabel);CHKERRQ(ierr);
139   PetscFunctionReturn(0);
140 }
141 
142 #undef __FUNCT__
143 #define __FUNCT__ "PetscDrawAxisSetLimits"
144 /*@
145     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
146 
147     Logically Collective on PetscDrawAxis
148 
149     Input Parameters:
150 +   axis - the axis
151 .   xmin,xmax - limits in x
152 -   ymin,ymax - limits in y
153 
154     Options Database:
155 .   -drawaxis_hold - hold the initial set of axis limits for future plotting
156 
157     Level: advanced
158 
159 .seealso:  PetscDrawAxisSetHoldLimits()
160 
161 @*/
162 PetscErrorCode  PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
163 {
164   PetscErrorCode ierr;
165 
166   PetscFunctionBegin;
167   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
168   if (axis->hold) PetscFunctionReturn(0);
169   axis->xlow = xmin;
170   axis->xhigh= xmax;
171   axis->ylow = ymin;
172   axis->yhigh= ymax;
173   ierr = PetscOptionsHasName(((PetscObject)axis)->options,((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);CHKERRQ(ierr);
174   PetscFunctionReturn(0);
175 }
176 
177 #undef __FUNCT__
178 #define __FUNCT__ "PetscDrawAxisGetLimits"
179 /*@
180     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
181 
182     Not Collective
183 
184     Input Parameters:
185 +   axis - the axis
186 .   xmin,xmax - limits in x
187 -   ymin,ymax - limits in y
188 
189     Level: advanced
190 
191 .seealso:  PetscDrawAxisSetLimits()
192 
193 @*/
194 PetscErrorCode  PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
195 {
196   PetscFunctionBegin;
197   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
198   *xmin = axis->xlow;
199   *xmax = axis->xhigh;
200   *ymin = axis->ylow;
201   *ymax = axis->yhigh;
202   PetscFunctionReturn(0);
203 }
204 
205 #undef __FUNCT__
206 #define __FUNCT__ "PetscDrawAxisSetHoldLimits"
207 /*@
208     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
209         again
210 
211     Logically Collective on PetscDrawAxis
212 
213     Input Parameters:
214 +   axis - the axis
215 -   hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed
216 
217     Level: advanced
218 
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
222 
223 .seealso:  PetscDrawAxisSetLimits()
224 
225 @*/
226 PetscErrorCode  PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold)
227 {
228   PetscFunctionBegin;
229   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
230   PetscValidLogicalCollectiveBool(axis,hold,2);
231   axis->hold = hold;
232   PetscFunctionReturn(0);
233 }
234 
235 #undef __FUNCT__
236 #define __FUNCT__ "PetscDrawAxisDraw"
237 /*@
238     PetscDrawAxisDraw - PetscDraws an axis.
239 
240     Collective on PetscDrawAxis
241 
242     Input Parameter:
243 .   axis - Axis structure
244 
245     Level: advanced
246 
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;
263   PetscErrorCode ierr;
264 
265   PetscFunctionBegin;
266   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
267   ierr = PetscDrawIsNull(axis->win,&isnull);CHKERRQ(ierr);
268   if (isnull) PetscFunctionReturn(0);
269   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);CHKERRQ(ierr);
270 
271   draw = axis->win;
272 
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;}
276 
277   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
278   if (rank) goto finally;
279 
280   /* get cannonical string size */
281   ierr = PetscDrawSetCoordinates(draw,0,0,1,1);CHKERRQ(ierr);
282   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
283   /* lower spacing */
284   //if (axis->xlabelstr || axis->xlabel) dyl = 0.5*th;
285   if (axis->xlabelstr) dyl += 1.5*th;
286   if (axis->xlabel)    dyl += 1.5*th;
287   /* left spacing */
288   if (axis->ylabelstr) dxl += 7.5*tw;
289   if (axis->ylabel)    dxl += 2.0*tw;
290   /* right and top spacing */
291   if (axis->xlabelstr) dxr = 2.5*tw;
292   if (axis->ylabelstr) dyr = 0.5*th;
293   if (axis->toplabel)  dyr = 1.5*th;
294   /* extra spacing */
295   dxl += 0.7*tw; dxr += 0.5*tw;
296   dyl += 0.2*th; dyr += 0.2*th;
297   /* determine coordinates */
298   xl = (dxl*axis->xhigh + dxr*axis->xlow - axis->xlow)  / (dxl + dxr - 1);
299   xr = (dxl*axis->xhigh + dxr*axis->xlow - axis->xhigh) / (dxl + dxr - 1);
300   yl = (dyl*axis->yhigh + dyr*axis->ylow - axis->ylow)  / (dyl + dyr - 1);
301   yr = (dyl*axis->yhigh + dyr*axis->ylow - axis->yhigh) / (dyl + dyr - 1);
302   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
303   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
304 
305   /* PetscDraw the axis lines */
306   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);CHKERRQ(ierr);
307   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);CHKERRQ(ierr);
308   ierr = PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr);
309   ierr = PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr);
310 
311   /* PetscDraw the top label */
312   if (axis->toplabel) {
313     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th;
314     ierr = PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);CHKERRQ(ierr);
315   }
316 
317   /* PetscDraw the X ticks and labels */
318   if (axis->xticks) {
319     numx = (int)(.15*(axis->xhigh-axis->xlow)/tw); numx = PetscClipInterval(numx,2,6);
320     ierr = (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
321     /* PetscDraw in tick marks */
322     for (i=0; i<ntick; i++) {
323       ierr = PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);CHKERRQ(ierr);
324       ierr = PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);CHKERRQ(ierr);
325     }
326     /* label ticks */
327     if (axis->xlabelstr) {
328       for (i=0; i<ntick; i++) {
329         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
330         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
331         else               sep = 0.0;
332         ierr = (*axis->xlabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
333         ierr = PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);CHKERRQ(ierr);
334       }
335     }
336   }
337   if (axis->xlabel) {
338     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->ylow - 1.5*th;
339     if (axis->xlabelstr) y -= 1.5*th;
340     ierr = PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);CHKERRQ(ierr);
341   }
342 
343   /* PetscDraw the Y ticks and labels */
344   if (axis->yticks) {
345     numy = (int)(.50*(axis->yhigh-axis->ylow)/th); numy = PetscClipInterval(numy,2,6);
346     ierr = (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
347     /* PetscDraw in tick marks */
348     for (i=0; i<ntick; i++) {
349       ierr = PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);CHKERRQ(ierr);
350       ierr = PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);CHKERRQ(ierr);
351     }
352     /* label ticks */
353     if (axis->ylabelstr) {
354       for (i=0; i<ntick; i++) {
355         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
356         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
357         else               sep = 0.0;
358         ierr = (*axis->ylabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
359         ierr = PetscStrlen(p,&len);CHKERRQ(ierr); ytlen = PetscMax(ytlen,len);
360         ierr = PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);CHKERRQ(ierr);
361       }
362     }
363   }
364   if (axis->ylabel) {
365     PetscReal x = axis->xlow - 2.0*tw, y = (axis->ylow + axis->yhigh)/2;
366     if (axis->ylabelstr) x -= (ytlen+.5)*tw;
367     ierr = PetscStrlen(axis->ylabel,&len);CHKERRQ(ierr);
368     ierr = PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);CHKERRQ(ierr);
369   }
370 
371   ierr = PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);CHKERRQ(ierr);
372 finally:
373   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
374   ierr = MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
375   ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr);
376   PetscFunctionReturn(0);
377 }
378 
379 #undef __FUNCT__
380 #define __FUNCT__ "PetscStripe0"
381 /*
382     Removes all zeros but one from .0000
383 */
384 PetscErrorCode PetscStripe0(char *buf)
385 {
386   PetscErrorCode ierr;
387   size_t         n;
388   PetscBool      flg;
389   char           *str;
390 
391   PetscFunctionBegin;
392   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
393   ierr = PetscStrendswith(buf,"e00",&flg);CHKERRQ(ierr);
394   if (flg) buf[n-3] = 0;
395   ierr = PetscStrstr(buf,"e0",&str);CHKERRQ(ierr);
396   if (str) {
397     buf[n-2] = buf[n-1];
398     buf[n-1] = 0;
399   }
400   ierr = PetscStrstr(buf,"e-0",&str);CHKERRQ(ierr);
401   if (str) {
402     buf[n-2] = buf[n-1];
403     buf[n-1] = 0;
404   }
405   PetscFunctionReturn(0);
406 }
407 
408 #undef __FUNCT__
409 #define __FUNCT__ "PetscStripAllZeros"
410 /*
411     Removes all zeros but one from .0000
412 */
413 PetscErrorCode PetscStripAllZeros(char *buf)
414 {
415   PetscErrorCode ierr;
416   size_t         i,n;
417 
418   PetscFunctionBegin;
419   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
420   if (buf[0] != '.') PetscFunctionReturn(0);
421   for (i=1; i<n; i++) {
422     if (buf[i] != '0') PetscFunctionReturn(0);
423   }
424   buf[0] = '0';
425   buf[1] = 0;
426   PetscFunctionReturn(0);
427 }
428 
429 #undef __FUNCT__
430 #define __FUNCT__ "PetscStripTrailingZeros"
431 /*
432     Removes trailing zeros
433 */
434 PetscErrorCode PetscStripTrailingZeros(char *buf)
435 {
436   PetscErrorCode ierr;
437   char           *found;
438   size_t         i,n,m = PETSC_MAX_INT;
439 
440   PetscFunctionBegin;
441   /* if there is an e in string DO NOT strip trailing zeros */
442   ierr = PetscStrchr(buf,'e',&found);CHKERRQ(ierr);
443   if (found) PetscFunctionReturn(0);
444 
445   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
446   /* locate decimal point */
447   for (i=0; i<n; i++) {
448     if (buf[i] == '.') {m = i; break;}
449   }
450   /* if not decimal point then no zeros to remove */
451   if (m == PETSC_MAX_INT) PetscFunctionReturn(0);
452   /* start at right end of string removing 0s */
453   for (i=n-1; i>m; i++) {
454     if (buf[i] != '0') PetscFunctionReturn(0);
455     buf[i] = 0;
456   }
457   PetscFunctionReturn(0);
458 }
459 
460 #undef __FUNCT__
461 #define __FUNCT__ "PetscStripInitialZero"
462 /*
463     Removes leading 0 from 0.22 or -0.22
464 */
465 PetscErrorCode PetscStripInitialZero(char *buf)
466 {
467   PetscErrorCode ierr;
468   size_t         i,n;
469 
470   PetscFunctionBegin;
471   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
472   if (buf[0] == '0') {
473     for (i=0; i<n; i++) buf[i] = buf[i+1];
474   } else if (buf[0] == '-' && buf[1] == '0') {
475     for (i=1; i<n; i++) buf[i] = buf[i+1];
476   }
477   PetscFunctionReturn(0);
478 }
479 
480 #undef __FUNCT__
481 #define __FUNCT__ "PetscStripZeros"
482 /*
483      Removes the extraneous zeros in numbers like 1.10000e6
484 */
485 PetscErrorCode PetscStripZeros(char *buf)
486 {
487   PetscErrorCode ierr;
488   size_t         i,j,n;
489 
490   PetscFunctionBegin;
491   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
492   if (n<5) PetscFunctionReturn(0);
493   for (i=1; i<n-1; i++) {
494     if (buf[i] == 'e' && buf[i-1] == '0') {
495       for (j=i; j<n+1; j++) buf[j-1] = buf[j];
496       ierr = PetscStripZeros(buf);CHKERRQ(ierr);
497       PetscFunctionReturn(0);
498     }
499   }
500   PetscFunctionReturn(0);
501 }
502 
503 #undef __FUNCT__
504 #define __FUNCT__ "PetscStripZerosPlus"
505 /*
506       Removes the plus in something like 1.1e+2 or 1.1e+02
507 */
508 PetscErrorCode PetscStripZerosPlus(char *buf)
509 {
510   PetscErrorCode ierr;
511   size_t         i,j,n;
512 
513   PetscFunctionBegin;
514   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
515   if (n<5) PetscFunctionReturn(0);
516   for (i=1; i<n-2; i++) {
517     if (buf[i] == '+') {
518       if (buf[i+1] == '0') {
519         for (j=i+1; j<n; j++) buf[j-1] = buf[j+1];
520         PetscFunctionReturn(0);
521       } else {
522         for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
523         PetscFunctionReturn(0);
524       }
525     } else if (buf[i] == '-') {
526       if (buf[i+1] == '0') {
527         for (j=i+1; j<n; j++) buf[j] = buf[j+1];
528         PetscFunctionReturn(0);
529       }
530     }
531   }
532   PetscFunctionReturn(0);
533 }
534