Actual source code: dtri.c

  1: #include <petsc/private/drawimpl.h>

  3: /*@
  4:   PetscDrawTriangle - draws a triangle  onto a drawable.

  6:   Not Collective

  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

 20:   Level: beginner

 22: .seealso: `PetscDraw`, `PetscDrawLine()`, `PetscDrawRectangle()`, `PetscDrawEllipse()`, `PetscDrawMarker()`, `PetscDrawPoint()`, `PetscDrawArrow()`
 23: @*/
 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;
 28:   PetscUseTypeMethod(draw, triangle, x1, y_1, x2, y2, x3, y3, c1, c2, c3);
 29:   PetscFunctionReturn(PETSC_SUCCESS);
 30: }

 32: #if defined(__GNUC__) && !defined(__clang__)
 33:   #pragma GCC diagnostic push
 34:   #pragma GCC diagnostic ignored "-Wclobbered"
 35: #endif
 36: /*@
 37:   PetscDrawScalePopup - draws a contour scale window.

 39:   Collective

 41:   Input Parameters:
 42: + popup - the window (often a window obtained via `PetscDrawGetPopup()`
 43: . min   - minimum value being plotted
 44: - max   - maximum value being plotted

 46:   Level: intermediate

 48:   Note:
 49:   All processors that share the draw MUST call this routine

 51: .seealso: `PetscDraw`, `PetscDrawGetPopup()`, `PetscDrawTensorContour()`
 52: @*/
 53: PetscErrorCode PetscDrawScalePopup(PetscDraw popup, PetscReal min, PetscReal max)
 54: {
 55:   PetscBool   isnull;
 56:   PetscReal   xl = 0.0, yl = 0.0, xr = 1.0, yr = 1.0;
 57:   PetscMPIInt rank;
 58:   int         i;
 59:   char        string[32];

 61:   PetscFunctionBegin;
 62:   if (!popup) PetscFunctionReturn(PETSC_SUCCESS);
 64:   PetscCall(PetscDrawIsNull(popup, &isnull));
 65:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
 66:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)popup), &rank));

 68:   PetscCall(PetscDrawCheckResizedWindow(popup));
 69:   PetscCall(PetscDrawClear(popup));
 70:   PetscCall(PetscDrawSetTitle(popup, "Contour Scale"));
 71:   PetscCall(PetscDrawSetCoordinates(popup, xl, yl, xr, yr));
 72:   PetscDrawCollectiveBegin(popup);
 73:   if (rank == 0) {
 74:     for (i = 0; i < 10; i++) {
 75:       int c = PetscDrawRealToColor((PetscReal)i / 9, 0, 1);
 76:       PetscCall(PetscDrawRectangle(popup, xl, yl, xr, yr, c, c, c, c));
 77:       yl += 0.1;
 78:     }
 79:     for (i = 0; i < 10; i++) {
 80:       PetscReal value = min + ((PetscReal)i) * (max - min) / 9;
 81:       /* look for a value that should be zero, but is not due to round-off */
 82:       if (PetscAbsReal(value) < 1.e-10 && max - min > 1.e-6) value = 0.0;
 83:       PetscCall(PetscSNPrintf(string, sizeof(string), "%18.16e", (double)value));
 84:       PetscCall(PetscDrawString(popup, 0.2, 0.02 + i / 10.0, PETSC_DRAW_BLACK, string));
 85:     }
 86:   }
 87:   PetscDrawCollectiveEnd(popup);
 88:   PetscCall(PetscDrawFlush(popup));
 89:   PetscCall(PetscDrawSave(popup));
 90:   PetscFunctionReturn(PETSC_SUCCESS);
 91: }
 92: #if defined(__GNUC__) && !defined(__clang__)
 93:   #pragma GCC diagnostic pop
 94: #endif

 96: typedef struct {
 97:   int        m, n;
 98:   PetscReal *x, *y, min, max, *v;
 99:   PetscBool  showgrid;
100: } ZoomCtx;

102: static PetscErrorCode PetscDrawTensorContour_Zoom(PetscDraw win, void *dctx)
103: {
104:   int      i;
105:   ZoomCtx *ctx = (ZoomCtx *)dctx;

107:   PetscFunctionBegin;
108:   PetscCall(PetscDrawTensorContourPatch(win, ctx->m, ctx->n, ctx->x, ctx->y, ctx->min, ctx->max, ctx->v));
109:   if (ctx->showgrid) {
110:     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));
111:     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));
112:   }
113:   PetscFunctionReturn(PETSC_SUCCESS);
114: }

116: /*@
117:   PetscDrawTensorContour - draws a contour plot for a two-dimensional array

119:   Collective, but `draw` must be sequential

121:   Input Parameters:
122: + draw - the draw context
123: . m    - the number of local mesh points in the x direction
124: . n    - the number of local mesh points in the y direction
125: . xi   - the locations of the global mesh points in the horizontal direction (optional, use `NULL` to indicate uniform spacing on [0,1])
126: . yi   - the locations of the global mesh points in the vertical direction (optional, use `NULL` to indicate uniform spacing on [0,1])
127: - v    - the values

129:   Options Database Keys:
130: + -draw_x_shared_colormap - Indicates use of private colormap
131: - -draw_contour_grid      - draws grid contour

133:   Level: intermediate

135: .seealso: `PetscDraw`, `PetscDrawTensorContourPatch()`, `PetscDrawScalePopup()`
136: @*/
137: PetscErrorCode PetscDrawTensorContour(PetscDraw draw, int m, int n, const PetscReal xi[], const PetscReal yi[], PetscReal v[])
138: {
139:   int         N = m * n;
140:   PetscBool   isnull;
141:   PetscDraw   popup;
142:   int         xin = 1, yin = 1, i;
143:   PetscMPIInt size;
144:   PetscReal   h;
145:   ZoomCtx     ctx;

147:   PetscFunctionBegin;
149:   PetscCall(PetscDrawIsNull(draw, &isnull));
150:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
151:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
152:   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "May only be used with single processor PetscDraw");
153:   PetscCheck(N > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n %d and m %d must be positive", m, n);

155:   ctx.v   = v;
156:   ctx.m   = m;
157:   ctx.n   = n;
158:   ctx.max = ctx.min = v[0];
159:   for (i = 0; i < N; i++) {
160:     if (ctx.max < ctx.v[i]) ctx.max = ctx.v[i];
161:     if (ctx.min > ctx.v[i]) ctx.min = ctx.v[i];
162:   }
163:   if (ctx.max - ctx.min < 1.e-7) {
164:     ctx.min -= 5.e-8;
165:     ctx.max += 5.e-8;
166:   }

168:   /* PetscDraw the scale window */
169:   PetscCall(PetscDrawGetPopup(draw, &popup));
170:   PetscCall(PetscDrawScalePopup(popup, ctx.min, ctx.max));

172:   ctx.showgrid = PETSC_FALSE;
173:   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, NULL, "-draw_contour_grid", &ctx.showgrid, NULL));

175:   /* fill up x and y coordinates */
176:   if (!xi) {
177:     xin = 0;
178:     PetscCall(PetscMalloc1(ctx.m, &ctx.x));
179:     h        = 1.0 / (ctx.m - 1);
180:     ctx.x[0] = 0.0;
181:     for (i = 1; i < ctx.m; i++) ctx.x[i] = ctx.x[i - 1] + h;
182:   } else ctx.x = (PetscReal *)xi;

184:   if (!yi) {
185:     yin = 0;
186:     PetscCall(PetscMalloc1(ctx.n, &ctx.y));
187:     h        = 1.0 / (ctx.n - 1);
188:     ctx.y[0] = 0.0;
189:     for (i = 1; i < ctx.n; i++) ctx.y[i] = ctx.y[i - 1] + h;
190:   } else ctx.y = (PetscReal *)yi;

192:   PetscCall(PetscDrawZoom(draw, PetscDrawTensorContour_Zoom, &ctx));

194:   if (!xin) PetscCall(PetscFree(ctx.x));
195:   if (!yin) PetscCall(PetscFree(ctx.y));
196:   PetscFunctionReturn(PETSC_SUCCESS);
197: }

199: /*@
200:   PetscDrawTensorContourPatch - draws a rectangular patch of a contour plot
201:   for a two-dimensional array.

203:   Not Collective

205:   Input Parameters:
206: + draw - the draw context
207: . m    - the number of local mesh points in the x direction
208: . n    - the number of local mesh points in the y direction
209: . x    - the horizontal locations of the local mesh points
210: . y    - the vertical locations of the local mesh points
211: . min  - the minimum value in the entire contour
212: . max  - the maximum value in the entire contour
213: - v    - the data

215:   Options Database Key:
216: . -draw_x_shared_colormap - Activates private colormap

218:   Level: advanced

220:   Note:
221:   This is a lower level support routine, usually the user will call
222:   `PetscDrawTensorContour()`.

224: .seealso: `PetscDraw`, `PetscDrawTensorContour()`
225: @*/
226: PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v)
227: {
228:   int       c1, c2, c3, c4, i, j;
229:   PetscReal x1, x2, x3, x4, y_1, y2, y3, y4;

231:   PetscFunctionBegin;
233:   /* PetscDraw the contour plot patch */
234:   for (j = 0; j < n - 1; j++) {
235:     for (i = 0; i < m - 1; i++) {
236:       x1  = x[i];
237:       y_1 = y[j];
238:       c1  = PetscDrawRealToColor(v[i + j * m], min, max);
239:       x2  = x[i + 1];
240:       y2  = y_1;
241:       c2  = PetscDrawRealToColor(v[i + j * m + 1], min, max);
242:       x3  = x2;
243:       y3  = y[j + 1];
244:       c3  = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max);
245:       x4  = x1;
246:       y4  = y3;
247:       c4  = PetscDrawRealToColor(v[i + j * m + m], min, max);

249:       PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3));
250:       PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4));
251:     }
252:   }
253:   PetscFunctionReturn(PETSC_SUCCESS);
254: }