stroke.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /****************************************************************************
  2. *
  3. * MODULE: Symbol library
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. *
  7. * PURPOSE: Stroke symbol
  8. *
  9. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <stdlib.h>
  17. #include <math.h>
  18. #include <grass/gis.h>
  19. #include <grass/symbol.h>
  20. #define PI M_PI
  21. void add_coor(SYMBCHAIN *chain, double x, double y)
  22. {
  23. G_debug(5, " add_coor %f, %f", x, y);
  24. if (chain->scount == chain->salloc) {
  25. chain->salloc += 10;
  26. chain->sx = (double *)G_realloc(chain->sx, chain->salloc * sizeof(double));
  27. chain->sy = (double *)G_realloc(chain->sy, chain->salloc * sizeof(double));
  28. }
  29. chain->sx[chain->scount] = x;
  30. chain->sy[chain->scount] = y;
  31. chain->scount++;
  32. }
  33. /* draw chain
  34. * s - scale
  35. * ch - chain number
  36. * rotation - degrees CCW from East
  37. */
  38. int stroke_chain(SYMBPART *part, int ch, double s, double rotation)
  39. {
  40. int k, l, first;
  41. SYMBEL *elem;
  42. SYMBCHAIN *chain;
  43. double r;
  44. double a1, a2, da;
  45. double x, y, x0, y0;
  46. G_debug(5, " stroke_chain(): ch = %d", ch);
  47. chain = part->chain[ch];
  48. G_debug(5, " element count = %d", chain->count);
  49. first = 1;
  50. for (k = 0; k < chain->count; k++) {
  51. elem = chain->elem[k];
  52. switch (elem->type) {
  53. case S_LINE:
  54. G_debug(5, " LINE count = %d", elem->coor.line.count);
  55. for (l = 0; l < elem->coor.line.count; l++) {
  56. x = s * elem->coor.line.x[l];
  57. y = s * elem->coor.line.y[l];
  58. if (rotation != 0.0)
  59. G_rotate_around_point(0, 0, &x, &y, rotation);
  60. add_coor(chain, x, y);
  61. if (first) {
  62. x0 = x;
  63. y0 = y;
  64. first = 0;
  65. }
  66. }
  67. break;
  68. case S_ARC:
  69. if (s >= 50)
  70. da = 1 * PI / 180; /* later calc from size and tolerance */
  71. else
  72. da = 10 * PI / 180;
  73. r = elem->coor.arc.r;
  74. G_debug(5, " ARC da = %f r = %f", da, r);
  75. /* convert to positive angles */
  76. a1 = PI * elem->coor.arc.a1 / 180;
  77. if (a1 < 0)
  78. a1 += 2 * PI;
  79. a2 = PI * elem->coor.arc.a2 / 180;
  80. if (a2 < 0)
  81. a2 += 2 * PI;
  82. if (elem->coor.arc.clock) { /* clockwise */
  83. while (1) {
  84. x = s * elem->coor.arc.x + s * r * cos(a1);
  85. y = s * elem->coor.arc.y + s * r * sin(a1);
  86. if (rotation != 0.0)
  87. G_rotate_around_point(0, 0, &x, &y, rotation);
  88. add_coor(chain, x, y);
  89. if (first) {
  90. x0 = x;
  91. y0 = y;
  92. first = 0;
  93. }
  94. if (a1 == a2)
  95. break;
  96. a1 -= da;
  97. if (a1 < a2)
  98. a1 = a2;
  99. }
  100. }
  101. else {
  102. while (1) {
  103. x = s * elem->coor.arc.x + s * r * cos(a1);
  104. y = s * elem->coor.arc.y + s * r * sin(a1);
  105. if (rotation != 0.0)
  106. G_rotate_around_point(0, 0, &x, &y, rotation);
  107. add_coor(chain, x, y);
  108. if (first) {
  109. x0 = x;
  110. y0 = y;
  111. first = 0;
  112. }
  113. if (a1 == a2)
  114. break;
  115. a1 += da;
  116. if (a1 > a2)
  117. a1 = a2;
  118. }
  119. }
  120. break;
  121. }
  122. }
  123. if (part->type == S_POLYGON) {
  124. add_coor(chain, x0, y0); /* Close ring */
  125. }
  126. return 0;
  127. }
  128. /*!
  129. * \brief Stroke symbol to form used for Xdriver.
  130. *
  131. * tolerance currently not supported
  132. *
  133. * \param Symb pointer to
  134. * \param size symbol size
  135. * \param rotation symbol rotation, degrees CCW from East
  136. * \param tolerance currently not supported
  137. *
  138. */
  139. void S_stroke(SYMBOL *Symb, double size, double rotation, int tolerance)
  140. {
  141. int i, j;
  142. double s;
  143. SYMBPART *part;
  144. G_debug(3, "S_stroke(): size = %.2f, rotation = %.2f, tolerance = %d",
  145. size, rotation, tolerance);
  146. /* TODO: support for tolerance */
  147. s = size * Symb->scale;
  148. for (i = 0; i < Symb->count; i++) {
  149. G_debug(4, " part %d", i);
  150. part = Symb->part[i];
  151. switch (part->type) {
  152. case S_POLYGON:
  153. for (j = 0; j < part->count; j++) { /* RINGS */
  154. stroke_chain(part, j, s, rotation);
  155. }
  156. break;
  157. case S_STRING: /* string has 1 chain */
  158. stroke_chain(part, 0, s, rotation);
  159. break;
  160. }
  161. }
  162. }