gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
gl2pgf.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 //
6 // Contributed by Sebastian Eiser
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include "GmshConfig.h"
11 #include "PixelBuffer.h"
12 #include "OS.h"
13 #include "Context.h"
14 #include "PView.h"
15 #include "PViewData.h"
16 #include "Numeric.h"
17 #include "Options.h"
18 #include "StringUtils.h"
19 #include "gl2png.h"
20 
21 static int assembleColmapStr(const int num, const int intType, int &samples,
22  std::string &ret)
23 {
24  GmshColorTable *ct = GetColorTable(num); // i
25  ret.assign("\\pgfplotsset{\ncolormap={gmshcolormap}{%% note: "
26  "Only needed once if colorbars do not change\n");
27 
28  samples = (int)opt_view_nb_iso(num, GMSH_GET, 0);
29  double step = 0.;
30  switch(intType) {
31  case 2:
32  samples = 64;
33  break; // continuous is approximated by 64 samples
34  case 3:
35  break; // filled (sampled colorbar)
36  case 1:
37  break; // iso lines
38  case 4: // numericals
39  default: return 1;
40  }
41  step = (double)(1. * ct->size) / (samples - 1.);
42  int r, g, b, a;
43  unsigned int idx;
44  char tmp[265];
45  for(unsigned int j = 0; j < (unsigned int)samples - 1; j++ /*j+=4*/) {
46  idx = (unsigned int)j * step;
47  // printf("j=%d, idx=%d step=%f\n", j, idx, step);
48  r = CTX::instance()->unpackRed(ct->table[idx]);
49  g = CTX::instance()->unpackGreen(ct->table[idx]);
50  b = CTX::instance()->unpackBlue(ct->table[idx]);
51  a = CTX::instance()->unpackAlpha(ct->table[idx]);
52  if(a != 255)
53  Msg::Warning("PGF export does not handle transparent colormaps");
54 
55  sprintf(tmp, "rgb255=(%d,%d,%d) ", r, g, b);
56  ret.append(tmp);
57 
58  if(intType != 2) // sampled
59  // reinsert, because then the end color is interpreted correctly
60  // for shader=flat mean
61  ret.append(tmp);
62  }
63  // endpoint
64  r = CTX::instance()->unpackRed(ct->table[ct->size - 1]);
65  g = CTX::instance()->unpackGreen(ct->table[ct->size - 1]);
66  b = CTX::instance()->unpackBlue(ct->table[ct->size - 1]);
67  sprintf(tmp, "rgb255=(%d,%d,%d) ", r, g, b);
68  ret.append(tmp);
69  if(intType != 2) // sampled
70  // reinsert, because then the end color is interpreted correctly
71  // for shader=flat mean
72  ret.append(tmp);
73 
74  ret.append("}\n}%%\n");
75 
76  return 0;
77 }
78 
79 static int assembleColbarStr(const int num, const int intType,
80  const int samples, std::string &ret)
81 {
82  double cbmin, cbmax;
83  cbmin = opt_view_min(num, GMSH_GET, 0);
84  cbmax = opt_view_max(num, GMSH_GET, 0);
85  int rangeType = (int)opt_view_range_type(num, GMSH_GET, 0);
86  char tmp[265];
87  switch(rangeType) {
88  case 2: {
89  cbmin = opt_view_custom_min(num, GMSH_GET, 0);
90  cbmax = opt_view_custom_max(num, GMSH_GET, 0);
91  break;
92  }
93  case 1: // default
94  case 3: // per time step FIXME
95  default: break;
96  }
97  ret.assign("\tcolorbar style={\n\t\t%%width=0.5cm, "
98  "%% adjust width of colorbar\n"
99  "\t\t%%height=6cm,%% adjust height of colorbar,\n");
100  if(intType != 2) { // sampled
101  sprintf(tmp, "\t\tsamples=%d,\n", samples + 1);
102  ret.append(tmp);
103  }
104 
105  int scaleType = (int)opt_view_scale_type(num, GMSH_GET, 0);
106  int horizontal = (int)opt_print_pgf_horiz_bar(0, GMSH_GET, 0);
107  // 1 linear
108  // 2 log
109  // 3 double log ???
110  if(scaleType == 2) { // log
111  // see
112  // http://tex.stackexchange.com/questions/23750/log-color-bar-meta-data-in-pgfplot
113  if(horizontal)
114  sprintf(tmp, "\t\txticklabel={$10^{\\pgfmathparse{\\tick}"
115  "\\pgfmathprintnumber\\pgfmathresult}$},\n");
116  else
117  sprintf(tmp, "\t\tyticklabel={$10^{\\pgfmathparse{\\tick}"
118  "\\pgfmathprintnumber\\pgfmathresult}$},\n");
119  ret.append(tmp);
120  }
121 
122  ret.append("\t}]\n\t %% a dummy plot for the colorbar (invisible):\n");
123  if(scaleType == 2) { // log
124  cbmin = log10(cbmin);
125  cbmax = log10(cbmax);
126  }
127  sprintf(
128  tmp,
129  "\t \\addplot[point meta min=%f,"
130  "point meta max=%f, update limits=false, draw=none, colorbar source]\n\t"
131  "coordinates{(1,1)};\n",
132  cbmin, cbmax);
133  ret.append(tmp);
134  return 0;
135 }
136 
137 static int assemblePostAxis(const int num, const int intType, std::string &ret)
138 {
139  int horizontal = (int)opt_print_pgf_horiz_bar(0, GMSH_GET, 0);
140  std::string post_var;
141  char tmp[265];
142  post_var = PView::list[num]->getData()->getName();
143 
144  if(!post_var.empty()) {
145  sprintf(tmp, "\ttitle={%s},\n", post_var.c_str());
146  ret.assign(tmp);
147  }
148  ret.append("\tcolorbar,\n\tcolormap name=gmshcolormap,\n");
149  if(horizontal) {
150  ret.append("\tcolorbar horizontal,\n");
151  }
152  else {
153  ret.append("\tcolorbar right, %% or left...\n");
154  }
155  if(intType == 3) { // sampled
156  ret.append("\tcolorbar sampled,\n");
157  }
158  else if(intType == 1) {
159  ret.append("\tcolorbar sampled line,\n");
160  }
161  return 0;
162 }
163 
164 static int getMinMaxOfAxis(const int num, double result[8][3])
165 {
166  double xmin, xmax, ymin, ymax, zmin, zmax;
167  // axes ranges
168  if(!(int)opt_general_axes_auto_position(0, GMSH_GET, 0)) {
169  // needs to get manual axes set
170  xmin = opt_general_axes_xmin(0, GMSH_GET, 0);
171  xmax = opt_general_axes_xmax(0, GMSH_GET, 0);
172  ymin = opt_general_axes_ymin(0, GMSH_GET, 0);
173  ymax = opt_general_axes_ymax(0, GMSH_GET, 0);
174  zmin = opt_general_axes_zmin(0, GMSH_GET, 0);
175  zmax = opt_general_axes_zmax(0, GMSH_GET, 0);
176  fprintf(stderr, "General axes non auto, using\n");
177  fprintf(stderr, "x=(%f,%f), y=(%f,%f), z=(%f,%f)\n", xmin, xmax, ymin, ymax,
178  zmin, zmax);
179  }
180  else if(num >= 0 && !(int)opt_view_axes_auto_position(num, GMSH_GET, 0)) {
181  // needs to get manual axes set
182  xmin = opt_view_axes_xmin(num, GMSH_GET, 0);
183  xmax = opt_view_axes_xmax(num, GMSH_GET, 0);
184  ymin = opt_view_axes_ymin(num, GMSH_GET, 0);
185  ymax = opt_view_axes_ymax(num, GMSH_GET, 0);
186  zmin = opt_view_axes_zmin(num, GMSH_GET, 0);
187  zmax = opt_view_axes_zmax(num, GMSH_GET, 0);
188  fprintf(stderr, "View axes non auto, using:\n");
189  fprintf(stderr, "x=(%f,%f), y=(%f,%f), z=(%f,%f)\n", xmin, xmax, ymin, ymax,
190  zmin, zmax);
191  }
192  else { // default
193  xmin = CTX::instance()->min[0];
194  xmax = CTX::instance()->max[0];
195  ymin = CTX::instance()->min[1];
196  ymax = CTX::instance()->max[1];
197  zmin = CTX::instance()->min[2];
198  zmax = CTX::instance()->max[2];
199  fprintf(stderr, "Axes auto, using:\n");
200  fprintf(stderr, "x=(%f,%f), y=(%f,%f), z=(%f,%f)\n", xmin, xmax, ymin, ymax,
201  zmin, zmax);
202  }
203  result[0][0] = result[1][0] = result[2][0] = result[3][0] = xmin;
204  result[4][0] = result[5][0] = result[6][0] = result[7][0] = xmax;
205 
206  result[0][1] = result[1][1] = result[4][1] = result[5][1] = ymin;
207  result[2][1] = result[3][1] = result[6][1] = result[7][1] = ymax;
208 
209  result[0][2] = result[2][2] = result[4][2] = result[6][2] = zmin;
210  result[1][2] = result[3][2] = result[5][2] = result[7][2] = zmax;
211  // result = {
212  // { xmin, ymin, zmin}, // origin
213  // { xmin, ymin, zmax}, // y end
214  // { xmin, ymax, zmin}, // y end z end
215  // { xmin, ymax, zmax}, // y end z end
216  // { xmax, ymin, zmin}, // x end
217  // { xmax, ymin, zmax}, // x end y end
218  // { xmax, ymax, zmin}, // x end y end z end
219  // { xmax, ymax, zmax} // x end z end
220  // };
221  return 0;
222 }
223 
224 static int assemble2d(const int num, const int exportAxis, std::string &axisstr,
225  std::string &plotstr, double *eulerAngles)
226 {
227  double axPts[8][3];
228  double factor = 1.;
229  double xmin, xmax, ymin, ymax;
230 
231  axisstr.append("\taxis equal image, %% use png aspect ratio\n");
232 
233  if(exportAxis) {
234  getMinMaxOfAxis(num, axPts);
235  std::string xlab, ylab, zlab;
236  xlab = CTX::instance()->axesLabel[0];
237  ylab = CTX::instance()->axesLabel[1];
238  zlab = CTX::instance()->axesLabel[2];
239  if(xlab.empty()) xlab = "x";
240  if(ylab.empty()) ylab = "y";
241  if(zlab.empty()) zlab = "z";
242 
243  fprintf(stderr, "Euler two dim: 0:%f, 1:%f, 2:%f\n", eulerAngles[0],
244  eulerAngles[1], eulerAngles[2]);
245  int r0 = (int)(eulerAngles[0] + 0.5);
246  int r1 = (int)(eulerAngles[1] + 0.5);
247  int r2 = (int)(eulerAngles[2] + 0.5);
248  if(r0 % 90 != 0 || r1 % 90 != 0 || r2 % 90 != 0) {
249  fprintf(stderr, "Euler two dim: 0:%d, 1:%d, 2:%d\n", r0, r1, r2);
250  Msg::Error("Please select a plane view (X, Y, Z)");
251  return 1;
252  }
253  if(r0 % 180 == 0 && r1 % 360 == 0 && r2 % 180 == 0) {
254  // xy
255  xmin = axPts[0][0];
256  xmax = axPts[4][0];
257  ymin = axPts[0][1];
258  ymax = axPts[2][1];
259  if(r2 == 180) axisstr.append("\tx dir=reverse,\n");
260  if((r2 == 180 && abs(r0) < 1) || (r0 == 180 && abs(r2) < 1))
261  axisstr.append("\ty dir=reverse,\n");
262  axisstr.append("\txlabel={" + xlab + "},\n");
263  axisstr.append("\tylabel={" + ylab + "},\n");
264  }
265  else if(r0 % 180 == 0 && r1 % 360 == 0 && (r2 == 90 || r2 == 270)) {
266  // yx
267  xmin = axPts[0][1];
268  xmax = axPts[2][1];
269  ymin = axPts[0][0];
270  ymax = axPts[4][0];
271  if(r2 == 90) axisstr.append("\tx dir=reverse,\n");
272  if(r2 == 270 || (r2 == 90 && r0 == 180))
273  axisstr.append("\ty dir=reverse,\n");
274  axisstr.append("\txlabel={" + ylab + "},\n");
275  axisstr.append("\tylabel={" + xlab + "},\n");
276  }
277  else if((r0 == 90 || r0 == 270) && r1 % 360 == 0 &&
278  (r2 == 90 || r2 == 270)) {
279  xmin = axPts[0][1];
280  xmax = axPts[2][1];
281  ymin = axPts[0][2];
282  ymax = axPts[1][2];
283  if(r2 == 90) axisstr.append("\tx dir=reverse,\n");
284  if(r0 == 90) axisstr.append("\ty dir=reverse,\n");
285  // yz
286  axisstr.append("\txlabel={" + ylab + "},\n");
287  axisstr.append("\tylabel={" + zlab + "},\n");
288  }
289  else if(r0 % 360 == 0 && (r1 == 90 || r1 == 270) && r2 % 180 == 0) {
290  // zy
291  xmin = axPts[0][2];
292  xmax = axPts[1][2];
293  ymin = axPts[0][1];
294  ymax = axPts[2][1];
295  if(r1 == 270) axisstr.append("\tx dir=reverse,\n");
296  if(r2 == 180) axisstr.append("\ty dir=reverse,\n");
297  axisstr.append("\txlabel={" + zlab + "},\n");
298  axisstr.append("\tylabel={" + ylab + "},\n");
299  }
300  else if((r0 == 90 || r0 == 270) && r1 % 360 == 0 && r2 % 180 == 0) {
301  // xz
302  xmin = axPts[0][0];
303  xmax = axPts[4][0];
304  ymin = axPts[0][2];
305  ymax = axPts[1][2];
306  if(r2 == 180) // x dir=reverse
307  axisstr.append("\tx dir=reverse,\n");
308  if(r0 == 90) axisstr.append("\ty dir=reverse,\n");
309  axisstr.append("\txlabel={" + xlab + "},\n");
310  axisstr.append("\tylabel={" + zlab + "},\n");
311  }
312  else if(r0 % 360 == 0 && (r1 == 90 || r1 == 270) &&
313  (r2 == 90 || r2 == 270)) {
314  if(r1 == 270) axisstr.append("\tx dir=reverse,\n");
315  if(r2 == 270) axisstr.append("\ty dir=reverse,\n");
316  // zx
317  xmin = axPts[0][2];
318  xmax = axPts[1][2];
319  ymin = axPts[0][0];
320  ymax = axPts[4][0];
321  axisstr.append("\txlabel={" + zlab + "},\n");
322  axisstr.append("\tylabel={" + xlab + "},\n");
323  }
324  else {
325  Msg::Error("Cannot infer orientation from Euler angles...");
326  // this should not happen
327  // error=true;
328  return 2;
329  }
330  if(fabs(xmax - xmin) < 1e-8 || fabs(ymax - ymin) < 1e-8) {
331  Msg::Error(
332  "I inferred x (%f) or y (%f) dimension to be zero. Cannot produce.",
333  fabs(xmax - xmin), fabs(ymax - ymin));
334  return 3;
335  }
336 
337  double diagonal[3] = {xmax - xmin, ymax - ymin, 0};
338  double minlen = norm3(diagonal);
339  std::string suffix;
340  if(minlen < 1e-5) {
341  factor = 1e6;
342  suffix.assign(" / $\\mu$m");
343  }
344  else if(minlen < 0.01) {
345  factor = 1e3;
346  suffix.assign(" / mm");
347  }
348  else if(minlen > 1e6) {
349  factor = 1e-6;
350  suffix.assign(" / Mm");
351  }
352  else if(minlen > 1000) {
353  factor = 1e-3;
354  suffix.assign(" / Km");
355  }
356  if(factor != 1) {
357  char tmp[265];
358  sprintf(tmp,
359  "The pgf output has been rescaled in order to please "
360  "the TeX number precision/range. Rescaling your results by "
361  "a factor %g",
362  factor);
363  Msg::Warning(tmp);
364  // sprintf(tmp, "$\\times 10^{%d}$},",(int)(log10(factor)+0.5));
365  // std::string repl = tmp;
366  // replace two labels
367  std::size_t foundy = axisstr.rfind("},");
368  if(foundy != std::string::npos)
369  axisstr.insert(foundy, suffix);
370  else
371  return 4;
372 
373  std::size_t foundx = axisstr.rfind("},", foundy);
374  if(foundx != std::string::npos)
375  axisstr.insert(foundx, suffix);
376  else
377  return 4;
378  }
379  // axis options
380  axisstr.append("\tenlargelimits=false, %% tight axis, use xmin=<val>, ");
381  axisstr.append("xmax=<val> for custom bounding box\n");
382  axisstr.append("\taxis on top,\n\tscale only axis,\n");
383  }
384  else {
385  // no axis
386  xmin = 0, xmax = 1, ymin = 0, ymax = 1;
387  axisstr.append("\thide axis,\n");
388  }
389  char tmp[265];
390  sprintf(tmp, "\t \\addplot graphics[xmin=%f, xmax=%f, ymin=%f, ymax=%f]\n",
391  xmin * factor, xmax * factor, ymin * factor, ymax * factor);
392 
393  plotstr.assign(tmp);
394 
395  return 0;
396 }
397 
398 static int assemble3d(const int num, const int exportAxis, std::string &axisstr,
399  std::string &plotstr, double *eulerAngles, int *viewport,
400  double *proj, double *model, int ypix, int xpix)
401 {
402  if(exportAxis) {
403  axisstr.append("\tenlargelimits=false, %% tight axis, use xmin=<val>, ");
404  axisstr.append("xmax=<val> for custom bounding box\n");
405  axisstr.append("\tgrid=both,\n\tminor tick num=1,\n");
406  std::string xlab, ylab, zlab;
407  xlab = CTX::instance()->axesLabel[0];
408  ylab = CTX::instance()->axesLabel[1];
409  zlab = CTX::instance()->axesLabel[2];
410  if(xlab.empty()) xlab = "x";
411  if(ylab.empty()) ylab = "y";
412  if(zlab.empty()) zlab = "z";
413  axisstr.append("\txlabel={" + xlab + "}, %%\n\tylabel={" + ylab +
414  "},\n\tzlabel={" + zlab + "},\n");
415 
416  axisstr.append("\tzlabel style={rotate=-90},\n"); // bug?
417  }
418  else {
419  if(opt_general_orthographic(0, GMSH_GET, 0) == 0) {
420  Msg::Warning("Axes are not orthogonal, but because you do not want "
421  "any axes, I'll continue with a 2d picture.");
422  return assemble2d(num, 0, axisstr, plotstr, eulerAngles);
423  }
424  if(CTX::instance()->camera) {
425  Msg::Warning("Camera output not supported, but since you do not want "
426  "any axes, I'll continue with a 2d picture.");
427  return assemble2d(num, 0, axisstr, plotstr, eulerAngles);
428  }
429  axisstr.append("\thide axis,\n");
430  }
431 
432  if(opt_general_orthographic(0, GMSH_GET, 0) == 0 && exportAxis) {
433  Msg::Warning("Cannot produce output if axes are not orthogonal.");
434  Msg::Error("Please switch to orthographic projection mode "
435  "('Alt + o') and retry if you want to output axes.");
436  return 1;
437  }
438 
439  double axPts[8][3];
440  getMinMaxOfAxis(num, axPts);
441  double factor = 1.;
442  // requires the pixel coordinates of the axis ends (actually any four
443  // points with all different x/y/z <pixX, pixY> would suffice)
444  double axViewPt[8][3];
445  std::vector<int> acceptableAnchors;
446  std::vector<int> masked;
447 
448  bool reorder = false;
449  double minlen = 0.;
450  std::string suffix;
451  for(unsigned int j = 0; j < 8; j++) {
452  // project the 8 axis end points to pixel coordinates,
453  // accept if they are in the screen range.
454 
455  gluProject(axPts[j][0], axPts[j][1], axPts[j][2], model, proj, viewport,
456  &axViewPt[j][0], &axViewPt[j][1], &axViewPt[j][2]);
457  // printf("x=%f, y=%f, z=%f\n", axPts[j][0], axPts[j][1], axPts[j][2]);
458  // printf("xprn=%f, yprn=%f, zprn=%f\n",
459  // axViewPt[j][0], axViewPt[j][1], axViewPt[j][2]);
460  if((int)(axViewPt[j][0] + 0.5) <= xpix &&
461  (int)(axViewPt[j][1] + 0.5) <= ypix) {
462  acceptableAnchors.push_back(j);
463  }
464  else
465  masked.push_back(j);
466  if(j > 0) {
467  // respecting TeXs range limts (1e-4 relative precision)
468  minlen = norm3(axPts[j]);
469  // fprintf(stderr,"j=%d, vec length %f:\n", j, minlen);
470  if(minlen < 1e-5) {
471  factor = 1e6;
472  suffix.assign("/$\\mu$m");
473  }
474  else if(minlen < 0.01) {
475  factor = 1e3;
476  suffix.assign("/mm");
477  }
478  else if(minlen > 1e6) {
479  factor = 1e-6;
480  suffix.assign("/Mm");
481  }
482  else if(minlen > 1000) {
483  factor = 1e-3;
484  suffix.assign("/Km");
485  }
486  }
487  if(j == 1 && acceptableAnchors.size() == 2) {
488  // precaution: if the first two coordinates are accepted, a
489  // division by zero can occur in pgfplots
490  // furthermore, four points with equal x=xmin leads to
491  // singular system in pgfplots
492  reorder = true;
493  acceptableAnchors.pop_back();
494  }
495  }
496  if(reorder) acceptableAnchors.push_back(1);
497 
498  if(acceptableAnchors.size() < 4) {
499  Msg::Error("Unable to calculate anchors for pgf output. "
500  "Make sure the entire scene is visible or adjust "
501  "the axes min/max values to fit inside your screen.");
502  return 2;
503  }
504  if(factor != 1) {
505  char tmp[265];
506  sprintf(tmp,
507  "The pgf output has been rescaled in order to please "
508  "the TeX number precision/range. Rescaling your results by "
509  "a factor %g",
510  factor);
511  Msg::Warning(tmp);
512  // replace three labels
513  if(exportAxis) {
514  // xlabel={x<>}, %%
515  // ylabel={y<>},
516  // zlabel={z<>},
517  // zlabel style={rotate=-90},
518  std::size_t foundrot = axisstr.rfind("},");
519  std::size_t foundz = axisstr.rfind("},", foundrot - 1);
520  if(foundz != std::string::npos)
521  axisstr.insert(foundz, suffix);
522  else
523  return 4;
524  std::size_t foundy = axisstr.rfind("},", foundz);
525  if(foundy != std::string::npos)
526  axisstr.insert(foundy, suffix);
527  else
528  return 4;
529 
530  std::size_t foundx = axisstr.rfind("},", foundy);
531  if(foundx != std::string::npos)
532  axisstr.insert(foundx, suffix);
533  else
534  return 4;
535  }
536  }
537 
538  char tmp[265];
539  plotstr.assign("\t \\addplot3[surf] graphics[debug=false,%%=visual,\n");
540  plotstr.append("\t points={%%\n");
541 
542  unsigned int j = 0;
543  for(auto it = acceptableAnchors.begin();
544  it != acceptableAnchors.end(); ++it, j++) {
545  sprintf(tmp, "\t (%f,%f,%f)", factor * axPts[*it][0],
546  factor * axPts[*it][1], factor * axPts[*it][2]);
547  plotstr.append(tmp);
548  if(j > 3) {
549  plotstr.append("%%");
550  }
551  // ypix-y syntax for easier debugging w/ e.g. gimp pixel
552  sprintf(tmp, " => (%d, %d-%d)\n", (int)(axViewPt[*it][0] + 0.5), ypix,
553  ypix - (int)(axViewPt[*it][1] + 0.5));
554  plotstr.append(tmp);
555  }
556  for(auto it = masked.begin(); it != masked.end();
557  ++it) {
558  sprintf(tmp, "\t (%f,%f,%f)", factor * axPts[*it][0],
559  factor * axPts[*it][1], factor * axPts[*it][2]);
560  plotstr.append(tmp);
561  plotstr.append(" %% out of pixel range, discarded\n");
562  }
563  plotstr.append("\t }]\n");
564  return 0;
565 }
566 
567 int print_pgf(const std::string &name, const int num, const int cnt,
568  PixelBuffer *buffer, double *eulerAngles, int *viewport,
569  double *proj, double *model)
570 {
571  int ypix = buffer->getHeight();
572  int xpix = buffer->getWidth();
573 
574  std::string base = SplitFileName(name)[1];
575  std::string path = SplitFileName(name)[0];
576  std::string pngfilen = path + base + ".png";
577  std::string pgffilen = path + base + ".pgf";
578  std::string texfilen = path + base + ".tex";
579  FILE *fp = Fopen(pngfilen.c_str(), "wb");
580  if(!fp) {
581  Msg::Error("Unable to open file '%s'", pngfilen.c_str());
582  return 1;
583  }
584  create_png(fp, buffer, 100);
585  fclose(fp);
586 
587  // write pgf
588  int twoDim = (int)opt_print_pgf_two_dim(0, GMSH_GET, 0);
589  int exportAxis = (int)opt_print_pgf_export_axis(0, GMSH_GET, 0);
590  if(cnt > 1)
591  Msg::Warning("PGF colorbar output works only with a single visible "
592  "scale. Consider disabling all but one. I can only create a "
593  "single colorbar. Colorbar will be suppressed");
594 
595  int samples;
596  std::string colmap_s, colbar_s, post_axis_s;
597  // color map
598  if(cnt == 1) { // one post processing view scale visible
599  int intType = (int)opt_view_intervals_type(num, GMSH_GET, 0);
600  if(assembleColmapStr(num, intType, samples, colmap_s) != 0) {
601  Msg::Error("Unable to assemble colormap for PGF output");
602  return 1;
603  }
604  if(assemblePostAxis(num, intType, post_axis_s) != 0) {
605  Msg::Error("Unable to assemble post processing axis for PGF output");
606  return 1;
607  }
608  if(assembleColbarStr(num, intType, samples, colbar_s) != 0) {
609  Msg::Error("Unable to assemble colorbar for PGF output");
610  return 1;
611  }
612  }
613  else {
614  colbar_s.assign("\t]\n"); // close axis without colorbar and dummy plot
615  }
616 
617  std::string axis_s, plot_s;
618  axis_s.assign("\\begin{tikzpicture}\n\\begin{axis}[\n\twidth=.5\\linewidth,"
619  "%% set figure width here\n");
620  if(twoDim) {
621  if(assemble2d(num, exportAxis, axis_s, plot_s, eulerAngles) != 0) {
622  return 1;
623  }
624  }
625  else { // 3d
626  if(assemble3d(num, exportAxis, axis_s, plot_s, eulerAngles, viewport, proj,
627  model, ypix, xpix) != 0) {
628  return 1;
629  }
630  }
631  char tmp[265];
632  sprintf(tmp, "\t {%s.png};\n", base.c_str());
633  plot_s.append(tmp);
634 
635  fp = Fopen(pgffilen.c_str(), "wb");
636  if(!fp) {
637  Msg::Error("Unable to open file '%s'", pgffilen.c_str());
638  return 1;
639  }
640  fprintf(fp, "%s", colmap_s.c_str());
641  fprintf(fp, "%s", axis_s.c_str());
642  fprintf(fp, "%s", post_axis_s.c_str());
643  fprintf(fp, "%s", colbar_s.c_str());
644  fprintf(fp, "%s", plot_s.c_str());
645  fprintf(fp, "\\end{axis}\n\\end{tikzpicture}%%\n");
646  fclose(fp);
647 
648  if(twoDim) {
649  // try to trim the png...
650  char tmp[2048];
651  if(system(nullptr)) {
652  std::string pngname = name;
653  pngname.replace(pngname.end() - 3, pngname.end(), "png");
654  sprintf(tmp, "convert -trim %s %s", pngname.c_str(), pngname.c_str());
655  Msg::Info("Running:");
656  Msg::Info(tmp);
657  int ret = system(tmp);
658  Msg::Info("Conversion returned value %d", ret);
659  if(ret == 0) // success
660  Msg::Info("Automatic trim successful.");
661  else {
662  Msg::Warning("Cannot automatically trim output png.");
663  sprintf(tmp,
664  "One should now manually crop the margins, using e.g."
665  "gimp or `convert -trim %s %s` to get rid of any remaining"
666  "margins.",
667  pngfilen.c_str(), pngfilen.c_str());
668  Msg::Warning(tmp);
669  }
670  }
671  else {
672  Msg::Warning("Cannot automatically trim output png.");
673  sprintf(tmp,
674  "One should now manually crop the margins, using e.g."
675  "gimp or `convert -trim %s %s` to get rid of any remaining"
676  "margins.",
677  pngfilen.c_str(), pngfilen.c_str());
678  Msg::Warning(tmp);
679  }
680  }
681 
682  // try to add transparency, do not(!) crop otherwise the transformation
683  // matrix is wrong!!!!
684  if(!twoDim) {
685  char tmp[2048];
686  if(system(nullptr)) {
687  std::string pngname = name;
688  pngname.replace(pngname.end() - 3, pngname.end(), "png");
689  sprintf(tmp, "convert -transparent white %s %s", pngname.c_str(),
690  pngname.c_str());
691  Msg::Info("Running:");
692  Msg::Info(tmp);
693  int ret = system(tmp);
694  Msg::Info("Conversion returned value %d", ret);
695  if(ret == 0) // success
696  Msg::Info("Automatic transparent white background successful.");
697  else {
698  Msg::Warning("Cannot automatically add transparency to png.");
699  sprintf(tmp,
700  "One should now manually add a transparent layer in "
701  "order to not obstruct the axis. e.g. using gimp or "
702  "convert -transparent white %s %s`.",
703  pngfilen.c_str(), pngfilen.c_str());
704  Msg::Warning(tmp);
705  }
706  }
707  else { // exit (EXIT_FAILURE);
708  Msg::Warning("Cannot automatically add transparency to output png.");
709  sprintf(tmp,
710  "One should now manually add a transparent layer in "
711  "order to not obstruct the axis. e.g. using gimp or "
712  "`convert -transparent white %s %s`.",
713  pngfilen.c_str(), pngfilen.c_str());
714  Msg::Warning(tmp);
715  }
716  }
717 
718  // try to write a helper tex file just in case it does not exist
719  fp = Fopen(texfilen.c_str(), "r");
720  if(fp) {
721  fclose(fp);
722  Msg::Info("File '%s' exists, please add '\\input{%s}' by yourself.",
723  texfilen.c_str(), pgffilen.c_str());
724  }
725  else {
726  fp = Fopen(texfilen.c_str(), "w");
727  fprintf(fp, "\\documentclass{article}\n\\usepackage{pgfplots}\n"
728  "\\pgfplotsset{compat=1.8}\n\\begin{document}\n");
729  fprintf(fp, "\n\\input{%s}\n", pgffilen.c_str());
730  fprintf(fp, "\n\\end{document}\n");
731  fclose(fp);
732  }
733  return 0;
734 }
assemble2d
static int assemble2d(const int num, const int exportAxis, std::string &axisstr, std::string &plotstr, double *eulerAngles)
Definition: gl2pgf.cpp:224
opt_print_pgf_export_axis
double opt_print_pgf_export_axis(OPT_ARGS_NUM)
Definition: Options.cpp:9332
opt_view_nb_iso
double opt_view_nb_iso(OPT_ARGS_NUM)
Definition: Options.cpp:8078
SplitFileName
std::vector< std::string > SplitFileName(const std::string &fileName)
Definition: StringUtils.cpp:93
opt_general_orthographic
double opt_general_orthographic(OPT_ARGS_NUM)
Definition: Options.cpp:2962
assembleColmapStr
static int assembleColmapStr(const int num, const int intType, int &samples, std::string &ret)
Definition: gl2pgf.cpp:21
GMSH_GET
#define GMSH_GET
Definition: Options.h:13
gl2png.h
opt_view_range_type
double opt_view_range_type(OPT_ARGS_NUM)
Definition: Options.cpp:8594
CTX::unpackBlue
int unpackBlue(unsigned int X)
Definition: Context.cpp:152
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
OS.h
opt_print_pgf_horiz_bar
double opt_print_pgf_horiz_bar(OPT_ARGS_NUM)
Definition: Options.cpp:9337
PixelBuffer::getHeight
int getHeight()
Definition: PixelBuffer.h:71
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
PixelBuffer.h
assemble3d
static int assemble3d(const int num, const int exportAxis, std::string &axisstr, std::string &plotstr, double *eulerAngles, int *viewport, double *proj, double *model, int ypix, int xpix)
Definition: gl2pgf.cpp:398
CTX::axesLabel
std::string axesLabel[3]
Definition: Context.h:250
PView.h
print_pgf
int print_pgf(const std::string &name, const int num, const int cnt, PixelBuffer *buffer, double *eulerAngles, int *viewport, double *proj, double *model)
Definition: gl2pgf.cpp:567
PViewData.h
opt_general_axes_ymin
double opt_general_axes_ymin(OPT_ARGS_NUM)
Definition: Options.cpp:3182
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
opt_view_intervals_type
double opt_view_intervals_type(OPT_ARGS_NUM)
Definition: Options.cpp:7650
norm3
double norm3(double a[3])
Definition: Numeric.h:119
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
assemblePostAxis
static int assemblePostAxis(const int num, const int intType, std::string &ret)
Definition: gl2pgf.cpp:137
opt_view_axes_xmin
double opt_view_axes_xmin(OPT_ARGS_NUM)
Definition: Options.cpp:7934
create_png
void create_png(FILE *file, PixelBuffer *buffer, int quality)
Definition: gl2png.cpp:11
getMinMaxOfAxis
static int getMinMaxOfAxis(const int num, double result[8][3])
Definition: gl2pgf.cpp:164
opt_view_axes_ymin
double opt_view_axes_ymin(OPT_ARGS_NUM)
Definition: Options.cpp:7966
CTX::min
double min[3]
Definition: Context.h:229
opt_view_axes_auto_position
double opt_view_axes_auto_position(OPT_ARGS_NUM)
Definition: Options.cpp:7917
Numeric.h
opt_general_axes_ymax
double opt_general_axes_ymax(OPT_ARGS_NUM)
Definition: Options.cpp:3193
CTX::unpackGreen
int unpackGreen(unsigned int X)
Definition: Context.cpp:144
opt_view_axes_xmax
double opt_view_axes_xmax(OPT_ARGS_NUM)
Definition: Options.cpp:7950
CTX::max
double max[3]
Definition: Context.h:229
opt_general_axes_xmax
double opt_general_axes_xmax(OPT_ARGS_NUM)
Definition: Options.cpp:3171
opt_view_custom_min
double opt_view_custom_min(OPT_ARGS_NUM)
Definition: Options.cpp:7101
opt_view_scale_type
double opt_view_scale_type(OPT_ARGS_NUM)
Definition: Options.cpp:8574
opt_general_axes_zmin
double opt_general_axes_zmin(OPT_ARGS_NUM)
Definition: Options.cpp:3204
opt_general_axes_auto_position
double opt_general_axes_auto_position(OPT_ARGS_NUM)
Definition: Options.cpp:3114
PixelBuffer::getWidth
int getWidth()
Definition: PixelBuffer.h:70
StringUtils.h
CTX::unpackAlpha
int unpackAlpha(unsigned int X)
Definition: Context.cpp:160
GetColorTable
GmshColorTable * GetColorTable(int num)
Definition: Options.cpp:566
opt_view_custom_max
double opt_view_custom_max(OPT_ARGS_NUM)
Definition: Options.cpp:7120
opt_view_max
double opt_view_max(OPT_ARGS_NUM)
Definition: Options.cpp:7059
opt_view_axes_zmin
double opt_view_axes_zmin(OPT_ARGS_NUM)
Definition: Options.cpp:7998
Context.h
GmshColorTable
Definition: ColorTable.h:16
GmshColorTable::size
int size
Definition: ColorTable.h:18
opt_view_axes_zmax
double opt_view_axes_zmax(OPT_ARGS_NUM)
Definition: Options.cpp:8014
GmshColorTable::table
unsigned int table[COLORTABLE_NBMAX_COLOR]
Definition: ColorTable.h:17
PixelBuffer
Definition: PixelBuffer.h:32
Options.h
opt_print_pgf_two_dim
double opt_print_pgf_two_dim(OPT_ARGS_NUM)
Definition: Options.cpp:9327
assembleColbarStr
static int assembleColbarStr(const int num, const int intType, const int samples, std::string &ret)
Definition: gl2pgf.cpp:79
PView::list
static std::vector< PView * > list
Definition: PView.h:112
opt_general_axes_xmin
double opt_general_axes_xmin(OPT_ARGS_NUM)
Definition: Options.cpp:3160
opt_view_min
double opt_view_min(OPT_ARGS_NUM)
Definition: Options.cpp:7047
CTX::unpackRed
int unpackRed(unsigned int X)
Definition: Context.cpp:136
opt_view_axes_ymax
double opt_view_axes_ymax(OPT_ARGS_NUM)
Definition: Options.cpp:7982
opt_general_axes_zmax
double opt_general_axes_zmax(OPT_ARGS_NUM)
Definition: Options.cpp:3215