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