grid_decimation.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /****************************************************************************
  2. *
  3. * MODULE: v.decimate
  4. * AUTHOR(S): Vaclav Petras
  5. * PURPOSE: Reduce the number of points in a vector map
  6. * COPYRIGHT: (C) 2015 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public
  9. * License (>=v2). Read the COPYING file that comes with GRASS
  10. * for details.
  11. *
  12. *****************************************************************************/
  13. #include "grid_decimation.h"
  14. #include <stdlib.h>
  15. /* max size: rows * cols < max of size_t (using 1D array) */
  16. void grid_decimation_create(struct GridDecimation *grid_decimation,
  17. size_t rows, size_t cols)
  18. {
  19. grid_decimation->grid_points =
  20. G_calloc(rows * cols, sizeof(struct DecimationPoint *));
  21. grid_decimation->grid_sizes = G_calloc(rows * cols, sizeof(size_t));
  22. grid_decimation->rows = rows;
  23. grid_decimation->cols = cols;
  24. grid_decimation->if_add_point = NULL;
  25. grid_decimation->on_add_point = NULL;
  26. grid_decimation->if_context = NULL;
  27. grid_decimation->on_context = NULL;
  28. }
  29. void grid_decimation_destroy(struct GridDecimation *grid_decimation)
  30. {
  31. /* TODO: we could also offer mode without dealloc (faster) */
  32. int row, col;
  33. size_t point, npoints;
  34. for (row = 0; row < grid_decimation->rows; row++) {
  35. for (col = 0; col < grid_decimation->cols; col++) {
  36. /* TODO: make index function */
  37. size_t index = row * grid_decimation->cols + col;
  38. if ((npoints = grid_decimation->grid_sizes[index])) {
  39. /* delete points in list */
  40. for (point = 0; point < npoints; point++)
  41. G_free(grid_decimation->grid_points[index][point]);
  42. /* delete list */
  43. G_free(grid_decimation->grid_points[index]);
  44. }
  45. }
  46. }
  47. G_free(grid_decimation->grid_points);
  48. G_free(grid_decimation->grid_sizes);
  49. }
  50. /* TODO: use Cell_head as storage? */
  51. void grid_decimation_create_from_region(struct GridDecimation
  52. *grid_decimation,
  53. struct Cell_head *region)
  54. {
  55. grid_decimation_create(grid_decimation, region->rows, region->cols);
  56. grid_decimation_set_region(grid_decimation, region->west, region->east,
  57. region->south, region->north, region->ew_res,
  58. region->ns_res);
  59. }
  60. /* TODO: change order of ns_res and ew_res to match xy */
  61. void grid_decimation_set_region(struct GridDecimation *grid_decimation,
  62. double minx, double maxx, double miny,
  63. double maxy, double ew_res, double ns_res)
  64. {
  65. grid_decimation->minx = minx;
  66. grid_decimation->maxx = maxx;
  67. grid_decimation->miny = miny;
  68. grid_decimation->maxy = maxy;
  69. grid_decimation->ns_res = ns_res;
  70. grid_decimation->ew_res = ew_res;
  71. }
  72. void grid_decimation_create_list_with_point(struct GridDecimation
  73. *grid_decimation, size_t index,
  74. struct DecimationPoint *point,
  75. size_t npoints)
  76. {
  77. struct DecimationPoint **point_list =
  78. G_malloc(1 * sizeof(struct DecimationPoint *));
  79. point_list[0] = point;
  80. grid_decimation->grid_points[index] = point_list;
  81. grid_decimation->grid_sizes[index] = 1;
  82. }
  83. void grid_decimation_add_point_to_list(struct GridDecimation *grid_decimation,
  84. size_t index,
  85. struct DecimationPoint *point,
  86. size_t npoints)
  87. {
  88. /* TODO: this might be too much reallocation */
  89. /* TODO: line_ptns struct could be reused, it is not meant for this but it would work */
  90. struct DecimationPoint **point_list =
  91. G_realloc(grid_decimation->grid_points[index],
  92. (npoints + 1) * sizeof(struct DecimationPoint *));
  93. point_list[npoints] = point;
  94. grid_decimation->grid_points[index] = point_list;
  95. grid_decimation->grid_sizes[index] = npoints + 1;
  96. }
  97. static size_t grid_decimation_xy_to_index(struct GridDecimation
  98. *grid_decimation, double x,
  99. double y)
  100. {
  101. /* TODO: test x, y */
  102. int row = (y - grid_decimation->miny) / grid_decimation->ns_res;
  103. int col = (x - grid_decimation->minx) / grid_decimation->ew_res;
  104. if (row < 0 || row > grid_decimation->rows || col < 0 ||
  105. col > grid_decimation->cols) {
  106. G_fatal_error
  107. ("Row (%d) or column (%d) outside of range (0 - %d, 0 - %d)", row,
  108. col, grid_decimation->rows, grid_decimation->cols);
  109. }
  110. size_t index = row * grid_decimation->cols + col;
  111. /* TODO: are the tests really needed, especially the second one? */
  112. if (row * grid_decimation->cols + col >
  113. grid_decimation->rows * grid_decimation->cols) {
  114. G_fatal_error("Index (%d) out of range (max: %d)",
  115. row * grid_decimation->cols + col,
  116. grid_decimation->rows * grid_decimation->cols);
  117. }
  118. return index;
  119. }
  120. void grid_decimation_try_add_point(struct GridDecimation *grid_decimation,
  121. int cat, double x, double y, double z, void *point_data)
  122. {
  123. size_t index = grid_decimation_xy_to_index(grid_decimation, x, y);
  124. int npoints = grid_decimation->grid_sizes[index];
  125. /* TODO: when max is 1, we don't have to store the point at all */
  126. if (grid_decimation->max_points && grid_decimation->max_points == npoints)
  127. return;
  128. struct DecimationPoint *point = G_malloc(sizeof(struct DecimationPoint));
  129. point->cat = cat;
  130. point->x = x;
  131. point->y = y;
  132. point->z = z;
  133. if (!npoints) {
  134. grid_decimation_create_list_with_point(grid_decimation, index, point,
  135. npoints);
  136. if (grid_decimation->on_add_point)
  137. grid_decimation->on_add_point(point, point_data, grid_decimation->on_context);
  138. }
  139. else {
  140. if (grid_decimation->if_add_point
  141. (point, point_data, grid_decimation->grid_points[index], npoints,
  142. grid_decimation->if_context)) {
  143. grid_decimation_add_point_to_list(grid_decimation, index, point,
  144. npoints);
  145. if (grid_decimation->on_add_point)
  146. grid_decimation->on_add_point(point, point_data,
  147. grid_decimation->on_context);
  148. }
  149. else {
  150. G_free(point);
  151. }
  152. }
  153. }