xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision e611a964e9853b74d61a56642fe9d06a6e51780f)
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) 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   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
302   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
303 
304   /* PetscDraw the axis lines */
305   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);CHKERRQ(ierr);
306   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);CHKERRQ(ierr);
307   ierr = PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr);
308   ierr = PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr);
309 
310   /* PetscDraw the top label */
311   if (axis->toplabel) {
312     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th;
313     ierr = PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);CHKERRQ(ierr);
314   }
315 
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     ierr = (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
320     /* PetscDraw in tick marks */
321     for (i=0; i<ntick; i++) {
322       ierr = PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);CHKERRQ(ierr);
323       ierr = PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);CHKERRQ(ierr);
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         ierr = (*axis->xlabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
332         ierr = PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);CHKERRQ(ierr);
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     ierr = PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);CHKERRQ(ierr);
340   }
341 
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     ierr = (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
346     /* PetscDraw in tick marks */
347     for (i=0; i<ntick; i++) {
348       ierr = PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);CHKERRQ(ierr);
349       ierr = PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);CHKERRQ(ierr);
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         ierr = (*axis->ylabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
358         ierr = PetscStrlen(p,&len);CHKERRQ(ierr); ytlen = PetscMax(ytlen,len);
359         ierr = PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);CHKERRQ(ierr);
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     ierr = PetscStrlen(axis->ylabel,&len);CHKERRQ(ierr);
367     ierr = PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);CHKERRQ(ierr);
368   }
369 
370   ierr = PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);CHKERRQ(ierr);
371 finally:
372   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
373   ierr = MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
374   ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr);
375   PetscFunctionReturn(0);
376 }
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "PetscStripe0"
380 /*
381     Removes all zeros but one from .0000
382 */
383 PetscErrorCode PetscStripe0(char *buf)
384 {
385   PetscErrorCode ierr;
386   size_t         n;
387   PetscBool      flg;
388   char           *str;
389 
390   PetscFunctionBegin;
391   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
392   ierr = PetscStrendswith(buf,"e00",&flg);CHKERRQ(ierr);
393   if (flg) buf[n-3] = 0;
394   ierr = PetscStrstr(buf,"e0",&str);CHKERRQ(ierr);
395   if (str) {
396     buf[n-2] = buf[n-1];
397     buf[n-1] = 0;
398   }
399   ierr = PetscStrstr(buf,"e-0",&str);CHKERRQ(ierr);
400   if (str) {
401     buf[n-2] = buf[n-1];
402     buf[n-1] = 0;
403   }
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "PetscStripAllZeros"
409 /*
410     Removes all zeros but one from .0000
411 */
412 PetscErrorCode PetscStripAllZeros(char *buf)
413 {
414   PetscErrorCode ierr;
415   size_t         i,n;
416 
417   PetscFunctionBegin;
418   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
419   if (buf[0] != '.') PetscFunctionReturn(0);
420   for (i=1; i<n; i++) {
421     if (buf[i] != '0') PetscFunctionReturn(0);
422   }
423   buf[0] = '0';
424   buf[1] = 0;
425   PetscFunctionReturn(0);
426 }
427 
428 #undef __FUNCT__
429 #define __FUNCT__ "PetscStripTrailingZeros"
430 /*
431     Removes trailing zeros
432 */
433 PetscErrorCode PetscStripTrailingZeros(char *buf)
434 {
435   PetscErrorCode ierr;
436   char           *found;
437   size_t         i,n,m = PETSC_MAX_INT;
438 
439   PetscFunctionBegin;
440   /* if there is an e in string DO NOT strip trailing zeros */
441   ierr = PetscStrchr(buf,'e',&found);CHKERRQ(ierr);
442   if (found) PetscFunctionReturn(0);
443 
444   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
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) PetscFunctionReturn(0);
451   /* start at right end of string removing 0s */
452   for (i=n-1; i>m; i++) {
453     if (buf[i] != '0') PetscFunctionReturn(0);
454     buf[i] = 0;
455   }
456   PetscFunctionReturn(0);
457 }
458 
459 #undef __FUNCT__
460 #define __FUNCT__ "PetscStripInitialZero"
461 /*
462     Removes leading 0 from 0.22 or -0.22
463 */
464 PetscErrorCode PetscStripInitialZero(char *buf)
465 {
466   PetscErrorCode ierr;
467   size_t         i,n;
468 
469   PetscFunctionBegin;
470   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
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   PetscFunctionReturn(0);
477 }
478 
479 #undef __FUNCT__
480 #define __FUNCT__ "PetscStripZeros"
481 /*
482      Removes the extraneous zeros in numbers like 1.10000e6
483 */
484 PetscErrorCode PetscStripZeros(char *buf)
485 {
486   PetscErrorCode ierr;
487   size_t         i,j,n;
488 
489   PetscFunctionBegin;
490   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
491   if (n<5) PetscFunctionReturn(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       ierr = PetscStripZeros(buf);CHKERRQ(ierr);
496       PetscFunctionReturn(0);
497     }
498   }
499   PetscFunctionReturn(0);
500 }
501 
502 #undef __FUNCT__
503 #define __FUNCT__ "PetscStripZerosPlus"
504 /*
505       Removes the plus in something like 1.1e+2 or 1.1e+02
506 */
507 PetscErrorCode PetscStripZerosPlus(char *buf)
508 {
509   PetscErrorCode ierr;
510   size_t         i,j,n;
511 
512   PetscFunctionBegin;
513   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
514   if (n<5) PetscFunctionReturn(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         PetscFunctionReturn(0);
520       } else {
521         for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
522         PetscFunctionReturn(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         PetscFunctionReturn(0);
528       }
529     }
530   }
531   PetscFunctionReturn(0);
532 }
533