123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /****************************************************************************
- *
- * MODULE: r.buffer
- *
- * AUTHOR(S): Michael Shapiro - CERL
- *
- * PURPOSE: This program creates distance zones from non-zero
- * cells in a grid layer. Distances are specified in
- * meters (on the command-line). Window does not have to
- * have square cells. Works both for planimetric
- * (UTM, State Plane) and lat-long.
- *
- * COPYRIGHT: (C) 2005 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.
- *
- ****************************************************************************/
- #include <grass/gis.h>
- #include "distance.h"
- #include "local_proto.h"
- static int cur_row;
- int begin_distance(int row)
- {
- cur_row = row;
- if (window.proj == PROJECTION_LL)
- G_set_geodesic_distance_lat1(window.north -
- (row + .5) * window.ns_res);
- return 0;
- }
- /* Determine number of columns for each distance zone
- * (-1 means doesn't occur)
- * Returns: first zone to occur (-1 if none)
- * Note: modifies distances structure (global)
- */
- int find_distances(int row)
- {
- int i;
- double dist;
- double scale;
- double ns_dist;
- if (window.proj == PROJECTION_LL)
- G_set_geodesic_distance_lat2(window.north -
- (row + .5) * window.ns_res);
- /* if at same row, distance is constant across each cell */
- if (row == cur_row) {
- if (window.proj == PROJECTION_LL) {
- scale = 1.0 / G_geodesic_distance_lon_to_lon(0.0, window.ew_res);
- for (i = 0; i < ndist; i++) {
- distances[i].prev_ncols = (int)(scale * distances[i].dist);
- distances[i].ncols = find_ll_distance_ncols(i);
- }
- }
- else { /* note - see parse_dist.c for more info */
- for (i = 0; i < ndist; i++)
- distances[i].ncols = distances[i].prev_ncols
- = (int)distances[i].dist;
- }
- }
- else {
- if (window.proj == PROJECTION_LL)
- for (i = 0; i < ndist; i++)
- distances[i].ncols = find_ll_distance_ncols(i);
- else {
- i = cur_row - row;
- ns_dist = (i * i) * ns_to_ew_squared;
- for (i = 0; i < ndist; i++) {
- dist = distances[i].dist - ns_dist;
- if (dist < 0.0)
- distances[i].ncols = -1;
- else
- distances[i].ncols = (int)dist;
- }
- }
- }
- for (i = 0; i < ndist; i++)
- if (distances[i].ncols >= 0)
- return i;
- return -1;
- }
- int reset_distances(void)
- {
- register int i;
- for (i = 0; i < ndist; i++)
- distances[i].ncols = distances[i].prev_ncols;
- return 0;
- }
- int find_ll_distance_ncols(int i)
- {
- int col;
- double lon;
- register double d;
- register double dist;
- /* use the ncols from previous distances as a starting point
- * to figure the new ncols
- */
- col = distances[i].ncols - 1;
- if (col < 0)
- col = 0;
- dist = distances[i].dist;
- lon = window.ew_res * col;
- d = G_geodesic_distance_lon_to_lon(0.0, lon);
- if (d > dist) { /*backup */
- while (d > dist) {
- if (--col < 0)
- break;
- lon -= window.ew_res;
- d = G_geodesic_distance_lon_to_lon(0.0, lon);
- }
- return col;
- }
- if (d == dist)
- return col;
- while (d < dist && lon < 180.00 && col <= window.cols) {
- col++;
- lon += window.ew_res;
- d = G_geodesic_distance_lon_to_lon(0.0, lon);
- }
- return col - 1;
- }
|