xref: /petsc/src/sys/classes/draw/utils/axis.c (revision 29aa02fc2fafbb5e1dc372248076d6e234c6a228)
1 
2 #include <../src/sys/classes/draw/utils/axisimpl.h>
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "PetscRint"
6 static PetscErrorCode PetscRint(PetscReal x,PetscReal *result)
7 {
8   PetscFunctionBegin;
9   if (x > 0) *result = floor(x + 0.5);
10   else       *result = floor(x - 0.5);
11   PetscFunctionReturn(0);
12 }
13 
14 #undef __FUNCT__
15 #define __FUNCT__ "PetscDrawAxisSetLimits"
16 /*@
17     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
18 
19     Not Collective (ignored on all processors except processor 0 of PetscDrawAxis)
20 
21     Input Parameters:
22 +   axis - the axis
23 .   xmin,xmax - limits in x
24 -   ymin,ymax - limits in y
25 
26     Level: advanced
27 
28 .seealso:  PetscDrawAxisSetHoldLimits()
29 
30 @*/
31 PetscErrorCode  PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
32 {
33   PetscFunctionBegin;
34   if (!axis) PetscFunctionReturn(0);
35   if (axis->hold) PetscFunctionReturn(0);
36   axis->xlow = xmin;
37   axis->xhigh= xmax;
38   axis->ylow = ymin;
39   axis->yhigh= ymax;
40   PetscFunctionReturn(0);
41 }
42 
43 #undef __FUNCT__
44 #define __FUNCT__ "PetscDrawAxisGetLimits"
45 /*@
46     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
47 
48     Not Collective (ignored on all processors except processor 0 of PetscDrawAxis)
49 
50     Input Parameters:
51 +   axis - the axis
52 .   xmin,xmax - limits in x
53 -   ymin,ymax - limits in y
54 
55     Level: advanced
56 
57 .seealso:  PetscDrawAxisSetLimits()
58 
59 @*/
60 PetscErrorCode  PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
61 {
62   PetscFunctionBegin;
63   if (!axis) PetscFunctionReturn(0);
64   if (axis->hold) PetscFunctionReturn(0);
65   *xmin = axis->xlow;
66   *xmax = axis->xhigh;
67   *ymin = axis->ylow;
68   *ymax = axis->yhigh;
69   PetscFunctionReturn(0);
70 }
71 
72 #undef __FUNCT__
73 #define __FUNCT__ "PetscADefLabel"
74 /*
75    val is the label value.  sep is the separation to the next (or previous)
76    label; this is useful in determining how many significant figures to
77    keep.
78  */
79 PetscErrorCode PetscADefLabel(PetscReal val,PetscReal sep,char **p)
80 {
81   static char    buf[40];
82   char           fmat[10];
83   PetscErrorCode ierr;
84   int            w,d;
85   PetscReal      rval;
86 
87   PetscFunctionBegin;
88   /* Find the string */
89   if (PetscAbsReal(val)/sep <  1.e-6) {
90     buf[0] = '0'; buf[1] = 0;
91   } else if (PetscAbsReal(val) < 1.0e6 && PetscAbsReal(val) > 1.e-4) {
92     /* Compute the number of digits */
93     w = 0;
94     d = 0;
95     if (sep > 0.0) {
96 	d = (int)ceil(- log10 (sep));
97 	if (d < 0) d = 0;
98 	if (PetscAbsReal(val) < 1.0e-6*sep) {
99 	    /* This is the case where we are near zero and less than a small
100 	       fraction of the sep.  In this case, we use 0 as the value */
101 	    val = 0.0;
102 	    w   = d;
103         }
104 	else if (val == 0.0) w   = d;
105 	else w = (int)(ceil(log10(PetscAbsReal(val))) + d);
106 	if (w < 1)   w ++;
107 	if (val < 0) w ++;
108     }
109 
110     ierr = PetscRint(val,&rval);CHKERRQ(ierr);
111     if (rval == val) {
112 	if (w > 0) sprintf(fmat,"%%%dd",w);
113 	else {ierr = PetscStrcpy(fmat,"%d");CHKERRQ(ierr);}
114 	sprintf(buf,fmat,(int)val);
115         ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
116         ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
117         ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
118     } else {
119 	/* The code used here is inappropriate for a val of 0, which
120 	   tends to print with an excessive numer of digits.  In this
121 	   case, we should look at the next/previous values and
122 	   use those widths */
123 	if (w > 0) sprintf(fmat,"%%%d.%dlf",w + 1,d);
124 	else {ierr = PetscStrcpy(fmat,"%lf");CHKERRQ(ierr);}
125 	sprintf(buf,fmat,(double)val);
126         ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
127         ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
128         ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
129     }
130   } else {
131     ierr = PetscSNPrintf(buf,40,"%g",(double)val);
132     /* remove the extraneous 0 before the e */
133     ierr = PetscStripZeros(buf);CHKERRQ(ierr);
134     ierr = PetscStripZerosPlus(buf);CHKERRQ(ierr);
135     ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
136     ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
137     ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
138   }
139   *p =buf;
140   PetscFunctionReturn(0);
141 }
142 
143 #undef __FUNCT__
144 #define __FUNCT__ "PetscADefTicks"
145 /* Finds "nice" locations for the ticks */
146 PetscErrorCode PetscADefTicks(PetscReal low,PetscReal high,int num,int *ntick,PetscReal * tickloc,int  maxtick)
147 {
148   PetscErrorCode ierr;
149   int            i,power;
150   PetscReal      x = 0.0,base=0.0;
151 
152   PetscFunctionBegin;
153   /* patch if low == high */
154   if (low == high) {
155     low  -= .01;
156     high += .01;
157   }
158 
159   /*  if (PetscAbsReal(low-high) < 1.e-8) {
160     low  -= .01;
161     high += .01;
162   } */
163 
164   ierr = PetscAGetBase(low,high,num,&base,&power);CHKERRQ(ierr);
165   ierr = PetscAGetNice(low,base,-1,&x);CHKERRQ(ierr);
166 
167   /* Values are of the form j * base */
168   /* Find the starting value */
169   if (x < low) x += base;
170 
171   i = 0;
172   while (i < maxtick && x <= high) {
173     tickloc[i++] = x;
174     x += base;
175   }
176   *ntick = i;
177 
178   if (i < 2 && num < 10) {
179     ierr = PetscADefTicks(low,high,num+1,ntick,tickloc,maxtick);CHKERRQ(ierr);
180   }
181   PetscFunctionReturn(0);
182 }
183 
184 #define EPS 1.e-6
185 
186 #undef __FUNCT__
187 #define __FUNCT__ "PetscExp10"
188 PetscErrorCode PetscExp10(PetscReal d,PetscReal *result)
189 {
190   PetscFunctionBegin;
191   *result = pow((PetscReal)10.0,d);
192   PetscFunctionReturn(0);
193 }
194 
195 #undef __FUNCT__
196 #define __FUNCT__ "PetscMod"
197 PetscErrorCode PetscMod(PetscReal x,PetscReal y,PetscReal *result)
198 {
199   int     i;
200 
201   PetscFunctionBegin;
202   if (y == 1) {
203     *result = 0.0;
204     PetscFunctionReturn(0);
205   }
206   i   = ((int)x) / ((int)y);
207   x   = x - i * y;
208   while (x > y) x -= y;
209   *result = x;
210   PetscFunctionReturn(0);
211 }
212 
213 #undef __FUNCT__
214 #define __FUNCT__ "PetscCopysign"
215 PetscErrorCode PetscCopysign(PetscReal a,PetscReal b,PetscReal *result)
216 {
217   PetscFunctionBegin;
218   if (b >= 0) *result = a;
219   else        *result = -a;
220   PetscFunctionReturn(0);
221 }
222 
223 #undef __FUNCT__
224 #define __FUNCT__ "PetscAGetNice"
225 /*
226     Given a value "in" and a "base", return a nice value.
227     based on "sign", extend up (+1) or down (-1)
228  */
229 PetscErrorCode PetscAGetNice(PetscReal in,PetscReal base,int sign,PetscReal *result)
230 {
231   PetscReal      etmp,s,s2,m;
232   PetscErrorCode ierr;
233 
234   PetscFunctionBegin;
235   ierr    = PetscCopysign (0.5,(double)sign,&s);CHKERRQ(ierr);
236   etmp    = in / base + 0.5 + s;
237   ierr    = PetscCopysign (0.5,etmp,&s);CHKERRQ(ierr);
238   ierr    = PetscCopysign (EPS * etmp,(double)sign,&s2);CHKERRQ(ierr);
239   etmp    = etmp - 0.5 + s - s2;
240   ierr    = PetscMod(etmp,1.0,&m);CHKERRQ(ierr);
241   etmp    = base * (etmp -  m);
242   *result = etmp;
243   PetscFunctionReturn(0);
244 }
245 
246 #undef __FUNCT__
247 #define __FUNCT__ "PetscAGetBase"
248 PetscErrorCode PetscAGetBase(PetscReal vmin,PetscReal vmax,int num,PetscReal*Base,int*power)
249 {
250   PetscReal        base,ftemp,e10;
251   static PetscReal base_try[5] = {10.0,5.0,2.0,1.0,0.5};
252   PetscErrorCode   ierr;
253   int              i;
254 
255   PetscFunctionBegin;
256   /* labels of the form n * BASE */
257   /* get an approximate value for BASE */
258   base    = (vmax - vmin) / (double)(num + 1);
259 
260   /* make it of form   m x 10^power,  m in [1.0, 10) */
261   if (base <= 0.0) {
262     base    = PetscAbsReal(vmin);
263     if (base < 1.0) base = 1.0;
264   }
265   ftemp   = log10((1.0 + EPS) * base);
266   if (ftemp < 0.0)  ftemp   -= 1.0;
267   *power  = (int)ftemp;
268   ierr = PetscExp10((double)- *power,&e10);CHKERRQ(ierr);
269   base    = base * e10;
270   if (base < 1.0) base    = 1.0;
271   /* now reduce it to one of 1, 2, or 5 */
272   for (i=1; i<5; i++) {
273     if (base >= base_try[i]) {
274       ierr = PetscExp10((double)*power,&e10);CHKERRQ(ierr);
275       base = base_try[i-1] * e10;
276       if (i == 1) *power    = *power + 1;
277       break;
278     }
279   }
280   *Base   = base;
281   PetscFunctionReturn(0);
282 }
283 
284 
285 
286 
287 
288 
289