xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision 9be3f403e6dfdc4afd0fa2e761af1e0cdbb5f7f2)
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,"PetscDrawAxis","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__ "PetscDrawAxisSetHoldLimits"
144 /*@
145     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
146         again
147 
148     Logically Collective on PetscDrawAxis
149 
150     Input Parameters:
151 +   axis - the axis
152 -   hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed
153 
154     Level: advanced
155 
156     Notes:
157         Once this has been called with PETSC_TRUE the limits will not change if you call
158      PetscDrawAxisSetLimits() until you call this with PETSC_FALSE
159 
160 .seealso:  PetscDrawAxisSetLimits()
161 
162 @*/
163 PetscErrorCode  PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold)
164 {
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
167   PetscValidLogicalCollectiveBool(axis,hold,2);
168   axis->hold = hold;
169   PetscFunctionReturn(0);
170 }
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "PetscDrawAxisDraw"
174 /*@
175     PetscDrawAxisDraw - PetscDraws an axis.
176 
177     Collective on PetscDrawAxis
178 
179     Input Parameter:
180 .   axis - Axis structure
181 
182     Level: advanced
183 
184     Note:
185     This draws the actual axis.  The limits etc have already been set.
186     By picking special routines for the ticks and labels, special
187     effects may be generated.  These routines are part of the Axis
188     structure (axis).
189 @*/
190 PetscErrorCode  PetscDrawAxisDraw(PetscDrawAxis axis)
191 {
192   int            i,ntick,numx,numy,ac,tc,cc;
193   PetscMPIInt    rank;
194   size_t         len;
195   PetscReal      coors[4],tickloc[MAXSEGS],sep,h,w,tw,th,xl,xr,yl,yr;
196   char           *p;
197   PetscDraw      draw;
198   PetscBool      isnull;
199   PetscErrorCode ierr;
200 
201   PetscFunctionBegin;
202   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
203   ierr = PetscDrawIsNull(axis->win,&isnull);CHKERRQ(ierr);
204   if (isnull) PetscFunctionReturn(0);
205   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);CHKERRQ(ierr);
206 
207   draw = axis->win;
208   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
209   if (rank) goto finally;
210 
211   ac = axis->ac; tc = axis->tc; cc = axis->cc;
212   if (axis->xlow == axis->xhigh) {axis->xlow -= .5; axis->xhigh += .5;}
213   if (axis->ylow == axis->yhigh) {axis->ylow -= .5; axis->yhigh += .5;}
214   xl = axis->xlow; xr = axis->xhigh; yl = axis->ylow; yr = axis->yhigh;
215 
216   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
217   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
218   numx = (int)(.15*(xr-xl)/tw); if (numx > 6) numx = 6; if (numx< 2) numx = 2;
219   numy = (int)(.50*(yr-yl)/th); if (numy > 6) numy = 6; if (numy< 2) numy = 2;
220   xl -= 11*tw; xr += 2*tw; yl -= 2.5*th; yr += 2*th;
221   if (axis->xlabel) yl -= 2*th;
222   if (axis->ylabel) xl -= 2*tw;
223   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
224   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
225 
226   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);CHKERRQ(ierr);
227   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);CHKERRQ(ierr);
228 
229   if (axis->toplabel) {
230     h    = axis->yhigh;
231     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),axis->yhigh,cc,axis->toplabel);CHKERRQ(ierr);
232   }
233 
234   /* PetscDraw the ticks and labels */
235   if (axis->xticks) {
236     ierr = (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
237     /* PetscDraw in tick marks */
238     for (i=0; i<ntick; i++) {
239       ierr = PetscDrawLine(draw,tickloc[i],axis->ylow-.5*th,tickloc[i],axis->ylow+.5*th,tc);CHKERRQ(ierr);
240     }
241     /* label ticks */
242     for (i=0; i<ntick; i++) {
243       if (axis->xlabelstr) {
244         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
245         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
246         else               sep = 0.0;
247         ierr = (*axis->xlabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
248         ierr = PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.2*th,cc,p);CHKERRQ(ierr);
249       }
250     }
251   }
252   if (axis->xlabel) {
253     h    = axis->ylow - 2.5*th;
254     ierr = PetscDrawStringCentered(draw,.5*(xl + xr),h,cc,axis->xlabel);CHKERRQ(ierr);
255   }
256   if (axis->yticks) {
257     ierr = (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
258     /* PetscDraw in tick marks */
259     for (i=0; i<ntick; i++) {
260       ierr = PetscDrawLine(draw,axis->xlow -.5*tw,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);CHKERRQ(ierr);
261     }
262     /* label ticks */
263     for (i=0; i<ntick; i++) {
264       if (axis->ylabelstr) {
265         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
266         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
267         else               sep = 0.0;
268         ierr = (*axis->xlabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
269         ierr = PetscStrlen(p,&len);CHKERRQ(ierr);
270         w    = axis->xlow - len * tw - 1.2*tw;
271         ierr = PetscDrawString(draw,w,tickloc[i]-.5*th,cc,p);CHKERRQ(ierr);
272       }
273     }
274   }
275   if (axis->ylabel) {
276     ierr = PetscStrlen(axis->ylabel,&len);CHKERRQ(ierr);
277     h    = yl + .5*(yr - yl) + .5*len*th;
278     w    = xl + 1.5*tw;
279     ierr = PetscDrawStringVertical(draw,w,h,cc,axis->ylabel);CHKERRQ(ierr);
280   }
281 
282   ierr = PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);CHKERRQ(ierr);
283 finally:
284   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
285   ierr = MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
286   ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr);
287   PetscFunctionReturn(0);
288 }
289 
290 #undef __FUNCT__
291 #define __FUNCT__ "PetscStripe0"
292 /*
293     Removes all zeros but one from .0000
294 */
295 PetscErrorCode PetscStripe0(char *buf)
296 {
297   PetscErrorCode ierr;
298   size_t         n;
299   PetscBool      flg;
300   char           *str;
301 
302   PetscFunctionBegin;
303   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
304   ierr = PetscStrendswith(buf,"e00",&flg);CHKERRQ(ierr);
305   if (flg) buf[n-3] = 0;
306   ierr = PetscStrstr(buf,"e0",&str);CHKERRQ(ierr);
307   if (str) {
308     buf[n-2] = buf[n-1];
309     buf[n-1] = 0;
310   }
311   ierr = PetscStrstr(buf,"e-0",&str);CHKERRQ(ierr);
312   if (str) {
313     buf[n-2] = buf[n-1];
314     buf[n-1] = 0;
315   }
316   PetscFunctionReturn(0);
317 }
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "PetscStripAllZeros"
321 /*
322     Removes all zeros but one from .0000
323 */
324 PetscErrorCode PetscStripAllZeros(char *buf)
325 {
326   PetscErrorCode ierr;
327   size_t         i,n;
328 
329   PetscFunctionBegin;
330   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
331   if (buf[0] != '.') PetscFunctionReturn(0);
332   for (i=1; i<n; i++) {
333     if (buf[i] != '0') PetscFunctionReturn(0);
334   }
335   buf[0] = '0';
336   buf[1] = 0;
337   PetscFunctionReturn(0);
338 }
339 
340 #undef __FUNCT__
341 #define __FUNCT__ "PetscStripTrailingZeros"
342 /*
343     Removes trailing zeros
344 */
345 PetscErrorCode PetscStripTrailingZeros(char *buf)
346 {
347   PetscErrorCode ierr;
348   char           *found;
349   size_t         i,n,m = PETSC_MAX_INT;
350 
351   PetscFunctionBegin;
352   /* if there is an e in string DO NOT strip trailing zeros */
353   ierr = PetscStrchr(buf,'e',&found);CHKERRQ(ierr);
354   if (found) PetscFunctionReturn(0);
355 
356   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
357   /* locate decimal point */
358   for (i=0; i<n; i++) {
359     if (buf[i] == '.') {m = i; break;}
360   }
361   /* if not decimal point then no zeros to remove */
362   if (m == PETSC_MAX_INT) PetscFunctionReturn(0);
363   /* start at right end of string removing 0s */
364   for (i=n-1; i>m; i++) {
365     if (buf[i] != '0') PetscFunctionReturn(0);
366     buf[i] = 0;
367   }
368   PetscFunctionReturn(0);
369 }
370 
371 #undef __FUNCT__
372 #define __FUNCT__ "PetscStripInitialZero"
373 /*
374     Removes leading 0 from 0.22 or -0.22
375 */
376 PetscErrorCode PetscStripInitialZero(char *buf)
377 {
378   PetscErrorCode ierr;
379   size_t         i,n;
380 
381   PetscFunctionBegin;
382   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
383   if (buf[0] == '0') {
384     for (i=0; i<n; i++) buf[i] = buf[i+1];
385   } else if (buf[0] == '-' && buf[1] == '0') {
386     for (i=1; i<n; i++) buf[i] = buf[i+1];
387   }
388   PetscFunctionReturn(0);
389 }
390 
391 #undef __FUNCT__
392 #define __FUNCT__ "PetscStripZeros"
393 /*
394      Removes the extraneous zeros in numbers like 1.10000e6
395 */
396 PetscErrorCode PetscStripZeros(char *buf)
397 {
398   PetscErrorCode ierr;
399   size_t         i,j,n;
400 
401   PetscFunctionBegin;
402   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
403   if (n<5) PetscFunctionReturn(0);
404   for (i=1; i<n-1; i++) {
405     if (buf[i] == 'e' && buf[i-1] == '0') {
406       for (j=i; j<n+1; j++) buf[j-1] = buf[j];
407       ierr = PetscStripZeros(buf);CHKERRQ(ierr);
408       PetscFunctionReturn(0);
409     }
410   }
411   PetscFunctionReturn(0);
412 }
413 
414 #undef __FUNCT__
415 #define __FUNCT__ "PetscStripZerosPlus"
416 /*
417       Removes the plus in something like 1.1e+2 or 1.1e+02
418 */
419 PetscErrorCode PetscStripZerosPlus(char *buf)
420 {
421   PetscErrorCode ierr;
422   size_t         i,j,n;
423 
424   PetscFunctionBegin;
425   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
426   if (n<5) PetscFunctionReturn(0);
427   for (i=1; i<n-2; i++) {
428     if (buf[i] == '+') {
429       if (buf[i+1] == '0') {
430         for (j=i+1; j<n; j++) buf[j-1] = buf[j+1];
431         PetscFunctionReturn(0);
432       } else {
433         for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
434         PetscFunctionReturn(0);
435       }
436     } else if (buf[i] == '-') {
437       if (buf[i+1] == '0') {
438         for (j=i+1; j<n; j++) buf[j] = buf[j+1];
439         PetscFunctionReturn(0);
440       }
441     }
442   }
443   PetscFunctionReturn(0);
444 }
445