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 char fmat[10]; 89 PetscErrorCode ierr; 90 int w,d; 91 PetscReal rval; 92 93 PetscFunctionBegin; 94 /* Find the string */ 95 if (PetscAbsReal(val)/sep < 1.e-6) { 96 buf[0] = '0'; buf[1] = 0; 97 } else if (PetscAbsReal(val) < 1.0e6 && PetscAbsReal(val) > 1.e-4) { 98 /* Compute the number of digits */ 99 w = 0; 100 d = 0; 101 if (sep > 0.0) { 102 d = (int)ceil(- log10 (sep)); 103 if (d < 0) d = 0; 104 if (PetscAbsReal(val) < 1.0e-6*sep) { 105 /* This is the case where we are near zero and less than a small 106 fraction of the sep. In this case, we use 0 as the value */ 107 val = 0.0; 108 w = d; 109 } 110 else if (val == 0.0) w = d; 111 else w = (int)(ceil(log10(PetscAbsReal(val))) + d); 112 if (w < 1) w ++; 113 if (val < 0) w ++; 114 } 115 116 ierr = PetscRint(val,&rval);CHKERRQ(ierr); 117 if (rval == val) { 118 if (w > 0) sprintf(fmat,"%%%dd",w); 119 else {ierr = PetscStrcpy(fmat,"%d");CHKERRQ(ierr);} 120 sprintf(buf,fmat,(int)val); 121 ierr = PetscStripInitialZero(buf);CHKERRQ(ierr); 122 ierr = PetscStripAllZeros(buf);CHKERRQ(ierr); 123 ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr); 124 } else { 125 /* The code used here is inappropriate for a val of 0, which 126 tends to print with an excessive numer of digits. In this 127 case, we should look at the next/previous values and 128 use those widths */ 129 if (w > 0) sprintf(fmat,"%%%d.%dlf",w + 1,d); 130 else {ierr = PetscStrcpy(fmat,"%lf");CHKERRQ(ierr);} 131 sprintf(buf,fmat,(double)val); 132 ierr = PetscStripInitialZero(buf);CHKERRQ(ierr); 133 ierr = PetscStripAllZeros(buf);CHKERRQ(ierr); 134 ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr); 135 } 136 } else { 137 ierr = PetscSNPrintf(buf,40,"%g",(double)val); 138 /* remove the extraneous 0 before the e */ 139 ierr = PetscStripZeros(buf);CHKERRQ(ierr); 140 ierr = PetscStripZerosPlus(buf);CHKERRQ(ierr); 141 ierr = PetscStripInitialZero(buf);CHKERRQ(ierr); 142 ierr = PetscStripAllZeros(buf);CHKERRQ(ierr); 143 ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr); 144 } 145 *p =buf; 146 PetscFunctionReturn(0); 147 } 148 149 #undef __FUNCT__ 150 #define __FUNCT__ "PetscADefTicks" 151 /* Finds "nice" locations for the ticks */ 152 PetscErrorCode PetscADefTicks(PetscReal low,PetscReal high,int num,int *ntick,PetscReal * tickloc,int maxtick) 153 { 154 PetscErrorCode ierr; 155 int i,power; 156 PetscReal x = 0.0,base=0.0; 157 158 PetscFunctionBegin; 159 /* patch if low == high */ 160 if (low == high) { 161 low -= .01; 162 high += .01; 163 } 164 165 /* if (PetscAbsReal(low-high) < 1.e-8) { 166 low -= .01; 167 high += .01; 168 } */ 169 170 ierr = PetscAGetBase(low,high,num,&base,&power);CHKERRQ(ierr); 171 ierr = PetscAGetNice(low,base,-1,&x);CHKERRQ(ierr); 172 173 /* Values are of the form j * base */ 174 /* Find the starting value */ 175 if (x < low) x += base; 176 177 i = 0; 178 while (i < maxtick && x <= high) { 179 tickloc[i++] = x; 180 x += base; 181 } 182 *ntick = i; 183 184 if (i < 2 && num < 10) { 185 ierr = PetscADefTicks(low,high,num+1,ntick,tickloc,maxtick);CHKERRQ(ierr); 186 } 187 PetscFunctionReturn(0); 188 } 189 190 #define EPS 1.e-6 191 192 #undef __FUNCT__ 193 #define __FUNCT__ "PetscExp10" 194 PetscErrorCode PetscExp10(PetscReal d,PetscReal *result) 195 { 196 PetscFunctionBegin; 197 *result = pow((PetscReal)10.0,d); 198 PetscFunctionReturn(0); 199 } 200 201 #undef __FUNCT__ 202 #define __FUNCT__ "PetscMod" 203 PetscErrorCode PetscMod(PetscReal x,PetscReal y,PetscReal *result) 204 { 205 int i; 206 207 PetscFunctionBegin; 208 if (y == 1) { 209 *result = 0.0; 210 PetscFunctionReturn(0); 211 } 212 i = ((int)x) / ((int)y); 213 x = x - i * y; 214 while (x > y) x -= y; 215 *result = x; 216 PetscFunctionReturn(0); 217 } 218 219 #undef __FUNCT__ 220 #define __FUNCT__ "PetscCopysign" 221 PetscErrorCode PetscCopysign(PetscReal a,PetscReal b,PetscReal *result) 222 { 223 PetscFunctionBegin; 224 if (b >= 0) *result = a; 225 else *result = -a; 226 PetscFunctionReturn(0); 227 } 228 229 #undef __FUNCT__ 230 #define __FUNCT__ "PetscAGetNice" 231 /* 232 Given a value "in" and a "base", return a nice value. 233 based on "sign", extend up (+1) or down (-1) 234 */ 235 PetscErrorCode PetscAGetNice(PetscReal in,PetscReal base,int sign,PetscReal *result) 236 { 237 PetscReal etmp,s,s2,m; 238 PetscErrorCode ierr; 239 240 PetscFunctionBegin; 241 ierr = PetscCopysign (0.5,(double)sign,&s);CHKERRQ(ierr); 242 etmp = in / base + 0.5 + s; 243 ierr = PetscCopysign (0.5,etmp,&s);CHKERRQ(ierr); 244 ierr = PetscCopysign (EPS * etmp,(double)sign,&s2);CHKERRQ(ierr); 245 etmp = etmp - 0.5 + s - s2; 246 ierr = PetscMod(etmp,1.0,&m);CHKERRQ(ierr); 247 etmp = base * (etmp - m); 248 *result = etmp; 249 PetscFunctionReturn(0); 250 } 251 252 #undef __FUNCT__ 253 #define __FUNCT__ "PetscAGetBase" 254 PetscErrorCode PetscAGetBase(PetscReal vmin,PetscReal vmax,int num,PetscReal*Base,int*power) 255 { 256 PetscReal base,ftemp,e10; 257 static PetscReal base_try[5] = {10.0,5.0,2.0,1.0,0.5}; 258 PetscErrorCode ierr; 259 int i; 260 261 PetscFunctionBegin; 262 /* labels of the form n * BASE */ 263 /* get an approximate value for BASE */ 264 base = (vmax - vmin) / (double)(num + 1); 265 266 /* make it of form m x 10^power, m in [1.0, 10) */ 267 if (base <= 0.0) { 268 base = PetscAbsReal(vmin); 269 if (base < 1.0) base = 1.0; 270 } 271 ftemp = log10((1.0 + EPS) * base); 272 if (ftemp < 0.0) ftemp -= 1.0; 273 *power = (int)ftemp; 274 ierr = PetscExp10((double)- *power,&e10);CHKERRQ(ierr); 275 base = base * e10; 276 if (base < 1.0) base = 1.0; 277 /* now reduce it to one of 1, 2, or 5 */ 278 for (i=1; i<5; i++) { 279 if (base >= base_try[i]) { 280 ierr = PetscExp10((double)*power,&e10);CHKERRQ(ierr); 281 base = base_try[i-1] * e10; 282 if (i == 1) *power = *power + 1; 283 break; 284 } 285 } 286 *Base = base; 287 PetscFunctionReturn(0); 288 } 289 290 291 292 293 294 295