xref: /petsc/src/sys/classes/draw/impls/tikz/tikz.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
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   PetscErrorCode ierr;
46 
47   PetscFunctionBegin;
48   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME);CHKERRQ(ierr);
49   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_DOCUMENT);CHKERRQ(ierr);
50   ierr = PetscFClose(PetscObjectComm((PetscObject)draw),win->fd);CHKERRQ(ierr);
51   ierr = PetscFree(win->filename);CHKERRQ(ierr);
52   ierr = PetscFree(draw->data);CHKERRQ(ierr);
53   PetscFunctionReturn(0);
54 }
55 
56 static const char *TikZColors[] = {"white","black","red","green","cyan","blue","magenta",0,0,"orange","violet","brown","pink",0,"yellow",0};
57 
58 PETSC_STATIC_INLINE const char *TikZColorMap(int cl)
59 {
60   return((cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black");
61 }
62 
63 /*
64      These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
65 */
66 #define XTRANS(draw,x)  (double)(((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl))))
67 #define YTRANS(draw,y)  (double)(((draw)->port_yl + (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl))))
68 
69 static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw)
70 {
71   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
72   PetscBool      written;
73   PetscErrorCode ierr;
74 
75   PetscFunctionBegin;
76   /* often PETSc generates unneeded clears, we want avoid creating empy pictures for them */
77   ierr = MPI_Allreduce(&win->written,&written,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)(draw)));CHKERRQ(ierr);
78   if (!written) PetscFunctionReturn(0);
79   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME);CHKERRQ(ierr);
80   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME);CHKERRQ(ierr);
81   win->written = PETSC_FALSE;
82   PetscFunctionReturn(0);
83 }
84 
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;
88   PetscErrorCode ierr;
89 
90   PetscFunctionBegin;
91   win->written = PETSC_TRUE;
92   ierr = 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));CHKERRQ(ierr);
93   PetscFunctionReturn(0);
94 }
95 
96 static PetscErrorCode PetscDrawRectangle_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
97 {
98   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
99   PetscErrorCode ierr;
100 
101   PetscFunctionBegin;
102   win->written = PETSC_TRUE;
103   ierr = 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));CHKERRQ(ierr);
104   PetscFunctionReturn(0);
105 }
106 
107 static PetscErrorCode PetscDrawTriangle_TikZ(PetscDraw draw,PetscReal x1,PetscReal y1,PetscReal x2,PetscReal y2,PetscReal x3,PetscReal y3,int c1,int c2,int c3)
108 {
109   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
110   PetscErrorCode ierr;
111 
112   PetscFunctionBegin;
113   win->written = PETSC_TRUE;
114   ierr = 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));CHKERRQ(ierr);
115   PetscFunctionReturn(0);
116 }
117 
118 static PetscErrorCode PetscDrawEllipse_TikZ(PetscDraw draw,PetscReal x,PetscReal y,PetscReal a,PetscReal b,int c)
119 {
120   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
121   PetscReal      rx,ry;
122   PetscErrorCode ierr;
123 
124   PetscFunctionBegin;
125   win->written = PETSC_TRUE;
126   rx = a/2*(draw->port_xr-draw->port_xl)/(draw->coor_xr-draw->coor_xl);
127   ry = b/2*(draw->port_yr-draw->port_yl)/(draw->coor_yr-draw->coor_yl);
128   ierr = 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),rx,ry);CHKERRQ(ierr);
129   PetscFunctionReturn(0);
130 }
131 
132 static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
133 {
134   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
135   PetscErrorCode ierr;
136 
137   PetscFunctionBegin;
138   win->written = PETSC_TRUE;
139   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,"\\node [above right, %s] at (%g,%g) {%s};\n",TikZColorMap(cl),XTRANS(draw,xl),YTRANS(draw,yl),text);CHKERRQ(ierr);
140   PetscFunctionReturn(0);
141 }
142 
143 static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
144 {
145   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
146   PetscErrorCode ierr;
147   size_t         len;
148   PetscReal      width;
149 
150   PetscFunctionBegin;
151   win->written = PETSC_TRUE;
152   ierr = PetscStrlen(text,&len);CHKERRQ(ierr);
153   ierr = PetscDrawStringGetSize(draw,&width,NULL);CHKERRQ(ierr);
154   yl   = yl - len*width*(draw->coor_yr - draw->coor_yl)/(draw->coor_xr - draw->coor_xl);
155   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,"\\node [rotate=90, %s] at (%g,%g) {%s};\n",TikZColorMap(cl),XTRANS(draw,xl),YTRANS(draw,yl),text);CHKERRQ(ierr);
156   PetscFunctionReturn(0);
157 }
158 
159 /*
160     Does not handle multiline strings correctly
161 */
162 static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,int ct,const char text[],PetscReal *w,PetscReal *h)
163 {
164   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
165   PetscErrorCode ierr;
166   size_t         len;
167 
168   PetscFunctionBegin;
169   win->written = PETSC_TRUE;
170   ierr = 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);CHKERRQ(ierr);
171 
172   /* make up totally bogus height and width of box */
173   ierr = PetscStrlen(text,&len);CHKERRQ(ierr);
174   if (w) *w = .07*len;
175   if (h) *h = .07;
176   PetscFunctionReturn(0);
177 }
178 
179 static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw,PetscReal *x,PetscReal  *y)
180 {
181   PetscFunctionBegin;
182   if (x) *x = .014*(draw->coor_xr - draw->coor_xl)/((draw->port_xr - draw->port_xl));
183   if (y) *y = .05*(draw->coor_yr - draw->coor_yl)/((draw->port_yr - draw->port_yl));
184   PetscFunctionReturn(0);
185 }
186 
187 static struct _PetscDrawOps DvOps = { 0,
188                                       0,
189                                       PetscDrawLine_TikZ,
190                                       0,
191                                       0,
192                                       0,
193                                       0,
194                                       PetscDrawString_TikZ,
195                                       PetscDrawStringVertical_TikZ,
196                                       0,
197                                       PetscDrawStringGetSize_TikZ,
198                                       0,
199                                       PetscDrawClear_TikZ,
200                                       PetscDrawRectangle_TikZ,
201                                       PetscDrawTriangle_TikZ,
202                                       PetscDrawEllipse_TikZ,
203                                       0,
204                                       0,
205                                       0,
206                                       0,
207                                       0,
208                                       0,
209                                       0,
210                                       0,
211                                       PetscDrawDestroy_TikZ,
212                                       0,
213                                       0,
214                                       0,
215                                       0,
216                                       0,
217                                       0,
218                                       0,
219                                       0,
220                                       0,
221                                       0,
222                                       PetscDrawStringBoxed_TikZ};
223 
224 PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw)
225 {
226   PetscDraw_TikZ *win;
227   PetscErrorCode ierr;
228 
229   PetscFunctionBegin;
230   ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
231   ierr = PetscNew(&win);CHKERRQ(ierr);
232   ierr = PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_TikZ));CHKERRQ(ierr);
233 
234   draw->data = (void*) win;
235 
236   if (draw->title) {
237     ierr = PetscStrallocpy(draw->title,&win->filename);CHKERRQ(ierr);
238   } else {
239     const char *fname;
240     ierr = PetscObjectGetName((PetscObject)draw,&fname);CHKERRQ(ierr);
241     ierr = PetscStrallocpy(fname,&win->filename);CHKERRQ(ierr);
242   }
243   ierr = PetscFOpen(PetscObjectComm((PetscObject)draw),win->filename,"w",&win->fd);CHKERRQ(ierr);
244   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_DOCUMENT);CHKERRQ(ierr);
245   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME);CHKERRQ(ierr);
246 
247   win->written = PETSC_FALSE;
248   PetscFunctionReturn(0);
249 }
250