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:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_FRAME);
 50:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_DOCUMENT);
 51:   PetscFClose(PetscObjectComm((PetscObject)draw), win->fd);
 52:   PetscFree(win->filename);
 53:   PetscFree(draw->data);
 54:   return 0;
 55: }

 57: static const char *TikZColors[] = {"white", "black", "red", "green", "cyan", "blue", "magenta", NULL, NULL, "orange", "violet", "brown", "pink", NULL, "yellow", NULL};

 59: static inline const char *TikZColorMap(int cl)
 60: {
 61:   return ((cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black");
 62: }

 64: /*
 65:      These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
 66: */
 67: #define XTRANS(draw, x) (double)(((draw)->port_xl + (((x - (draw)->coor_xl) * ((draw)->port_xr - (draw)->port_xl)) / ((draw)->coor_xr - (draw)->coor_xl))))
 68: #define YTRANS(draw, y) (double)(((draw)->port_yl + (((y - (draw)->coor_yl) * ((draw)->port_yr - (draw)->port_yl)) / ((draw)->coor_yr - (draw)->coor_yl))))

 70: static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw)
 71: {
 72:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
 73:   PetscBool       written;

 75:   /* often PETSc generates unneeded clears, we want avoid creating empty pictures for them */
 76:   MPI_Allreduce(&win->written, &written, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)(draw)));
 77:   if (!written) return 0;
 78:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_FRAME);
 79:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_FRAME);
 80:   win->written = PETSC_FALSE;
 81:   return 0;
 82: }

 84: static PetscErrorCode PetscDrawLine_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int cl)
 85: {
 86:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;

 88:   win->written = PETSC_TRUE;
 89:   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));
 90:   return 0;
 91: }

 93: static PetscErrorCode PetscDrawRectangle_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4)
 94: {
 95:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;

 97:   win->written = PETSC_TRUE;
 98:   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));
 99:   return 0;
100: }

102: static PetscErrorCode PetscDrawTriangle_TikZ(PetscDraw draw, PetscReal x1, PetscReal y1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3)
103: {
104:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;

106:   win->written = PETSC_TRUE;
107:   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));
108:   return 0;
109: }

111: static PetscErrorCode PetscDrawEllipse_TikZ(PetscDraw draw, PetscReal x, PetscReal y, PetscReal a, PetscReal b, int c)
112: {
113:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
114:   PetscReal       rx, ry;

116:   win->written = PETSC_TRUE;
117:   rx           = a / 2 * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl);
118:   ry           = b / 2 * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl);
119:   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);
120:   return 0;
121: }

123: static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, const char text[])
124: {
125:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;

127:   win->written = PETSC_TRUE;
128:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\node [above right, %s] at (%g,%g) {%s};\n", TikZColorMap(cl), XTRANS(draw, xl), YTRANS(draw, yl), text);
129:   return 0;
130: }

132: static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, const char text[])
133: {
134:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
135:   size_t          len;
136:   PetscReal       width;

138:   win->written = PETSC_TRUE;
139:   PetscStrlen(text, &len);
140:   PetscDrawStringGetSize(draw, &width, NULL);
141:   yl = yl - len * width * (draw->coor_yr - draw->coor_yl) / (draw->coor_xr - draw->coor_xl);
142:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, "\\node [rotate=90, %s] at (%g,%g) {%s};\n", TikZColorMap(cl), XTRANS(draw, xl), YTRANS(draw, yl), text);
143:   return 0;
144: }

146: /*
147:     Does not handle multiline strings correctly
148: */
149: static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, int ct, const char text[], PetscReal *w, PetscReal *h)
150: {
151:   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
152:   size_t          len;

154:   win->written = PETSC_TRUE;
155:   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);

157:   /* make up totally bogus height and width of box */
158:   PetscStrlen(text, &len);
159:   if (w) *w = .07 * len;
160:   if (h) *h = .07;
161:   return 0;
162: }

164: static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw, PetscReal *x, PetscReal *y)
165: {
166:   if (x) *x = .014 * (draw->coor_xr - draw->coor_xl) / ((draw->port_xr - draw->port_xl));
167:   if (y) *y = .05 * (draw->coor_yr - draw->coor_yl) / ((draw->port_yr - draw->port_yl));
168:   return 0;
169: }

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

173: PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw)
174: {
175:   PetscDraw_TikZ *win;

177:   PetscMemcpy(draw->ops, &DvOps, sizeof(DvOps));
178:   PetscNew(&win);

180:   draw->data = (void *)win;

182:   if (draw->title) {
183:     PetscStrallocpy(draw->title, &win->filename);
184:   } else {
185:     const char *fname;
186:     PetscObjectGetName((PetscObject)draw, &fname);
187:     PetscStrallocpy(fname, &win->filename);
188:   }
189:   PetscFOpen(PetscObjectComm((PetscObject)draw), win->filename, "w", &win->fd);
190:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_DOCUMENT);
191:   PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_FRAME);

193:   win->written = PETSC_FALSE;
194:   return 0;
195: }