source: grass/trunk/raster/r.volume/centroids.c

Last change on this file was 70491, checked in by wenzeslaus, 8 years ago

r.volume: the first item in the array is unused, so don't read from it

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 3.4 KB
Line 
1/* Find 'centroids' of all cats. Most useful with cats which are
2 * like clumps (contiguous areas), but will work on any file.
3 * Respects the current window and mask.
4 * Category zero and negative categories are not done!
5 * Returned centroids are (row, col) pairs in n, e.
6 * Returned value is 0 for most cases, > 0 if 'both' method
7 * selected and some values fell outside 'clumps', and were
8 * adjusted.
9 * Two methods can be used: 'distance-weighted' and 'counting'.
10 *
11 * Method 0 = 'counting' or 'clump'; centroid point guaranteed
12 * to be at a cell of the given category.
13 * 1 = Both 0 and 2 are run; if method 2 centroid is on
14 * cell of proper cat, it is used, otherwise
15 * method 1 value is substituted.
16 * 2 = 'distance-weighted'; row = sigma(row)/n,
17 * col = sigma(col)/n.
18 */
19#include <grass/gis.h>
20#include <grass/raster.h>
21
22int centroids(int fd, /* File descriptor of map layer to process */
23 /* This file is assumed to be opened before calling */
24 /* centroids. */
25 unsigned long *e, unsigned long *n, /* Pointers to arrays at least max+1 long */
26 int method, /* 0, 1, or 2; see above. */
27 int max)
28{ /* Highest positive cat number in map layer */
29 CELL *cell_buf, v;
30 int i, adjusted, numb, left, right;
31 long int *count;
32 int row, col, rows, cols;
33
34 adjusted = 0;
35
36 cell_buf = Rast_allocate_c_buf();
37 /* space to accumulate counts */
38 count = (long int *)G_malloc((max + 1) * sizeof(long int));
39
40 /* zero the count totals */
41 for (i = 1; i <= max; i++) {
42 count[i] = 0;
43 e[i] = 0;
44 n[i] = 0;
45 }
46
47 /* do rows and columns through window and mask */
48 /* to do counting */
49 rows = Rast_window_rows();
50 cols = Rast_window_cols();
51 for (row = 0; row < rows; row++) {
52 Rast_get_c_row(fd, cell_buf, row); /* get a row */
53 for (col = 0; col < cols; col++) {
54 v = cell_buf[col]; /* next cell value in row */
55 if (v < 1)
56 continue; /* can't handle 0 or - values */
57 count[v]++;
58 if (method > 0) { /* acccumulate row, col weights */
59 e[v] += col;
60 n[v] += row;
61 }
62 }
63 }
64
65 /* compute averages */
66 if (method > 0)
67 for (i = 1; i <= max; i++) {
68 if (count[i]) {
69 numb = count[i];
70 e[i] /= numb;
71 n[i] /= numb;
72 }
73 }
74
75 /* substitute 'count' centroids for 'weighted' ones, if necessary */
76 if (method == 1) {
77 for (i = 1; i <= max; i++) {
78 if (count[i]) {
79 row = n[i];
80 col = e[i];
81 /* get cell at row,col */
82 Rast_get_c_row(fd, cell_buf, row);
83 v = cell_buf[col];
84 if (v > 0) {
85 if (v == i)
86 count[i] = 0; /* weighted is acceptable */
87 else
88 adjusted++;
89 }
90 }
91 }
92 }
93
94 /* compute middle cell; zeros will remain zeros */
95 for (i = 1; i <= max; i++)
96 count[i] = (count[i] + 1) / 2;
97
98 /* go through map again */
99 for (row = 0; row < rows; row++) {
100 Rast_get_c_row(fd, cell_buf, row);
101 for (col = 0; col < cols; col++) {
102 v = cell_buf[col];
103 if (v < 1)
104 continue;
105 if (count[v] == 0)
106 continue;
107 if ((--count[v]) == 0) { /* then this is middle cell */
108 n[v] = row;
109 /* find row-center in this clump */
110 left = right = col;
111 /* left edge first */
112 while (left > 0)
113 if (cell_buf[--left] != v) {
114 left++;
115 break;
116 }
117 /* then right edge */
118 while (right < cols)
119 if (cell_buf[++right] != v) {
120 right--;
121 break;
122 }
123 e[v] = (left + right) / 2;
124 }
125 }
126 }
127 G_free(cell_buf);
128 G_free(count);
129 return (adjusted);
130} /* end of centroids() */
Note: See TracBrowser for help on using the repository browser.