xref: /petsc/src/sys/classes/draw/impls/tikz/tikz.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
142963b84SBarry Smith /*
2183a438dSBarry Smith     Defines the operations for the TikZ PetscDraw implementation.
342963b84SBarry Smith */
442963b84SBarry Smith 
5af0996ceSBarry Smith #include <petsc/private/drawimpl.h> /*I  "petscsys.h" I*/
642963b84SBarry Smith 
742963b84SBarry Smith typedef struct {
842963b84SBarry Smith   char     *filename;
942963b84SBarry Smith   FILE     *fd;
1042963b84SBarry Smith   PetscBool written; /* something has been written to the current frame */
1142963b84SBarry Smith } PetscDraw_TikZ;
1242963b84SBarry Smith 
13*9371c9d4SSatish Balay #define TikZ_BEGIN_DOCUMENT \
14*9371c9d4SSatish Balay   "\\documentclass{beamer}\n\n\
1542963b84SBarry Smith \\usepackage{tikz}\n\
1642963b84SBarry Smith \\usepackage{pgflibraryshapes}\n\
1742963b84SBarry Smith \\usetikzlibrary{backgrounds}\n\
1842963b84SBarry Smith \\usetikzlibrary{arrows}\n\
1942963b84SBarry Smith \\newenvironment{changemargin}[2]{%%\n\
2042963b84SBarry Smith   \\begin{list}{}{%%\n\
2142963b84SBarry Smith     \\setlength{\\topsep}{0pt}%%\n\
2242963b84SBarry Smith     \\setlength{\\leftmargin}{#1}%%\n\
2342963b84SBarry Smith     \\setlength{\\rightmargin}{#2}%%\n\
2442963b84SBarry Smith     \\setlength{\\listparindent}{\\parindent}%%\n\
2542963b84SBarry Smith     \\setlength{\\itemindent}{\\parindent}%%\n\
2642963b84SBarry Smith     \\setlength{\\parsep}{\\parskip}%%\n\
2742963b84SBarry Smith   }%%\n\
2842963b84SBarry Smith   \\item[]}{\\end{list}}\n\n\
2942963b84SBarry Smith \\begin{document}\n"
3042963b84SBarry Smith 
31*9371c9d4SSatish Balay #define TikZ_BEGIN_FRAME \
32*9371c9d4SSatish Balay   "\\begin{frame}{}\n\
3342963b84SBarry Smith \\begin{changemargin}{-1cm}{0cm}\n\
3442963b84SBarry Smith \\begin{center}\n\
3542963b84SBarry Smith \\begin{tikzpicture}[scale = 10.00,font=\\fontsize{8}{8}\\selectfont]\n"
3642963b84SBarry Smith 
37*9371c9d4SSatish Balay #define TikZ_END_FRAME \
38*9371c9d4SSatish Balay   "\\end{tikzpicture}\n\
3942963b84SBarry Smith \\end{center}\n\
4042963b84SBarry Smith \\end{changemargin}\n\
4142963b84SBarry Smith \\end{frame}\n"
4242963b84SBarry Smith 
4342963b84SBarry Smith #define TikZ_END_DOCUMENT "\\end{document}\n"
4442963b84SBarry Smith 
45*9371c9d4SSatish Balay static PetscErrorCode PetscDrawDestroy_TikZ(PetscDraw draw) {
4642963b84SBarry Smith   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
4742963b84SBarry Smith 
4842963b84SBarry Smith   PetscFunctionBegin;
499566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_FRAME));
509566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_DOCUMENT));
519566063dSJacob Faibussowitsch   PetscCall(PetscFClose(PetscObjectComm((PetscObject)draw), win->fd));
529566063dSJacob Faibussowitsch   PetscCall(PetscFree(win->filename));
539566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->data));
5442963b84SBarry Smith   PetscFunctionReturn(0);
5542963b84SBarry Smith }
5642963b84SBarry Smith 
5702c9f0b5SLisandro Dalcin static const char *TikZColors[] = {"white", "black", "red", "green", "cyan", "blue", "magenta", NULL, NULL, "orange", "violet", "brown", "pink", NULL, "yellow", NULL};
5842963b84SBarry Smith 
59*9371c9d4SSatish Balay static inline const char *TikZColorMap(int cl) {
6042963b84SBarry Smith   return ((cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black");
6142963b84SBarry Smith }
6242963b84SBarry Smith 
6342963b84SBarry Smith /*
6442963b84SBarry Smith      These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
6542963b84SBarry Smith */
6642963b84SBarry Smith #define XTRANS(draw, x) (double)(((draw)->port_xl + (((x - (draw)->coor_xl) * ((draw)->port_xr - (draw)->port_xl)) / ((draw)->coor_xr - (draw)->coor_xl))))
6742963b84SBarry Smith #define YTRANS(draw, y) (double)(((draw)->port_yl + (((y - (draw)->coor_yl) * ((draw)->port_yr - (draw)->port_yl)) / ((draw)->coor_yr - (draw)->coor_yl))))
6842963b84SBarry Smith 
69*9371c9d4SSatish Balay static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw) {
7042963b84SBarry Smith   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
715b399a63SLisandro Dalcin   PetscBool       written;
7242963b84SBarry Smith 
7342963b84SBarry Smith   PetscFunctionBegin;
7442963b84SBarry Smith   /* often PETSc generates unneeded clears, we want avoid creating empy pictures for them */
759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&win->written, &written, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)(draw))));
765b399a63SLisandro Dalcin   if (!written) PetscFunctionReturn(0);
779566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_END_FRAME));
789566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_FRAME));
795b399a63SLisandro Dalcin   win->written = PETSC_FALSE;
8071d8d82dSLisandro Dalcin   PetscFunctionReturn(0);
8171d8d82dSLisandro Dalcin }
8271d8d82dSLisandro Dalcin 
83*9371c9d4SSatish Balay static PetscErrorCode PetscDrawLine_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int cl) {
8442963b84SBarry Smith   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
8542963b84SBarry Smith 
8642963b84SBarry Smith   PetscFunctionBegin;
8742963b84SBarry Smith   win->written = PETSC_TRUE;
889566063dSJacob Faibussowitsch   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)));
8942963b84SBarry Smith   PetscFunctionReturn(0);
9042963b84SBarry Smith }
9142963b84SBarry Smith 
92*9371c9d4SSatish Balay static PetscErrorCode PetscDrawRectangle_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4) {
9332115b0cSJose E. Roman   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
9432115b0cSJose E. Roman 
9532115b0cSJose E. Roman   PetscFunctionBegin;
9632115b0cSJose E. Roman   win->written = PETSC_TRUE;
979566063dSJacob Faibussowitsch   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)));
9832115b0cSJose E. Roman   PetscFunctionReturn(0);
9932115b0cSJose E. Roman }
10032115b0cSJose E. Roman 
101*9371c9d4SSatish Balay static PetscErrorCode PetscDrawTriangle_TikZ(PetscDraw draw, PetscReal x1, PetscReal y1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3) {
10232115b0cSJose E. Roman   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
10332115b0cSJose E. Roman 
10432115b0cSJose E. Roman   PetscFunctionBegin;
10532115b0cSJose E. Roman   win->written = PETSC_TRUE;
1069566063dSJacob Faibussowitsch   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)));
10732115b0cSJose E. Roman   PetscFunctionReturn(0);
10832115b0cSJose E. Roman }
10932115b0cSJose E. Roman 
110*9371c9d4SSatish Balay static PetscErrorCode PetscDrawEllipse_TikZ(PetscDraw draw, PetscReal x, PetscReal y, PetscReal a, PetscReal b, int c) {
11132115b0cSJose E. Roman   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
11232115b0cSJose E. Roman   PetscReal       rx, ry;
11332115b0cSJose E. Roman 
11432115b0cSJose E. Roman   PetscFunctionBegin;
11532115b0cSJose E. Roman   win->written = PETSC_TRUE;
11632115b0cSJose E. Roman   rx           = a / 2 * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl);
11732115b0cSJose E. Roman   ry           = b / 2 * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl);
1189566063dSJacob Faibussowitsch   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));
11932115b0cSJose E. Roman   PetscFunctionReturn(0);
12032115b0cSJose E. Roman }
12132115b0cSJose E. Roman 
122*9371c9d4SSatish Balay static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, const char text[]) {
12342963b84SBarry Smith   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
12442963b84SBarry Smith 
12542963b84SBarry Smith   PetscFunctionBegin;
12642963b84SBarry Smith   win->written = PETSC_TRUE;
1279566063dSJacob Faibussowitsch   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));
12842963b84SBarry Smith   PetscFunctionReturn(0);
12942963b84SBarry Smith }
13042963b84SBarry Smith 
131*9371c9d4SSatish Balay static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, const char text[]) {
132d6ed00deSBarry Smith   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
133d6ed00deSBarry Smith   size_t          len;
134d6ed00deSBarry Smith   PetscReal       width;
135d6ed00deSBarry Smith 
136d6ed00deSBarry Smith   PetscFunctionBegin;
137d6ed00deSBarry Smith   win->written = PETSC_TRUE;
1389566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(text, &len));
1399566063dSJacob Faibussowitsch   PetscCall(PetscDrawStringGetSize(draw, &width, NULL));
140d6ed00deSBarry Smith   yl = yl - len * width * (draw->coor_yr - draw->coor_yl) / (draw->coor_xr - draw->coor_xl);
1419566063dSJacob Faibussowitsch   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));
142d6ed00deSBarry Smith   PetscFunctionReturn(0);
143d6ed00deSBarry Smith }
144d6ed00deSBarry Smith 
14542963b84SBarry Smith /*
14642963b84SBarry Smith     Does not handle multiline strings correctly
14742963b84SBarry Smith */
148*9371c9d4SSatish Balay static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw, PetscReal xl, PetscReal yl, int cl, int ct, const char text[], PetscReal *w, PetscReal *h) {
14942963b84SBarry Smith   PetscDraw_TikZ *win = (PetscDraw_TikZ *)draw->data;
15042963b84SBarry Smith   size_t          len;
15142963b84SBarry Smith 
15242963b84SBarry Smith   PetscFunctionBegin;
15342963b84SBarry Smith   win->written = PETSC_TRUE;
1549566063dSJacob Faibussowitsch   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));
15542963b84SBarry Smith 
15642963b84SBarry Smith   /* make up totally bogus height and width of box */
1579566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(text, &len));
15842963b84SBarry Smith   if (w) *w = .07 * len;
15942963b84SBarry Smith   if (h) *h = .07;
16042963b84SBarry Smith   PetscFunctionReturn(0);
16142963b84SBarry Smith }
16242963b84SBarry Smith 
163*9371c9d4SSatish Balay static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw, PetscReal *x, PetscReal *y) {
164d6ed00deSBarry Smith   PetscFunctionBegin;
165d6ed00deSBarry Smith   if (x) *x = .014 * (draw->coor_xr - draw->coor_xl) / ((draw->port_xr - draw->port_xl));
166d6ed00deSBarry Smith   if (y) *y = .05 * (draw->coor_yr - draw->coor_yl) / ((draw->port_yr - draw->port_yl));
167d6ed00deSBarry Smith   PetscFunctionReturn(0);
168d6ed00deSBarry Smith }
169d6ed00deSBarry Smith 
170*9371c9d4SSatish Balay 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};
17142963b84SBarry Smith 
172*9371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw) {
17342963b84SBarry Smith   PetscDraw_TikZ *win;
17442963b84SBarry Smith 
17542963b84SBarry Smith   PetscFunctionBegin;
1769566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(draw->ops, &DvOps, sizeof(DvOps)));
1779566063dSJacob Faibussowitsch   PetscCall(PetscNew(&win));
1789566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject)draw, sizeof(PetscDraw_TikZ)));
179a297a907SKarl Rupp 
18042963b84SBarry Smith   draw->data = (void *)win;
18142963b84SBarry Smith 
18242963b84SBarry Smith   if (draw->title) {
1839566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(draw->title, &win->filename));
18442963b84SBarry Smith   } else {
18542963b84SBarry Smith     const char *fname;
1869566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)draw, &fname));
1879566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(fname, &win->filename));
18842963b84SBarry Smith   }
1899566063dSJacob Faibussowitsch   PetscCall(PetscFOpen(PetscObjectComm((PetscObject)draw), win->filename, "w", &win->fd));
1909566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_DOCUMENT));
1919566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw), win->fd, TikZ_BEGIN_FRAME));
192a297a907SKarl Rupp 
19342963b84SBarry Smith   win->written = PETSC_FALSE;
19442963b84SBarry Smith   PetscFunctionReturn(0);
19542963b84SBarry Smith }
196