xref: /petsc/src/sys/classes/draw/interface/dtri.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1 
2 /*
3        Provides the calling sequences for all the basic PetscDraw routines.
4 */
5 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/
6 
7 /*@
8    PetscDrawTriangle - PetscDraws a triangle  onto a drawable.
9 
10    Not Collective
11 
12    Input Parameters:
13 +  draw - the drawing context
14 .  x1,y1,x2,y2,x3,y3 - the coordinates of the vertices
15 -  c1,c2,c3 - the colors of the three vertices in the same order as the xi,yi
16 
17    Level: beginner
18 
19 .seealso: `PetscDrawLine()`, `PetscDrawRectangle()`, `PetscDrawEllipse()`, `PetscDrawMarker()`, `PetscDrawPoint()`, `PetscDrawArrow()`
20 @*/
21 PetscErrorCode PetscDrawTriangle(PetscDraw draw, PetscReal x1, PetscReal y_1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3) {
22   PetscFunctionBegin;
23   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
24   PetscUseTypeMethod(draw, triangle, x1, y_1, x2, y2, x3, y3, c1, c2, c3);
25   PetscFunctionReturn(0);
26 }
27 
28 /*@
29    PetscDrawScalePopup - draws a contour scale window.
30 
31    Collective on PetscDraw
32 
33    Input Parameters:
34 +  popup - the window (often a window obtained via PetscDrawGetPopup()
35 .  min - minimum value being plotted
36 -  max - maximum value being plotted
37 
38    Level: intermediate
39 
40    Notes:
41     All processors that share the draw MUST call this routine
42 
43 .seealso: `PetscDrawGetPopup()`, `PetscDrawTensorContour()`
44 
45 @*/
46 PetscErrorCode PetscDrawScalePopup(PetscDraw popup, PetscReal min, PetscReal max) {
47   PetscBool   isnull;
48   PetscReal   xl = 0.0, yl = 0.0, xr = 1.0, yr = 1.0;
49   PetscMPIInt rank;
50   int         i;
51   char        string[32];
52 
53   PetscFunctionBegin;
54   if (!popup) PetscFunctionReturn(0);
55   PetscValidHeaderSpecific(popup, PETSC_DRAW_CLASSID, 1);
56   PetscCall(PetscDrawIsNull(popup, &isnull));
57   if (isnull) PetscFunctionReturn(0);
58   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)popup), &rank));
59 
60   PetscCall(PetscDrawCheckResizedWindow(popup));
61   PetscCall(PetscDrawClear(popup));
62   PetscCall(PetscDrawSetTitle(popup, "Contour Scale"));
63   PetscCall(PetscDrawSetCoordinates(popup, xl, yl, xr, yr));
64   PetscDrawCollectiveBegin(popup);
65   if (rank == 0) {
66     for (i = 0; i < 10; i++) {
67       int c = PetscDrawRealToColor((PetscReal)i / 9, 0, 1);
68       PetscCall(PetscDrawRectangle(popup, xl, yl, xr, yr, c, c, c, c));
69       yl += 0.1;
70     }
71     for (i = 0; i < 10; i++) {
72       PetscReal value = min + i * (max - min) / 9;
73       /* look for a value that should be zero, but is not due to round-off */
74       if (PetscAbsReal(value) < 1.e-10 && max - min > 1.e-6) value = 0.0;
75       PetscCall(PetscSNPrintf(string, sizeof(string), "%18.16e", (double)value));
76       PetscCall(PetscDrawString(popup, 0.2, 0.02 + i / 10.0, PETSC_DRAW_BLACK, string));
77     }
78   }
79   PetscDrawCollectiveEnd(popup);
80   PetscCall(PetscDrawFlush(popup));
81   PetscCall(PetscDrawSave(popup));
82   PetscFunctionReturn(0);
83 }
84 
85 typedef struct {
86   int        m, n;
87   PetscReal *x, *y, min, max, *v;
88   PetscBool  showgrid;
89 } ZoomCtx;
90 
91 static PetscErrorCode PetscDrawTensorContour_Zoom(PetscDraw win, void *dctx) {
92   int      i;
93   ZoomCtx *ctx = (ZoomCtx *)dctx;
94 
95   PetscFunctionBegin;
96   PetscCall(PetscDrawTensorContourPatch(win, ctx->m, ctx->n, ctx->x, ctx->y, ctx->min, ctx->max, ctx->v));
97   if (ctx->showgrid) {
98     for (i = 0; i < ctx->m; i++) { PetscCall(PetscDrawLine(win, ctx->x[i], ctx->y[0], ctx->x[i], ctx->y[ctx->n - 1], PETSC_DRAW_BLACK)); }
99     for (i = 0; i < ctx->n; i++) { PetscCall(PetscDrawLine(win, ctx->x[0], ctx->y[i], ctx->x[ctx->m - 1], ctx->y[i], PETSC_DRAW_BLACK)); }
100   }
101   PetscFunctionReturn(0);
102 }
103 
104 /*@C
105    PetscDrawTensorContour - PetscDraws a contour plot for a two-dimensional array
106    that is stored as a PETSc vector.
107 
108    Collective on PetscDraw, but PetscDraw must be sequential
109 
110    Input Parameters:
111 +   draw  - the draw context
112 .   m,n   - the global number of mesh points in the x and y directions
113 .   xi,yi - the locations of the global mesh points (optional, use NULL
114             to indicate uniform spacing on [0,1])
115 -   V     - the values
116 
117    Options Database Keys:
118 +  -draw_x_shared_colormap - Indicates use of private colormap
119 -  -draw_contour_grid - PetscDraws grid contour
120 
121    Level: intermediate
122 
123 .seealso: `PetscDrawTensorContourPatch()`, `PetscDrawScalePopup()`
124 
125 @*/
126 PetscErrorCode PetscDrawTensorContour(PetscDraw draw, int m, int n, const PetscReal xi[], const PetscReal yi[], PetscReal *v) {
127   int         N = m * n;
128   PetscBool   isnull;
129   PetscDraw   popup;
130   int         xin = 1, yin = 1, i;
131   PetscMPIInt size;
132   PetscReal   h;
133   ZoomCtx     ctx;
134 
135   PetscFunctionBegin;
136   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
137   PetscCall(PetscDrawIsNull(draw, &isnull));
138   if (isnull) PetscFunctionReturn(0);
139   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
140   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "May only be used with single processor PetscDraw");
141   PetscCheck(N > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n %d and m %d must be positive", m, n);
142 
143   ctx.v   = v;
144   ctx.m   = m;
145   ctx.n   = n;
146   ctx.max = ctx.min = v[0];
147   for (i = 0; i < N; i++) {
148     if (ctx.max < ctx.v[i]) ctx.max = ctx.v[i];
149     if (ctx.min > ctx.v[i]) ctx.min = ctx.v[i];
150   }
151   if (ctx.max - ctx.min < 1.e-7) {
152     ctx.min -= 5.e-8;
153     ctx.max += 5.e-8;
154   }
155 
156   /* PetscDraw the scale window */
157   PetscCall(PetscDrawGetPopup(draw, &popup));
158   PetscCall(PetscDrawScalePopup(popup, ctx.min, ctx.max));
159 
160   ctx.showgrid = PETSC_FALSE;
161   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, NULL, "-draw_contour_grid", &ctx.showgrid, NULL));
162 
163   /* fill up x and y coordinates */
164   if (!xi) {
165     xin = 0;
166     PetscCall(PetscMalloc1(ctx.m, &ctx.x));
167     h        = 1.0 / (ctx.m - 1);
168     ctx.x[0] = 0.0;
169     for (i = 1; i < ctx.m; i++) ctx.x[i] = ctx.x[i - 1] + h;
170   } else ctx.x = (PetscReal *)xi;
171 
172   if (!yi) {
173     yin = 0;
174     PetscCall(PetscMalloc1(ctx.n, &ctx.y));
175     h        = 1.0 / (ctx.n - 1);
176     ctx.y[0] = 0.0;
177     for (i = 1; i < ctx.n; i++) ctx.y[i] = ctx.y[i - 1] + h;
178   } else ctx.y = (PetscReal *)yi;
179 
180   PetscCall(PetscDrawZoom(draw, PetscDrawTensorContour_Zoom, &ctx));
181 
182   if (!xin) PetscCall(PetscFree(ctx.x));
183   if (!yin) PetscCall(PetscFree(ctx.y));
184   PetscFunctionReturn(0);
185 }
186 
187 /*@
188    PetscDrawTensorContourPatch - PetscDraws a rectangular patch of a contour plot
189    for a two-dimensional array.
190 
191    Not Collective
192 
193    Input Parameters:
194 +  draw - the draw context
195 .  m,n - the number of local mesh points in the x and y direction
196 .  x,y - the locations of the local mesh points
197 .  min,max - the minimum and maximum value in the entire contour
198 -  v - the data
199 
200    Options Database Keys:
201 .  -draw_x_shared_colormap - Activates private colormap
202 
203    Level: advanced
204 
205    Note:
206    This is a lower level support routine, usually the user will call
207    PetscDrawTensorContour().
208 
209 .seealso: `PetscDrawTensorContour()`
210 
211 @*/
212 PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v) {
213   int       c1, c2, c3, c4, i, j;
214   PetscReal x1, x2, x3, x4, y_1, y2, y3, y4;
215 
216   PetscFunctionBegin;
217   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
218   /* PetscDraw the contour plot patch */
219   for (j = 0; j < n - 1; j++) {
220     for (i = 0; i < m - 1; i++) {
221       x1  = x[i];
222       y_1 = y[j];
223       c1  = PetscDrawRealToColor(v[i + j * m], min, max);
224       x2  = x[i + 1];
225       y2  = y_1;
226       c2  = PetscDrawRealToColor(v[i + j * m + 1], min, max);
227       x3  = x2;
228       y3  = y[j + 1];
229       c3  = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max);
230       x4  = x1;
231       y4  = y3;
232       c4  = PetscDrawRealToColor(v[i + j * m + m], min, max);
233 
234       PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3));
235       PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4));
236     }
237   }
238   PetscFunctionReturn(0);
239 }
240