gnuplot.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * gnuplot.c - Dump objects in gnuplot 2D format
  3. *
  4. * Written 2011 by Werner Almesberger
  5. * Copyright 2011 by Werner Almesberger
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "coord.h"
  15. #include "inst.h"
  16. #include "gnuplot.h"
  17. #define ARC_STEP 0.1 /* @@@ make configurable */
  18. static void recurse_id(FILE *file, const struct inst *inst)
  19. {
  20. if (inst->obj->frame->name) {
  21. recurse_id(file, inst->outer);
  22. fprintf(file, "/%s", inst->obj->frame->name);
  23. }
  24. }
  25. static void identify(FILE *file, const struct inst *inst)
  26. {
  27. fprintf(file, "#%%id=");
  28. recurse_id(file, inst);
  29. fprintf(file, "\n");
  30. }
  31. static void gnuplot_line(FILE *file, const struct inst *inst)
  32. {
  33. double xa, ya, xb, yb;
  34. xa = units_to_mm(inst->base.x);
  35. ya = units_to_mm(inst->base.y);
  36. xb = units_to_mm(inst->u.rect.end.x);
  37. yb = units_to_mm(inst->u.rect.end.y);
  38. identify(file, inst);
  39. fprintf(file, "#%%r=%f\n%f %f\n%f %f\n\n",
  40. units_to_mm(inst->u.rect.width), xa, ya, xb, yb);
  41. }
  42. static void gnuplot_rect(FILE *file, const struct inst *inst)
  43. {
  44. double xa, ya, xb, yb;
  45. xa = units_to_mm(inst->base.x);
  46. ya = units_to_mm(inst->base.y);
  47. xb = units_to_mm(inst->u.rect.end.x);
  48. yb = units_to_mm(inst->u.rect.end.y);
  49. identify(file, inst);
  50. fprintf(file, "#%%r=%f\n", units_to_mm(inst->u.rect.width));
  51. fprintf(file, "%f %f\n", xa, ya);
  52. fprintf(file, "%f %f\n", xa, yb);
  53. fprintf(file, "%f %f\n", xb, yb);
  54. fprintf(file, "%f %f\n", xb, ya);
  55. fprintf(file, "%f %f\n\n", xa, ya);
  56. }
  57. static void gnuplot_circ(FILE *file, const struct inst *inst)
  58. {
  59. double cx, cy, r;
  60. double a;
  61. int n, i;
  62. cx = units_to_mm(inst->base.x);
  63. cy = units_to_mm(inst->base.y);
  64. r = units_to_mm(inst->u.arc.r);
  65. identify(file, inst);
  66. fprintf(file, "#%%r=%f\n", units_to_mm(inst->u.arc.width));
  67. n = ceil(2*r*M_PI/ARC_STEP);
  68. if (n < 2)
  69. n = 2;
  70. for (i = 0; i <= n; i++) {
  71. a = 2*M_PI/n*i;
  72. fprintf(file, "%f %f\n", cx+r*sin(a), cy+r*cos(a));
  73. }
  74. fprintf(file, "\n");
  75. }
  76. static void gnuplot_arc(FILE *file, const struct inst *inst)
  77. {
  78. double cx, cy, r;
  79. double a, tmp;
  80. int n, i;
  81. cx = units_to_mm(inst->base.x);
  82. cy = units_to_mm(inst->base.y);
  83. r = units_to_mm(inst->u.arc.r);
  84. a = inst->u.arc.a2-inst->u.arc.a1;
  85. while (a <= 0)
  86. a += 360;
  87. while (a > 360)
  88. a =- 360;
  89. n = ceil(2*r*M_PI/360*a/ARC_STEP);
  90. if (n < 2)
  91. n = 2;
  92. for (i = 0; i <= n; i++) {
  93. tmp = (inst->u.arc.a1+a/n*i)*M_PI/180;
  94. fprintf(file, "%f %f\n", cx+r*cos(tmp), cy+r*sin(tmp));
  95. }
  96. fprintf(file, "\n");
  97. }
  98. static void gnuplot_inst(FILE *file, enum inst_prio prio,
  99. const struct inst *inst)
  100. {
  101. switch (prio) {
  102. case ip_pad_copper:
  103. case ip_pad_special:
  104. /* complain ? */
  105. break;
  106. case ip_hole:
  107. /* complain ? */
  108. break;
  109. case ip_line:
  110. gnuplot_line(file, inst);
  111. break;
  112. case ip_rect:
  113. gnuplot_rect(file, inst);
  114. break;
  115. case ip_circ:
  116. gnuplot_circ(file, inst);
  117. break;
  118. case ip_arc:
  119. gnuplot_arc(file, inst);
  120. break;
  121. default:
  122. /*
  123. * Don't try to export vectors, frame references, or
  124. * measurements.
  125. */
  126. break;
  127. }
  128. }
  129. static void gnuplot_package(FILE *file, const struct pkg *pkg)
  130. {
  131. enum inst_prio prio;
  132. const struct inst *inst;
  133. /*
  134. * Package name
  135. */
  136. fprintf(file, "# %s\n", pkg->name);
  137. FOR_INST_PRIOS_UP(prio) {
  138. for (inst = pkgs->insts[prio]; inst; inst = inst->next)
  139. gnuplot_inst(file, prio, inst);
  140. for (inst = pkg->insts[prio]; inst; inst = inst->next)
  141. gnuplot_inst(file, prio, inst);
  142. }
  143. fprintf(file, "\n");
  144. }
  145. int gnuplot(FILE *file, const char *one)
  146. {
  147. const struct pkg *pkg;
  148. for (pkg = pkgs; pkg; pkg = pkg->next)
  149. if (pkg->name)
  150. if (!one || !strcmp(pkg->name, one))
  151. gnuplot_package(file, pkg);
  152. fflush(file);
  153. return !ferror(file);
  154. }