xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision 2fe279fdf3e687a416e4eadb7d3c7a82d60442c6)
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 
9c3339decSBarry Smith    Collective
105c6c1daeSBarry Smith 
11*2fe279fdSBarry Smith    Input Parameter:
12811af0c4SBarry 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 
17811af0c4SBarry Smith    Note:
18811af0c4SBarry Smith    The MPI communicator that owns the underlying draw object owns the `PetscDrawAxis` object, but calls to set `PetscDrawAxis` options are
19811af0c4SBarry 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 @*/
27d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisCreate(PetscDraw draw, PetscDrawAxis *axis)
28d71ae5a4SJacob Faibussowitsch {
29e118a51fSLisandro Dalcin   PetscDrawAxis ad;
305c6c1daeSBarry Smith 
315c6c1daeSBarry Smith   PetscFunctionBegin;
325c6c1daeSBarry Smith   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
335c6c1daeSBarry Smith   PetscValidPointer(axis, 2);
34e118a51fSLisandro Dalcin 
359566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(ad, PETSC_DRAWAXIS_CLASSID, "DrawAxis", "Draw Axis", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawAxisDestroy, NULL));
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;
523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
535c6c1daeSBarry Smith }
545c6c1daeSBarry Smith 
555c6c1daeSBarry Smith /*@
565c6c1daeSBarry Smith     PetscDrawAxisDestroy - Frees the space used by an axis structure.
575c6c1daeSBarry Smith 
58c3339decSBarry Smith     Collective
595c6c1daeSBarry Smith 
60*2fe279fdSBarry Smith     Input Parameter:
615c6c1daeSBarry Smith .   axis - the axis context
625c6c1daeSBarry Smith 
635c6c1daeSBarry Smith     Level: advanced
645c6c1daeSBarry Smith 
65811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`
665c6c1daeSBarry Smith @*/
67d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis)
68d71ae5a4SJacob Faibussowitsch {
695c6c1daeSBarry Smith   PetscFunctionBegin;
703ba16761SJacob Faibussowitsch   if (!*axis) PetscFunctionReturn(PETSC_SUCCESS);
71e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(*axis, PETSC_DRAWAXIS_CLASSID, 1);
729371c9d4SSatish Balay   if (--((PetscObject)(*axis))->refct > 0) {
739371c9d4SSatish Balay     *axis = NULL;
743ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
759371c9d4SSatish Balay   }
765c6c1daeSBarry Smith 
779566063dSJacob Faibussowitsch   PetscCall(PetscFree((*axis)->toplabel));
789566063dSJacob Faibussowitsch   PetscCall(PetscFree((*axis)->xlabel));
799566063dSJacob Faibussowitsch   PetscCall(PetscFree((*axis)->ylabel));
809566063dSJacob Faibussowitsch   PetscCall(PetscDrawDestroy(&(*axis)->win));
819566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(axis));
823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
835c6c1daeSBarry Smith }
845c6c1daeSBarry Smith 
855c6c1daeSBarry Smith /*@
865c6c1daeSBarry Smith     PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
875c6c1daeSBarry Smith                          tickmarks, and text.
885c6c1daeSBarry Smith 
89c3339decSBarry Smith     Logically Collective
905c6c1daeSBarry Smith 
915c6c1daeSBarry Smith     Input Parameters:
925c6c1daeSBarry Smith +   axis - the axis
935c6c1daeSBarry Smith .   ac - the color of the axis lines
945c6c1daeSBarry Smith .   tc - the color of the tick marks
955c6c1daeSBarry Smith -   cc - the color of the text strings
965c6c1daeSBarry Smith 
975c6c1daeSBarry Smith     Level: advanced
985c6c1daeSBarry Smith 
99811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
1005c6c1daeSBarry Smith @*/
101d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis, int ac, int tc, int cc)
102d71ae5a4SJacob Faibussowitsch {
1035c6c1daeSBarry Smith   PetscFunctionBegin;
104e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1055b399a63SLisandro Dalcin   PetscValidLogicalCollectiveInt(axis, ac, 2);
1065b399a63SLisandro Dalcin   PetscValidLogicalCollectiveInt(axis, tc, 3);
1075b399a63SLisandro Dalcin   PetscValidLogicalCollectiveInt(axis, cc, 4);
1089371c9d4SSatish Balay   axis->ac = ac;
1099371c9d4SSatish Balay   axis->tc = tc;
1109371c9d4SSatish Balay   axis->cc = cc;
1113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1125c6c1daeSBarry Smith }
1135c6c1daeSBarry Smith 
1145c6c1daeSBarry Smith /*@C
1155c6c1daeSBarry Smith     PetscDrawAxisSetLabels -  Sets the x and y axis labels.
1165c6c1daeSBarry Smith 
117c3339decSBarry Smith     Logically Collective
1185c6c1daeSBarry Smith 
1195c6c1daeSBarry Smith     Input Parameters:
1205c6c1daeSBarry Smith +   axis - the axis
1215c6c1daeSBarry Smith .   top - the label at the top of the image
1225c6c1daeSBarry Smith -   xlabel,ylabel - the labes for the x and y axis
1235c6c1daeSBarry Smith 
124*2fe279fdSBarry Smith     Level: advanced
125*2fe279fdSBarry Smith 
12695452b02SPatrick Sanan     Notes:
127811af0c4SBarry Smith     Must be called before `PetscDrawAxisDraw()` or `PetscDrawLGDraw()`
128811af0c4SBarry Smith 
1295c6c1daeSBarry Smith     There should be no newlines in the arguments
1305c6c1daeSBarry Smith 
131811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
1325c6c1daeSBarry Smith @*/
133d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis, const char top[], const char xlabel[], const char ylabel[])
134d71ae5a4SJacob Faibussowitsch {
1355c6c1daeSBarry Smith   PetscFunctionBegin;
136e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1379566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->xlabel));
1389566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->ylabel));
1399566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->toplabel));
1409566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(xlabel, &axis->xlabel));
1419566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ylabel, &axis->ylabel));
1429566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(top, &axis->toplabel));
1433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1445c6c1daeSBarry Smith }
1455c6c1daeSBarry Smith 
14671917b75SLisandro Dalcin /*@
14771917b75SLisandro Dalcin     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
14871917b75SLisandro Dalcin 
149c3339decSBarry Smith     Logically Collective
15071917b75SLisandro Dalcin 
15171917b75SLisandro Dalcin     Input Parameters:
15271917b75SLisandro Dalcin +   axis - the axis
15371917b75SLisandro Dalcin .   xmin,xmax - limits in x
15471917b75SLisandro Dalcin -   ymin,ymax - limits in y
15571917b75SLisandro Dalcin 
156811af0c4SBarry Smith     Options Database Key:
15771917b75SLisandro Dalcin .   -drawaxis_hold - hold the initial set of axis limits for future plotting
15871917b75SLisandro Dalcin 
15971917b75SLisandro Dalcin     Level: advanced
16071917b75SLisandro Dalcin 
161db781477SPatrick Sanan .seealso: `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
16271917b75SLisandro Dalcin @*/
163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax)
164d71ae5a4SJacob Faibussowitsch {
16571917b75SLisandro Dalcin   PetscFunctionBegin;
16671917b75SLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1673ba16761SJacob Faibussowitsch   if (axis->hold) PetscFunctionReturn(PETSC_SUCCESS);
16871917b75SLisandro Dalcin   axis->xlow  = xmin;
16971917b75SLisandro Dalcin   axis->xhigh = xmax;
17071917b75SLisandro Dalcin   axis->ylow  = ymin;
17171917b75SLisandro Dalcin   axis->yhigh = ymax;
1729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)axis)->options, ((PetscObject)axis)->prefix, "-drawaxis_hold", &axis->hold));
1733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17471917b75SLisandro Dalcin }
17571917b75SLisandro Dalcin 
17671917b75SLisandro Dalcin /*@
17771917b75SLisandro Dalcin     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
17871917b75SLisandro Dalcin 
17971917b75SLisandro Dalcin     Not Collective
18071917b75SLisandro Dalcin 
18171917b75SLisandro Dalcin     Input Parameters:
18271917b75SLisandro Dalcin +   axis - the axis
18371917b75SLisandro Dalcin .   xmin,xmax - limits in x
18471917b75SLisandro Dalcin -   ymin,ymax - limits in y
18571917b75SLisandro Dalcin 
18671917b75SLisandro Dalcin     Level: advanced
18771917b75SLisandro Dalcin 
188db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
18971917b75SLisandro Dalcin @*/
190d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis, PetscReal *xmin, PetscReal *xmax, PetscReal *ymin, PetscReal *ymax)
191d71ae5a4SJacob Faibussowitsch {
19271917b75SLisandro Dalcin   PetscFunctionBegin;
19371917b75SLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
194bb046f40SHong Zhang   if (xmin) *xmin = axis->xlow;
195bb046f40SHong Zhang   if (xmax) *xmax = axis->xhigh;
196bb046f40SHong Zhang   if (ymin) *ymin = axis->ylow;
197bb046f40SHong Zhang   if (ymax) *ymax = axis->yhigh;
1983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19971917b75SLisandro Dalcin }
20071917b75SLisandro Dalcin 
2015c6c1daeSBarry Smith /*@
2025c6c1daeSBarry Smith     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
2035c6c1daeSBarry Smith         again
2045c6c1daeSBarry Smith 
205c3339decSBarry Smith     Logically Collective
2065c6c1daeSBarry Smith 
2075c6c1daeSBarry Smith     Input Parameters:
2085c6c1daeSBarry Smith +   axis - the axis
209811af0c4SBarry Smith -   hold - `PETSC_TRUE` - hold current limits, `PETSC_FALSE` allow limits to be changed
2105c6c1daeSBarry Smith 
2115c6c1daeSBarry Smith     Level: advanced
2125c6c1daeSBarry Smith 
213811af0c4SBarry Smith     Note:
214811af0c4SBarry Smith         Once this has been called with `PETSC_TRUE` the limits will not change if you call
215811af0c4SBarry Smith      `PetscDrawAxisSetLimits()` until you call this with `PETSC_FALSE`
2165c6c1daeSBarry Smith 
217db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
2185c6c1daeSBarry Smith @*/
219d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis, PetscBool hold)
220d71ae5a4SJacob Faibussowitsch {
2215c6c1daeSBarry Smith   PetscFunctionBegin;
222e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
2235b399a63SLisandro Dalcin   PetscValidLogicalCollectiveBool(axis, hold, 2);
2245c6c1daeSBarry Smith   axis->hold = hold;
2253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2265c6c1daeSBarry Smith }
2275c6c1daeSBarry Smith 
2285c6c1daeSBarry Smith /*@
229811af0c4SBarry Smith     PetscDrawAxisDraw - draws an axis.
2305c6c1daeSBarry Smith 
231c3339decSBarry Smith     Collective
2325c6c1daeSBarry Smith 
2335c6c1daeSBarry Smith     Input Parameter:
234811af0c4SBarry Smith .   axis - `PetscDrawAxis` structure
2355c6c1daeSBarry Smith 
2365c6c1daeSBarry Smith     Level: advanced
2375c6c1daeSBarry Smith 
2385c6c1daeSBarry Smith     Note:
2395c6c1daeSBarry Smith     This draws the actual axis.  The limits etc have already been set.
2405c6c1daeSBarry Smith     By picking special routines for the ticks and labels, special
2415c6c1daeSBarry Smith     effects may be generated.  These routines are part of the Axis
2425c6c1daeSBarry Smith     structure (axis).
2430afdd333SBarry Smith 
244db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
2455c6c1daeSBarry Smith @*/
246d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis)
247d71ae5a4SJacob Faibussowitsch {
248e118a51fSLisandro Dalcin   int         i, ntick, numx, numy, ac, tc, cc;
249e118a51fSLisandro Dalcin   PetscMPIInt rank;
25071917b75SLisandro Dalcin   size_t      len, ytlen = 0;
251999739cfSJacob Faibussowitsch   PetscReal   coors[4], tickloc[PETSC_DRAW_AXIS_MAX_SEGMENTS], sep, tw, th;
25271917b75SLisandro Dalcin   PetscReal   xl, xr, yl, yr, dxl = 0, dyl = 0, dxr = 0, dyr = 0;
2535c6c1daeSBarry Smith   char       *p;
254e118a51fSLisandro Dalcin   PetscDraw   draw;
255e118a51fSLisandro Dalcin   PetscBool   isnull;
2565c6c1daeSBarry Smith 
2575c6c1daeSBarry Smith   PetscFunctionBegin;
258e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
2599566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(axis->win, &isnull));
2603ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
2619566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)axis), &rank));
2625c6c1daeSBarry Smith 
2638f69470aSLisandro Dalcin   draw = axis->win;
2645b399a63SLisandro Dalcin 
2659371c9d4SSatish Balay   ac = axis->ac;
2669371c9d4SSatish Balay   tc = axis->tc;
2679371c9d4SSatish Balay   cc = axis->cc;
2689371c9d4SSatish Balay   if (axis->xlow == axis->xhigh) {
2699371c9d4SSatish Balay     axis->xlow -= .5;
2709371c9d4SSatish Balay     axis->xhigh += .5;
2719371c9d4SSatish Balay   }
2729371c9d4SSatish Balay   if (axis->ylow == axis->yhigh) {
2739371c9d4SSatish Balay     axis->ylow -= .5;
2749371c9d4SSatish Balay     axis->yhigh += .5;
2759371c9d4SSatish Balay   }
276e118a51fSLisandro Dalcin 
277d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
27871917b75SLisandro Dalcin   if (rank) goto finally;
27971917b75SLisandro Dalcin 
280da81f932SPierre Jolivet   /* get canonical string size */
2819566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, 0, 0, 1, 1));
2829566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
28371917b75SLisandro Dalcin   /* lower spacing */
28471917b75SLisandro Dalcin   if (axis->xlabelstr) dyl += 1.5 * th;
28571917b75SLisandro Dalcin   if (axis->xlabel) dyl += 1.5 * th;
28671917b75SLisandro Dalcin   /* left spacing */
28771917b75SLisandro Dalcin   if (axis->ylabelstr) dxl += 7.5 * tw;
28871917b75SLisandro Dalcin   if (axis->ylabel) dxl += 2.0 * tw;
28971917b75SLisandro Dalcin   /* right and top spacing */
29071917b75SLisandro Dalcin   if (axis->xlabelstr) dxr = 2.5 * tw;
29171917b75SLisandro Dalcin   if (axis->ylabelstr) dyr = 0.5 * th;
29271917b75SLisandro Dalcin   if (axis->toplabel) dyr = 1.5 * th;
29371917b75SLisandro Dalcin   /* extra spacing */
2949371c9d4SSatish Balay   dxl += 0.7 * tw;
2959371c9d4SSatish Balay   dxr += 0.5 * tw;
2969371c9d4SSatish Balay   dyl += 0.2 * th;
2979371c9d4SSatish Balay   dyr += 0.2 * th;
29871917b75SLisandro Dalcin   /* determine coordinates */
29971917b75SLisandro Dalcin   xl = (dxl * axis->xhigh + dxr * axis->xlow - axis->xlow) / (dxl + dxr - 1);
30071917b75SLisandro Dalcin   xr = (dxl * axis->xhigh + dxr * axis->xlow - axis->xhigh) / (dxl + dxr - 1);
30171917b75SLisandro Dalcin   yl = (dyl * axis->yhigh + dyr * axis->ylow - axis->ylow) / (dyl + dyr - 1);
30271917b75SLisandro Dalcin   yr = (dyl * axis->yhigh + dyr * axis->ylow - axis->yhigh) / (dyl + dyr - 1);
3039566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
3049566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
3055c6c1daeSBarry Smith 
30671917b75SLisandro Dalcin   /* PetscDraw the axis lines */
3079566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xhigh, axis->ylow, ac));
3089566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xlow, axis->yhigh, ac));
3099566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->yhigh, axis->xhigh, axis->yhigh, ac));
3109566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xhigh, axis->ylow, axis->xhigh, axis->yhigh, ac));
3115c6c1daeSBarry Smith 
31271917b75SLisandro Dalcin   /* PetscDraw the top label */
3135c6c1daeSBarry Smith   if (axis->toplabel) {
31471917b75SLisandro Dalcin     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->yhigh + 0.5 * th;
3159566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->toplabel));
3165c6c1daeSBarry Smith   }
3175c6c1daeSBarry Smith 
31871917b75SLisandro Dalcin   /* PetscDraw the X ticks and labels */
3195c6c1daeSBarry Smith   if (axis->xticks) {
3209371c9d4SSatish Balay     numx = (int)(.15 * (axis->xhigh - axis->xlow) / tw);
3219371c9d4SSatish Balay     numx = PetscClipInterval(numx, 2, 6);
3229566063dSJacob Faibussowitsch     PetscCall((*axis->xticks)(axis->xlow, axis->xhigh, numx, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
3235c6c1daeSBarry Smith     /* PetscDraw in tick marks */
3245c6c1daeSBarry Smith     for (i = 0; i < ntick; i++) {
3259566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, tickloc[i], axis->ylow, tickloc[i], axis->ylow + .5 * th, tc));
3269566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, tickloc[i], axis->yhigh, tickloc[i], axis->yhigh - .5 * th, tc));
3275c6c1daeSBarry Smith     }
3285c6c1daeSBarry Smith     /* label ticks */
3295c6c1daeSBarry Smith     if (axis->xlabelstr) {
33071917b75SLisandro Dalcin       for (i = 0; i < ntick; i++) {
3315c6c1daeSBarry Smith         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
3325c6c1daeSBarry Smith         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
3335c6c1daeSBarry Smith         else sep = 0.0;
3349566063dSJacob Faibussowitsch         PetscCall((*axis->xlabelstr)(tickloc[i], sep, &p));
3359566063dSJacob Faibussowitsch         PetscCall(PetscDrawStringCentered(draw, tickloc[i], axis->ylow - 1.5 * th, cc, p));
3365c6c1daeSBarry Smith       }
3375c6c1daeSBarry Smith     }
3385c6c1daeSBarry Smith   }
3395c6c1daeSBarry Smith   if (axis->xlabel) {
34071917b75SLisandro Dalcin     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->ylow - 1.5 * th;
34171917b75SLisandro Dalcin     if (axis->xlabelstr) y -= 1.5 * th;
3429566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->xlabel));
3435c6c1daeSBarry Smith   }
34471917b75SLisandro Dalcin 
34571917b75SLisandro Dalcin   /* PetscDraw the Y ticks and labels */
3465c6c1daeSBarry Smith   if (axis->yticks) {
3479371c9d4SSatish Balay     numy = (int)(.50 * (axis->yhigh - axis->ylow) / th);
3489371c9d4SSatish Balay     numy = PetscClipInterval(numy, 2, 6);
3499566063dSJacob Faibussowitsch     PetscCall((*axis->yticks)(axis->ylow, axis->yhigh, numy, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
3505c6c1daeSBarry Smith     /* PetscDraw in tick marks */
3515c6c1daeSBarry Smith     for (i = 0; i < ntick; i++) {
3529566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, axis->xlow, tickloc[i], axis->xlow + .5 * tw, tickloc[i], tc));
3539566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, axis->xhigh, tickloc[i], axis->xhigh - .5 * tw, tickloc[i], tc));
3545c6c1daeSBarry Smith     }
3555c6c1daeSBarry Smith     /* label ticks */
3565c6c1daeSBarry Smith     if (axis->ylabelstr) {
35771917b75SLisandro Dalcin       for (i = 0; i < ntick; i++) {
3585c6c1daeSBarry Smith         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
3595c6c1daeSBarry Smith         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
3605c6c1daeSBarry Smith         else sep = 0.0;
3619566063dSJacob Faibussowitsch         PetscCall((*axis->ylabelstr)(tickloc[i], sep, &p));
3629371c9d4SSatish Balay         PetscCall(PetscStrlen(p, &len));
3639371c9d4SSatish Balay         ytlen = PetscMax(ytlen, len);
3649566063dSJacob Faibussowitsch         PetscCall(PetscDrawString(draw, axis->xlow - (len + .5) * tw, tickloc[i] - .5 * th, cc, p));
3655c6c1daeSBarry Smith       }
3665c6c1daeSBarry Smith     }
3675c6c1daeSBarry Smith   }
3685c6c1daeSBarry Smith   if (axis->ylabel) {
36971917b75SLisandro Dalcin     PetscReal x = axis->xlow - 2.0 * tw, y = (axis->ylow + axis->yhigh) / 2;
37071917b75SLisandro Dalcin     if (axis->ylabelstr) x -= (ytlen + .5) * tw;
3719566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(axis->ylabel, &len));
3729566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringVertical(draw, x, y + len * th / 2, cc, axis->ylabel));
3735c6c1daeSBarry Smith   }
3745b399a63SLisandro Dalcin 
3759566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &coors[0], &coors[1], &coors[2], &coors[3]));
3765b399a63SLisandro Dalcin finally:
377d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
3789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(coors, 4, MPIU_REAL, 0, PetscObjectComm((PetscObject)draw)));
3799566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, coors[0], coors[1], coors[2], coors[3]));
3803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3815c6c1daeSBarry Smith }
3825c6c1daeSBarry Smith 
38336c9bc0dSBarry Smith /*
38436c9bc0dSBarry Smith     Removes all zeros but one from .0000
38536c9bc0dSBarry Smith */
386d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripe0(char *buf)
387d71ae5a4SJacob Faibussowitsch {
38836c9bc0dSBarry Smith   size_t    n;
38936c9bc0dSBarry Smith   PetscBool flg;
390bbcf679cSJacob Faibussowitsch   char     *str = NULL;
39136c9bc0dSBarry Smith 
39236c9bc0dSBarry Smith   PetscFunctionBegin;
3939566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
3949566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(buf, "e00", &flg));
395a297a907SKarl Rupp   if (flg) buf[n - 3] = 0;
3969566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buf, "e0", &str));
39736c9bc0dSBarry Smith   if (str) {
39836c9bc0dSBarry Smith     buf[n - 2] = buf[n - 1];
39936c9bc0dSBarry Smith     buf[n - 1] = 0;
40036c9bc0dSBarry Smith   }
4019566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buf, "e-0", &str));
40236c9bc0dSBarry Smith   if (str) {
40336c9bc0dSBarry Smith     buf[n - 2] = buf[n - 1];
40436c9bc0dSBarry Smith     buf[n - 1] = 0;
40536c9bc0dSBarry Smith   }
4063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40736c9bc0dSBarry Smith }
40836c9bc0dSBarry Smith 
4095c6c1daeSBarry Smith /*
4105c6c1daeSBarry Smith     Removes all zeros but one from .0000
4115c6c1daeSBarry Smith */
412d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripAllZeros(char *buf)
413d71ae5a4SJacob Faibussowitsch {
4145c6c1daeSBarry Smith   size_t i, n;
4155c6c1daeSBarry Smith 
4165c6c1daeSBarry Smith   PetscFunctionBegin;
4179566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4183ba16761SJacob Faibussowitsch   if (buf[0] != '.') PetscFunctionReturn(PETSC_SUCCESS);
4195c6c1daeSBarry Smith   for (i = 1; i < n; i++) {
4203ba16761SJacob Faibussowitsch     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
4215c6c1daeSBarry Smith   }
4225c6c1daeSBarry Smith   buf[0] = '0';
4235c6c1daeSBarry Smith   buf[1] = 0;
4243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4255c6c1daeSBarry Smith }
4265c6c1daeSBarry Smith 
4275c6c1daeSBarry Smith /*
4285c6c1daeSBarry Smith     Removes trailing zeros
4295c6c1daeSBarry Smith */
4304279555eSSatish Balay #if (PETSC_SIZEOF_SIZE_T == 8)
4314279555eSSatish Balay   #define MAX_SIZE_T PETSC_INT64_MAX
4324279555eSSatish Balay #else
4334279555eSSatish Balay   #define MAX_SIZE_T INT_MAX
4344279555eSSatish Balay #endif
435d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripTrailingZeros(char *buf)
436d71ae5a4SJacob Faibussowitsch {
437bbcf679cSJacob Faibussowitsch   char  *found = NULL;
4384279555eSSatish Balay   size_t i, n, m = MAX_SIZE_T;
4395c6c1daeSBarry Smith 
4405c6c1daeSBarry Smith   PetscFunctionBegin;
4415c6c1daeSBarry Smith   /* if there is an e in string DO NOT strip trailing zeros */
4429566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(buf, 'e', &found));
4433ba16761SJacob Faibussowitsch   if (found) PetscFunctionReturn(PETSC_SUCCESS);
4445c6c1daeSBarry Smith 
4459566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4465c6c1daeSBarry Smith   /* locate decimal point */
4475c6c1daeSBarry Smith   for (i = 0; i < n; i++) {
4489371c9d4SSatish Balay     if (buf[i] == '.') {
4499371c9d4SSatish Balay       m = i;
4509371c9d4SSatish Balay       break;
4519371c9d4SSatish Balay     }
4525c6c1daeSBarry Smith   }
4535c6c1daeSBarry Smith   /* if not decimal point then no zeros to remove */
4544279555eSSatish Balay   if (m == MAX_SIZE_T) PetscFunctionReturn(PETSC_SUCCESS);
4555c6c1daeSBarry Smith   /* start at right end of string removing 0s */
4565c6c1daeSBarry Smith   for (i = n - 1; i > m; i++) {
4573ba16761SJacob Faibussowitsch     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
4585c6c1daeSBarry Smith     buf[i] = 0;
4595c6c1daeSBarry Smith   }
4603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4615c6c1daeSBarry Smith }
4625c6c1daeSBarry Smith 
4635c6c1daeSBarry Smith /*
4645c6c1daeSBarry Smith     Removes leading 0 from 0.22 or -0.22
4655c6c1daeSBarry Smith */
466d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripInitialZero(char *buf)
467d71ae5a4SJacob Faibussowitsch {
4685c6c1daeSBarry Smith   size_t i, n;
4695c6c1daeSBarry Smith 
4705c6c1daeSBarry Smith   PetscFunctionBegin;
4719566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4725c6c1daeSBarry Smith   if (buf[0] == '0') {
473a297a907SKarl Rupp     for (i = 0; i < n; i++) buf[i] = buf[i + 1];
4745c6c1daeSBarry Smith   } else if (buf[0] == '-' && buf[1] == '0') {
475a297a907SKarl Rupp     for (i = 1; i < n; i++) buf[i] = buf[i + 1];
4765c6c1daeSBarry Smith   }
4773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4785c6c1daeSBarry Smith }
4795c6c1daeSBarry Smith 
4805c6c1daeSBarry Smith /*
4815c6c1daeSBarry Smith      Removes the extraneous zeros in numbers like 1.10000e6
4825c6c1daeSBarry Smith */
483d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripZeros(char *buf)
484d71ae5a4SJacob Faibussowitsch {
4855c6c1daeSBarry Smith   size_t i, j, n;
4865c6c1daeSBarry Smith 
4875c6c1daeSBarry Smith   PetscFunctionBegin;
4889566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4893ba16761SJacob Faibussowitsch   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
4905c6c1daeSBarry Smith   for (i = 1; i < n - 1; i++) {
4915c6c1daeSBarry Smith     if (buf[i] == 'e' && buf[i - 1] == '0') {
4925c6c1daeSBarry Smith       for (j = i; j < n + 1; j++) buf[j - 1] = buf[j];
4939566063dSJacob Faibussowitsch       PetscCall(PetscStripZeros(buf));
4943ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
4955c6c1daeSBarry Smith     }
4965c6c1daeSBarry Smith   }
4973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4985c6c1daeSBarry Smith }
4995c6c1daeSBarry Smith 
5005c6c1daeSBarry Smith /*
5015c6c1daeSBarry Smith       Removes the plus in something like 1.1e+2 or 1.1e+02
5025c6c1daeSBarry Smith */
503d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripZerosPlus(char *buf)
504d71ae5a4SJacob Faibussowitsch {
5055c6c1daeSBarry Smith   size_t i, j, n;
5065c6c1daeSBarry Smith 
5075c6c1daeSBarry Smith   PetscFunctionBegin;
5089566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
5093ba16761SJacob Faibussowitsch   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
5105c6c1daeSBarry Smith   for (i = 1; i < n - 2; i++) {
5115c6c1daeSBarry Smith     if (buf[i] == '+') {
5125c6c1daeSBarry Smith       if (buf[i + 1] == '0') {
5135c6c1daeSBarry Smith         for (j = i + 1; j < n; j++) buf[j - 1] = buf[j + 1];
5143ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
5155c6c1daeSBarry Smith       } else {
5165c6c1daeSBarry Smith         for (j = i + 1; j < n + 1; j++) buf[j - 1] = buf[j];
5173ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
5185c6c1daeSBarry Smith       }
5195c6c1daeSBarry Smith     } else if (buf[i] == '-') {
5205c6c1daeSBarry Smith       if (buf[i + 1] == '0') {
5215c6c1daeSBarry Smith         for (j = i + 1; j < n; j++) buf[j] = buf[j + 1];
5223ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
5235c6c1daeSBarry Smith       }
5245c6c1daeSBarry Smith     }
5255c6c1daeSBarry Smith   }
5263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5275c6c1daeSBarry Smith }
528