xref: /petsc/src/sys/classes/draw/utils/axis.c (revision 36c9bc0d608efe1a596e7d8b972c2154d3f5669d)
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     Options Database:
27 .   -drawaxis_hold - hold the initial set of axis limits for future plotting
28 
29     Level: advanced
30 
31 .seealso:  PetscDrawAxisSetHoldLimits()
32 
33 @*/
34 PetscErrorCode  PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
35 {
36   PetscErrorCode ierr;
37 
38   PetscFunctionBegin;
39   if (!axis) PetscFunctionReturn(0);
40   if (axis->hold) PetscFunctionReturn(0);
41   axis->xlow = xmin;
42   axis->xhigh= xmax;
43   axis->ylow = ymin;
44   axis->yhigh= ymax;
45   ierr = PetscOptionsHasName(((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);CHKERRQ(ierr);
46   PetscFunctionReturn(0);
47 }
48 
49 #undef __FUNCT__
50 #define __FUNCT__ "PetscDrawAxisGetLimits"
51 /*@
52     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
53 
54     Not Collective (ignored on all processors except processor 0 of PetscDrawAxis)
55 
56     Input Parameters:
57 +   axis - the axis
58 .   xmin,xmax - limits in x
59 -   ymin,ymax - limits in y
60 
61     Level: advanced
62 
63 .seealso:  PetscDrawAxisSetLimits()
64 
65 @*/
66 PetscErrorCode  PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
67 {
68   PetscFunctionBegin;
69   if (!axis) PetscFunctionReturn(0);
70   if (axis->hold) PetscFunctionReturn(0);
71   *xmin = axis->xlow;
72   *xmax = axis->xhigh;
73   *ymin = axis->ylow;
74   *ymax = axis->yhigh;
75   PetscFunctionReturn(0);
76 }
77 
78 #undef __FUNCT__
79 #define __FUNCT__ "PetscADefLabel"
80 /*
81    val is the label value.  sep is the separation to the next (or previous)
82    label; this is useful in determining how many significant figures to
83    keep.
84  */
85 PetscErrorCode PetscADefLabel(PetscReal val,PetscReal sep,char **p)
86 {
87   static char    buf[40];
88   PetscErrorCode ierr;
89   PetscReal      rval;
90 
91   PetscFunctionBegin;
92   /* Find the string */
93   if (PetscAbsReal(val)/sep <  1.e-4) {
94     buf[0] = '0'; buf[1] = 0;
95   } else {
96     ierr = PetscRint(val,&rval);CHKERRQ(ierr);
97     if (rval == val) {
98       sprintf(buf,"%d",(int)val);
99       ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
100       ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
101       ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
102     } else {
103       sprintf(buf,"%0.1le",(double)val);
104       ierr = PetscStripe0(buf);CHKERRQ(ierr);
105       ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
106       ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
107       ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
108     }
109   }
110   *p =buf;
111   PetscFunctionReturn(0);
112 }
113 
114 #undef __FUNCT__
115 #define __FUNCT__ "PetscADefTicks"
116 /* Finds "nice" locations for the ticks */
117 PetscErrorCode PetscADefTicks(PetscReal low,PetscReal high,int num,int *ntick,PetscReal * tickloc,int  maxtick)
118 {
119   PetscErrorCode ierr;
120   int            i,power;
121   PetscReal      x = 0.0,base=0.0;
122 
123   PetscFunctionBegin;
124   /* patch if low == high */
125   if (low == high) {
126     low  -= .01;
127     high += .01;
128   }
129 
130   /*  if (PetscAbsReal(low-high) < 1.e-8) {
131     low  -= .01;
132     high += .01;
133   } */
134 
135   ierr = PetscAGetBase(low,high,num,&base,&power);CHKERRQ(ierr);
136   ierr = PetscAGetNice(low,base,-1,&x);CHKERRQ(ierr);
137 
138   /* Values are of the form j * base */
139   /* Find the starting value */
140   if (x < low) x += base;
141 
142   i = 0;
143   while (i < maxtick && x <= high) {
144     tickloc[i++] = x;
145     x += base;
146   }
147   *ntick = i;
148 
149   if (i < 2 && num < 10) {
150     ierr = PetscADefTicks(low,high,num+1,ntick,tickloc,maxtick);CHKERRQ(ierr);
151   }
152   if (num == 10) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"trouble");
153   PetscFunctionReturn(0);
154 }
155 
156 #define EPS 1.e-6
157 
158 #undef __FUNCT__
159 #define __FUNCT__ "PetscExp10"
160 PetscErrorCode PetscExp10(PetscReal d,PetscReal *result)
161 {
162   PetscFunctionBegin;
163   *result = pow((PetscReal)10.0,d);
164   PetscFunctionReturn(0);
165 }
166 
167 #undef __FUNCT__
168 #define __FUNCT__ "PetscMod"
169 PetscErrorCode PetscMod(PetscReal x,PetscReal y,PetscReal *result)
170 {
171   int     i;
172 
173   PetscFunctionBegin;
174   if (y == 1) {
175     *result = 0.0;
176     PetscFunctionReturn(0);
177   }
178   i   = ((int)x) / ((int)y);
179   x   = x - i * y;
180   while (x > y) x -= y;
181   *result = x;
182   PetscFunctionReturn(0);
183 }
184 
185 #undef __FUNCT__
186 #define __FUNCT__ "PetscCopysign"
187 PetscErrorCode PetscCopysign(PetscReal a,PetscReal b,PetscReal *result)
188 {
189   PetscFunctionBegin;
190   if (b >= 0) *result = a;
191   else        *result = -a;
192   PetscFunctionReturn(0);
193 }
194 
195 #undef __FUNCT__
196 #define __FUNCT__ "PetscAGetNice"
197 /*
198     Given a value "in" and a "base", return a nice value.
199     based on "sign", extend up (+1) or down (-1)
200  */
201 PetscErrorCode PetscAGetNice(PetscReal in,PetscReal base,int sign,PetscReal *result)
202 {
203   PetscReal      etmp,s,s2,m;
204   PetscErrorCode ierr;
205 
206   PetscFunctionBegin;
207   ierr    = PetscCopysign (0.5,(double)sign,&s);CHKERRQ(ierr);
208   etmp    = in / base + 0.5 + s;
209   ierr    = PetscCopysign (0.5,etmp,&s);CHKERRQ(ierr);
210   ierr    = PetscCopysign (EPS * etmp,(double)sign,&s2);CHKERRQ(ierr);
211   etmp    = etmp - 0.5 + s - s2;
212   ierr    = PetscMod(etmp,1.0,&m);CHKERRQ(ierr);
213   etmp    = base * (etmp -  m);
214   *result = etmp;
215   PetscFunctionReturn(0);
216 }
217 
218 #undef __FUNCT__
219 #define __FUNCT__ "PetscAGetBase"
220 PetscErrorCode PetscAGetBase(PetscReal vmin,PetscReal vmax,int num,PetscReal*Base,int*power)
221 {
222   PetscReal        base,ftemp,e10;
223   static PetscReal base_try[5] = {10.0,5.0,2.0,1.0,0.5};
224   PetscErrorCode   ierr;
225   int              i;
226 
227   PetscFunctionBegin;
228   /* labels of the form n * BASE */
229   /* get an approximate value for BASE */
230   base    = (vmax - vmin) / (double)(num + 1);
231 
232   /* make it of form   m x 10^power,  m in [1.0, 10) */
233   if (base <= 0.0) {
234     base    = PetscAbsReal(vmin);
235     if (base < 1.0) base = 1.0;
236   }
237   ftemp   = log10((1.0 + EPS) * base);
238   if (ftemp < 0.0)  ftemp   -= 1.0;
239   *power  = (int)ftemp;
240   ierr = PetscExp10((double)- *power,&e10);CHKERRQ(ierr);
241   base    = base * e10;
242   if (base < 1.0) base    = 1.0;
243   /* now reduce it to one of 1, 2, or 5 */
244   for (i=1; i<5; i++) {
245     if (base >= base_try[i]) {
246       ierr = PetscExp10((double)*power,&e10);CHKERRQ(ierr);
247       base = base_try[i-1] * e10;
248       if (i == 1) *power    = *power + 1;
249       break;
250     }
251   }
252   *Base   = base;
253   PetscFunctionReturn(0);
254 }
255 
256 
257 
258 
259 
260 
261