xref: /petsc/src/sys/classes/draw/impls/tikz/tikz.c (revision ffa8c5705e8ab2cf85ee1d14dbe507a6e2eb5283)
1 /*
2     Defines the operations for the TikZ PetscDraw implementation.
3 */
4 
5 #include <petsc/private/drawimpl.h>         /*I  "petscsys.h" I*/
6 
7 typedef struct {
8   char      *filename;
9   FILE      *fd;
10   PetscBool written;  /* something has been written to the current frame */
11 } PetscDraw_TikZ;
12 
13 #define TikZ_BEGIN_DOCUMENT  "\\documentclass{beamer}\n\n\
14 \\usepackage{tikz}\n\
15 \\usepackage{pgflibraryshapes}\n\
16 \\usetikzlibrary{backgrounds}\n\
17 \\usetikzlibrary{arrows}\n\
18 \\newenvironment{changemargin}[2]{%%\n\
19   \\begin{list}{}{%%\n\
20     \\setlength{\\topsep}{0pt}%%\n\
21     \\setlength{\\leftmargin}{#1}%%\n\
22     \\setlength{\\rightmargin}{#2}%%\n\
23     \\setlength{\\listparindent}{\\parindent}%%\n\
24     \\setlength{\\itemindent}{\\parindent}%%\n\
25     \\setlength{\\parsep}{\\parskip}%%\n\
26   }%%\n\
27   \\item[]}{\\end{list}}\n\n\
28 \\begin{document}\n"
29 
30 #define TikZ_BEGIN_FRAME "\\begin{frame}{}\n\
31 \\begin{changemargin}{-1cm}{0cm}\n\
32 \\begin{center}\n\
33 \\begin{tikzpicture}[scale = 10.00,font=\\fontsize{8}{8}\\selectfont]\n"
34 
35 #define TikZ_END_FRAME "\\end{tikzpicture}\n\
36 \\end{center}\n\
37 \\end{changemargin}\n\
38 \\end{frame}\n"
39 
40 #define TikZ_END_DOCUMENT  "\\end{document}\n"
41 
42 static PetscErrorCode  PetscDrawDestroy_TikZ(PetscDraw draw)
43 {
44   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
45 
46   PetscFunctionBegin;
47   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME));
48   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_DOCUMENT));
49   PetscCall(PetscFClose(PetscObjectComm((PetscObject)draw),win->fd));
50   PetscCall(PetscFree(win->filename));
51   PetscCall(PetscFree(draw->data));
52   PetscFunctionReturn(0);
53 }
54 
55 static const char *TikZColors[] = {"white","black","red","green","cyan","blue","magenta",NULL,NULL,"orange","violet","brown","pink",NULL,"yellow",NULL};
56 
57 static inline const char *TikZColorMap(int cl)
58 {
59   return((cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black");
60 }
61 
62 /*
63      These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
64 */
65 #define XTRANS(draw,x)  (double)(((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl))))
66 #define YTRANS(draw,y)  (double)(((draw)->port_yl + (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl))))
67 
68 static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw)
69 {
70   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
71   PetscBool      written;
72 
73   PetscFunctionBegin;
74   /* often PETSc generates unneeded clears, we want avoid creating empy pictures for them */
75   PetscCallMPI(MPI_Allreduce(&win->written,&written,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)(draw))));
76   if (!written) PetscFunctionReturn(0);
77   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME));
78   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME));
79   win->written = PETSC_FALSE;
80   PetscFunctionReturn(0);
81 }
82 
83 static PetscErrorCode PetscDrawLine_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
84 {
85   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
86 
87   PetscFunctionBegin;
88   win->written = PETSC_TRUE;
89   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)));
90   PetscFunctionReturn(0);
91 }
92 
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;
96 
97   PetscFunctionBegin;
98   win->written = PETSC_TRUE;
99   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)));
100   PetscFunctionReturn(0);
101 }
102 
103 static PetscErrorCode PetscDrawTriangle_TikZ(PetscDraw draw,PetscReal x1,PetscReal y1,PetscReal x2,PetscReal y2,PetscReal x3,PetscReal y3,int c1,int c2,int c3)
104 {
105   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
106 
107   PetscFunctionBegin;
108   win->written = PETSC_TRUE;
109   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)));
110   PetscFunctionReturn(0);
111 }
112 
113 static PetscErrorCode PetscDrawEllipse_TikZ(PetscDraw draw,PetscReal x,PetscReal y,PetscReal a,PetscReal b,int c)
114 {
115   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
116   PetscReal      rx,ry;
117 
118   PetscFunctionBegin;
119   win->written = PETSC_TRUE;
120   rx = a/2*(draw->port_xr-draw->port_xl)/(draw->coor_xr-draw->coor_xl);
121   ry = b/2*(draw->port_yr-draw->port_yl)/(draw->coor_yr-draw->coor_yl);
122   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));
123   PetscFunctionReturn(0);
124 }
125 
126 static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
127 {
128   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
129 
130   PetscFunctionBegin;
131   win->written = PETSC_TRUE;
132   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));
133   PetscFunctionReturn(0);
134 }
135 
136 static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
137 {
138   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
139   size_t         len;
140   PetscReal      width;
141 
142   PetscFunctionBegin;
143   win->written = PETSC_TRUE;
144   PetscCall(PetscStrlen(text,&len));
145   PetscCall(PetscDrawStringGetSize(draw,&width,NULL));
146   yl   = yl - len*width*(draw->coor_yr - draw->coor_yl)/(draw->coor_xr - draw->coor_xl);
147   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));
148   PetscFunctionReturn(0);
149 }
150 
151 /*
152     Does not handle multiline strings correctly
153 */
154 static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,int ct,const char text[],PetscReal *w,PetscReal *h)
155 {
156   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
157   size_t         len;
158 
159   PetscFunctionBegin;
160   win->written = PETSC_TRUE;
161   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));
162 
163   /* make up totally bogus height and width of box */
164   PetscCall(PetscStrlen(text,&len));
165   if (w) *w = .07*len;
166   if (h) *h = .07;
167   PetscFunctionReturn(0);
168 }
169 
170 static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw,PetscReal *x,PetscReal  *y)
171 {
172   PetscFunctionBegin;
173   if (x) *x = .014*(draw->coor_xr - draw->coor_xl)/((draw->port_xr - draw->port_xl));
174   if (y) *y = .05*(draw->coor_yr - draw->coor_yl)/((draw->port_yr - draw->port_yl));
175   PetscFunctionReturn(0);
176 }
177 
178 static struct _PetscDrawOps DvOps = { NULL,
179                                       NULL,
180                                       PetscDrawLine_TikZ,
181                                       NULL,
182                                       NULL,
183                                       NULL,
184                                       NULL,
185                                       PetscDrawString_TikZ,
186                                       PetscDrawStringVertical_TikZ,
187                                       NULL,
188                                       PetscDrawStringGetSize_TikZ,
189                                       NULL,
190                                       PetscDrawClear_TikZ,
191                                       PetscDrawRectangle_TikZ,
192                                       PetscDrawTriangle_TikZ,
193                                       PetscDrawEllipse_TikZ,
194                                       NULL,
195                                       NULL,
196                                       NULL,
197                                       NULL,
198                                       NULL,
199                                       NULL,
200                                       NULL,
201                                       NULL,
202                                       PetscDrawDestroy_TikZ,
203                                       NULL,
204                                       NULL,
205                                       NULL,
206                                       NULL,
207                                       NULL,
208                                       NULL,
209                                       NULL,
210                                       NULL,
211                                       NULL,
212                                       NULL,
213                                       PetscDrawStringBoxed_TikZ};
214 
215 PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw)
216 {
217   PetscDraw_TikZ *win;
218 
219   PetscFunctionBegin;
220   PetscCall(PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps)));
221   PetscCall(PetscNew(&win));
222   PetscCall(PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_TikZ)));
223 
224   draw->data = (void*) win;
225 
226   if (draw->title) {
227     PetscCall(PetscStrallocpy(draw->title,&win->filename));
228   } else {
229     const char *fname;
230     PetscCall(PetscObjectGetName((PetscObject)draw,&fname));
231     PetscCall(PetscStrallocpy(fname,&win->filename));
232   }
233   PetscCall(PetscFOpen(PetscObjectComm((PetscObject)draw),win->filename,"w",&win->fd));
234   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_DOCUMENT));
235   PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME));
236 
237   win->written = PETSC_FALSE;
238   PetscFunctionReturn(0);
239 }
240