n_geom.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*****************************************************************************
  2. *
  3. * MODULE: Grass PDE Numerical Library
  4. * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
  5. * soerengebbert <at> gmx <dot> de
  6. *
  7. * PURPOSE: part of the gpde library
  8. * allocation, destroying and initializing the geometric struct
  9. *
  10. * COPYRIGHT: (C) 2000 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <grass/N_pde.h>
  18. /* *************************************************************** *
  19. * *********** Konstruktor *************************************** *
  20. * *************************************************************** */
  21. /*!
  22. * \brief Allocate the pde geometry data structure and return a pointer to the new allocated structure
  23. *
  24. * \return N_geom_data *
  25. * */
  26. N_geom_data *N_alloc_geom_data(void)
  27. {
  28. N_geom_data *geom = (N_geom_data *) G_calloc(1, sizeof(N_geom_data));
  29. geom->area = NULL;
  30. geom->planimetric = 1;
  31. geom->dim = 0;
  32. return geom;
  33. }
  34. /* *************************************************************** *
  35. * *********** Destruktor **************************************** *
  36. * *************************************************************** */
  37. /*!
  38. * \brief Release memory of a pde geometry data structure
  39. *
  40. * \param geom N_geom_data *
  41. * \return void
  42. * */
  43. void N_free_geom_data(N_geom_data * geom)
  44. {
  45. if (geom->area != NULL)
  46. G_free(geom->area);
  47. G_free(geom);
  48. return;
  49. }
  50. /* *************************************************************** *
  51. * *************************************************************** *
  52. * *************************************************************** */
  53. /*!
  54. * \brief Initiate a pde geometry data structure with a 3d region
  55. *
  56. * If the projection is not planimetric, a double array will be created based on the
  57. * number of rows of the provided region
  58. *
  59. * \param region3d RASTER3D_Region *
  60. * \param geodata N_geom_data * - if a NULL pointer is given, a new structure will be allocatet and returned
  61. *
  62. * \return N_geom_data *
  63. * */
  64. N_geom_data *N_init_geom_data_3d(RASTER3D_Region * region3d, N_geom_data * geodata)
  65. {
  66. N_geom_data *geom = geodata;
  67. struct Cell_head region2d;
  68. #pragma omp critical
  69. {
  70. G_debug(2,
  71. "N_init_geom_data_3d: initializing the geometry structure");
  72. if (geom == NULL)
  73. geom = N_alloc_geom_data();
  74. geom->dz = region3d->tb_res * G_database_units_to_meters_factor(); /*this function is not thread safe */
  75. geom->depths = region3d->depths;
  76. geom->dim = 3;
  77. /*convert the 3d into a 2d region and begin the area calculation */
  78. G_get_set_window(&region2d); /*this function is not thread safe */
  79. Rast3d_region_to_cell_head(region3d, &region2d);
  80. }
  81. return N_init_geom_data_2d(&region2d, geom);
  82. }
  83. /* *************************************************************** *
  84. * *************************************************************** *
  85. * *************************************************************** */
  86. /*!
  87. * \brief Initiate a pde geometry data structure with a 2d region
  88. *
  89. * If the projection is not planimetric, a double array will be created based on the
  90. * number of rows of the provided region storing all computed areas for each row
  91. *
  92. * \param region sruct Cell_head *
  93. * \param geodata N_geom_data * - if a NULL pointer is given, a new structure will be allocatet and returned
  94. *
  95. * \return N_geom_data *
  96. * */
  97. N_geom_data *N_init_geom_data_2d(struct Cell_head * region,
  98. N_geom_data * geodata)
  99. {
  100. N_geom_data *geom = geodata;
  101. struct Cell_head backup;
  102. double meters;
  103. short ll = 0;
  104. int i;
  105. /*create an openmp lock to assure that only one thread at a time will access this function */
  106. #pragma omp critical
  107. {
  108. G_debug(2,
  109. "N_init_geom_data_2d: initializing the geometry structure");
  110. /*make a backup from this region */
  111. G_get_set_window(&backup); /*this function is not thread safe */
  112. /*set the current region */
  113. Rast_set_window(region); /*this function is not thread safe */
  114. if (geom == NULL)
  115. geom = N_alloc_geom_data();
  116. meters = G_database_units_to_meters_factor(); /*this function is not thread safe */
  117. /*set the dim to 2d if it was not initiated with 3, that's a bit ugly :( */
  118. if (geom->dim != 3)
  119. geom->dim = 2;
  120. geom->planimetric = 1;
  121. geom->rows = region->rows;
  122. geom->cols = region->cols;
  123. geom->dx = region->ew_res * meters;
  124. geom->dy = region->ns_res * meters;
  125. geom->Az = geom->dy * geom->dx; /*square meters in planimetric proj */
  126. /*depths and dz are initialized with a 3d region */
  127. /*Begin the area calculation */
  128. ll = G_begin_cell_area_calculations(); /*this function is not thread safe */
  129. /*if the projection is not planimetric, calc the area for each row */
  130. if (ll == 2) {
  131. G_debug(2,
  132. "N_init_geom_data_2d: calculating the areas for non parametric projection");
  133. geom->planimetric = 0;
  134. if (geom->area != NULL)
  135. G_free(geom->area);
  136. else
  137. geom->area = G_calloc(geom->rows, sizeof(double));
  138. /*fill the area vector */
  139. for (i = 0; i < geom->rows; i++) {
  140. geom->area[i] = G_area_of_cell_at_row(i); /*square meters */
  141. }
  142. }
  143. /*restore the old region */
  144. Rast_set_window(&backup); /*this function is not thread safe */
  145. }
  146. return geom;
  147. }
  148. /* *************************************************************** *
  149. * *************************************************************** *
  150. * *************************************************************** */
  151. /*!
  152. * \brief Get the areay size in square meter of one cell (x*y) at row
  153. *
  154. * This function works for two and three dimensions
  155. *
  156. * \param geom N_geom_data *
  157. * \param row int
  158. * \return area double
  159. *
  160. * */
  161. double N_get_geom_data_area_of_cell(N_geom_data * geom, int row)
  162. {
  163. if (geom->planimetric) {
  164. G_debug(6, "N_get_geom_data_area_of_cell: %g", geom->Az);
  165. return geom->Az;
  166. }
  167. else {
  168. G_debug(6, "N_get_geom_data_area_of_cell: %g", geom->area[row]);
  169. return geom->area[row];
  170. }
  171. return 0.0;
  172. }