Actual source code: tikz.c
1: /*
2: Defines the operations for the TikZ PetscDraw implementation.
3: */
5: #include <petsc/private/drawimpl.h>
7: typedef struct {
8: char *filename;
9: FILE *fd;
10: PetscBool written; /* something has been written to the current frame */
11: } PetscDraw_TikZ;
13: #define TikZ_BEGIN_DOCUMENT \
14: "\\documentclass{beamer}\n\n\
15: \\usepackage{tikz}\n\
16: \\usepackage{pgflibraryshapes}\n\
17: \\usetikzlibrary{backgrounds}\n\
18: \\usetikzlibrary{arrows}\n\
19: \\newenvironment{changemargin}[2]{%%\n\
20: \\begin{list}{}{%%\n\
21: \\setlength{\\topsep}{0pt}%%\n\
22: \\setlength{\\leftmargin}{#1}%%\n\
23: \\setlength{\\rightmargin}{#2}%%\n\
24: \\setlength{\\listparindent}{\\parindent}%%\n\
25: \\setlength{\\itemindent}{\\parindent}%%\n\
26: \\setlength{\\parsep}{\\parskip}%%\n\
27: }%%\n\
28: \\item[]}{\\end{list}}\n\n\
29: \\begin{document}\n"
31: #define TikZ_BEGIN_FRAME \
32: "\\begin{frame}{}\n\
33: \\begin{changemargin}{-1cm}{0cm}\n\
34: \\begin{center}\n\
35: \\begin{tikzpicture}[scale = 10.00,font=\\fontsize{8}{8}\\selectfont]\n"
37: #define TikZ_END_FRAME \
38: "\\end{tikzpicture}\n\
39: \\end{center}\n\
40: \\end{changemargin}\n\
41: \\end{frame}\n"
43: #define TikZ_END_DOCUMENT "\\end{document}\n"
45: static PetscErrorCode PetscDrawDestroy_TikZ(PetscDraw draw)
46: {
47: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
49: PetscFunctionBegin;
50: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_FRAME));
51: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_DOCUMENT));
52: PetscCall(PetscFClose(PetscObjectComm((PetscObject)draw), win->fd));
53: PetscCall(PetscFree(win->filename));
54: PetscCall(PetscFree(draw->data));
55: PetscFunctionReturn(PETSC_SUCCESS);
56: }
58: static const char *TikZColors[] = {"white", "black", "red", "green", "cyan", "blue", "magenta", NULL, NULL, "orange", "violet", "brown", "pink", NULL, "yellow", NULL};
60: static inline const char *TikZColorMap(int cl)
61: {
62: return (cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black";
63: }
65: /*
66: These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
67: */
68: #define XTRANS(draw, x) (double)((draw)->port_xl + (((x - (draw)->coor_xl) * ((draw)->port_xr - (draw)->port_xl)) / ((draw)->coor_xr - (draw)->coor_xl)))
69: #define YTRANS(draw, y) (double)((draw)->port_yl + (((y - (draw)->coor_yl) * ((draw)->port_yr - (draw)->port_yl)) / ((draw)->coor_yr - (draw)->coor_yl)))
71: static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw)
72: {
73: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
75: PetscFunctionBegin;
76: /* often PETSc generates unneeded clears, we want avoid creating empty pictures for them */
77: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &win->written, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)draw)));
78: if (!win->written) PetscFunctionReturn(PETSC_SUCCESS);
79: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_FRAME));
80: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_FRAME));
81: win->written = PETSC_FALSE;
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: static PetscErrorCode PetscDrawLine_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int cl)
86: {
87: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
89: PetscFunctionBegin;
90: win->written = PETSC_TRUE;
91: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\draw [%s] (%g,%g) --(%g,%g);\n", TikZColorMap(cl), XTRANS(draw, xl), YTRANS(draw, yl), XTRANS(draw, xr), YTRANS(draw, yr)));
92: PetscFunctionReturn(PETSC_SUCCESS);
93: }
95: static PetscErrorCode PetscDrawRectangle_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4)
96: {
97: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
99: PetscFunctionBegin;
100: win->written = PETSC_TRUE;
101: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\fill [bottom color=%s,top color=%s] (%g,%g) rectangle (%g,%g);\n", TikZColorMap(c1), TikZColorMap(c4), XTRANS(draw, xl), YTRANS(draw, yl), XTRANS(draw, xr), YTRANS(draw, yr)));
102: PetscFunctionReturn(PETSC_SUCCESS);
103: }
105: static PetscErrorCode PetscDrawTriangle_TikZ(PetscDraw draw, PetscReal x1, PetscReal y1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3)
106: {
107: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
109: PetscFunctionBegin;
110: win->written = PETSC_TRUE;
111: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\fill [color=%s] (%g,%g) -- (%g,%g) -- (%g,%g) -- cycle;\n", TikZColorMap(c1), XTRANS(draw, x1), YTRANS(draw, y1), XTRANS(draw, x2), YTRANS(draw, y2), XTRANS(draw, x3), YTRANS(draw, y3)));
112: PetscFunctionReturn(PETSC_SUCCESS);
113: }
115: static PetscErrorCode PetscDrawEllipse_TikZ(PetscDraw draw, PetscReal x, PetscReal y, PetscReal a, PetscReal b, int c)
116: {
117: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
118: PetscReal rx, ry;
120: PetscFunctionBegin;
121: win->written = PETSC_TRUE;
122: rx = a / 2 * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl);
123: ry = b / 2 * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl);
124: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\fill [color=%s] (%g,%g) circle [x radius=%g,y radius=%g];\n", TikZColorMap(c), XTRANS(draw, x), YTRANS(draw, y), (double)rx, (double)ry));
125: PetscFunctionReturn(PETSC_SUCCESS);
126: }
128: static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, const char text[])
129: {
130: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
132: PetscFunctionBegin;
133: win->written = PETSC_TRUE;
134: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\node [above right, %s] at (%g,%g) {%s};\n", TikZColorMap(cl), XTRANS(draw, xl), YTRANS(draw, yl), text));
135: PetscFunctionReturn(PETSC_SUCCESS);
136: }
138: static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, const char text[])
139: {
140: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
141: size_t len;
142: PetscReal width;
144: PetscFunctionBegin;
145: win->written = PETSC_TRUE;
146: PetscCall(PetscStrlen(text, &len));
147: PetscCall(PetscDrawStringGetSize(draw, &width, NULL));
148: yl = yl - ((PetscReal)len) * width * (draw->coor_yr - draw->coor_yl) / (draw->coor_xr - draw->coor_xl);
149: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\node [rotate=90, %s] at (%g,%g) {%s};\n", TikZColorMap(cl), XTRANS(draw, xl), YTRANS(draw, yl), text));
150: PetscFunctionReturn(PETSC_SUCCESS);
151: }
153: /*
154: Does not handle multiline strings correctly
155: */
156: static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, int ct, const char text[], PetscReal *w, PetscReal *h)
157: {
158: PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
159: size_t len;
161: PetscFunctionBegin;
162: win->written = PETSC_TRUE;
163: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\draw (%g,%g) node [rectangle, draw, align=center, inner sep=1ex] {%s};\n", XTRANS(draw, xl), YTRANS(draw, yl), text));
165: /* make up totally bogus height and width of box */
166: PetscCall(PetscStrlen(text, &len));
167: if (w) *w = .07 * (PetscReal)len;
168: if (h) *h = .07;
169: PetscFunctionReturn(PETSC_SUCCESS);
170: }
172: static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw, PetscReal *x, PetscReal *y)
173: {
174: PetscFunctionBegin;
175: if (x) *x = .014 * (draw->coor_xr - draw->coor_xl) / (draw->port_xr - draw->port_xl);
176: if (y) *y = .05 * (draw->coor_yr - draw->coor_yl) / (draw->port_yr - draw->port_yl);
177: PetscFunctionReturn(PETSC_SUCCESS);
178: }
180: static struct _PetscDrawOps DvOps = {NULL, NULL, PetscDrawLine_TikZ, NULL, NULL, NULL, NULL, PetscDrawString_TikZ, PetscDrawStringVertical_TikZ, NULL, PetscDrawStringGetSize_TikZ, NULL, PetscDrawClear_TikZ, PetscDrawRectangle_TikZ, PetscDrawTriangle_TikZ, PetscDrawEllipse_TikZ, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, PetscDrawDestroy_TikZ, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, PetscDrawStringBoxed_TikZ, NULL};
182: PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw)
183: {
184: PetscDraw_TikZ *win;
186: PetscFunctionBegin;
187: draw->ops[0] = DvOps;
188: PetscCall(PetscNew(&win));
190: draw->data = (void *)win;
192: if (draw->title) {
193: PetscCall(PetscStrallocpy(draw->title, &win->filename));
194: } else {
195: const char *fname;
196: PetscCall(PetscObjectGetName((PetscObject)draw, &fname));
197: PetscCall(PetscStrallocpy(fname, &win->filename));
198: }
199: PetscCall(PetscFOpen(PetscObjectComm((PetscObject)draw), win->filename, "w", &win->fd));
200: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_DOCUMENT));
201: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_FRAME));
203: win->written = PETSC_FALSE;
204: PetscFunctionReturn(PETSC_SUCCESS);
205: }