label.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include <grass/gis.h>
  2. #include <grass/vector.h>
  3. #include <grass/display.h>
  4. #include <grass/glocale.h>
  5. #include "local_proto.h"
  6. #include "plot.h"
  7. static int process_line(int, const struct line_pnts *,
  8. const struct line_cats *, LATTR *,
  9. int, const struct cat_list *);
  10. int display_label(struct Map_info *Map, int type,
  11. struct cat_list *Clist, LATTR *lattr, int chcat)
  12. {
  13. int ltype;
  14. struct line_pnts *Points;
  15. struct line_cats *Cats;
  16. int ogr_centroids;
  17. const struct Format_info *finfo;
  18. Points = Vect_new_line_struct();
  19. Cats = Vect_new_cats_struct();
  20. Vect_rewind(Map);
  21. ogr_centroids = FALSE;
  22. finfo = Vect_get_finfo(Map);
  23. if (Vect_maptype(Map) == GV_FORMAT_OGR ||
  24. (Vect_maptype(Map) == GV_FORMAT_POSTGIS &&
  25. finfo->pg.toposchema_name == NULL)) {
  26. if (Vect_level(Map) < 2)
  27. G_warning(_("Topology level required for drawing centroids "
  28. "for OGR layers"));
  29. else if (Vect_get_num_primitives(Map, GV_CENTROID) > 0 &&
  30. type & GV_CENTROID)
  31. /* label centroids from topo, don't label boundaries */
  32. ogr_centroids = TRUE;
  33. }
  34. while (TRUE) {
  35. ltype = Vect_read_next_line(Map, Points, Cats);
  36. if (ltype == -1)
  37. G_fatal_error(_("Unable to read vector map"));
  38. else if (ltype == -2) /* EOF */
  39. break;
  40. if (!(type & ltype) && !((type & GV_AREA) && (ltype & GV_CENTROID)))
  41. continue; /* used for both lines and labels */
  42. if (ogr_centroids && ltype == GV_BOUNDARY)
  43. /* do not label boundaries */
  44. continue;
  45. process_line(ltype, Points, Cats, lattr, chcat, Clist);
  46. }
  47. if (ogr_centroids) {
  48. /* show label for centroids stored in topo (for OGR layers
  49. only) */
  50. int line, nlines;
  51. struct bound_box box;
  52. struct boxlist *list;
  53. list = Vect_new_boxlist(FALSE); /* bboxes not needed */
  54. Vect_get_constraint_box(Map, &box);
  55. nlines = Vect_select_lines_by_box(Map, &box, GV_CENTROID, list);
  56. G_debug(3, "ncentroids (ogr) = %d", nlines);
  57. for (line = 0; line < nlines; line++) {
  58. ltype = Vect_read_line(Map, Points, Cats, list->id[line]);
  59. process_line(ltype, Points, Cats, lattr, chcat, Clist);
  60. }
  61. Vect_destroy_boxlist(list);
  62. }
  63. Vect_destroy_line_struct(Points);
  64. Vect_destroy_cats_struct(Cats);
  65. return 0;
  66. }
  67. int process_line(int ltype, const struct line_pnts *Points,
  68. const struct line_cats *Cats, LATTR *lattr,
  69. int chcat, const struct cat_list *Clist)
  70. {
  71. int i, cat, len;
  72. char *text = NULL, buf[100];
  73. D_RGB_color(lattr->color.R, lattr->color.G, lattr->color.B);
  74. D_text_size(lattr->size, lattr->size);
  75. if (lattr->font)
  76. D_font(lattr->font);
  77. if (lattr->enc)
  78. D_encoding(lattr->enc);
  79. if (chcat) {
  80. int found = 0;
  81. for (i = 0; i < Cats->n_cats; i++) {
  82. if (Cats->field[i] == Clist->field &&
  83. Vect_cat_in_cat_list(Cats->cat[i], Clist)) {
  84. found = 1;
  85. break;
  86. }
  87. }
  88. if (!found)
  89. return 0;
  90. }
  91. else if (Clist->field > 0) {
  92. int found = 0;
  93. for (i = 0; i < Cats->n_cats; i++) {
  94. if (Cats->field[i] == Clist->field) {
  95. found = 1;
  96. break;
  97. }
  98. }
  99. /* lines with no category will be displayed */
  100. if (Cats->n_cats > 0 && !found)
  101. return 0;
  102. }
  103. if (Vect_cat_get(Cats, lattr->field, &cat)) {
  104. for (i = 0; i < Cats->n_cats; i++) {
  105. G_debug(3, "cat lab: field = %d, cat = %d", Cats->field[i],
  106. Cats->cat[i]);
  107. if (Cats->field[i] == lattr->field) { /* all cats of given lfield */
  108. if (!text) {
  109. sprintf(buf, "%d", Cats->cat[i]);
  110. text = G_calloc(strlen(buf), sizeof(char));
  111. text[0] = '\0';
  112. strcpy(text, buf);
  113. }
  114. else {
  115. sprintf(buf, "/%d", Cats->cat[i]);
  116. len = strlen(text) + strlen(buf) + 1;
  117. text = G_realloc(text, len * sizeof(char));
  118. strcat(text, buf);
  119. }
  120. }
  121. }
  122. show_label_line(Points, ltype, lattr, text);
  123. }
  124. if (text)
  125. G_free(text);
  126. return 1;
  127. }
  128. void show_label(double *px, double *py, LATTR *lattr, const char *text)
  129. {
  130. double X = *px, Y = *py;
  131. int Xoffset, Yoffset;
  132. double xarr[5], yarr[5];
  133. double T, B, L, R;
  134. X = X + D_get_d_to_u_xconv() * 0.5 * lattr->size;
  135. Y = Y + D_get_d_to_u_yconv() * 1.5 * lattr->size;
  136. D_pos_abs(X, Y);
  137. D_get_text_box(text, &T, &B, &L, &R);
  138. /* Expand border 1/2 of text size */
  139. T = T - D_get_d_to_u_yconv() * lattr->size / 2;
  140. B = B + D_get_d_to_u_yconv() * lattr->size / 2;
  141. L = L - D_get_d_to_u_xconv() * lattr->size / 2;
  142. R = R + D_get_d_to_u_xconv() * lattr->size / 2;
  143. Xoffset = 0;
  144. Yoffset = 0;
  145. if (lattr->xref == LCENTER)
  146. Xoffset = -(R - L) / 2;
  147. if (lattr->xref == LRIGHT)
  148. Xoffset = -(R - L);
  149. if (lattr->yref == LCENTER)
  150. Yoffset = -(B - T) / 2;
  151. if (lattr->yref == LBOTTOM)
  152. Yoffset = -(B - T);
  153. if (lattr->has_bgcolor || lattr->has_bcolor) {
  154. xarr[0] = xarr[1] = xarr[4] = L + Xoffset;
  155. xarr[2] = xarr[3] = R + Xoffset;
  156. yarr[0] = yarr[3] = yarr[4] = B + Yoffset;
  157. yarr[1] = yarr[2] = T + Yoffset;
  158. if (lattr->has_bgcolor) {
  159. D_RGB_color(lattr->bgcolor.R, lattr->bgcolor.G,
  160. lattr->bgcolor.B);
  161. D_polygon_abs(xarr, yarr, 5);
  162. }
  163. if (lattr->has_bcolor) {
  164. D_RGB_color(lattr->bcolor.R, lattr->bcolor.G,
  165. lattr->bcolor.B);
  166. D_polyline_abs(xarr, yarr, 5);
  167. }
  168. D_RGB_color(lattr->color.R, lattr->color.G, lattr->color.B);
  169. }
  170. D_pos_abs(X + Xoffset, Y + Yoffset);
  171. D_text(text);
  172. }
  173. void show_label_line(const struct line_pnts *Points, int ltype, LATTR *lattr,
  174. const char *text)
  175. {
  176. double X, Y;
  177. if ((ltype & GV_POINTS) || Points->n_points == 1)
  178. /* point/centroid or line/boundary with one coor */
  179. {
  180. X = Points->x[0];
  181. Y = Points->y[0];
  182. }
  183. else if (Points->n_points == 2) { /* line with two coors */
  184. X = (Points->x[0] + Points->x[1]) / 2;
  185. Y = (Points->y[0] + Points->y[1]) / 2;
  186. }
  187. else {
  188. int i = Points->n_points / 2;
  189. X = Points->x[i];
  190. Y = Points->y[i];
  191. }
  192. show_label(&X, &Y, lattr, text);
  193. }