area.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * \file area.c
  3. *
  4. * \brief GIS Library - Area calculation functions.
  5. *
  6. * (C) 2001-2008 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author GRASS GIS Development Team
  12. *
  13. * \date 1999-2008
  14. */
  15. #include <grass/gis.h>
  16. static struct state {
  17. struct Cell_head window;
  18. double square_meters;
  19. int projection;
  20. double units_to_meters_squared;
  21. /* these next are for lat-long only */
  22. int next_row;
  23. double north_value;
  24. double north;
  25. double (*darea0) (double);
  26. } state;
  27. static struct state *st = &state;
  28. /**
  29. * \brief Begin cell area calculations.
  30. *
  31. * This routine must be called once before any call to
  32. * <i>G_area_of_cell_at_row()</i>. It perform all inititalizations
  33. * needed to do area calculations for grid cells, based on the current
  34. * window "projection" field. It can be used in either planimetric
  35. * projections or the latitude-longitude projection.
  36. * <br>
  37. * If the return value is 1 or 0, all the grid cells in the map have
  38. * the same area. Otherwise, the area of a grid cell varies with the row.
  39. *
  40. * \return 0 if the projection is not measurable (ie. imagery or xy)
  41. * \return 1 if the projection is planimetric (ie. UTM or SP)
  42. * \return 2 if the projection is non-planimetric (ie. latitude-longitude)
  43. */
  44. int G_begin_cell_area_calculations(void)
  45. {
  46. double a, e2;
  47. double factor;
  48. G_get_set_window(&st->window);
  49. switch (st->projection = st->window.proj) {
  50. case PROJECTION_LL:
  51. G_get_ellipsoid_parameters(&a, &e2);
  52. if (e2) {
  53. G_begin_zone_area_on_ellipsoid(a, e2, st->window.ew_res / 360.0);
  54. st->darea0 = G_darea0_on_ellipsoid;
  55. }
  56. else {
  57. G_begin_zone_area_on_sphere(a, st->window.ew_res / 360.0);
  58. st->darea0 = G_darea0_on_sphere;
  59. }
  60. st->next_row = 0;
  61. st->north = st->window.north;
  62. st->north_value = st->darea0(st->north);
  63. return 2;
  64. default:
  65. st->square_meters = st->window.ns_res * st->window.ew_res;
  66. factor = G_database_units_to_meters_factor();
  67. if (factor > 0.0)
  68. st->square_meters *= (factor * factor);
  69. return (factor > 0.0);
  70. }
  71. }
  72. /**
  73. * \brief Cell area in specified <b>row</b>.
  74. *
  75. * This routine returns the area in square meters of a cell in the
  76. * specified <b>row</b>. This value is constant for planimetric grids
  77. * and varies with the row if the projection is latitude-longitude.
  78. *
  79. * \param[in] row
  80. * \return double
  81. */
  82. double G_area_of_cell_at_row(int row)
  83. {
  84. double south_value;
  85. double cell_area;
  86. if (st->projection != PROJECTION_LL)
  87. return st->square_meters;
  88. if (row != st->next_row) {
  89. st->north = st->window.north - row * st->window.ns_res;
  90. st->north_value = st->darea0(st->north);
  91. }
  92. st->north -= st->window.ns_res;
  93. south_value = st->darea0(st->north);
  94. cell_area = st->north_value - south_value;
  95. st->next_row = row + 1;
  96. st->north_value = south_value;
  97. return cell_area;
  98. }
  99. /**
  100. * \brief Begin polygon area calculations.
  101. *
  102. * This initializes the polygon area calculation routines. It is used
  103. * both for planimetric and latitude-longitude projections.
  104. *
  105. * \return 0 if the projection is not measurable (ie. imagery or xy)
  106. * \return 1 if the projection is planimetric (ie. UTM or SP)
  107. * \return 2 if the projection is non-planimetric (ie. latitude-longitude)
  108. */
  109. int G_begin_polygon_area_calculations(void)
  110. {
  111. double a, e2;
  112. double factor;
  113. if ((st->projection = G_projection()) == PROJECTION_LL) {
  114. G_get_ellipsoid_parameters(&a, &e2);
  115. G_begin_ellipsoid_polygon_area(a, e2);
  116. return 2;
  117. }
  118. factor = G_database_units_to_meters_factor();
  119. if (factor > 0.0) {
  120. st->units_to_meters_squared = factor * factor;
  121. return 1;
  122. }
  123. st->units_to_meters_squared = 1.0;
  124. return 0;
  125. }
  126. /**
  127. * \brief Area in square meters of polygon.
  128. *
  129. * Returns the area in square meters of the polygon described by the
  130. * <b>n</b> pairs of <b>x,y</b> coordinate vertices. It is used both for
  131. * planimetric and latitude-longitude projections.
  132. * <br>
  133. * Returns the area in coordinate units of the polygon described by the
  134. * <b>n</b> pairs of <b>x,y</b> coordinate vertices for planimetric grids.
  135. * If the units for <b>x,y</b> are meters, then the area is in square meters.
  136. * If the units are feet, then the area is in square feet, and so on.
  137. * <br>
  138. * <b>Note:</b> If the database is planimetric with the non-meter grid,
  139. * this routine performs the required unit conversion to produce square
  140. * meters.
  141. *
  142. * \param[in] x array of x coordinates
  143. * \param[in] y array of y coordinates
  144. * \param[in] n number of x,y coordinate pairs
  145. * \return area in coordinate units of the polygon
  146. */
  147. double G_area_of_polygon(const double *x, const double *y, int n)
  148. {
  149. double area;
  150. if (st->projection == PROJECTION_LL)
  151. area = G_ellipsoid_polygon_area(x, y, n);
  152. else
  153. area = G_planimetric_polygon_area(x, y, n) * st->units_to_meters_squared;
  154. return area;
  155. }