area.c 4.7 KB

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