stroke.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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, int x, int y)
  22. {
  23. G_debug(5, " add_coor %d, %d", x, y);
  24. if (chain->scount == chain->salloc) {
  25. chain->salloc += 10;
  26. chain->sx = (int *)G_realloc(chain->sx, chain->salloc * sizeof(int));
  27. chain->sy = (int *)G_realloc(chain->sy, chain->salloc * sizeof(int));
  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. int 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_int(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. da = 10 * PI / 180; /* later calc from size and tolerance */
  70. r = elem->coor.arc.r;
  71. G_debug(5, " ARC da = %f r = %f", da, r);
  72. /* convert to positive angles */
  73. a1 = PI * elem->coor.arc.a1 / 180;
  74. if (a1 < 0)
  75. a1 += 2 * PI;
  76. a2 = PI * elem->coor.arc.a2 / 180;
  77. if (a2 < 0)
  78. a2 += 2 * PI;
  79. if (elem->coor.arc.clock) { /* clockwise */
  80. while (1) {
  81. x = s * elem->coor.arc.x + s * r * cos(a1);
  82. y = s * elem->coor.arc.y + s * r * sin(a1);
  83. if (rotation != 0.0)
  84. G_rotate_around_point_int(0, 0, &x, &y, rotation);
  85. add_coor(chain, x, y);
  86. if (first) {
  87. x0 = x;
  88. y0 = y;
  89. first = 0;
  90. }
  91. if (a1 == a2)
  92. break;
  93. a1 -= da;
  94. if (a1 < a2)
  95. a1 = a2;
  96. }
  97. }
  98. else {
  99. while (1) {
  100. x = s * elem->coor.arc.x + s * r * cos(a1);
  101. y = s * elem->coor.arc.y + s * r * sin(a1);
  102. if (rotation != 0.0)
  103. G_rotate_around_point_int(0, 0, &x, &y, rotation);
  104. add_coor(chain, x, y);
  105. if (first) {
  106. x0 = x;
  107. y0 = y;
  108. first = 0;
  109. }
  110. if (a1 == a2)
  111. break;
  112. a1 += da;
  113. if (a1 > a2)
  114. a1 = a2;
  115. }
  116. }
  117. break;
  118. }
  119. }
  120. if (part->type == S_POLYGON) {
  121. add_coor(chain, x0, y0); /* Close ring */
  122. }
  123. return 0;
  124. }
  125. /*!
  126. * \brief Stroke symbol to form used for Xdriver.
  127. *
  128. * tolerance currently not supported
  129. *
  130. * \param Symb pointer to
  131. * \param size symbol size
  132. * \param rotation symbol rotation, degrees CCW from East
  133. * \param tolerance currently not supported
  134. *
  135. */
  136. void S_stroke(SYMBOL *Symb, double size, double rotation, int tolerance)
  137. {
  138. int i, j;
  139. double s;
  140. SYMBPART *part;
  141. G_debug(3, "S_stroke(): size = %.2f, rotation = %.2f, tolerance = %d",
  142. size, rotation, tolerance);
  143. /* TODO: support for tolerance */
  144. s = size * Symb->scale;
  145. for (i = 0; i < Symb->count; i++) {
  146. G_debug(4, " part %d", i);
  147. part = Symb->part[i];
  148. switch (part->type) {
  149. case S_POLYGON:
  150. for (j = 0; j < part->count; j++) { /* RINGS */
  151. stroke_chain(part, j, s, rotation);
  152. }
  153. break;
  154. case S_STRING: /* string has 1 chain */
  155. stroke_chain(part, 0, s, rotation);
  156. break;
  157. }
  158. }
  159. }