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