TPCCLIB
Loading...
Searching...
No Matches
svg_plot.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6#include "libtpcsvg.h"
7/*****************************************************************************/
9extern int SVG_INLINE;
10/*****************************************************************************/
11
12/*****************************************************************************/
21 const double a1x,
23 const double a1y,
25 const double a2x,
27 const double a2y,
29 const double b1x,
31 const double b1y,
33 const double b2x,
35 const double b2y,
37 double *ix,
39 double *iy,
41 int verbose
42) {
43 double sax, say, sbx, sby, s, t, d;
44
45 if(verbose>0) {
46 printf("%s(%g, %g, %g, %g, %g, %g, %g, %g, ix, iy, %d)\n",
47 __func__, a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y, verbose);
48 fflush(stdout);
49 }
50
51 if(a1x==a2x && a1y==a2y) return(0);
52 sax=a2x-a1x; say=a2y-a1y;
53 sbx=b2x-b1x; sby=b2y-b1y;
54 d=-sbx*say+sax*sby; if(d==0.0) return(0);
55 s=(-say*(a1x-b1x) + sax*(a1y-b1y)) / d;
56 t=(+sbx*(a1y-b1y) - sby*(a1x-b1x)) / d;
57//if(s>=0.0 && s<=1.0 && t>=0.0 && t<=1.0) {
58 if(s>0.0 && s<1.0 && t>0.0 && t<1.0) {
59 if(verbose>3) printf("s=%g t=%g\n", s, t);
60 if(ix!=NULL) *ix=a1x+(t*sax);
61 if(iy!=NULL) *iy=a1y+(t*say);
62 return(1);
63 }
64 return(0);
65}
66/*****************************************************************************/
67
68/*****************************************************************************/
75 const double x1,
77 const double y1,
79 const double x2,
81 const double y2,
83 struct svg_viewport_pos *cavp,
85 double *nx1,
87 double *ny1,
89 double *nx2,
91 double *ny2,
93 int verbose
94) {
95 int i=0, n, crossings=0;
96 double ix, iy;
97 double mx[2], my[2];
98
99 if(verbose>0) {
100 printf("%s(%g, %g, %g, %g, cavp, nx1, ny1, nx2, ny2, %d)\n",
101 __func__, x1, y1, x2, y2, verbose);
102 fflush(stdout);
103 }
104
105 mx[0]=x1; my[0]=y1; mx[1]=x2; my[1]=y2;
106 /* Upper border */
107 n=get_line_intersection(x1, y1, x2, y2, 0.0, 0.0, (double)cavp->w, 0.0, &ix, &iy, verbose);
108 if(n>0) {
109 if(crossings==0) {
110 if(y1<iy) i=0; else i=1; // which point was out? change that one
111 } else { // both are out, change the other than first time
112 if(i==0) i=1; else i=0;
113 }
114 mx[i]=ix; my[i]=iy; crossings++;
115 if(verbose>3)
116 printf("line between (%g,%g) and (%g,%g) would cross upper border at (%g,%g)\n",
117 x1, y1, x2, y2, ix, iy);
118 }
119 /* Lower border */
120 n=get_line_intersection(x1, y1, x2, y2,
121 0.0, (double)cavp->h, (double)cavp->w, (double)cavp->h, &ix, &iy, verbose);
122 if(n>0) {
123 if(crossings==0) {
124 if(y1>iy) i=0; else i=1; // which point was out? change that one
125 } else { // both are out, change the other than first time
126 if(i==0) i=1; else i=0;
127 }
128 mx[i]=ix; my[i]=iy; crossings++;
129 if(verbose>3)
130 printf("line between (%g,%g) and (%g,%g) would cross lower border at (%g,%g)\n",
131 x1, y1, x2, y2, ix, iy);
132 }
133 /* Left border */
134 n=get_line_intersection(x1, y1, x2, y2,
135 0.0, 0.0, 0.0, cavp->h,
136 &ix, &iy, verbose);
137 if(n>0) {
138 if(crossings==0) {
139 if(x1<ix) i=0; else i=1; // which point was out? change that one
140 } else { // both are out, change the other than first time
141 if(i==0) i=1; else i=0;
142 }
143 mx[i]=ix; my[i]=iy; crossings++;
144 if(verbose>3)
145 printf("line between (%g,%g) and (%g,%g) would cross left border at (%g,%g)\n",
146 x1, y1, x2, y2, ix, iy);
147 }
148 /* Right border */
149 n=get_line_intersection(x1, y1, x2, y2,
150 (double)cavp->w, 0.0, (double)cavp->w, (double)cavp->h,
151 &ix, &iy, verbose);
152 if(n>0) {
153 if(crossings==0) {
154 if(x1>ix) i=0; else i=1; // which point was out? change that one
155 } else { // both are out, change the other than first time
156 if(i==0) i=1; else i=0;
157 }
158 mx[i]=ix; my[i]=iy; crossings++;
159 if(verbose>3)
160 printf("line between (%g,%g) and (%g,%g) would cross right border at (%g,%g)\n",
161 x1, y1, x2, y2, ix, iy);
162 }
163 if(verbose>3 && crossings>0) printf("crossings=%d\n", crossings);
164
165 if(nx1!=NULL) *nx1=mx[0];
166 if(ny1!=NULL) *ny1=my[0];
167 if(nx2!=NULL) *nx2=mx[1];
168 if(ny2!=NULL) *ny2=my[1];
169 if(verbose>2 && crossings>0)
170 printf("modified line (%g,%g) -> (%g,%g)\n", mx[0], my[0], mx[1], my[1]);
171
172 return(crossings);
173}
174/*****************************************************************************/
175
176/*****************************************************************************/
183 FILE *fp,
185 struct svg_viewports *vp,
188 char *errmsg,
190 int verbose
191) {
192 char tmp[1024], line[128], ilc[9];
193
194 if(verbose>0) {
195 printf("%s(fp, vp, errmsg, %d)\n", __func__, verbose);
196 fflush(stdout);
197 }
198
199 /* Check the input */
200 if(fp==NULL) {
201 if(errmsg!=NULL) sprintf(errmsg, "file was closed too early");
202 return(1);
203 }
204 if(SVG_INLINE) strcpy(ilc, "svg:"); else strcpy(ilc, "");
205
206 /* Create a new viewport for plot area */
207 strcpy(tmp, "\n <!-- Plot area viewport -->\n");
208 strcat(tmp, " <"); strcat(tmp, ilc); strcat(tmp, "svg");
209 sprintf(line, " x=\"%dpx\" y=\"%dpx\" width=\"%dpx\" height=\"%d\"",
211 vp->plot_area_viewport.w, vp->plot_area_viewport.h); strcat(tmp, line);
212 sprintf(line, "\n viewBox=\"0 0 %d %d\"",
213 vp->plot_area_viewport.w, vp->plot_area_viewport.h); strcat(tmp, line);
214 strcat(tmp, "\n preserveAspectRatio=\"xMidYMid meet\"");
215 strcat(tmp, ">\n");
216 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(4);}
217
218#if(0)
219 sprintf(tmp, " <%srect width=\"%dpx\" height=\"%dpx\" stroke=\"none\" fill=\"yellow\" fill-opacity=\"0.1\" />\n",
221 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(99);}
222#endif
223
224#if(0) // moved elsewhere
225 /* Create symbols for later use */
226 if(svg_define_symbols(fp, errmsg)!=0) {return(6);}
227#endif
228
229 return(0);
230}
231/*****************************************************************************/
232
233/*****************************************************************************/
240 FILE *fp,
241 // /** Struct containing the viewport sizes */
242 // struct svg_viewports *vp,
245 char *errmsg,
247 int verbose
248) {
249 char tmp[1024];
250
251 if(verbose>0) {
252 printf("%s(fp, vp, errmsg, %d)\n", __func__, verbose);
253 fflush(stdout);
254 }
255
256 /* Check the input */
257 if(fp==NULL) {
258 if(errmsg!=NULL) sprintf(errmsg, "file was closed too early");
259 return(1);
260 }
261
262 /* Write the end tag */
263 if(SVG_INLINE) strcpy(tmp, " </svg:svg>\n"); else strcpy(tmp, " </svg>\n");
264
265 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(2);}
266
267 return(0);
268}
269/*****************************************************************************/
270
271/*****************************************************************************/
278 FILE *fp,
280 struct svg_viewports *vp,
283 char *errmsg,
285 int verbose
286) {
287 char tmp[1024], line[128];
288
289 if(verbose>0) {
290 printf("%s(fp, vp, errmsg, %d)\n", __func__, verbose);
291 fflush(stdout);
292 }
293
294 /* Check the input */
295 if(fp==NULL) {
296 if(errmsg!=NULL) sprintf(errmsg, "file was closed too early");
297 return(1);
298 }
299
300 /* Create a new viewport for plot area */
301 strcpy(tmp, "\n <!-- Coordinate area viewport -->\n");
302 if(SVG_INLINE) strcat(tmp, " <svg:"); else strcat(tmp, " <");
303 sprintf(line, "svg x=\"%dpx\" y=\"%dpx\" width=\"%dpx\" height=\"%d\"",
305 vp->coordinate_area_viewport.w, vp->coordinate_area_viewport.h); strcat(tmp, line);
306 sprintf(line, "\n viewBox=\"0 0 %d %d\"",
307 vp->coordinate_area_viewport.w, vp->coordinate_area_viewport.h); strcat(tmp, line);
308 strcat(tmp, "\n preserveAspectRatio=\"xMidYMid meet\"");
309 strcat(tmp, ">\n");
310 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(4);}
311
312#if(0)
313 sprintf(tmp, " <rect width=\"%dpx\" height=\"%dpx\" stroke=\"none\" fill=\"silver\" fill-opacity=\"0.3\" />\n",
315 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(99);}
316#endif
317
318 return(0);
319}
320/*****************************************************************************/
321
322/*****************************************************************************/
329 FILE *fp,
332 char *errmsg,
334 int verbose
335) {
336 char tmp[1024];
337
338 if(verbose>0) {
339 printf("%s(fp, errmsg, %d)\n", __func__, verbose);
340 fflush(stdout);
341 }
342
343 /* Check the input */
344 if(fp==NULL) {
345 if(errmsg!=NULL) sprintf(errmsg, "file was closed too early");
346 return(1);
347 }
348
349 if(SVG_INLINE) strcpy(tmp, " </svg:svg>\n\n");
350 else strcpy(tmp, " </svg>\n\n");
351 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(2);}
352
353 return(0);
354}
355/*****************************************************************************/
356
357/*****************************************************************************/
366 struct svg_viewports *vp,
368 int verbose
369) {
370 int ret, ti, prec;
371 double orig_min, orig_max;
372
373 if(verbose>0) {
374 printf("%s(vp, %d)\n", __func__, verbose);
375 fflush(stdout);
376 }
377
378 /* x axis */
379 orig_min=vp->x.min; orig_max=vp->x.max;
380 axis_check_range(&vp->x.min, &vp->x.max, verbose);
381 if(vp->x.fixed_min) vp->x.min=orig_min;
382 if(vp->x.fixed_max) vp->x.max=orig_max;
383 if(verbose>1) printf("x-range %g - %g -> %g - %g\n", orig_min, orig_max, vp->x.min, vp->x.max);
385 if((fabs(vp->x.max)<0.1 || fabs(vp->x.max)>10000) && vp->x.tick_nr>8) vp->x.tick_nr=8; // Only few long tick labels can fit on x axis
386 if((fabs(vp->x.max)<0.01 || fabs(vp->x.max)>100000) && vp->x.tick_nr>6) vp->x.tick_nr=5; // even fewer tick labels can fit on x axis
387 if(vp->label_area_viewport.is) vp->x.tick_nr=1+vp->x.tick_nr/2; // Legends reduce the width of x axis
389 vp->x.min, vp->x.max, vp->x.tick, &vp->x.tick_nr, &vp->x.tickscale,
390 &vp->x.tick_decimals, verbose);
391 if(ret!=0) return(ret+100);
392
393 /* create tick labels to be written later */
394 prec=vp->x.tick_decimals-1-(int)vp->x.tickscale; if(prec<0) prec=0;
395 for(ti=0; ti<vp->x.tick_nr; ti++) {
396 if(vp->x.tickscale<-2 || vp->x.tickscale>3) {
397 sprintf(vp->x.tick_label[ti], "%.*E", vp->x.tick_decimals-1, vp->x.tick[ti]);
398 strRmExpZeroes(vp->x.tick_label[ti]);
399 } else if(vp->x.tickscale<=0)
400 sprintf(vp->x.tick_label[ti], "%.*f", prec, vp->x.tick[ti]);
401 else
402 sprintf(vp->x.tick_label[ti], "%.*f", prec, vp->x.tick[ti]);
403 }
404
405 /* y axis */
406 orig_min=vp->y.min; orig_max=vp->y.max;
407 axis_check_range(&vp->y.min, &vp->y.max, verbose);
408 if(vp->y.fixed_min) vp->y.min=orig_min;
409 if(vp->y.fixed_max) vp->y.max=orig_max;
410 if(verbose>1) printf("y-range %g - %g -> %g - %g\n", orig_min, orig_max, vp->y.min, vp->y.max);
411 vp->y.tick_nr=MAX_TICK_NR; // 10
413 vp->y.min, vp->y.max, vp->y.tick, &vp->y.tick_nr, &vp->y.tickscale,
414 &vp->y.tick_decimals, verbose);
415 if(ret!=0) return(ret+200);
416 /* create tick labels to be written later */
417 prec=vp->y.tick_decimals-1-(int)vp->y.tickscale; if(prec<0) prec=0;
418 for(ti=0; ti<vp->y.tick_nr; ti++) {
419 if(vp->y.tickscale<-2 || vp->y.tickscale>3) {
420 sprintf(vp->y.tick_label[ti], "%.*E", vp->y.tick_decimals-1, vp->y.tick[ti]);
421 strRmExpZeroes(vp->y.tick_label[ti]);
422 } else if(vp->y.tickscale<=0)
423 sprintf(vp->y.tick_label[ti], "%.*f", prec, vp->y.tick[ti]);
424 else
425 sprintf(vp->y.tick_label[ti], "%.*f", prec, vp->y.tick[ti]);
426 }
427
428 return(0);
429}
430/*****************************************************************************/
431
432/*****************************************************************************/
439 FILE *fp,
441 struct svg_viewports *vp,
443 char *errmsg,
445 int verbose
446) {
447 int linew=20, coordw=10;
448 char tmp[1024], line[128], ilc[9];
449 double f;
450
451 if(verbose>0) {
452 printf("%s(fp, vp, errmsg, %d)\n", __func__, verbose);
453 fflush(stdout);
454 }
455
456 /* Check the input */
457 if(fp==NULL) {
458 if(errmsg!=NULL) sprintf(errmsg, "file was closed too early");
459 return(1);
460 }
461 if(vp->x.min>=vp->x.max || vp->y.min>=vp->y.max) {
462 if(errmsg!=NULL) sprintf(errmsg, "invalid plot range");
463 if(verbose>1) {
464 printf("vp->x.min=%g vp->x.max=%g\n", vp->x.min, vp->x.max);
465 printf("vp->y.min=%g vp->y.max=%g\n", vp->y.min, vp->y.max);
466 }
467 return(2);
468 }
469
470 if(SVG_INLINE) strcpy(ilc, "svg:"); else strcpy(ilc, "");
471
472 /* Draw the lines around the plot */
473 sprintf(tmp, " <%s", ilc);
474 sprintf(line, "polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%d\"\n", "black", linew);
475 strcat(tmp, line);
476#if(0)
477 sprintf(line, " points=\"%d,%d %d,%d %d,%d %d,%d %d,%d\" />\n",
478 linew/2, linew/2,
479 linew/2, vp->coordinate_area_viewport.h-linew,
481 vp->coordinate_area_viewport.w-linew/2, linew/2,
482 linew/2, linew/2);
483 strcat(tmp, line);
484#else
485 sprintf(line, " points=\"%d,%d %d,%d %d,%d %d,%d %d,%d\" />\n",
486 linew/2, linew/2,
487 linew/2, vp->coordinate_area_viewport.h-linew/2,
488 vp->coordinate_area_viewport.w-linew/2, vp->coordinate_area_viewport.h-linew/2,
489 vp->coordinate_area_viewport.w-linew/2, linew/2,
490 linew/2, linew/2);
491 strcat(tmp, line);
492#endif
493 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(4);}
494
495 /* Set the upper margins for both axes */
496 vp->y.upper_margin=0.04*(double)vp->coordinate_area_viewport.h;
497#if(1)
498 if(vp->label_area_viewport.is)
499 vp->x.upper_margin=0.02*(double)vp->coordinate_area_viewport.w;
500 else // If no legends, then more room may be needed to fit x tick labels
501 vp->x.upper_margin=0.08*(double)vp->coordinate_area_viewport.w;
502#else
503 vp->x.upper_margin=0.08*(double)vp->coordinate_area_viewport.w;
504#endif
505
506 /* Calculate the scale factors */
508 vp->x.scale=f/(vp->x.max-vp->x.min);
509 if(verbose>0) printf("xscalef:=%g (%g vs %g-%g)\n", vp->x.scale, f, vp->x.min, vp->x.max);
511 vp->y.scale=f/(vp->y.max-vp->y.min);
512 if(verbose>1) printf("yscalef:=%g (%g vs %g-%g)\n", vp->y.scale, f, vp->y.min, vp->y.max);
513
514 /* Calculate the origo in plot coordinates */
515 vp->x.origo=-vp->x.scale*vp->x.min;
516 if(verbose>1) printf("x.origo := %g\n", vp->x.origo);
517 vp->y.origo=-vp->y.scale*vp->y.min;
518 if(verbose>1) printf("y.origo := %g\n", vp->y.origo);
519
520 /* Draw the x=0 line, if necessary */
521 if(vp->x.origo>0 && vp->x.origo<vp->coordinate_area_viewport.w/*-vp->x.upper_margin*/) {
522 if(verbose>1) printf("drawing x=0 line\n");
523 sprintf(tmp, " <%s", ilc);
524 sprintf(line, "line fill=\"none\" stroke=\"%s\" stroke-width=\"%d\"\n", "black", coordw);
525 strcat(tmp, line);
526 sprintf(line, " x1=\"%g\" x2=\"%g\" y1=\"%d\" y2=\"%d\" />\n",
527 vp->x.origo, vp->x.origo, 0, vp->coordinate_area_viewport.h);
528 strcat(tmp, line);
529 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(6);}
530 }
531
532 /* Draw the y=0 line, if necessary */
533 if(vp->y.origo>0 && vp->y.origo<vp->coordinate_area_viewport.h /*- vp->y.upper_margin*/) {
534 if(verbose>1) printf("drawing y=0 line\n");
535 sprintf(tmp, " <%s", ilc);
536 sprintf(line, "line fill=\"none\" stroke=\"%s\" stroke-width=\"%d\"\n", "black", coordw);
537 strcat(tmp, line);
538 sprintf(line, " x1=\"%d\" x2=\"%d\" y1=\"%g\" y2=\"%g\" />\n",
542 strcat(tmp, line);
543 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(7);}
544 }
545
546 return(0);
547}
548/*****************************************************************************/
549
550/*****************************************************************************/
557 FILE *fp,
559 struct svg_viewports *vp,
562 char *errmsg,
564 int verbose
565) {
566 char tmp[1024], line[128], ilc[9];
567 int ti;
568 double pos, ypos, yheight;
569
570 if(verbose>0) {printf("%s(fp, vp, errmsg, %d)\n", __func__, verbose); fflush(stdout);}
571
572 /* Check the input */
573 if(vp->x.tick_nr<1 || vp->plot_area_viewport.h==vp->coordinate_area_viewport.h) return(0);
574 if(fp==NULL) {if(errmsg!=NULL) sprintf(errmsg, "file was closed too early"); return(1);}
575
576 if(SVG_INLINE) strcpy(ilc, "svg:"); else strcpy(ilc, "");
577
580
581 strcpy(tmp, "\n <!-- X axis ticks inside plot area -->\n");
582#if(0)
583 sprintf(tmp, " <%srect x=\"0px\" y=\"%dpx\" width=\"%dpx\" height=\"%gpx\" stroke=\"none\" fill=\"aqua\" fill-opacity=\"0.3\" />\n",
584 ilc, vp->coordinate_area_viewport.h, vp->plot_area_viewport.w, yheight);
585#endif
586 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(99);}
587
588 /* Write ticks */
589 sprintf(tmp, " <%sg", ilc);
590 sprintf(line, " stroke=\"%s\"", "black"); strcat(tmp, line);
591 sprintf(line, " stroke-width=\"%g\"", 20.); strcat(tmp, line);
592 sprintf(line, " fill=\"%s\"", "none"); strcat(tmp, line);
593 strcat(tmp, ">\n");
594 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(5);}
595
596 if(verbose>9) {
597 printf("vp->plot_area_viewport.w := %d\n", vp->plot_area_viewport.w);
598 printf("vp->coordinate_area_viewport.w := %d\n", vp->coordinate_area_viewport.w);
599 }
600 for(ti=0; ti<vp->x.tick_nr; ti++) {
601 pos=vp->x.origo+vp->x.scale*vp->x.tick[ti];
603 if(verbose>1) printf("ti=%d: x tick pos=%g\n", ti, pos);
604 sprintf(tmp, " <%s", ilc);
605 sprintf(line, "line x1=\"%g\" x2=\"%g\" y1=\"%g\" y2=\"%g\" />\n",
606 pos, pos, ypos, ypos+yheight/8);
607 strcat(tmp, line);
608 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(6);}
609 }
610 // try to write one extra tick, if there is space
611 pos=vp->x.origo+vp->x.scale*(2.0*vp->x.tick[vp->x.tick_nr-1] - vp->x.tick[vp->x.tick_nr-2]);
613 if(pos<vp->plot_area_viewport.w) {
614 if(verbose>1) printf("extra ti=%d: x tick pos=%g\n", ti, pos);
615 sprintf(tmp, " <%s", ilc);
616 sprintf(line, "line x1=\"%g\" x2=\"%g\" y1=\"%g\" y2=\"%g\" />\n",
617 pos, pos, ypos, ypos+yheight/8);
618 strcat(tmp, line);
619 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(6);}
620 }
621 sprintf(tmp, " </%sg>\n", ilc);
622 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(7);}
623
624 /* Write ticks labels */
625 sprintf(tmp, " <%sg", ilc);
626 sprintf(line, " font-family=\"Sans-serif\""); strcat(tmp, line);
627 sprintf(line, " text-anchor=\"middle\""); strcat(tmp, line);
628 sprintf(line, " font-size=\"%d\"", vp->coordinate_area_viewport.chr_size); strcat(tmp, line);
629 sprintf(line, " fill=\"black\""); strcat(tmp, line);
630 strcat(tmp, ">\n");
631 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(8);}
632 for(ti=0; ti<vp->x.tick_nr; ti++) {
633 pos=vp->x.origo+vp->x.scale*vp->x.tick[ti];
635 if(verbose>1) printf("ti=%d: x tick pos=%g\n", ti, pos);
636 sprintf(tmp, " <%s", ilc);
637 sprintf(line, "text x=\"%g\" y=\"%g\"", pos, ypos+0.92*(double)yheight); strcat(tmp, line);
638 sprintf(line, ">"); strcat(tmp, line);
639 strcat(tmp, vp->x.tick_label[ti]);
640 strcat(tmp, "</"); strcat(tmp, ilc); strcat(tmp, "text>\n");
641 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(9);}
642 }
643 sprintf(tmp, " </%sg>\n", ilc);
644 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(10);}
645
646 return(0);
647}
648/*****************************************************************************/
649
650/*****************************************************************************/
657 FILE *fp,
659 struct svg_viewports *vp,
662 char *errmsg,
664 int verbose
665) {
666 char tmp[1024], line[128], ilc[9];
667 int ti;
668 double pos, xwidth;
669
670 if(verbose>0) {printf("%s(fp, vp, errmsg, %d)\n", __func__, verbose); fflush(stdout);}
671
672 /* Check the input */
673 if(vp->y.tick_nr<1 || vp->plot_area_viewport.w==vp->coordinate_area_viewport.w) return(0);
674 if(fp==NULL) {if(errmsg!=NULL) sprintf(errmsg, "file was closed too early"); return(1);}
675
676 if(SVG_INLINE) strcpy(ilc, "svg:"); else strcpy(ilc, "");
677
679
680 strcpy(tmp, "\n <!-- Y axis ticks inside plot area -->\n");
681#if(0)
682 sprintf(tmp,
683 " <%srect width=\"%gpx\" height=\"%dpx\" stroke=\"none\" fill=\"aqua\" fill-opacity=\"0.3\" />\n",
684 ilc, xwidth, vp->plot_area_viewport.h);
685#endif
686 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(99);}
687
688 if(verbose>0) {
689 printf("vp->y.tick_nr=%d\n", vp->y.tick_nr);
690 printf("vp->y.tickscale=%g\n", vp->y.tickscale);
691 printf("vp->y.tick_decimals=%d\n", vp->y.tick_decimals);
692 }
693
694 /* Write ticks */
695 sprintf(tmp, " <%sg", ilc);
696 sprintf(line, " stroke=\"%s\"", "black"); strcat(tmp, line);
697 sprintf(line, " stroke-width=\"%g\"", 20.); strcat(tmp, line);
698 sprintf(line, " fill=\"%s\"", "none"); strcat(tmp, line);
699 strcat(tmp, ">\n");
700 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(5);}
701 for(ti=0; ti<vp->y.tick_nr; ti++) {
702 pos=vp->coordinate_area_viewport.h-(vp->y.origo+vp->y.scale*vp->y.tick[ti]);
703 if(verbose>1) printf("ti=%d: y tick pos=%g\n", ti, pos);
704 sprintf(tmp, " <%s", ilc);
705 sprintf(line, "line x1=\"%g\" x2=\"%g\" y1=\"%g\" y2=\"%g\" />\n",
706 xwidth,
707 xwidth-(double)vp->coordinate_area_viewport.chr_size/8.0,
708 pos, pos); strcat(tmp, line);
709 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(6);}
710 }
711 sprintf(tmp, " </%sg>\n", ilc);
712 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(7);}
713
714 /* Write ticks labels */
715 sprintf(tmp, " <%sg", ilc);
716 sprintf(line, " font-family=\"Sans-serif\""); strcat(tmp, line);
717 sprintf(line, " text-anchor=\"end\""); strcat(tmp, line);
718 sprintf(line, " font-size=\"%d\"", vp->coordinate_area_viewport.chr_size); strcat(tmp, line);
719 sprintf(line, " fill=\"black\""); strcat(tmp, line);
720 strcat(tmp, ">\n");
721 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(8);}
722 for(ti=0; ti<vp->y.tick_nr; ti++) {
723 pos=vp->coordinate_area_viewport.h-(vp->y.origo+vp->y.scale*vp->y.tick[ti]);
724 if(verbose>1) printf("ti=%d: y tick pos=%g\n", ti, pos);
725 sprintf(tmp, " <%s", ilc);
726 sprintf(line, "text x=\"%g\" y=\"%g\"",
727 0.92*xwidth, pos+0.4*(double)vp->coordinate_area_viewport.chr_size);
728 strcat(tmp, line);
729 sprintf(line, ">"); strcat(tmp, line);
730 strcat(tmp, vp->y.tick_label[ti]);
731 strcat(tmp, "</"); strcat(tmp, ilc); strcat(tmp, "text>\n");
732 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(9);}
733 }
734 sprintf(tmp, " </%sg>\n", ilc);
735 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(10);}
736
737 return(0);
738}
739/*****************************************************************************/
740
741/*****************************************************************************/
748 FILE *fp,
750 struct svg_viewports *vp,
752 const int plot_type,
754 const char *tac_id,
756 const char *tac_title,
758 double *x,
760 double *y,
762 const int data_nr,
766 const char *color,
769 const svgSymbolType symbol_type,
771 const svgSymbolFill symbol_fill,
774 char *errmsg,
776 int verbose
777) {
778 char tmp[1024], line[128], ilc[9];
779 int i, j;
780 double px, py, size=100.0, trgsize=140.0, circsize=120.0;
781
782 if(verbose>0) {
783 printf("%s(fp, vp, %d, %s, %s, x, y, %d, %s, %d, %d, errmsg, %d)\n", __func__,
784 plot_type, tac_id, tac_title, data_nr, color, (int)symbol_type, (int)symbol_fill, verbose);
785 fflush(stdout);
786 }
787
788 /* Check the input */
789 if(data_nr<1) return(0);
790 if(fp==NULL) {if(errmsg!=NULL) sprintf(errmsg, "file was closed too early"); return(1);}
791 if(color==NULL || strlen(color)<2) {
792 if(errmsg!=NULL) sprintf(errmsg, "invalid color");
793 return(1);
794 }
795
796 if(SVG_INLINE) strcpy(ilc, "svg:"); else strcpy(ilc, "");
797
798 /* Initiate the curve object group */
799 sprintf(tmp, "\n <!-- %s : %s -->\n <%sg", tac_id, tac_title, ilc);
800 sprintf(line, " stroke=\"%s\"", color); strcat(tmp, line);
801 sprintf(line, " stroke-width=\"%g\"", 0.25*size); strcat(tmp, line);
802 sprintf(line, " fill=\"%s\"", color); strcat(tmp, line);
803 if(symbol_fill==SYMBOLOPEN) sprintf(line, " fill-opacity=\"0.02\"");
804 else sprintf(line, " fill-opacity=\"0.92\"");
805 strcat(tmp, line); strcat(tmp, ">\n");
806 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(11);}
807 /* Set the curve title */
808 sprintf(tmp, " <%s", ilc);
809 sprintf(line, "title>"); strcat(tmp, line);
810 char *senc=svg_str_encode(tac_title);
811 if(senc==NULL) strcat(tmp, tac_title); else {strcat(tmp, senc); free(senc);}
812 strcat(tmp, "</"); strcat(tmp, ilc); strcat(tmp, "title>\n");
813 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(12);}
814
815 /* Plot the line, if required */
816 strcpy(tmp, ""); strcpy(line, "");
817 if(plot_type==0 || plot_type==1) {
818 int lineon=0, path_started=0, prev_exists=0, cross_nr;
819 double prev_px=-1, prev_py=-1, nx1, ny1, nx2, ny2;
820 /* Start a new print line */
821 strcpy(line, "\n ");
822 /* Write line coordinates */
823 for(i=j=0; i<data_nr; i++) {
824 if(isnan(x[i]) || isnan(y[i])) {lineon=0; continue;}
825 /* Print recent line coordinates in file */
826 if(j>=5) { /* line end */
827 if(path_started==0) {
828 sprintf(tmp, " <%spath fill=\"none\" d=\"", ilc);
829 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(14);}
830 path_started=1;
831 }
832 if(svg_write(fp, line, errmsg, verbose-5)!=0) {return(15);}
833 /* Start a new line */
834 j=0; strcpy(line, "\n ");
835 }
836 /* Compute the point coordinates in viewport */
837 if(verbose>3) printf("x[%d]=%g y[%d]=%g\n", i, x[i], i, y[i]);
838 px=vp->x.origo+x[i]*vp->x.scale;
839 py=vp->coordinate_area_viewport.h-(vp->y.origo+vp->y.scale*y[i]);
840 /* Make sure that prev point exists */
841 if(prev_exists==0) {prev_px=px; prev_py=py; prev_exists=1;}
842 /* Check if line would cross viewport border(s) */
843 cross_nr=check_intersection_with_viewport(prev_px, prev_py, px, py,
844 &vp->coordinate_area_viewport, &nx1, &ny1, &nx2, &ny2, verbose);
845 if(verbose>2 &&cross_nr>0)
846 printf("new line coordinates (%g,%g) -> (%g,%g)\n", nx1, ny1, nx2, ny2);
847 if(cross_nr==2) {
848 // Move to nx1,ny1 and draw line from nx1,ny1 to nx2,ny2
849 if(j>0) strcat(line, " ");
850 sprintf(tmp, "M%.0f %.0f L%.0f %.0f", nx1, ny1, nx2, ny2);
851 if(verbose>4) printf(" write %s\n", tmp);
852 strcat(line, tmp); j+=2;
853 lineon=0;
854 // Proceed to next sample
855 prev_px=px; prev_py=py;
856 continue;
857 } else if(cross_nr==1) {
858 if(nx1!=prev_px || ny1!=prev_py) lineon=0;
859 // Draw line from nx1,ny1 to nx2,ny2
860 if(j>0) strcat(line, " ");
861 if(lineon==0) {sprintf(tmp, "M%.0f %.0f L%.0f %.0f", nx1, ny1, nx2, ny2); j+=2;}
862 else if(lineon==1) {sprintf(tmp, "L%.0f %.0f", nx2, ny2); j++;}
863 else {sprintf(tmp, "%.0f %.0f", nx2, ny2); j++;}
864 if(verbose>4) printf(" write %s\n", tmp);
865 strcat(line, tmp);
866 if(nx2!=px || ny2!=py) lineon=0; else lineon++;
867 // Proceed to next sample
868 prev_px=px; prev_py=py;
869 continue;
870 } else {
871 nx1=prev_px; ny1=prev_py; nx2=px; ny2=py;
872 }
873 /* Draw line if coordinates are within viewport */
874 if(nx1>=0 && nx1<=vp->coordinate_area_viewport.w+1 &&
875 nx2>=0 && nx2<=vp->coordinate_area_viewport.w+1 &&
876 ny1>=0 && ny1<=vp->coordinate_area_viewport.h+1 &&
877 ny2>=0 && ny2<=vp->coordinate_area_viewport.h+1)
878 {
879 if(j>0) strcat(line, " ");
880 if(lineon==0) {
881 if(nx1!=nx2 && ny1!=ny2) sprintf(tmp, "M%.0f %.0f L%.0f %.0f", nx1, ny1, nx2, ny2);
882 else sprintf(tmp, "M%.0f %.0f", nx2, ny2);
883 j+=2;
884 }
885 else if(lineon==1) {sprintf(tmp, "L%.0f %.0f", nx2, ny2); j++;}
886 else {sprintf(tmp, "%.0f %.0f", nx2, ny2); j++;}
887 if(verbose>4) printf(" write %s\n", tmp);
888 strcat(line, tmp);
889 lineon++;
890 } else {
891 lineon=0;
892 }
893 prev_px=px; prev_py=py;
894 }
895 /* Write into file the remaining (if any) points */
896 if(j>0) {
897 if(path_started==0) {
898 sprintf(tmp, " <%spath fill=\"none\" d=\"", ilc);
899 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(14);}
900 }
901 if(svg_write(fp, line, errmsg, verbose-5)!=0) {return(16);}
902 }
903 /* Close line */
904 strcpy(tmp, "\" />\n");
905 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(17);}
906 }
907
908 /* Plot the symbols, if required */
909 strcpy(tmp, "");
910 if(plot_type==0 || plot_type==2) {
911 int prev_px=-1, prev_py=-1;
912 for(i=0; i<data_nr; i++) {
913 if(isnan(x[i]) || isnan(y[i])) continue;
914 px=vp->x.origo+x[i]*vp->x.scale;
915 py=vp->coordinate_area_viewport.h-(vp->y.origo+vp->y.scale*y[i]);
916 /* Do not plot points outside viewport */
917 if(px<0 || py<0) continue;
918 if(px>vp->coordinate_area_viewport.w+1 || py>vp->coordinate_area_viewport.h+1) continue;
919 /* Do not plot 2nd time the same point */
920 if(px==prev_px && py==prev_py) continue;
921 prev_px=px; prev_py=py;
922 /* Draw the symbol */
923 sprintf(tmp, " <%suse ", ilc);
924 switch(symbol_type) {
925 case RECTANGLE:
926 sprintf(line, "xlink:href=\"#sym-rect\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
927 px-0.5*size, py-0.5*size, size, size);
928 break;
929 case UPTRIANGLE:
930 sprintf(line, "xlink:href=\"#sym-uptr\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
931 px-0.5*trgsize, py-0.5*trgsize, trgsize, trgsize);
932 break;
933 case DOWNTRIANGLE:
934 sprintf(line, "xlink:href=\"#sym-dotr\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
935 px-0.5*trgsize, py-0.5*trgsize, trgsize, trgsize);
936 break;
937 case DIAMOND:
938 sprintf(line, "xlink:href=\"#sym-diam\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
939 px-0.5*trgsize, py-0.5*trgsize, trgsize, trgsize);
940 break;
941 case LEFTTRIANGLE:
942 sprintf(line, "xlink:href=\"#sym-letr\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
943 px-0.5*trgsize, py-0.5*trgsize, trgsize, trgsize);
944 break;
945 case RIGHTTRIANGLE:
946 sprintf(line, "xlink:href=\"#sym-ritr\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
947 px-0.5*trgsize, py-0.5*trgsize, trgsize, trgsize);
948 break;
949 case CIRCLE:
950 default:
951 sprintf(line, "xlink:href=\"#sym-circ\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
952 px-0.5*circsize, py-0.5*circsize, circsize, circsize);
953 break;
954 }
955 strcat(tmp, line);
956 strcat(tmp, " />\n");
957 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(18);}
958 }
959 }
960
961 /* Close the curve object group */
962 sprintf(tmp, " </%sg>\n", ilc);
963 if(svg_write(fp, tmp, errmsg, verbose-5)!=0) {return(19);}
964
965 return(0);
966}
967/*****************************************************************************/
968
969/*****************************************************************************/
void strRmExpZeroes(char *str)
Definition axis.c:179
void axis_check_range(double *begin, double *end, int verbose)
Definition axis.c:116
int axis_tick_positions(const double begin, const double end, double *ticks, int *tick_nr, double *scale_factor, int *tick_decimals, int verbose)
Definition axis.c:14
Header file for libtpcsvg.
svgSymbolType
Definition libtpcsvg.h:44
#define MAX_TICK_NR
Definition libtpcsvg.h:25
int svg_define_symbols(FILE *fp, char *errmsg, int verbose)
Definition svg_defs.c:83
svgSymbolFill
Definition libtpcsvg.h:47
int svg_write(FILE *fp, const char *svg_string, char *errmsg, int verbose)
Definition svg_file.c:304
char * svg_str_encode(const char *s)
Definition svg_legend.c:256
int upper_margin
Definition libtpcsvg.h:93
double tickscale
Definition libtpcsvg.h:87
int tick_nr
Definition libtpcsvg.h:83
double origo
Definition libtpcsvg.h:81
double scale
Definition libtpcsvg.h:79
int fixed_max
Definition libtpcsvg.h:97
int tick_decimals
Definition libtpcsvg.h:89
double tick[MAX_TICK_NR]
Definition libtpcsvg.h:85
double max
Definition libtpcsvg.h:77
int fixed_min
Definition libtpcsvg.h:95
char tick_label[MAX_TICK_NR][MAX_TICK_LABEL_LEN+1]
Definition libtpcsvg.h:91
double min
Definition libtpcsvg.h:75
struct svg_viewport_pos coordinate_area_viewport
Definition libtpcsvg.h:116
struct svg_viewport_pos label_area_viewport
Definition libtpcsvg.h:112
struct svg_coord x
Definition libtpcsvg.h:118
struct svg_coord y
Definition libtpcsvg.h:120
struct svg_viewport_pos plot_area_viewport
Definition libtpcsvg.h:114
int svg_write_xticks(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:555
int SVG_INLINE
Definition svg_file.c:12
int svg_end_plot_viewport(FILE *fp, char *errmsg, int verbose)
Definition svg_plot.c:238
int svg_start_coordinate_viewport(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:276
int svg_calculate_axes(struct svg_viewports *vp, int verbose)
Definition svg_plot.c:364
int svg_write_axes(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:437
int svg_end_coordinate_viewport(FILE *fp, char *errmsg, int verbose)
Definition svg_plot.c:327
int svg_start_plot_viewport(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:181
int get_line_intersection(const double a1x, const double a1y, const double a2x, const double a2y, const double b1x, const double b1y, const double b2x, const double b2y, double *ix, double *iy, int verbose)
Definition svg_plot.c:19
int check_intersection_with_viewport(const double x1, const double y1, const double x2, const double y2, struct svg_viewport_pos *cavp, double *nx1, double *ny1, double *nx2, double *ny2, int verbose)
Definition svg_plot.c:73
int svg_write_yticks(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:655
int svg_write_tac(FILE *fp, struct svg_viewports *vp, const int plot_type, const char *tac_id, const char *tac_title, double *x, double *y, const int data_nr, const char *color, const svgSymbolType symbol_type, const svgSymbolFill symbol_fill, char *errmsg, int verbose)
Definition svg_plot.c:746