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