xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
1999739cfSJacob Faibussowitsch #include <petsc/private/drawimpl.h> /*I   "petscdraw.h"  I*/
25c6c1daeSBarry Smith 
3999739cfSJacob Faibussowitsch #define PETSC_DRAW_AXIS_MAX_SEGMENTS 20
45c6c1daeSBarry Smith PetscClassId PETSC_DRAWAXIS_CLASSID = 0;
55c6c1daeSBarry Smith 
65c6c1daeSBarry Smith /*@
75c6c1daeSBarry Smith    PetscDrawAxisCreate - Generate the axis data structure.
85c6c1daeSBarry Smith 
9*811af0c4SBarry Smith    Collective on draw
105c6c1daeSBarry Smith 
115c6c1daeSBarry Smith    Input Parameters:
12*811af0c4SBarry Smith .  win - `PetscDraw` object where axis to to be made
135c6c1daeSBarry Smith 
1401d2d390SJose E. Roman    Output Parameter:
155c6c1daeSBarry Smith .  axis - the axis datastructure
165c6c1daeSBarry Smith 
17*811af0c4SBarry Smith    Note:
18*811af0c4SBarry Smith    The MPI communicator that owns the underlying draw object owns the `PetscDrawAxis` object, but calls to set `PetscDrawAxis` options are
19*811af0c4SBarry Smith    ignored by all processes except the first MPI rank in the communicator
207e25d57eSBarry Smith 
215c6c1daeSBarry Smith    Level: advanced
225c6c1daeSBarry Smith 
23db781477SPatrick Sanan .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawLGGetAxis()`, `PetscDrawSPGetAxis()`,
24db781477SPatrick Sanan           `PetscDrawHGGetAxis()`, `PetscDrawBarGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisDestroy()`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetHoldLimits()`,
25db781477SPatrick Sanan           `PetscDrawAxisDraw()`
265c6c1daeSBarry Smith @*/
279371c9d4SSatish Balay PetscErrorCode PetscDrawAxisCreate(PetscDraw draw, PetscDrawAxis *axis) {
28e118a51fSLisandro Dalcin   PetscDrawAxis ad;
295c6c1daeSBarry Smith 
305c6c1daeSBarry Smith   PetscFunctionBegin;
315c6c1daeSBarry Smith   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
325c6c1daeSBarry Smith   PetscValidPointer(axis, 2);
33e118a51fSLisandro Dalcin 
349566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(ad, PETSC_DRAWAXIS_CLASSID, "DrawAxis", "Draw Axis", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawAxisDestroy, NULL));
359566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)draw, (PetscObject)ad));
36a297a907SKarl Rupp 
379566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)draw));
38e118a51fSLisandro Dalcin   ad->win = draw;
39e118a51fSLisandro Dalcin 
405c6c1daeSBarry Smith   ad->xticks    = PetscADefTicks;
415c6c1daeSBarry Smith   ad->yticks    = PetscADefTicks;
425c6c1daeSBarry Smith   ad->xlabelstr = PetscADefLabel;
435c6c1daeSBarry Smith   ad->ylabelstr = PetscADefLabel;
445c6c1daeSBarry Smith   ad->ac        = PETSC_DRAW_BLACK;
455c6c1daeSBarry Smith   ad->tc        = PETSC_DRAW_BLACK;
465c6c1daeSBarry Smith   ad->cc        = PETSC_DRAW_BLACK;
47e5ab1681SLisandro Dalcin   ad->xlabel    = NULL;
48e5ab1681SLisandro Dalcin   ad->ylabel    = NULL;
49e5ab1681SLisandro Dalcin   ad->toplabel  = NULL;
505c6c1daeSBarry Smith 
515c6c1daeSBarry Smith   *axis = ad;
525c6c1daeSBarry Smith   PetscFunctionReturn(0);
535c6c1daeSBarry Smith }
545c6c1daeSBarry Smith 
555c6c1daeSBarry Smith /*@
565c6c1daeSBarry Smith     PetscDrawAxisDestroy - Frees the space used by an axis structure.
575c6c1daeSBarry Smith 
58*811af0c4SBarry Smith     Collective on axis
595c6c1daeSBarry Smith 
605c6c1daeSBarry Smith     Input Parameters:
615c6c1daeSBarry Smith .   axis - the axis context
625c6c1daeSBarry Smith 
635c6c1daeSBarry Smith     Level: advanced
645c6c1daeSBarry Smith 
65*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`
665c6c1daeSBarry Smith @*/
679371c9d4SSatish Balay PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis) {
685c6c1daeSBarry Smith   PetscFunctionBegin;
695c6c1daeSBarry Smith   if (!*axis) PetscFunctionReturn(0);
70e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(*axis, PETSC_DRAWAXIS_CLASSID, 1);
719371c9d4SSatish Balay   if (--((PetscObject)(*axis))->refct > 0) {
729371c9d4SSatish Balay     *axis = NULL;
739371c9d4SSatish Balay     PetscFunctionReturn(0);
749371c9d4SSatish Balay   }
755c6c1daeSBarry Smith 
769566063dSJacob Faibussowitsch   PetscCall(PetscFree((*axis)->toplabel));
779566063dSJacob Faibussowitsch   PetscCall(PetscFree((*axis)->xlabel));
789566063dSJacob Faibussowitsch   PetscCall(PetscFree((*axis)->ylabel));
799566063dSJacob Faibussowitsch   PetscCall(PetscDrawDestroy(&(*axis)->win));
809566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(axis));
815c6c1daeSBarry Smith   PetscFunctionReturn(0);
825c6c1daeSBarry Smith }
835c6c1daeSBarry Smith 
845c6c1daeSBarry Smith /*@
855c6c1daeSBarry Smith     PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
865c6c1daeSBarry Smith                          tickmarks, and text.
875c6c1daeSBarry Smith 
88*811af0c4SBarry Smith     Logically Collective on axis
895c6c1daeSBarry Smith 
905c6c1daeSBarry Smith     Input Parameters:
915c6c1daeSBarry Smith +   axis - the axis
925c6c1daeSBarry Smith .   ac - the color of the axis lines
935c6c1daeSBarry Smith .   tc - the color of the tick marks
945c6c1daeSBarry Smith -   cc - the color of the text strings
955c6c1daeSBarry Smith 
965c6c1daeSBarry Smith     Level: advanced
975c6c1daeSBarry Smith 
98*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
995c6c1daeSBarry Smith @*/
1009371c9d4SSatish Balay PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis, int ac, int tc, int cc) {
1015c6c1daeSBarry Smith   PetscFunctionBegin;
102e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1035b399a63SLisandro Dalcin   PetscValidLogicalCollectiveInt(axis, ac, 2);
1045b399a63SLisandro Dalcin   PetscValidLogicalCollectiveInt(axis, tc, 3);
1055b399a63SLisandro Dalcin   PetscValidLogicalCollectiveInt(axis, cc, 4);
1069371c9d4SSatish Balay   axis->ac = ac;
1079371c9d4SSatish Balay   axis->tc = tc;
1089371c9d4SSatish Balay   axis->cc = cc;
1095c6c1daeSBarry Smith   PetscFunctionReturn(0);
1105c6c1daeSBarry Smith }
1115c6c1daeSBarry Smith 
1125c6c1daeSBarry Smith /*@C
1135c6c1daeSBarry Smith     PetscDrawAxisSetLabels -  Sets the x and y axis labels.
1145c6c1daeSBarry Smith 
115*811af0c4SBarry Smith     Logically Collective on axis
1165c6c1daeSBarry Smith 
1175c6c1daeSBarry Smith     Input Parameters:
1185c6c1daeSBarry Smith +   axis - the axis
1195c6c1daeSBarry Smith .   top - the label at the top of the image
1205c6c1daeSBarry Smith -   xlabel,ylabel - the labes for the x and y axis
1215c6c1daeSBarry Smith 
12295452b02SPatrick Sanan     Notes:
123*811af0c4SBarry Smith     Must be called before `PetscDrawAxisDraw()` or `PetscDrawLGDraw()`
124*811af0c4SBarry Smith 
1255c6c1daeSBarry Smith     There should be no newlines in the arguments
1265c6c1daeSBarry Smith 
1275c6c1daeSBarry Smith     Level: advanced
1285c6c1daeSBarry Smith 
129*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
1305c6c1daeSBarry Smith @*/
1319371c9d4SSatish Balay PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis, const char top[], const char xlabel[], const char ylabel[]) {
1325c6c1daeSBarry Smith   PetscFunctionBegin;
133e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1349566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->xlabel));
1359566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->ylabel));
1369566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->toplabel));
1379566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(xlabel, &axis->xlabel));
1389566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ylabel, &axis->ylabel));
1399566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(top, &axis->toplabel));
1405c6c1daeSBarry Smith   PetscFunctionReturn(0);
1415c6c1daeSBarry Smith }
1425c6c1daeSBarry Smith 
14371917b75SLisandro Dalcin /*@
14471917b75SLisandro Dalcin     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
14571917b75SLisandro Dalcin 
146*811af0c4SBarry Smith     Logically Collective on axis
14771917b75SLisandro Dalcin 
14871917b75SLisandro Dalcin     Input Parameters:
14971917b75SLisandro Dalcin +   axis - the axis
15071917b75SLisandro Dalcin .   xmin,xmax - limits in x
15171917b75SLisandro Dalcin -   ymin,ymax - limits in y
15271917b75SLisandro Dalcin 
153*811af0c4SBarry Smith     Options Database Key:
15471917b75SLisandro Dalcin .   -drawaxis_hold - hold the initial set of axis limits for future plotting
15571917b75SLisandro Dalcin 
15671917b75SLisandro Dalcin     Level: advanced
15771917b75SLisandro Dalcin 
158db781477SPatrick Sanan .seealso: `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
15971917b75SLisandro Dalcin @*/
1609371c9d4SSatish Balay PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax) {
16171917b75SLisandro Dalcin   PetscFunctionBegin;
16271917b75SLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
16371917b75SLisandro Dalcin   if (axis->hold) PetscFunctionReturn(0);
16471917b75SLisandro Dalcin   axis->xlow  = xmin;
16571917b75SLisandro Dalcin   axis->xhigh = xmax;
16671917b75SLisandro Dalcin   axis->ylow  = ymin;
16771917b75SLisandro Dalcin   axis->yhigh = ymax;
1689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)axis)->options, ((PetscObject)axis)->prefix, "-drawaxis_hold", &axis->hold));
16971917b75SLisandro Dalcin   PetscFunctionReturn(0);
17071917b75SLisandro Dalcin }
17171917b75SLisandro Dalcin 
17271917b75SLisandro Dalcin /*@
17371917b75SLisandro Dalcin     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
17471917b75SLisandro Dalcin 
17571917b75SLisandro Dalcin     Not Collective
17671917b75SLisandro Dalcin 
17771917b75SLisandro Dalcin     Input Parameters:
17871917b75SLisandro Dalcin +   axis - the axis
17971917b75SLisandro Dalcin .   xmin,xmax - limits in x
18071917b75SLisandro Dalcin -   ymin,ymax - limits in y
18171917b75SLisandro Dalcin 
18271917b75SLisandro Dalcin     Level: advanced
18371917b75SLisandro Dalcin 
184db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
18571917b75SLisandro Dalcin @*/
1869371c9d4SSatish Balay PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis, PetscReal *xmin, PetscReal *xmax, PetscReal *ymin, PetscReal *ymax) {
18771917b75SLisandro Dalcin   PetscFunctionBegin;
18871917b75SLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
189bb046f40SHong Zhang   if (xmin) *xmin = axis->xlow;
190bb046f40SHong Zhang   if (xmax) *xmax = axis->xhigh;
191bb046f40SHong Zhang   if (ymin) *ymin = axis->ylow;
192bb046f40SHong Zhang   if (ymax) *ymax = axis->yhigh;
19371917b75SLisandro Dalcin   PetscFunctionReturn(0);
19471917b75SLisandro Dalcin }
19571917b75SLisandro Dalcin 
1965c6c1daeSBarry Smith /*@
1975c6c1daeSBarry Smith     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
1985c6c1daeSBarry Smith         again
1995c6c1daeSBarry Smith 
200*811af0c4SBarry Smith     Logically Collective on axis
2015c6c1daeSBarry Smith 
2025c6c1daeSBarry Smith     Input Parameters:
2035c6c1daeSBarry Smith +   axis - the axis
204*811af0c4SBarry Smith -   hold - `PETSC_TRUE` - hold current limits, `PETSC_FALSE` allow limits to be changed
2055c6c1daeSBarry Smith 
2065c6c1daeSBarry Smith     Level: advanced
2075c6c1daeSBarry Smith 
208*811af0c4SBarry Smith     Note:
209*811af0c4SBarry Smith         Once this has been called with `PETSC_TRUE` the limits will not change if you call
210*811af0c4SBarry Smith      `PetscDrawAxisSetLimits()` until you call this with `PETSC_FALSE`
2115c6c1daeSBarry Smith 
212db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
2135c6c1daeSBarry Smith @*/
2149371c9d4SSatish Balay PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis, PetscBool hold) {
2155c6c1daeSBarry Smith   PetscFunctionBegin;
216e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
2175b399a63SLisandro Dalcin   PetscValidLogicalCollectiveBool(axis, hold, 2);
2185c6c1daeSBarry Smith   axis->hold = hold;
2195c6c1daeSBarry Smith   PetscFunctionReturn(0);
2205c6c1daeSBarry Smith }
2215c6c1daeSBarry Smith 
2225c6c1daeSBarry Smith /*@
223*811af0c4SBarry Smith     PetscDrawAxisDraw - draws an axis.
2245c6c1daeSBarry Smith 
225*811af0c4SBarry Smith     Collective on axis
2265c6c1daeSBarry Smith 
2275c6c1daeSBarry Smith     Input Parameter:
228*811af0c4SBarry Smith .   axis - `PetscDrawAxis` structure
2295c6c1daeSBarry Smith 
2305c6c1daeSBarry Smith     Level: advanced
2315c6c1daeSBarry Smith 
2325c6c1daeSBarry Smith     Note:
2335c6c1daeSBarry Smith     This draws the actual axis.  The limits etc have already been set.
2345c6c1daeSBarry Smith     By picking special routines for the ticks and labels, special
2355c6c1daeSBarry Smith     effects may be generated.  These routines are part of the Axis
2365c6c1daeSBarry Smith     structure (axis).
2370afdd333SBarry Smith 
238db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
2395c6c1daeSBarry Smith @*/
2409371c9d4SSatish Balay PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis) {
241e118a51fSLisandro Dalcin   int         i, ntick, numx, numy, ac, tc, cc;
242e118a51fSLisandro Dalcin   PetscMPIInt rank;
24371917b75SLisandro Dalcin   size_t      len, ytlen = 0;
244999739cfSJacob Faibussowitsch   PetscReal   coors[4], tickloc[PETSC_DRAW_AXIS_MAX_SEGMENTS], sep, tw, th;
24571917b75SLisandro Dalcin   PetscReal   xl, xr, yl, yr, dxl = 0, dyl = 0, dxr = 0, dyr = 0;
2465c6c1daeSBarry Smith   char       *p;
247e118a51fSLisandro Dalcin   PetscDraw   draw;
248e118a51fSLisandro Dalcin   PetscBool   isnull;
2495c6c1daeSBarry Smith 
2505c6c1daeSBarry Smith   PetscFunctionBegin;
251e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
2529566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(axis->win, &isnull));
253e118a51fSLisandro Dalcin   if (isnull) PetscFunctionReturn(0);
2549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)axis), &rank));
2555c6c1daeSBarry Smith 
2568f69470aSLisandro Dalcin   draw = axis->win;
2575b399a63SLisandro Dalcin 
2589371c9d4SSatish Balay   ac = axis->ac;
2599371c9d4SSatish Balay   tc = axis->tc;
2609371c9d4SSatish Balay   cc = axis->cc;
2619371c9d4SSatish Balay   if (axis->xlow == axis->xhigh) {
2629371c9d4SSatish Balay     axis->xlow -= .5;
2639371c9d4SSatish Balay     axis->xhigh += .5;
2649371c9d4SSatish Balay   }
2659371c9d4SSatish Balay   if (axis->ylow == axis->yhigh) {
2669371c9d4SSatish Balay     axis->ylow -= .5;
2679371c9d4SSatish Balay     axis->yhigh += .5;
2689371c9d4SSatish Balay   }
269e118a51fSLisandro Dalcin 
270d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
27171917b75SLisandro Dalcin   if (rank) goto finally;
27271917b75SLisandro Dalcin 
27371917b75SLisandro Dalcin   /* get cannonical string size */
2749566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, 0, 0, 1, 1));
2759566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
27671917b75SLisandro Dalcin   /* lower spacing */
27771917b75SLisandro Dalcin   if (axis->xlabelstr) dyl += 1.5 * th;
27871917b75SLisandro Dalcin   if (axis->xlabel) dyl += 1.5 * th;
27971917b75SLisandro Dalcin   /* left spacing */
28071917b75SLisandro Dalcin   if (axis->ylabelstr) dxl += 7.5 * tw;
28171917b75SLisandro Dalcin   if (axis->ylabel) dxl += 2.0 * tw;
28271917b75SLisandro Dalcin   /* right and top spacing */
28371917b75SLisandro Dalcin   if (axis->xlabelstr) dxr = 2.5 * tw;
28471917b75SLisandro Dalcin   if (axis->ylabelstr) dyr = 0.5 * th;
28571917b75SLisandro Dalcin   if (axis->toplabel) dyr = 1.5 * th;
28671917b75SLisandro Dalcin   /* extra spacing */
2879371c9d4SSatish Balay   dxl += 0.7 * tw;
2889371c9d4SSatish Balay   dxr += 0.5 * tw;
2899371c9d4SSatish Balay   dyl += 0.2 * th;
2909371c9d4SSatish Balay   dyr += 0.2 * th;
29171917b75SLisandro Dalcin   /* determine coordinates */
29271917b75SLisandro Dalcin   xl = (dxl * axis->xhigh + dxr * axis->xlow - axis->xlow) / (dxl + dxr - 1);
29371917b75SLisandro Dalcin   xr = (dxl * axis->xhigh + dxr * axis->xlow - axis->xhigh) / (dxl + dxr - 1);
29471917b75SLisandro Dalcin   yl = (dyl * axis->yhigh + dyr * axis->ylow - axis->ylow) / (dyl + dyr - 1);
29571917b75SLisandro Dalcin   yr = (dyl * axis->yhigh + dyr * axis->ylow - axis->yhigh) / (dyl + dyr - 1);
2969566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
2979566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
2985c6c1daeSBarry Smith 
29971917b75SLisandro Dalcin   /* PetscDraw the axis lines */
3009566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xhigh, axis->ylow, ac));
3019566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xlow, axis->yhigh, ac));
3029566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->yhigh, axis->xhigh, axis->yhigh, ac));
3039566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xhigh, axis->ylow, axis->xhigh, axis->yhigh, ac));
3045c6c1daeSBarry Smith 
30571917b75SLisandro Dalcin   /* PetscDraw the top label */
3065c6c1daeSBarry Smith   if (axis->toplabel) {
30771917b75SLisandro Dalcin     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->yhigh + 0.5 * th;
3089566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->toplabel));
3095c6c1daeSBarry Smith   }
3105c6c1daeSBarry Smith 
31171917b75SLisandro Dalcin   /* PetscDraw the X ticks and labels */
3125c6c1daeSBarry Smith   if (axis->xticks) {
3139371c9d4SSatish Balay     numx = (int)(.15 * (axis->xhigh - axis->xlow) / tw);
3149371c9d4SSatish Balay     numx = PetscClipInterval(numx, 2, 6);
3159566063dSJacob Faibussowitsch     PetscCall((*axis->xticks)(axis->xlow, axis->xhigh, numx, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
3165c6c1daeSBarry Smith     /* PetscDraw in tick marks */
3175c6c1daeSBarry Smith     for (i = 0; i < ntick; i++) {
3189566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, tickloc[i], axis->ylow, tickloc[i], axis->ylow + .5 * th, tc));
3199566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, tickloc[i], axis->yhigh, tickloc[i], axis->yhigh - .5 * th, tc));
3205c6c1daeSBarry Smith     }
3215c6c1daeSBarry Smith     /* label ticks */
3225c6c1daeSBarry Smith     if (axis->xlabelstr) {
32371917b75SLisandro Dalcin       for (i = 0; i < ntick; i++) {
3245c6c1daeSBarry Smith         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
3255c6c1daeSBarry Smith         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
3265c6c1daeSBarry Smith         else sep = 0.0;
3279566063dSJacob Faibussowitsch         PetscCall((*axis->xlabelstr)(tickloc[i], sep, &p));
3289566063dSJacob Faibussowitsch         PetscCall(PetscDrawStringCentered(draw, tickloc[i], axis->ylow - 1.5 * th, cc, p));
3295c6c1daeSBarry Smith       }
3305c6c1daeSBarry Smith     }
3315c6c1daeSBarry Smith   }
3325c6c1daeSBarry Smith   if (axis->xlabel) {
33371917b75SLisandro Dalcin     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->ylow - 1.5 * th;
33471917b75SLisandro Dalcin     if (axis->xlabelstr) y -= 1.5 * th;
3359566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->xlabel));
3365c6c1daeSBarry Smith   }
33771917b75SLisandro Dalcin 
33871917b75SLisandro Dalcin   /* PetscDraw the Y ticks and labels */
3395c6c1daeSBarry Smith   if (axis->yticks) {
3409371c9d4SSatish Balay     numy = (int)(.50 * (axis->yhigh - axis->ylow) / th);
3419371c9d4SSatish Balay     numy = PetscClipInterval(numy, 2, 6);
3429566063dSJacob Faibussowitsch     PetscCall((*axis->yticks)(axis->ylow, axis->yhigh, numy, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
3435c6c1daeSBarry Smith     /* PetscDraw in tick marks */
3445c6c1daeSBarry Smith     for (i = 0; i < ntick; i++) {
3459566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, axis->xlow, tickloc[i], axis->xlow + .5 * tw, tickloc[i], tc));
3469566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, axis->xhigh, tickloc[i], axis->xhigh - .5 * tw, tickloc[i], tc));
3475c6c1daeSBarry Smith     }
3485c6c1daeSBarry Smith     /* label ticks */
3495c6c1daeSBarry Smith     if (axis->ylabelstr) {
35071917b75SLisandro Dalcin       for (i = 0; i < ntick; i++) {
3515c6c1daeSBarry Smith         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
3525c6c1daeSBarry Smith         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
3535c6c1daeSBarry Smith         else sep = 0.0;
3549566063dSJacob Faibussowitsch         PetscCall((*axis->ylabelstr)(tickloc[i], sep, &p));
3559371c9d4SSatish Balay         PetscCall(PetscStrlen(p, &len));
3569371c9d4SSatish Balay         ytlen = PetscMax(ytlen, len);
3579566063dSJacob Faibussowitsch         PetscCall(PetscDrawString(draw, axis->xlow - (len + .5) * tw, tickloc[i] - .5 * th, cc, p));
3585c6c1daeSBarry Smith       }
3595c6c1daeSBarry Smith     }
3605c6c1daeSBarry Smith   }
3615c6c1daeSBarry Smith   if (axis->ylabel) {
36271917b75SLisandro Dalcin     PetscReal x = axis->xlow - 2.0 * tw, y = (axis->ylow + axis->yhigh) / 2;
36371917b75SLisandro Dalcin     if (axis->ylabelstr) x -= (ytlen + .5) * tw;
3649566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(axis->ylabel, &len));
3659566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringVertical(draw, x, y + len * th / 2, cc, axis->ylabel));
3665c6c1daeSBarry Smith   }
3675b399a63SLisandro Dalcin 
3689566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &coors[0], &coors[1], &coors[2], &coors[3]));
3695b399a63SLisandro Dalcin finally:
370d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
3719566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(coors, 4, MPIU_REAL, 0, PetscObjectComm((PetscObject)draw)));
3729566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, coors[0], coors[1], coors[2], coors[3]));
3735c6c1daeSBarry Smith   PetscFunctionReturn(0);
3745c6c1daeSBarry Smith }
3755c6c1daeSBarry Smith 
37636c9bc0dSBarry Smith /*
37736c9bc0dSBarry Smith     Removes all zeros but one from .0000
37836c9bc0dSBarry Smith */
3799371c9d4SSatish Balay PetscErrorCode PetscStripe0(char *buf) {
38036c9bc0dSBarry Smith   size_t    n;
38136c9bc0dSBarry Smith   PetscBool flg;
38236c9bc0dSBarry Smith   char     *str;
38336c9bc0dSBarry Smith 
38436c9bc0dSBarry Smith   PetscFunctionBegin;
3859566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
3869566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(buf, "e00", &flg));
387a297a907SKarl Rupp   if (flg) buf[n - 3] = 0;
3889566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buf, "e0", &str));
38936c9bc0dSBarry Smith   if (str) {
39036c9bc0dSBarry Smith     buf[n - 2] = buf[n - 1];
39136c9bc0dSBarry Smith     buf[n - 1] = 0;
39236c9bc0dSBarry Smith   }
3939566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buf, "e-0", &str));
39436c9bc0dSBarry Smith   if (str) {
39536c9bc0dSBarry Smith     buf[n - 2] = buf[n - 1];
39636c9bc0dSBarry Smith     buf[n - 1] = 0;
39736c9bc0dSBarry Smith   }
39836c9bc0dSBarry Smith   PetscFunctionReturn(0);
39936c9bc0dSBarry Smith }
40036c9bc0dSBarry Smith 
4015c6c1daeSBarry Smith /*
4025c6c1daeSBarry Smith     Removes all zeros but one from .0000
4035c6c1daeSBarry Smith */
4049371c9d4SSatish Balay PetscErrorCode PetscStripAllZeros(char *buf) {
4055c6c1daeSBarry Smith   size_t i, n;
4065c6c1daeSBarry Smith 
4075c6c1daeSBarry Smith   PetscFunctionBegin;
4089566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4095c6c1daeSBarry Smith   if (buf[0] != '.') PetscFunctionReturn(0);
4105c6c1daeSBarry Smith   for (i = 1; i < n; i++) {
4115c6c1daeSBarry Smith     if (buf[i] != '0') PetscFunctionReturn(0);
4125c6c1daeSBarry Smith   }
4135c6c1daeSBarry Smith   buf[0] = '0';
4145c6c1daeSBarry Smith   buf[1] = 0;
4155c6c1daeSBarry Smith   PetscFunctionReturn(0);
4165c6c1daeSBarry Smith }
4175c6c1daeSBarry Smith 
4185c6c1daeSBarry Smith /*
4195c6c1daeSBarry Smith     Removes trailing zeros
4205c6c1daeSBarry Smith */
4219371c9d4SSatish Balay PetscErrorCode PetscStripTrailingZeros(char *buf) {
4225c6c1daeSBarry Smith   char  *found;
4235c6c1daeSBarry Smith   size_t i, n, m = PETSC_MAX_INT;
4245c6c1daeSBarry Smith 
4255c6c1daeSBarry Smith   PetscFunctionBegin;
4265c6c1daeSBarry Smith   /* if there is an e in string DO NOT strip trailing zeros */
4279566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(buf, 'e', &found));
4285c6c1daeSBarry Smith   if (found) PetscFunctionReturn(0);
4295c6c1daeSBarry Smith 
4309566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4315c6c1daeSBarry Smith   /* locate decimal point */
4325c6c1daeSBarry Smith   for (i = 0; i < n; i++) {
4339371c9d4SSatish Balay     if (buf[i] == '.') {
4349371c9d4SSatish Balay       m = i;
4359371c9d4SSatish Balay       break;
4369371c9d4SSatish Balay     }
4375c6c1daeSBarry Smith   }
4385c6c1daeSBarry Smith   /* if not decimal point then no zeros to remove */
4395c6c1daeSBarry Smith   if (m == PETSC_MAX_INT) PetscFunctionReturn(0);
4405c6c1daeSBarry Smith   /* start at right end of string removing 0s */
4415c6c1daeSBarry Smith   for (i = n - 1; i > m; i++) {
4425c6c1daeSBarry Smith     if (buf[i] != '0') PetscFunctionReturn(0);
4435c6c1daeSBarry Smith     buf[i] = 0;
4445c6c1daeSBarry Smith   }
4455c6c1daeSBarry Smith   PetscFunctionReturn(0);
4465c6c1daeSBarry Smith }
4475c6c1daeSBarry Smith 
4485c6c1daeSBarry Smith /*
4495c6c1daeSBarry Smith     Removes leading 0 from 0.22 or -0.22
4505c6c1daeSBarry Smith */
4519371c9d4SSatish Balay PetscErrorCode PetscStripInitialZero(char *buf) {
4525c6c1daeSBarry Smith   size_t i, n;
4535c6c1daeSBarry Smith 
4545c6c1daeSBarry Smith   PetscFunctionBegin;
4559566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4565c6c1daeSBarry Smith   if (buf[0] == '0') {
457a297a907SKarl Rupp     for (i = 0; i < n; i++) buf[i] = buf[i + 1];
4585c6c1daeSBarry Smith   } else if (buf[0] == '-' && buf[1] == '0') {
459a297a907SKarl Rupp     for (i = 1; i < n; i++) buf[i] = buf[i + 1];
4605c6c1daeSBarry Smith   }
4615c6c1daeSBarry Smith   PetscFunctionReturn(0);
4625c6c1daeSBarry Smith }
4635c6c1daeSBarry Smith 
4645c6c1daeSBarry Smith /*
4655c6c1daeSBarry Smith      Removes the extraneous zeros in numbers like 1.10000e6
4665c6c1daeSBarry Smith */
4679371c9d4SSatish Balay PetscErrorCode PetscStripZeros(char *buf) {
4685c6c1daeSBarry Smith   size_t i, j, n;
4695c6c1daeSBarry Smith 
4705c6c1daeSBarry Smith   PetscFunctionBegin;
4719566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4725c6c1daeSBarry Smith   if (n < 5) PetscFunctionReturn(0);
4735c6c1daeSBarry Smith   for (i = 1; i < n - 1; i++) {
4745c6c1daeSBarry Smith     if (buf[i] == 'e' && buf[i - 1] == '0') {
4755c6c1daeSBarry Smith       for (j = i; j < n + 1; j++) buf[j - 1] = buf[j];
4769566063dSJacob Faibussowitsch       PetscCall(PetscStripZeros(buf));
4775c6c1daeSBarry Smith       PetscFunctionReturn(0);
4785c6c1daeSBarry Smith     }
4795c6c1daeSBarry Smith   }
4805c6c1daeSBarry Smith   PetscFunctionReturn(0);
4815c6c1daeSBarry Smith }
4825c6c1daeSBarry Smith 
4835c6c1daeSBarry Smith /*
4845c6c1daeSBarry Smith       Removes the plus in something like 1.1e+2 or 1.1e+02
4855c6c1daeSBarry Smith */
4869371c9d4SSatish Balay PetscErrorCode PetscStripZerosPlus(char *buf) {
4875c6c1daeSBarry Smith   size_t i, j, n;
4885c6c1daeSBarry Smith 
4895c6c1daeSBarry Smith   PetscFunctionBegin;
4909566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4915c6c1daeSBarry Smith   if (n < 5) PetscFunctionReturn(0);
4925c6c1daeSBarry Smith   for (i = 1; i < n - 2; i++) {
4935c6c1daeSBarry Smith     if (buf[i] == '+') {
4945c6c1daeSBarry Smith       if (buf[i + 1] == '0') {
4955c6c1daeSBarry Smith         for (j = i + 1; j < n; j++) buf[j - 1] = buf[j + 1];
4965c6c1daeSBarry Smith         PetscFunctionReturn(0);
4975c6c1daeSBarry Smith       } else {
4985c6c1daeSBarry Smith         for (j = i + 1; j < n + 1; j++) buf[j - 1] = buf[j];
4995c6c1daeSBarry Smith         PetscFunctionReturn(0);
5005c6c1daeSBarry Smith       }
5015c6c1daeSBarry Smith     } else if (buf[i] == '-') {
5025c6c1daeSBarry Smith       if (buf[i + 1] == '0') {
5035c6c1daeSBarry Smith         for (j = i + 1; j < n; j++) buf[j] = buf[j + 1];
5045c6c1daeSBarry Smith         PetscFunctionReturn(0);
5055c6c1daeSBarry Smith       }
5065c6c1daeSBarry Smith     }
5075c6c1daeSBarry Smith   }
5085c6c1daeSBarry Smith   PetscFunctionReturn(0);
5095c6c1daeSBarry Smith }
510