xref: /petsc/src/sys/classes/draw/interface/dtri.c (revision 0619917b5a674bb687c64e7daba2ab22be99af31)
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 . y_1  - 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    - the number of local mesh points in the x direction
118 . n    - the number of local mesh points in the y direction
119 . xi   - the locations of the global mesh points in the horizontal direction (optional, use `NULL` to indicate uniform spacing on [0,1])
120 . yi   - the locations of the global mesh points in the vertical direction (optional, use `NULL` to indicate uniform spacing on [0,1])
121 - v    - the values
122 
123   Options Database Keys:
124 + -draw_x_shared_colormap - Indicates use of private colormap
125 - -draw_contour_grid      - draws grid contour
126 
127   Level: intermediate
128 
129 .seealso: `PetscDraw`, `PetscDrawTensorContourPatch()`, `PetscDrawScalePopup()`
130 @*/
131 PetscErrorCode PetscDrawTensorContour(PetscDraw draw, int m, int n, const PetscReal xi[], const PetscReal yi[], PetscReal *v)
132 {
133   int         N = m * n;
134   PetscBool   isnull;
135   PetscDraw   popup;
136   int         xin = 1, yin = 1, i;
137   PetscMPIInt size;
138   PetscReal   h;
139   ZoomCtx     ctx;
140 
141   PetscFunctionBegin;
142   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
143   PetscCall(PetscDrawIsNull(draw, &isnull));
144   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
145   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
146   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "May only be used with single processor PetscDraw");
147   PetscCheck(N > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n %d and m %d must be positive", m, n);
148 
149   ctx.v   = v;
150   ctx.m   = m;
151   ctx.n   = n;
152   ctx.max = ctx.min = v[0];
153   for (i = 0; i < N; i++) {
154     if (ctx.max < ctx.v[i]) ctx.max = ctx.v[i];
155     if (ctx.min > ctx.v[i]) ctx.min = ctx.v[i];
156   }
157   if (ctx.max - ctx.min < 1.e-7) {
158     ctx.min -= 5.e-8;
159     ctx.max += 5.e-8;
160   }
161 
162   /* PetscDraw the scale window */
163   PetscCall(PetscDrawGetPopup(draw, &popup));
164   PetscCall(PetscDrawScalePopup(popup, ctx.min, ctx.max));
165 
166   ctx.showgrid = PETSC_FALSE;
167   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, NULL, "-draw_contour_grid", &ctx.showgrid, NULL));
168 
169   /* fill up x and y coordinates */
170   if (!xi) {
171     xin = 0;
172     PetscCall(PetscMalloc1(ctx.m, &ctx.x));
173     h        = 1.0 / (ctx.m - 1);
174     ctx.x[0] = 0.0;
175     for (i = 1; i < ctx.m; i++) ctx.x[i] = ctx.x[i - 1] + h;
176   } else ctx.x = (PetscReal *)xi;
177 
178   if (!yi) {
179     yin = 0;
180     PetscCall(PetscMalloc1(ctx.n, &ctx.y));
181     h        = 1.0 / (ctx.n - 1);
182     ctx.y[0] = 0.0;
183     for (i = 1; i < ctx.n; i++) ctx.y[i] = ctx.y[i - 1] + h;
184   } else ctx.y = (PetscReal *)yi;
185 
186   PetscCall(PetscDrawZoom(draw, PetscDrawTensorContour_Zoom, &ctx));
187 
188   if (!xin) PetscCall(PetscFree(ctx.x));
189   if (!yin) PetscCall(PetscFree(ctx.y));
190   PetscFunctionReturn(PETSC_SUCCESS);
191 }
192 
193 /*@
194   PetscDrawTensorContourPatch - draws a rectangular patch of a contour plot
195   for a two-dimensional array.
196 
197   Not Collective
198 
199   Input Parameters:
200 + draw - the draw context
201 . m    - the number of local mesh points in the x direction
202 . n    - the number of local mesh points in the y direction
203 . x    - the horizontal locations of the local mesh points
204 . y    - the vertical locations of the local mesh points
205 . min  - the minimum value in the entire contour
206 . max  - the maximum value in the entire contour
207 - v    - the data
208 
209   Options Database Key:
210 . -draw_x_shared_colormap - Activates private colormap
211 
212   Level: advanced
213 
214   Note:
215   This is a lower level support routine, usually the user will call
216   `PetscDrawTensorContour()`.
217 
218 .seealso: `PetscDraw`, `PetscDrawTensorContour()`
219 @*/
220 PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v)
221 {
222   int       c1, c2, c3, c4, i, j;
223   PetscReal x1, x2, x3, x4, y_1, y2, y3, y4;
224 
225   PetscFunctionBegin;
226   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
227   /* PetscDraw the contour plot patch */
228   for (j = 0; j < n - 1; j++) {
229     for (i = 0; i < m - 1; i++) {
230       x1  = x[i];
231       y_1 = y[j];
232       c1  = PetscDrawRealToColor(v[i + j * m], min, max);
233       x2  = x[i + 1];
234       y2  = y_1;
235       c2  = PetscDrawRealToColor(v[i + j * m + 1], min, max);
236       x3  = x2;
237       y3  = y[j + 1];
238       c3  = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max);
239       x4  = x1;
240       y4  = y3;
241       c4  = PetscDrawRealToColor(v[i + j * m + m], min, max);
242 
243       PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3));
244       PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4));
245     }
246   }
247   PetscFunctionReturn(PETSC_SUCCESS);
248 }
249