xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
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 
112fe279fdSBarry Smith   Input Parameter:
1215229ffcSPierre Jolivet . draw - `PetscDraw` object where axis 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);
334f572ea9SToby Isaac   PetscAssertPointer(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 
602fe279fdSBarry 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);
72*f4f49eeaSPierre Jolivet   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
12210450e9eSJacob Faibussowitsch . xlabel - the x axis label
12310450e9eSJacob Faibussowitsch - ylabel - the y axis label
1245c6c1daeSBarry Smith 
1252fe279fdSBarry Smith   Level: advanced
1262fe279fdSBarry Smith 
12795452b02SPatrick Sanan   Notes:
128811af0c4SBarry Smith   Must be called before `PetscDrawAxisDraw()` or `PetscDrawLGDraw()`
129811af0c4SBarry Smith 
1305c6c1daeSBarry Smith   There should be no newlines in the arguments
1315c6c1daeSBarry Smith 
132811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
1335c6c1daeSBarry Smith @*/
134d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis, const char top[], const char xlabel[], const char ylabel[])
135d71ae5a4SJacob Faibussowitsch {
1365c6c1daeSBarry Smith   PetscFunctionBegin;
137e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1389566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->xlabel));
1399566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->ylabel));
1409566063dSJacob Faibussowitsch   PetscCall(PetscFree(axis->toplabel));
1419566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(xlabel, &axis->xlabel));
1429566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ylabel, &axis->ylabel));
1439566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(top, &axis->toplabel));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1455c6c1daeSBarry Smith }
1465c6c1daeSBarry Smith 
14771917b75SLisandro Dalcin /*@
14871917b75SLisandro Dalcin   PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
14971917b75SLisandro Dalcin 
150c3339decSBarry Smith   Logically Collective
15171917b75SLisandro Dalcin 
15271917b75SLisandro Dalcin   Input Parameters:
15371917b75SLisandro Dalcin + axis - the axis
15410450e9eSJacob Faibussowitsch . xmin - the lower x limit
15510450e9eSJacob Faibussowitsch . xmax - the upper x limit
15610450e9eSJacob Faibussowitsch . ymin - the lower y limit
15710450e9eSJacob Faibussowitsch - ymax - the upper y limit
15871917b75SLisandro Dalcin 
159811af0c4SBarry Smith   Options Database Key:
16071917b75SLisandro Dalcin . -drawaxis_hold - hold the initial set of axis limits for future plotting
16171917b75SLisandro Dalcin 
16271917b75SLisandro Dalcin   Level: advanced
16371917b75SLisandro Dalcin 
164db781477SPatrick Sanan .seealso: `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
16571917b75SLisandro Dalcin @*/
166d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax)
167d71ae5a4SJacob Faibussowitsch {
16871917b75SLisandro Dalcin   PetscFunctionBegin;
16971917b75SLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
1703ba16761SJacob Faibussowitsch   if (axis->hold) PetscFunctionReturn(PETSC_SUCCESS);
17171917b75SLisandro Dalcin   axis->xlow  = xmin;
17271917b75SLisandro Dalcin   axis->xhigh = xmax;
17371917b75SLisandro Dalcin   axis->ylow  = ymin;
17471917b75SLisandro Dalcin   axis->yhigh = ymax;
1759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)axis)->options, ((PetscObject)axis)->prefix, "-drawaxis_hold", &axis->hold));
1763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17771917b75SLisandro Dalcin }
17871917b75SLisandro Dalcin 
17971917b75SLisandro Dalcin /*@
18071917b75SLisandro Dalcin   PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
18171917b75SLisandro Dalcin 
18271917b75SLisandro Dalcin   Not Collective
18371917b75SLisandro Dalcin 
18471917b75SLisandro Dalcin   Input Parameters:
18571917b75SLisandro Dalcin + axis - the axis
18610450e9eSJacob Faibussowitsch . xmin - the lower x limit
18710450e9eSJacob Faibussowitsch . xmax - the upper x limit
18810450e9eSJacob Faibussowitsch . ymin - the lower y limit
18910450e9eSJacob Faibussowitsch - ymax - the upper y limit
19071917b75SLisandro Dalcin 
19171917b75SLisandro Dalcin   Level: advanced
19271917b75SLisandro Dalcin 
193db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
19471917b75SLisandro Dalcin @*/
195d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis, PetscReal *xmin, PetscReal *xmax, PetscReal *ymin, PetscReal *ymax)
196d71ae5a4SJacob Faibussowitsch {
19771917b75SLisandro Dalcin   PetscFunctionBegin;
19871917b75SLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
199bb046f40SHong Zhang   if (xmin) *xmin = axis->xlow;
200bb046f40SHong Zhang   if (xmax) *xmax = axis->xhigh;
201bb046f40SHong Zhang   if (ymin) *ymin = axis->ylow;
202bb046f40SHong Zhang   if (ymax) *ymax = axis->yhigh;
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20471917b75SLisandro Dalcin }
20571917b75SLisandro Dalcin 
2065c6c1daeSBarry Smith /*@
2075c6c1daeSBarry Smith   PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
2085c6c1daeSBarry Smith   again
2095c6c1daeSBarry Smith 
210c3339decSBarry Smith   Logically Collective
2115c6c1daeSBarry Smith 
2125c6c1daeSBarry Smith   Input Parameters:
2135c6c1daeSBarry Smith + axis - the axis
214811af0c4SBarry Smith - hold - `PETSC_TRUE` - hold current limits, `PETSC_FALSE` allow limits to be changed
2155c6c1daeSBarry Smith 
2165c6c1daeSBarry Smith   Level: advanced
2175c6c1daeSBarry Smith 
218811af0c4SBarry Smith   Note:
219811af0c4SBarry Smith   Once this has been called with `PETSC_TRUE` the limits will not change if you call
220811af0c4SBarry Smith   `PetscDrawAxisSetLimits()` until you call this with `PETSC_FALSE`
2215c6c1daeSBarry Smith 
222db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
2235c6c1daeSBarry Smith @*/
224d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis, PetscBool hold)
225d71ae5a4SJacob Faibussowitsch {
2265c6c1daeSBarry Smith   PetscFunctionBegin;
227e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
2285b399a63SLisandro Dalcin   PetscValidLogicalCollectiveBool(axis, hold, 2);
2295c6c1daeSBarry Smith   axis->hold = hold;
2303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2315c6c1daeSBarry Smith }
2325c6c1daeSBarry Smith 
2335c6c1daeSBarry Smith /*@
234811af0c4SBarry Smith   PetscDrawAxisDraw - draws an axis.
2355c6c1daeSBarry Smith 
236c3339decSBarry Smith   Collective
2375c6c1daeSBarry Smith 
2385c6c1daeSBarry Smith   Input Parameter:
239811af0c4SBarry Smith . axis - `PetscDrawAxis` structure
2405c6c1daeSBarry Smith 
2415c6c1daeSBarry Smith   Level: advanced
2425c6c1daeSBarry Smith 
2435c6c1daeSBarry Smith   Note:
2445c6c1daeSBarry Smith   This draws the actual axis.  The limits etc have already been set.
2455c6c1daeSBarry Smith   By picking special routines for the ticks and labels, special
2465c6c1daeSBarry Smith   effects may be generated.  These routines are part of the Axis
2475c6c1daeSBarry Smith   structure (axis).
2480afdd333SBarry Smith 
249db781477SPatrick Sanan .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
2505c6c1daeSBarry Smith @*/
251d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis)
252d71ae5a4SJacob Faibussowitsch {
253e118a51fSLisandro Dalcin   int         i, ntick, numx, numy, ac, tc, cc;
254e118a51fSLisandro Dalcin   PetscMPIInt rank;
25571917b75SLisandro Dalcin   size_t      len, ytlen = 0;
256999739cfSJacob Faibussowitsch   PetscReal   coors[4], tickloc[PETSC_DRAW_AXIS_MAX_SEGMENTS], sep, tw, th;
25771917b75SLisandro Dalcin   PetscReal   xl, xr, yl, yr, dxl = 0, dyl = 0, dxr = 0, dyr = 0;
2585c6c1daeSBarry Smith   char       *p;
259e118a51fSLisandro Dalcin   PetscDraw   draw;
260e118a51fSLisandro Dalcin   PetscBool   isnull;
2615c6c1daeSBarry Smith 
2625c6c1daeSBarry Smith   PetscFunctionBegin;
263e118a51fSLisandro Dalcin   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
2649566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(axis->win, &isnull));
2653ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
2669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)axis), &rank));
2675c6c1daeSBarry Smith 
2688f69470aSLisandro Dalcin   draw = axis->win;
2695b399a63SLisandro Dalcin 
2709371c9d4SSatish Balay   ac = axis->ac;
2719371c9d4SSatish Balay   tc = axis->tc;
2729371c9d4SSatish Balay   cc = axis->cc;
2739371c9d4SSatish Balay   if (axis->xlow == axis->xhigh) {
2749371c9d4SSatish Balay     axis->xlow -= .5;
2759371c9d4SSatish Balay     axis->xhigh += .5;
2769371c9d4SSatish Balay   }
2779371c9d4SSatish Balay   if (axis->ylow == axis->yhigh) {
2789371c9d4SSatish Balay     axis->ylow -= .5;
2799371c9d4SSatish Balay     axis->yhigh += .5;
2809371c9d4SSatish Balay   }
281e118a51fSLisandro Dalcin 
282d0609cedSBarry Smith   PetscDrawCollectiveBegin(draw);
28371917b75SLisandro Dalcin   if (rank) goto finally;
28471917b75SLisandro Dalcin 
285da81f932SPierre Jolivet   /* get canonical string size */
2869566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, 0, 0, 1, 1));
2879566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
28871917b75SLisandro Dalcin   /* lower spacing */
28971917b75SLisandro Dalcin   if (axis->xlabelstr) dyl += 1.5 * th;
29071917b75SLisandro Dalcin   if (axis->xlabel) dyl += 1.5 * th;
29171917b75SLisandro Dalcin   /* left spacing */
29271917b75SLisandro Dalcin   if (axis->ylabelstr) dxl += 7.5 * tw;
29371917b75SLisandro Dalcin   if (axis->ylabel) dxl += 2.0 * tw;
29471917b75SLisandro Dalcin   /* right and top spacing */
29571917b75SLisandro Dalcin   if (axis->xlabelstr) dxr = 2.5 * tw;
29671917b75SLisandro Dalcin   if (axis->ylabelstr) dyr = 0.5 * th;
29771917b75SLisandro Dalcin   if (axis->toplabel) dyr = 1.5 * th;
29871917b75SLisandro Dalcin   /* extra spacing */
2999371c9d4SSatish Balay   dxl += 0.7 * tw;
3009371c9d4SSatish Balay   dxr += 0.5 * tw;
3019371c9d4SSatish Balay   dyl += 0.2 * th;
3029371c9d4SSatish Balay   dyr += 0.2 * th;
30371917b75SLisandro Dalcin   /* determine coordinates */
30471917b75SLisandro Dalcin   xl = (dxl * axis->xhigh + dxr * axis->xlow - axis->xlow) / (dxl + dxr - 1);
30571917b75SLisandro Dalcin   xr = (dxl * axis->xhigh + dxr * axis->xlow - axis->xhigh) / (dxl + dxr - 1);
30671917b75SLisandro Dalcin   yl = (dyl * axis->yhigh + dyr * axis->ylow - axis->ylow) / (dyl + dyr - 1);
30771917b75SLisandro Dalcin   yr = (dyl * axis->yhigh + dyr * axis->ylow - axis->yhigh) / (dyl + dyr - 1);
3089566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
3099566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
3105c6c1daeSBarry Smith 
31171917b75SLisandro Dalcin   /* PetscDraw the axis lines */
3129566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xhigh, axis->ylow, ac));
3139566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xlow, axis->yhigh, ac));
3149566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xlow, axis->yhigh, axis->xhigh, axis->yhigh, ac));
3159566063dSJacob Faibussowitsch   PetscCall(PetscDrawLine(draw, axis->xhigh, axis->ylow, axis->xhigh, axis->yhigh, ac));
3165c6c1daeSBarry Smith 
31771917b75SLisandro Dalcin   /* PetscDraw the top label */
3185c6c1daeSBarry Smith   if (axis->toplabel) {
31971917b75SLisandro Dalcin     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->yhigh + 0.5 * th;
3209566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->toplabel));
3215c6c1daeSBarry Smith   }
3225c6c1daeSBarry Smith 
32371917b75SLisandro Dalcin   /* PetscDraw the X ticks and labels */
3245c6c1daeSBarry Smith   if (axis->xticks) {
3259371c9d4SSatish Balay     numx = (int)(.15 * (axis->xhigh - axis->xlow) / tw);
3269371c9d4SSatish Balay     numx = PetscClipInterval(numx, 2, 6);
3279566063dSJacob Faibussowitsch     PetscCall((*axis->xticks)(axis->xlow, axis->xhigh, numx, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
3285c6c1daeSBarry Smith     /* PetscDraw in tick marks */
3295c6c1daeSBarry Smith     for (i = 0; i < ntick; i++) {
3309566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, tickloc[i], axis->ylow, tickloc[i], axis->ylow + .5 * th, tc));
3319566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, tickloc[i], axis->yhigh, tickloc[i], axis->yhigh - .5 * th, tc));
3325c6c1daeSBarry Smith     }
3335c6c1daeSBarry Smith     /* label ticks */
3345c6c1daeSBarry Smith     if (axis->xlabelstr) {
33571917b75SLisandro Dalcin       for (i = 0; i < ntick; i++) {
3365c6c1daeSBarry Smith         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
3375c6c1daeSBarry Smith         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
3385c6c1daeSBarry Smith         else sep = 0.0;
3399566063dSJacob Faibussowitsch         PetscCall((*axis->xlabelstr)(tickloc[i], sep, &p));
3409566063dSJacob Faibussowitsch         PetscCall(PetscDrawStringCentered(draw, tickloc[i], axis->ylow - 1.5 * th, cc, p));
3415c6c1daeSBarry Smith       }
3425c6c1daeSBarry Smith     }
3435c6c1daeSBarry Smith   }
3445c6c1daeSBarry Smith   if (axis->xlabel) {
34571917b75SLisandro Dalcin     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->ylow - 1.5 * th;
34671917b75SLisandro Dalcin     if (axis->xlabelstr) y -= 1.5 * th;
3479566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->xlabel));
3485c6c1daeSBarry Smith   }
34971917b75SLisandro Dalcin 
35071917b75SLisandro Dalcin   /* PetscDraw the Y ticks and labels */
3515c6c1daeSBarry Smith   if (axis->yticks) {
3529371c9d4SSatish Balay     numy = (int)(.50 * (axis->yhigh - axis->ylow) / th);
3539371c9d4SSatish Balay     numy = PetscClipInterval(numy, 2, 6);
3549566063dSJacob Faibussowitsch     PetscCall((*axis->yticks)(axis->ylow, axis->yhigh, numy, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
3555c6c1daeSBarry Smith     /* PetscDraw in tick marks */
3565c6c1daeSBarry Smith     for (i = 0; i < ntick; i++) {
3579566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, axis->xlow, tickloc[i], axis->xlow + .5 * tw, tickloc[i], tc));
3589566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, axis->xhigh, tickloc[i], axis->xhigh - .5 * tw, tickloc[i], tc));
3595c6c1daeSBarry Smith     }
3605c6c1daeSBarry Smith     /* label ticks */
3615c6c1daeSBarry Smith     if (axis->ylabelstr) {
36271917b75SLisandro Dalcin       for (i = 0; i < ntick; i++) {
3635c6c1daeSBarry Smith         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
3645c6c1daeSBarry Smith         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
3655c6c1daeSBarry Smith         else sep = 0.0;
3669566063dSJacob Faibussowitsch         PetscCall((*axis->ylabelstr)(tickloc[i], sep, &p));
3679371c9d4SSatish Balay         PetscCall(PetscStrlen(p, &len));
3689371c9d4SSatish Balay         ytlen = PetscMax(ytlen, len);
3699566063dSJacob Faibussowitsch         PetscCall(PetscDrawString(draw, axis->xlow - (len + .5) * tw, tickloc[i] - .5 * th, cc, p));
3705c6c1daeSBarry Smith       }
3715c6c1daeSBarry Smith     }
3725c6c1daeSBarry Smith   }
3735c6c1daeSBarry Smith   if (axis->ylabel) {
37471917b75SLisandro Dalcin     PetscReal x = axis->xlow - 2.0 * tw, y = (axis->ylow + axis->yhigh) / 2;
37571917b75SLisandro Dalcin     if (axis->ylabelstr) x -= (ytlen + .5) * tw;
3769566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(axis->ylabel, &len));
3779566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringVertical(draw, x, y + len * th / 2, cc, axis->ylabel));
3785c6c1daeSBarry Smith   }
3795b399a63SLisandro Dalcin 
3809566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &coors[0], &coors[1], &coors[2], &coors[3]));
3815b399a63SLisandro Dalcin finally:
382d0609cedSBarry Smith   PetscDrawCollectiveEnd(draw);
3839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(coors, 4, MPIU_REAL, 0, PetscObjectComm((PetscObject)draw)));
3849566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, coors[0], coors[1], coors[2], coors[3]));
3853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3865c6c1daeSBarry Smith }
3875c6c1daeSBarry Smith 
38836c9bc0dSBarry Smith /*
38936c9bc0dSBarry Smith     Removes all zeros but one from .0000
39036c9bc0dSBarry Smith */
391d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripe0(char *buf)
392d71ae5a4SJacob Faibussowitsch {
39336c9bc0dSBarry Smith   size_t    n;
39436c9bc0dSBarry Smith   PetscBool flg;
395bbcf679cSJacob Faibussowitsch   char     *str = NULL;
39636c9bc0dSBarry Smith 
39736c9bc0dSBarry Smith   PetscFunctionBegin;
3989566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
3999566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(buf, "e00", &flg));
400a297a907SKarl Rupp   if (flg) buf[n - 3] = 0;
4019566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buf, "e0", &str));
40236c9bc0dSBarry Smith   if (str) {
40336c9bc0dSBarry Smith     buf[n - 2] = buf[n - 1];
40436c9bc0dSBarry Smith     buf[n - 1] = 0;
40536c9bc0dSBarry Smith   }
4069566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(buf, "e-0", &str));
40736c9bc0dSBarry Smith   if (str) {
40836c9bc0dSBarry Smith     buf[n - 2] = buf[n - 1];
40936c9bc0dSBarry Smith     buf[n - 1] = 0;
41036c9bc0dSBarry Smith   }
4113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41236c9bc0dSBarry Smith }
41336c9bc0dSBarry Smith 
4145c6c1daeSBarry Smith /*
4155c6c1daeSBarry Smith     Removes all zeros but one from .0000
4165c6c1daeSBarry Smith */
417d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripAllZeros(char *buf)
418d71ae5a4SJacob Faibussowitsch {
4195c6c1daeSBarry Smith   size_t i, n;
4205c6c1daeSBarry Smith 
4215c6c1daeSBarry Smith   PetscFunctionBegin;
4229566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4233ba16761SJacob Faibussowitsch   if (buf[0] != '.') PetscFunctionReturn(PETSC_SUCCESS);
4245c6c1daeSBarry Smith   for (i = 1; i < n; i++) {
4253ba16761SJacob Faibussowitsch     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
4265c6c1daeSBarry Smith   }
4275c6c1daeSBarry Smith   buf[0] = '0';
4285c6c1daeSBarry Smith   buf[1] = 0;
4293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4305c6c1daeSBarry Smith }
4315c6c1daeSBarry Smith 
4325c6c1daeSBarry Smith /*
4335c6c1daeSBarry Smith     Removes trailing zeros
4345c6c1daeSBarry Smith */
4354279555eSSatish Balay #if (PETSC_SIZEOF_SIZE_T == 8)
4364279555eSSatish Balay   #define MAX_SIZE_T PETSC_INT64_MAX
4374279555eSSatish Balay #else
4384279555eSSatish Balay   #define MAX_SIZE_T INT_MAX
4394279555eSSatish Balay #endif
440d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripTrailingZeros(char *buf)
441d71ae5a4SJacob Faibussowitsch {
442bbcf679cSJacob Faibussowitsch   char  *found = NULL;
4434279555eSSatish Balay   size_t i, n, m = MAX_SIZE_T;
4445c6c1daeSBarry Smith 
4455c6c1daeSBarry Smith   PetscFunctionBegin;
4465c6c1daeSBarry Smith   /* if there is an e in string DO NOT strip trailing zeros */
4479566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(buf, 'e', &found));
4483ba16761SJacob Faibussowitsch   if (found) PetscFunctionReturn(PETSC_SUCCESS);
4495c6c1daeSBarry Smith 
4509566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4515c6c1daeSBarry Smith   /* locate decimal point */
4525c6c1daeSBarry Smith   for (i = 0; i < n; i++) {
4539371c9d4SSatish Balay     if (buf[i] == '.') {
4549371c9d4SSatish Balay       m = i;
4559371c9d4SSatish Balay       break;
4569371c9d4SSatish Balay     }
4575c6c1daeSBarry Smith   }
4585c6c1daeSBarry Smith   /* if not decimal point then no zeros to remove */
4594279555eSSatish Balay   if (m == MAX_SIZE_T) PetscFunctionReturn(PETSC_SUCCESS);
4605c6c1daeSBarry Smith   /* start at right end of string removing 0s */
4615c6c1daeSBarry Smith   for (i = n - 1; i > m; i++) {
4623ba16761SJacob Faibussowitsch     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
4635c6c1daeSBarry Smith     buf[i] = 0;
4645c6c1daeSBarry Smith   }
4653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4665c6c1daeSBarry Smith }
4675c6c1daeSBarry Smith 
4685c6c1daeSBarry Smith /*
4695c6c1daeSBarry Smith     Removes leading 0 from 0.22 or -0.22
4705c6c1daeSBarry Smith */
471d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripInitialZero(char *buf)
472d71ae5a4SJacob Faibussowitsch {
4735c6c1daeSBarry Smith   size_t i, n;
4745c6c1daeSBarry Smith 
4755c6c1daeSBarry Smith   PetscFunctionBegin;
4769566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4775c6c1daeSBarry Smith   if (buf[0] == '0') {
478a297a907SKarl Rupp     for (i = 0; i < n; i++) buf[i] = buf[i + 1];
4795c6c1daeSBarry Smith   } else if (buf[0] == '-' && buf[1] == '0') {
480a297a907SKarl Rupp     for (i = 1; i < n; i++) buf[i] = buf[i + 1];
4815c6c1daeSBarry Smith   }
4823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4835c6c1daeSBarry Smith }
4845c6c1daeSBarry Smith 
4855c6c1daeSBarry Smith /*
4865c6c1daeSBarry Smith      Removes the extraneous zeros in numbers like 1.10000e6
4875c6c1daeSBarry Smith */
488d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripZeros(char *buf)
489d71ae5a4SJacob Faibussowitsch {
4905c6c1daeSBarry Smith   size_t i, j, n;
4915c6c1daeSBarry Smith 
4925c6c1daeSBarry Smith   PetscFunctionBegin;
4939566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
4943ba16761SJacob Faibussowitsch   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
4955c6c1daeSBarry Smith   for (i = 1; i < n - 1; i++) {
4965c6c1daeSBarry Smith     if (buf[i] == 'e' && buf[i - 1] == '0') {
4975c6c1daeSBarry Smith       for (j = i; j < n + 1; j++) buf[j - 1] = buf[j];
4989566063dSJacob Faibussowitsch       PetscCall(PetscStripZeros(buf));
4993ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5005c6c1daeSBarry Smith     }
5015c6c1daeSBarry Smith   }
5023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5035c6c1daeSBarry Smith }
5045c6c1daeSBarry Smith 
5055c6c1daeSBarry Smith /*
5065c6c1daeSBarry Smith       Removes the plus in something like 1.1e+2 or 1.1e+02
5075c6c1daeSBarry Smith */
508d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStripZerosPlus(char *buf)
509d71ae5a4SJacob Faibussowitsch {
5105c6c1daeSBarry Smith   size_t i, j, n;
5115c6c1daeSBarry Smith 
5125c6c1daeSBarry Smith   PetscFunctionBegin;
5139566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(buf, &n));
5143ba16761SJacob Faibussowitsch   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
5155c6c1daeSBarry Smith   for (i = 1; i < n - 2; i++) {
5165c6c1daeSBarry Smith     if (buf[i] == '+') {
5175c6c1daeSBarry Smith       if (buf[i + 1] == '0') {
5185c6c1daeSBarry Smith         for (j = i + 1; j < n; j++) buf[j - 1] = buf[j + 1];
5193ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
5205c6c1daeSBarry Smith       } else {
5215c6c1daeSBarry Smith         for (j = i + 1; j < n + 1; j++) buf[j - 1] = buf[j];
5223ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
5235c6c1daeSBarry Smith       }
5245c6c1daeSBarry Smith     } else if (buf[i] == '-') {
5255c6c1daeSBarry Smith       if (buf[i + 1] == '0') {
5265c6c1daeSBarry Smith         for (j = i + 1; j < n; j++) buf[j] = buf[j + 1];
5273ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
5285c6c1daeSBarry Smith       }
5295c6c1daeSBarry Smith     }
5305c6c1daeSBarry Smith   }
5313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5325c6c1daeSBarry Smith }
533