report.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /****************************************************************************
  2. *
  3. * MODULE: r.distance
  4. *
  5. * AUTHOR(S): Michael Shapiro - CERL
  6. * Sort/reverse sort by distance by Huidae Cho
  7. *
  8. * PURPOSE: Locates the closest points between objects in two
  9. * raster maps.
  10. *
  11. * COPYRIGHT: (C) 2003-2014 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General
  14. * Public License (>=v2). Read the file COPYING that
  15. * comes with GRASS for details.
  16. *
  17. ***************************************************************************/
  18. #include <stdlib.h>
  19. #include <grass/glocale.h>
  20. #include "defs.h"
  21. struct ReportLine
  22. {
  23. CELL cat1;
  24. CELL cat2;
  25. int isnull1;
  26. int isnull2;
  27. double east1;
  28. double north1;
  29. double east2;
  30. double north2;
  31. double distance;
  32. };
  33. static void print(struct ReportLine *, struct Parms *);
  34. static int compare(const void *, const void *);
  35. static int revcompare(const void *, const void *);
  36. void report(struct Parms *parms)
  37. {
  38. int i1, i2;
  39. struct Map *map1, *map2;
  40. double distance, north1, east1, north2, east2;
  41. struct Cell_head region;
  42. struct CatEdgeList *list1, *list2;
  43. struct ReportLine *lines;
  44. int nlines;
  45. extern void find_minimum_distance();
  46. extern char *get_label();
  47. G_get_set_window(&region);
  48. G_begin_distance_calculations();
  49. map1 = &parms->map1;
  50. map2 = &parms->map2;
  51. G_message(_("Processing..."));
  52. if (parms->sort > 0)
  53. lines = (struct ReportLine *)G_malloc(
  54. map1->edges.ncats * map2->edges.ncats *
  55. sizeof(struct ReportLine));
  56. else
  57. lines = NULL;
  58. nlines = 0;
  59. for (i1 = 0; i1 < map1->edges.ncats; i1++) {
  60. int isnull1;
  61. list1 = &map1->edges.catlist[i1];
  62. isnull1 = parms->null ? Rast_is_c_null_value(&(list1->cat)) : 0;
  63. for (i2 = 0; i2 < map2->edges.ncats; i2++) {
  64. int isnull2;
  65. struct ReportLine line;
  66. list2 = &map2->edges.catlist[i2];
  67. isnull2 = parms->null ? Rast_is_c_null_value(&(list2->cat)) : 0;
  68. find_minimum_distance(list1, list2,
  69. &east1, &north1, &east2, &north2, &distance,
  70. &region, parms->overlap, map1->name,
  71. map2->name);
  72. line.cat1 = list1->cat;
  73. line.cat2 = list2->cat;
  74. line.isnull1 = isnull1;
  75. line.isnull2 = isnull2;
  76. line.east1 = east1;
  77. line.north1 = north1;
  78. line.east2 = east2;
  79. line.north2 = north2;
  80. line.distance = distance;
  81. if (parms->sort > 0)
  82. lines[nlines++] = line;
  83. else
  84. print(&line, parms);
  85. }
  86. }
  87. if (parms->sort > 0) {
  88. int i;
  89. if (parms->sort == 1)
  90. qsort(lines, nlines, sizeof(struct ReportLine), compare);
  91. else
  92. qsort(lines, nlines, sizeof(struct ReportLine), revcompare);
  93. for(i = 0; i < nlines; i++)
  94. print(&lines[i], parms);
  95. }
  96. }
  97. static void print(struct ReportLine *line, struct Parms *parms)
  98. {
  99. char *fs;
  100. char temp[100];
  101. fs = parms->fs;
  102. /* print cat numbers */
  103. if (line->isnull1 && line->isnull2)
  104. fprintf(stdout, "*%s*", fs);
  105. else if (line->isnull1)
  106. fprintf(stdout, "*%s%ld", fs, (long)line->cat2);
  107. else if (line->isnull2)
  108. fprintf(stdout, "%ld%s*", (long)line->cat1, fs);
  109. else
  110. fprintf(stdout, "%ld%s%ld", (long)line->cat1, fs, (long)line->cat2);
  111. /* print distance */
  112. sprintf(temp, "%.10f", line->distance);
  113. G_trim_decimal(temp);
  114. fprintf(stdout, "%s%s", fs, temp);
  115. /* print coordinates of the closest pair */
  116. G_format_easting(line->east1, temp,
  117. G_projection() == PROJECTION_LL ? -1 : 0);
  118. fprintf(stdout, "%s%s", fs, temp);
  119. G_format_northing(line->north1, temp,
  120. G_projection() == PROJECTION_LL ? -1 : 0);
  121. fprintf(stdout, "%s%s", fs, temp);
  122. G_format_easting(line->east2, temp,
  123. G_projection() == PROJECTION_LL ? -1 : 0);
  124. fprintf(stdout, "%s%s", fs, temp);
  125. G_format_northing(line->north2, temp,
  126. G_projection() == PROJECTION_LL ? -1 : 0);
  127. fprintf(stdout, "%s%s", fs, temp);
  128. /* print category labels */
  129. if (parms->labels) {
  130. struct Map *map1, *map2;
  131. map1 = &parms->map1;
  132. map2 = &parms->map2;
  133. fprintf(stdout, "%s%s", fs, get_label(map1, line->cat1));
  134. fprintf(stdout, "%s%s", fs, get_label(map2, line->cat2));
  135. }
  136. fprintf(stdout, "\n");
  137. }
  138. static int compare(const void *p1, const void *p2)
  139. {
  140. const struct ReportLine *line1, *line2;
  141. line1 = (const struct ReportLine *)p1;
  142. line2 = (const struct ReportLine *)p2;
  143. if (line1->distance < line2->distance) return -1; /* short distance first */
  144. if (line1->distance > line2->distance) return 1;
  145. if (!line1->isnull1 && line2->isnull1) return -1; /* non-null first */
  146. if (line1->isnull1 && !line2->isnull1) return 1;
  147. if (!line1->isnull1 && !line2->isnull1) {
  148. if (line1->cat1 < line2->cat1) return -1; /* small cat first */
  149. if (line1->cat1 > line2->cat1) return 1;
  150. }
  151. if (!line1->isnull2 && line2->isnull2) return -1;
  152. if (line1->isnull2 && !line2->isnull2) return 1;
  153. if (!line1->isnull2 && !line2->isnull2) {
  154. if (line1->cat2 < line2->cat2) return -1;
  155. if (line1->cat2 > line2->cat2) return 1;
  156. }
  157. return 0; /* same cat1, same cat2 */
  158. }
  159. static int revcompare(const void *p1, const void *p2)
  160. {
  161. return -compare(p1, p2);
  162. }