123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- /*!
- * \file lib/gis/area.c
- *
- * \brief GIS Library - Area calculation functions.
- *
- * (C) 2001-2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author CERL
- */
- #include <grass/gis.h>
- static struct state {
- struct Cell_head window;
- double square_meters;
- int projection;
- double units_to_meters_squared;
- /* these next are for lat-long only */
- int next_row;
- double north_value;
- double north;
- double (*darea0) (double);
- } state;
- static struct state *st = &state;
- /*!
- * \brief Begin cell area calculations.
- *
- * This routine must be called once before any call to
- * G_area_of_cell_at_row(). It perform all inititalizations needed to
- * do area calculations for grid cells, based on the current window
- * "projection" field. It can be used in either planimetric
- * projections or the latitude-longitude projection.
- *
- * \return 0 if the projection is not measurable (ie. imagery or xy)
- * \return 1 if the projection is planimetric (ie. UTM or SP)
- * \return 2 if the projection is non-planimetric (ie. latitude-longitude)
- */
- int G_begin_cell_area_calculations(void)
- {
- double a, e2;
- double factor;
- G_get_set_window(&st->window);
- switch (st->projection = st->window.proj) {
- case PROJECTION_LL:
- G_get_ellipsoid_parameters(&a, &e2);
- if (e2) {
- G_begin_zone_area_on_ellipsoid(a, e2, st->window.ew_res / 360.0);
- st->darea0 = G_darea0_on_ellipsoid;
- }
- else {
- G_begin_zone_area_on_sphere(a, st->window.ew_res / 360.0);
- st->darea0 = G_darea0_on_sphere;
- }
- st->next_row = 0;
- st->north = st->window.north;
- st->north_value = st->darea0(st->north);
- return 2;
- default:
- st->square_meters = st->window.ns_res * st->window.ew_res;
- factor = G_database_units_to_meters_factor();
- if (factor > 0.0)
- st->square_meters *= (factor * factor);
- return (factor > 0.0);
- }
- }
- /*!
- * \brief Cell area in specified row.
- *
- * This routine returns the area in square meters of a cell in the
- * specified <i>row</i>. This value is constant for planimetric grids
- * and varies with the row if the projection is latitude-longitude.
- *
- * \param row row number
- *
- * \return cell area
- */
- double G_area_of_cell_at_row(int row)
- {
- double south_value;
- double cell_area;
- if (st->projection != PROJECTION_LL)
- return st->square_meters;
- if (row != st->next_row) {
- st->north = st->window.north - row * st->window.ns_res;
- st->north_value = st->darea0(st->north);
- }
- st->north -= st->window.ns_res;
- south_value = st->darea0(st->north);
- cell_area = st->north_value - south_value;
- st->next_row = row + 1;
- st->north_value = south_value;
- return cell_area;
- }
- /*!
- * \brief Begin polygon area calculations.
- *
- * This initializes the polygon area calculation routines. It is used
- * both for planimetric and latitude-longitude projections.
- *
- * \return 0 if the projection is not measurable (ie. imagery or xy)
- * \return 1 if the projection is planimetric (ie. UTM or SP)
- * \return 2 if the projection is non-planimetric (ie. latitude-longitude)
- */
- int G_begin_polygon_area_calculations(void)
- {
- double a, e2;
- double factor;
- if ((st->projection = G_projection()) == PROJECTION_LL) {
- G_get_ellipsoid_parameters(&a, &e2);
- G_begin_ellipsoid_polygon_area(a, e2);
- return 2;
- }
- factor = G_database_units_to_meters_factor();
- if (factor > 0.0) {
- st->units_to_meters_squared = factor * factor;
- return 1;
- }
- st->units_to_meters_squared = 1.0;
- return 0;
- }
- /*!
- * \brief Area in square meters of polygon.
- *
- * Returns the area in square meters of the polygon described by the
- * <i>n</i> pairs of <i>x,y</i> coordinate vertices. It is used both for
- * planimetric and latitude-longitude projections.
- *
- * You should call G_begin_polygon_area_calculations() function before
- * calling this function.
- *
- * <b>Note:</b> If the database is planimetric with the non-meter grid,
- * this routine performs the required unit conversion to produce square
- * meters.
- *
- * \param x array of x coordinates
- * \param y array of y coordinates
- * \param n number of x,y coordinate pairs
- *
- * \return area in square meters of the polygon
- */
- double G_area_of_polygon(const double *x, const double *y, int n)
- {
- double area;
- if (st->projection == PROJECTION_LL)
- area = G_ellipsoid_polygon_area(x, y, n);
- else
- area = G_planimetric_polygon_area(x, y, n) * st->units_to_meters_squared;
- return area;
- }
|