xref: /petsc/src/sys/classes/draw/interface/dtri.c (revision 6d8694c4fbab79f9439f1ad13c0386ba7ee1ca4b)
1 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/
2 
3 /*@
4   PetscDrawTriangle - draws a triangle  onto a drawable.
5 
6   Not Collective
7 
8   Input Parameters:
9 + draw - the drawing context
10 . x1   - coordinate of the first vertex
11 . y_1  - coordinate of the first vertex
12 . x2   - coordinate of the second vertex
13 . y2   - coordinate of the second vertex
14 . x3   - coordinate of the third vertex
15 . y3   - coordinate of the third vertex
16 . c1   - color of the first vertex
17 . c2   - color of the second vertex
18 - c3   - color of the third vertext
19 
20   Level: beginner
21 
22 .seealso: `PetscDraw`, `PetscDrawLine()`, `PetscDrawRectangle()`, `PetscDrawEllipse()`, `PetscDrawMarker()`, `PetscDrawPoint()`, `PetscDrawArrow()`
23 @*/
PetscDrawTriangle(PetscDraw draw,PetscReal x1,PetscReal y_1,PetscReal x2,PetscReal y2,PetscReal x3,PetscReal y3,int c1,int c2,int c3)24 PetscErrorCode PetscDrawTriangle(PetscDraw draw, PetscReal x1, PetscReal y_1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3)
25 {
26   PetscFunctionBegin;
27   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
28   PetscUseTypeMethod(draw, triangle, x1, y_1, x2, y2, x3, y3, c1, c2, c3);
29   PetscFunctionReturn(PETSC_SUCCESS);
30 }
31 
32 /*@
33   PetscDrawScalePopup - draws a contour scale window.
34 
35   Collective
36 
37   Input Parameters:
38 + popup - the window (often a window obtained via `PetscDrawGetPopup()`
39 . min   - minimum value being plotted
40 - max   - maximum value being plotted
41 
42   Level: intermediate
43 
44   Note:
45   All processors that share the draw MUST call this routine
46 
47 .seealso: `PetscDraw`, `PetscDrawGetPopup()`, `PetscDrawTensorContour()`
48 @*/
PetscDrawScalePopup(PetscDraw popup,PetscReal min,PetscReal max)49 PetscErrorCode PetscDrawScalePopup(PetscDraw popup, PetscReal min, PetscReal max)
50 {
51   PetscBool   isnull;
52   PetscReal   xl = 0.0, yl = 0.0, xr = 1.0, yr = 1.0;
53   PetscMPIInt rank;
54   int         i;
55   char        string[32];
56 
57   PetscFunctionBegin;
58   if (!popup) PetscFunctionReturn(PETSC_SUCCESS);
59   PetscValidHeaderSpecific(popup, PETSC_DRAW_CLASSID, 1);
60   PetscCall(PetscDrawIsNull(popup, &isnull));
61   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
62   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)popup), &rank));
63 
64   PetscCall(PetscDrawCheckResizedWindow(popup));
65   PetscCall(PetscDrawClear(popup));
66   PetscCall(PetscDrawSetTitle(popup, "Contour Scale"));
67   PetscCall(PetscDrawSetCoordinates(popup, xl, yl, xr, yr));
68   PetscDrawCollectiveBegin(popup);
69   if (rank == 0) {
70     for (i = 0; i < 10; i++) {
71       int c = PetscDrawRealToColor((PetscReal)i / 9, 0, 1);
72       PetscCall(PetscDrawRectangle(popup, xl, yl, xr, yr, c, c, c, c));
73       yl += 0.1;
74     }
75     for (i = 0; i < 10; i++) {
76       PetscReal value = min + ((PetscReal)i) * (max - min) / 9;
77       /* look for a value that should be zero, but is not due to round-off */
78       if (PetscAbsReal(value) < 1.e-10 && max - min > 1.e-6) value = 0.0;
79       PetscCall(PetscSNPrintf(string, sizeof(string), "%18.16e", (double)value));
80       PetscCall(PetscDrawString(popup, 0.2, 0.02 + i / 10.0, PETSC_DRAW_BLACK, string));
81     }
82   }
83   PetscDrawCollectiveEnd(popup);
84   PetscCall(PetscDrawFlush(popup));
85   PetscCall(PetscDrawSave(popup));
86   PetscFunctionReturn(PETSC_SUCCESS);
87 }
88 
89 typedef struct {
90   int        m, n;
91   PetscReal *x, *y, min, max, *v;
92   PetscBool  showgrid;
93 } ZoomCtx;
94 
PetscDrawTensorContour_Zoom(PetscDraw win,void * dctx)95 static PetscErrorCode PetscDrawTensorContour_Zoom(PetscDraw win, void *dctx)
96 {
97   int      i;
98   ZoomCtx *ctx = (ZoomCtx *)dctx;
99 
100   PetscFunctionBegin;
101   PetscCall(PetscDrawTensorContourPatch(win, ctx->m, ctx->n, ctx->x, ctx->y, ctx->min, ctx->max, ctx->v));
102   if (ctx->showgrid) {
103     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));
104     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));
105   }
106   PetscFunctionReturn(PETSC_SUCCESS);
107 }
108 
109 /*@
110   PetscDrawTensorContour - draws a contour plot for a two-dimensional array
111 
112   Collective, but `draw` must be sequential
113 
114   Input Parameters:
115 + draw - the draw context
116 . m    - the number of local mesh points in the x direction
117 . n    - the number of local mesh points in the y direction
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 @*/
PetscDrawTensorContour(PetscDraw draw,int m,int n,const PetscReal xi[],const PetscReal yi[],PetscReal v[])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    - the number of local mesh points in the x direction
201 . n    - the number of local mesh points in the y direction
202 . x    - the horizontal locations of the local mesh points
203 . y    - the vertical locations of the local mesh points
204 . min  - the minimum value in the entire contour
205 . max  - the maximum value in the entire contour
206 - v    - the data
207 
208   Options Database Key:
209 . -draw_x_shared_colormap - Activates private colormap
210 
211   Level: advanced
212 
213   Note:
214   This is a lower level support routine, usually the user will call
215   `PetscDrawTensorContour()`.
216 
217 .seealso: `PetscDraw`, `PetscDrawTensorContour()`
218 @*/
PetscDrawTensorContourPatch(PetscDraw draw,int m,int n,PetscReal * x,PetscReal * y,PetscReal min,PetscReal max,PetscReal * v)219 PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v)
220 {
221   int       c1, c2, c3, c4, i, j;
222   PetscReal x1, x2, x3, x4, y_1, y2, y3, y4;
223 
224   PetscFunctionBegin;
225   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
226   /* PetscDraw the contour plot patch */
227   for (j = 0; j < n - 1; j++) {
228     for (i = 0; i < m - 1; i++) {
229       x1  = x[i];
230       y_1 = y[j];
231       c1  = PetscDrawRealToColor(v[i + j * m], min, max);
232       x2  = x[i + 1];
233       y2  = y_1;
234       c2  = PetscDrawRealToColor(v[i + j * m + 1], min, max);
235       x3  = x2;
236       y3  = y[j + 1];
237       c3  = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max);
238       x4  = x1;
239       y4  = y3;
240       c4  = PetscDrawRealToColor(v[i + j * m + m], min, max);
241 
242       PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3));
243       PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4));
244     }
245   }
246   PetscFunctionReturn(PETSC_SUCCESS);
247 }
248