xref: /petsc/src/sys/classes/draw/utils/axis.c (revision 36c9bc0d608efe1a596e7d8b972c2154d3f5669d)
15c6c1daeSBarry Smith 
25c6c1daeSBarry Smith #include <../src/sys/classes/draw/utils/axisimpl.h>
35c6c1daeSBarry Smith 
45c6c1daeSBarry Smith #undef __FUNCT__
55c6c1daeSBarry Smith #define __FUNCT__ "PetscRint"
65c6c1daeSBarry Smith static PetscErrorCode PetscRint(PetscReal x,PetscReal *result)
75c6c1daeSBarry Smith {
85c6c1daeSBarry Smith   PetscFunctionBegin;
95c6c1daeSBarry Smith   if (x > 0) *result = floor(x + 0.5);
105c6c1daeSBarry Smith   else       *result = floor(x - 0.5);
115c6c1daeSBarry Smith   PetscFunctionReturn(0);
125c6c1daeSBarry Smith }
135c6c1daeSBarry Smith 
145c6c1daeSBarry Smith #undef __FUNCT__
155c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawAxisSetLimits"
165c6c1daeSBarry Smith /*@
175c6c1daeSBarry Smith     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
185c6c1daeSBarry Smith 
195c6c1daeSBarry Smith     Not Collective (ignored on all processors except processor 0 of PetscDrawAxis)
205c6c1daeSBarry Smith 
215c6c1daeSBarry Smith     Input Parameters:
225c6c1daeSBarry Smith +   axis - the axis
235c6c1daeSBarry Smith .   xmin,xmax - limits in x
245c6c1daeSBarry Smith -   ymin,ymax - limits in y
255c6c1daeSBarry Smith 
261c059eddSBarry Smith     Options Database:
271c059eddSBarry Smith .   -drawaxis_hold - hold the initial set of axis limits for future plotting
281c059eddSBarry Smith 
295c6c1daeSBarry Smith     Level: advanced
305c6c1daeSBarry Smith 
315c6c1daeSBarry Smith .seealso:  PetscDrawAxisSetHoldLimits()
325c6c1daeSBarry Smith 
335c6c1daeSBarry Smith @*/
345c6c1daeSBarry Smith PetscErrorCode  PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
355c6c1daeSBarry Smith {
361c059eddSBarry Smith   PetscErrorCode ierr;
371c059eddSBarry Smith 
385c6c1daeSBarry Smith   PetscFunctionBegin;
395c6c1daeSBarry Smith   if (!axis) PetscFunctionReturn(0);
405c6c1daeSBarry Smith   if (axis->hold) PetscFunctionReturn(0);
415c6c1daeSBarry Smith   axis->xlow = xmin;
425c6c1daeSBarry Smith   axis->xhigh= xmax;
435c6c1daeSBarry Smith   axis->ylow = ymin;
445c6c1daeSBarry Smith   axis->yhigh= ymax;
451c059eddSBarry Smith   ierr = PetscOptionsHasName(((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);CHKERRQ(ierr);
465c6c1daeSBarry Smith   PetscFunctionReturn(0);
475c6c1daeSBarry Smith }
485c6c1daeSBarry Smith 
495c6c1daeSBarry Smith #undef __FUNCT__
505c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawAxisGetLimits"
515c6c1daeSBarry Smith /*@
525c6c1daeSBarry Smith     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
535c6c1daeSBarry Smith 
545c6c1daeSBarry Smith     Not Collective (ignored on all processors except processor 0 of PetscDrawAxis)
555c6c1daeSBarry Smith 
565c6c1daeSBarry Smith     Input Parameters:
575c6c1daeSBarry Smith +   axis - the axis
585c6c1daeSBarry Smith .   xmin,xmax - limits in x
595c6c1daeSBarry Smith -   ymin,ymax - limits in y
605c6c1daeSBarry Smith 
615c6c1daeSBarry Smith     Level: advanced
625c6c1daeSBarry Smith 
635c6c1daeSBarry Smith .seealso:  PetscDrawAxisSetLimits()
645c6c1daeSBarry Smith 
655c6c1daeSBarry Smith @*/
665c6c1daeSBarry Smith PetscErrorCode  PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
675c6c1daeSBarry Smith {
685c6c1daeSBarry Smith   PetscFunctionBegin;
695c6c1daeSBarry Smith   if (!axis) PetscFunctionReturn(0);
705c6c1daeSBarry Smith   if (axis->hold) PetscFunctionReturn(0);
715c6c1daeSBarry Smith   *xmin = axis->xlow;
725c6c1daeSBarry Smith   *xmax = axis->xhigh;
735c6c1daeSBarry Smith   *ymin = axis->ylow;
745c6c1daeSBarry Smith   *ymax = axis->yhigh;
755c6c1daeSBarry Smith   PetscFunctionReturn(0);
765c6c1daeSBarry Smith }
775c6c1daeSBarry Smith 
785c6c1daeSBarry Smith #undef __FUNCT__
795c6c1daeSBarry Smith #define __FUNCT__ "PetscADefLabel"
805c6c1daeSBarry Smith /*
815c6c1daeSBarry Smith    val is the label value.  sep is the separation to the next (or previous)
825c6c1daeSBarry Smith    label; this is useful in determining how many significant figures to
835c6c1daeSBarry Smith    keep.
845c6c1daeSBarry Smith  */
855c6c1daeSBarry Smith PetscErrorCode PetscADefLabel(PetscReal val,PetscReal sep,char **p)
865c6c1daeSBarry Smith {
875c6c1daeSBarry Smith   static char    buf[40];
885c6c1daeSBarry Smith   PetscErrorCode ierr;
895c6c1daeSBarry Smith   PetscReal      rval;
905c6c1daeSBarry Smith 
915c6c1daeSBarry Smith   PetscFunctionBegin;
925c6c1daeSBarry Smith   /* Find the string */
93ba129bcfSBarry Smith   if (PetscAbsReal(val)/sep <  1.e-4) {
945c6c1daeSBarry Smith     buf[0] = '0'; buf[1] = 0;
95*36c9bc0dSBarry Smith   } else {
965c6c1daeSBarry Smith     ierr = PetscRint(val,&rval);CHKERRQ(ierr);
975c6c1daeSBarry Smith     if (rval == val) {
98*36c9bc0dSBarry Smith       sprintf(buf,"%d",(int)val);
995c6c1daeSBarry Smith       ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
1005c6c1daeSBarry Smith       ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
1015c6c1daeSBarry Smith       ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
1025c6c1daeSBarry Smith     } else {
103*36c9bc0dSBarry Smith       sprintf(buf,"%0.1le",(double)val);
104*36c9bc0dSBarry Smith       ierr = PetscStripe0(buf);CHKERRQ(ierr);
1055c6c1daeSBarry Smith       ierr = PetscStripInitialZero(buf);CHKERRQ(ierr);
1065c6c1daeSBarry Smith       ierr = PetscStripAllZeros(buf);CHKERRQ(ierr);
1075c6c1daeSBarry Smith       ierr = PetscStripTrailingZeros(buf);CHKERRQ(ierr);
1085c6c1daeSBarry Smith     }
1095c6c1daeSBarry Smith   }
1105c6c1daeSBarry Smith   *p =buf;
1115c6c1daeSBarry Smith   PetscFunctionReturn(0);
1125c6c1daeSBarry Smith }
1135c6c1daeSBarry Smith 
1145c6c1daeSBarry Smith #undef __FUNCT__
1155c6c1daeSBarry Smith #define __FUNCT__ "PetscADefTicks"
1165c6c1daeSBarry Smith /* Finds "nice" locations for the ticks */
1175c6c1daeSBarry Smith PetscErrorCode PetscADefTicks(PetscReal low,PetscReal high,int num,int *ntick,PetscReal * tickloc,int  maxtick)
1185c6c1daeSBarry Smith {
1195c6c1daeSBarry Smith   PetscErrorCode ierr;
1205c6c1daeSBarry Smith   int            i,power;
1215c6c1daeSBarry Smith   PetscReal      x = 0.0,base=0.0;
1225c6c1daeSBarry Smith 
1235c6c1daeSBarry Smith   PetscFunctionBegin;
1245c6c1daeSBarry Smith   /* patch if low == high */
1255c6c1daeSBarry Smith   if (low == high) {
1265c6c1daeSBarry Smith     low  -= .01;
1275c6c1daeSBarry Smith     high += .01;
1285c6c1daeSBarry Smith   }
1295c6c1daeSBarry Smith 
1305c6c1daeSBarry Smith   /*  if (PetscAbsReal(low-high) < 1.e-8) {
1315c6c1daeSBarry Smith     low  -= .01;
1325c6c1daeSBarry Smith     high += .01;
1335c6c1daeSBarry Smith   } */
1345c6c1daeSBarry Smith 
1355c6c1daeSBarry Smith   ierr = PetscAGetBase(low,high,num,&base,&power);CHKERRQ(ierr);
1365c6c1daeSBarry Smith   ierr = PetscAGetNice(low,base,-1,&x);CHKERRQ(ierr);
1375c6c1daeSBarry Smith 
1385c6c1daeSBarry Smith   /* Values are of the form j * base */
1395c6c1daeSBarry Smith   /* Find the starting value */
1405c6c1daeSBarry Smith   if (x < low) x += base;
1415c6c1daeSBarry Smith 
1425c6c1daeSBarry Smith   i = 0;
1435c6c1daeSBarry Smith   while (i < maxtick && x <= high) {
1445c6c1daeSBarry Smith     tickloc[i++] = x;
1455c6c1daeSBarry Smith     x += base;
1465c6c1daeSBarry Smith   }
1475c6c1daeSBarry Smith   *ntick = i;
1485c6c1daeSBarry Smith 
1495c6c1daeSBarry Smith   if (i < 2 && num < 10) {
1505c6c1daeSBarry Smith     ierr = PetscADefTicks(low,high,num+1,ntick,tickloc,maxtick);CHKERRQ(ierr);
1515c6c1daeSBarry Smith   }
152db05f41bSBarry Smith   if (num == 10) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"trouble");
1535c6c1daeSBarry Smith   PetscFunctionReturn(0);
1545c6c1daeSBarry Smith }
1555c6c1daeSBarry Smith 
1565c6c1daeSBarry Smith #define EPS 1.e-6
1575c6c1daeSBarry Smith 
1585c6c1daeSBarry Smith #undef __FUNCT__
1595c6c1daeSBarry Smith #define __FUNCT__ "PetscExp10"
1605c6c1daeSBarry Smith PetscErrorCode PetscExp10(PetscReal d,PetscReal *result)
1615c6c1daeSBarry Smith {
1625c6c1daeSBarry Smith   PetscFunctionBegin;
1635c6c1daeSBarry Smith   *result = pow((PetscReal)10.0,d);
1645c6c1daeSBarry Smith   PetscFunctionReturn(0);
1655c6c1daeSBarry Smith }
1665c6c1daeSBarry Smith 
1675c6c1daeSBarry Smith #undef __FUNCT__
1685c6c1daeSBarry Smith #define __FUNCT__ "PetscMod"
1695c6c1daeSBarry Smith PetscErrorCode PetscMod(PetscReal x,PetscReal y,PetscReal *result)
1705c6c1daeSBarry Smith {
1715c6c1daeSBarry Smith   int     i;
1725c6c1daeSBarry Smith 
1735c6c1daeSBarry Smith   PetscFunctionBegin;
1745c6c1daeSBarry Smith   if (y == 1) {
1755c6c1daeSBarry Smith     *result = 0.0;
1765c6c1daeSBarry Smith     PetscFunctionReturn(0);
1775c6c1daeSBarry Smith   }
1785c6c1daeSBarry Smith   i   = ((int)x) / ((int)y);
1795c6c1daeSBarry Smith   x   = x - i * y;
1805c6c1daeSBarry Smith   while (x > y) x -= y;
1815c6c1daeSBarry Smith   *result = x;
1825c6c1daeSBarry Smith   PetscFunctionReturn(0);
1835c6c1daeSBarry Smith }
1845c6c1daeSBarry Smith 
1855c6c1daeSBarry Smith #undef __FUNCT__
1865c6c1daeSBarry Smith #define __FUNCT__ "PetscCopysign"
1875c6c1daeSBarry Smith PetscErrorCode PetscCopysign(PetscReal a,PetscReal b,PetscReal *result)
1885c6c1daeSBarry Smith {
1895c6c1daeSBarry Smith   PetscFunctionBegin;
1905c6c1daeSBarry Smith   if (b >= 0) *result = a;
1915c6c1daeSBarry Smith   else        *result = -a;
1925c6c1daeSBarry Smith   PetscFunctionReturn(0);
1935c6c1daeSBarry Smith }
1945c6c1daeSBarry Smith 
1955c6c1daeSBarry Smith #undef __FUNCT__
1965c6c1daeSBarry Smith #define __FUNCT__ "PetscAGetNice"
1975c6c1daeSBarry Smith /*
1985c6c1daeSBarry Smith     Given a value "in" and a "base", return a nice value.
1995c6c1daeSBarry Smith     based on "sign", extend up (+1) or down (-1)
2005c6c1daeSBarry Smith  */
2015c6c1daeSBarry Smith PetscErrorCode PetscAGetNice(PetscReal in,PetscReal base,int sign,PetscReal *result)
2025c6c1daeSBarry Smith {
2035c6c1daeSBarry Smith   PetscReal      etmp,s,s2,m;
2045c6c1daeSBarry Smith   PetscErrorCode ierr;
2055c6c1daeSBarry Smith 
2065c6c1daeSBarry Smith   PetscFunctionBegin;
2075c6c1daeSBarry Smith   ierr    = PetscCopysign (0.5,(double)sign,&s);CHKERRQ(ierr);
2085c6c1daeSBarry Smith   etmp    = in / base + 0.5 + s;
2095c6c1daeSBarry Smith   ierr    = PetscCopysign (0.5,etmp,&s);CHKERRQ(ierr);
2105c6c1daeSBarry Smith   ierr    = PetscCopysign (EPS * etmp,(double)sign,&s2);CHKERRQ(ierr);
2115c6c1daeSBarry Smith   etmp    = etmp - 0.5 + s - s2;
2125c6c1daeSBarry Smith   ierr    = PetscMod(etmp,1.0,&m);CHKERRQ(ierr);
2135c6c1daeSBarry Smith   etmp    = base * (etmp -  m);
2145c6c1daeSBarry Smith   *result = etmp;
2155c6c1daeSBarry Smith   PetscFunctionReturn(0);
2165c6c1daeSBarry Smith }
2175c6c1daeSBarry Smith 
2185c6c1daeSBarry Smith #undef __FUNCT__
2195c6c1daeSBarry Smith #define __FUNCT__ "PetscAGetBase"
2205c6c1daeSBarry Smith PetscErrorCode PetscAGetBase(PetscReal vmin,PetscReal vmax,int num,PetscReal*Base,int*power)
2215c6c1daeSBarry Smith {
2225c6c1daeSBarry Smith   PetscReal        base,ftemp,e10;
2235c6c1daeSBarry Smith   static PetscReal base_try[5] = {10.0,5.0,2.0,1.0,0.5};
2245c6c1daeSBarry Smith   PetscErrorCode   ierr;
2255c6c1daeSBarry Smith   int              i;
2265c6c1daeSBarry Smith 
2275c6c1daeSBarry Smith   PetscFunctionBegin;
2285c6c1daeSBarry Smith   /* labels of the form n * BASE */
2295c6c1daeSBarry Smith   /* get an approximate value for BASE */
2305c6c1daeSBarry Smith   base    = (vmax - vmin) / (double)(num + 1);
2315c6c1daeSBarry Smith 
2325c6c1daeSBarry Smith   /* make it of form   m x 10^power,  m in [1.0, 10) */
2335c6c1daeSBarry Smith   if (base <= 0.0) {
2345c6c1daeSBarry Smith     base    = PetscAbsReal(vmin);
2355c6c1daeSBarry Smith     if (base < 1.0) base = 1.0;
2365c6c1daeSBarry Smith   }
2375c6c1daeSBarry Smith   ftemp   = log10((1.0 + EPS) * base);
2385c6c1daeSBarry Smith   if (ftemp < 0.0)  ftemp   -= 1.0;
2395c6c1daeSBarry Smith   *power  = (int)ftemp;
2405c6c1daeSBarry Smith   ierr = PetscExp10((double)- *power,&e10);CHKERRQ(ierr);
2415c6c1daeSBarry Smith   base    = base * e10;
2425c6c1daeSBarry Smith   if (base < 1.0) base    = 1.0;
2435c6c1daeSBarry Smith   /* now reduce it to one of 1, 2, or 5 */
2445c6c1daeSBarry Smith   for (i=1; i<5; i++) {
2455c6c1daeSBarry Smith     if (base >= base_try[i]) {
2465c6c1daeSBarry Smith       ierr = PetscExp10((double)*power,&e10);CHKERRQ(ierr);
2475c6c1daeSBarry Smith       base = base_try[i-1] * e10;
2485c6c1daeSBarry Smith       if (i == 1) *power    = *power + 1;
2495c6c1daeSBarry Smith       break;
2505c6c1daeSBarry Smith     }
2515c6c1daeSBarry Smith   }
2525c6c1daeSBarry Smith   *Base   = base;
2535c6c1daeSBarry Smith   PetscFunctionReturn(0);
2545c6c1daeSBarry Smith }
2555c6c1daeSBarry Smith 
2565c6c1daeSBarry Smith 
2575c6c1daeSBarry Smith 
2585c6c1daeSBarry Smith 
2595c6c1daeSBarry Smith 
2605c6c1daeSBarry Smith 
261