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