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: /*@
 33:   PetscDrawScalePopup - draws a contour scale window.

 35:   Collective

 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

 42:   Level: intermediate

 44:   Note:
 45:   All processors that share the draw MUST call this routine

 47: .seealso: `PetscDraw`, `PetscDrawGetPopup()`, `PetscDrawTensorContour()`
 48: @*/
 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];

 57:   PetscFunctionBegin;
 58:   if (!popup) PetscFunctionReturn(PETSC_SUCCESS);
 60:   PetscCall(PetscDrawIsNull(popup, &isnull));
 61:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
 62:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)popup), &rank));

 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 + 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: }

 89: typedef struct {
 90:   int        m, n;
 91:   PetscReal *x, *y, min, max, *v;
 92:   PetscBool  showgrid;
 93: } ZoomCtx;

 95: static PetscErrorCode PetscDrawTensorContour_Zoom(PetscDraw win, void *dctx)
 96: {
 97:   int      i;
 98:   ZoomCtx *ctx = (ZoomCtx *)dctx;

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: }

109: /*@C
110:   PetscDrawTensorContour - draws a contour plot for a two-dimensional array

112:   Collective, but `draw` must be sequential

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

122:   Options Database Keys:
123: + -draw_x_shared_colormap - Indicates use of private colormap
124: - -draw_contour_grid      - draws grid contour

126:   Level: intermediate

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;

140:   PetscFunctionBegin;
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);

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:   }

161:   /* PetscDraw the scale window */
162:   PetscCall(PetscDrawGetPopup(draw, &popup));
163:   PetscCall(PetscDrawScalePopup(popup, ctx.min, ctx.max));

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

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;

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;

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

187:   if (!xin) PetscCall(PetscFree(ctx.x));
188:   if (!yin) PetscCall(PetscFree(ctx.y));
189:   PetscFunctionReturn(PETSC_SUCCESS);
190: }

192: /*@
193:   PetscDrawTensorContourPatch - draws a rectangular patch of a contour plot
194:   for a two-dimensional array.

196:   Not Collective

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

208:   Options Database Key:
209: . -draw_x_shared_colormap - Activates private colormap

211:   Level: advanced

213:   Note:
214:   This is a lower level support routine, usually the user will call
215:   `PetscDrawTensorContour()`.

217: .seealso: `PetscDraw`, `PetscDrawTensorContour()`
218: @*/
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;

224:   PetscFunctionBegin;
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);

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: }