GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gs_norms.c
Go to the documentation of this file.
1 
19 #include <math.h>
20 
21 #include <grass/gis.h>
22 #include <grass/gstypes.h>
23 
24 #include "gsget.h"
25 #include "rowcol.h"
26 
27 #define NTOP 0x00001000
28 #define NBOT 0x00000100
29 #define NLFT 0x00000010
30 #define NRGT 0x00000001
31 
32 #define NALL 0x00001111
33 
34 #define NTL 0x00001010
35 #define NTR 0x00001001
36 #define NBL 0x00000110
37 #define NBR 0x00000101
38 
42 #define SET_NORM(i) \
43  dz1 = z1 - z2; \
44  dz2 = z3 - z4; \
45  temp[0] = (float) -dz1 * y_res_z2; \
46  temp[1] = (float) dz2 * x_res_z2; \
47  temp[2] = c_z2; \
48  normalizer = sqrt(temp[0] * temp[0] + temp[1] * temp[1] + c_z2_sq); \
49  if (!normalizer) normalizer= 1.0; \
50  temp[X] /= normalizer; \
51  temp[Y] /= normalizer; \
52  temp[Z] /= normalizer; \
53  PNORM(i,temp);
54 
55 static long slice;
56 static float x_res_z2, y_res_z2;
57 static float c_z2, c_z2_sq;
58 static typbuff *elbuf;
59 static unsigned long *norm;
60 
61 /*
62  #define USE_GL_NORMALIZE
63  */
64 
72 void init_vars(geosurf * gs)
73 {
74  /* optimized - these are static - global to this file */
75  norm = gs->norms;
76  elbuf = gs_get_att_typbuff(gs, ATT_TOPO, 0);
77 
78 #ifdef USE_GL_NORMALIZE
79  c_z2 =
80  2.0 * gs->xres * gs->yres * gs->x_mod * gs->y_mod / GS_global_exag();
81  c_z2_sq = c_z2 * c_z2;
82  x_res_z2 = 2.0 * gs->xres * gs->z_exag * gs->x_mod;
83  y_res_z2 = 2.0 * gs->yres * gs->z_exag * gs->y_mod;
84 #else
85 
86  {
87  float sx, sy, sz;
88 
89  GS_get_scale(&sx, &sy, &sz, 1);
90 
91  c_z2 = 2.0 * gs->xres * gs->yres * gs->x_mod * gs->y_mod;
92  c_z2_sq = c_z2 * c_z2;
93  x_res_z2 = 2.0 * gs->xres * gs->z_exag * gs->x_mod;
94  y_res_z2 = 2.0 * gs->yres * gs->z_exag * gs->y_mod;
95  }
96 #endif
97 
98  slice = gs->y_mod * gs->cols;
99 
100  return;
101 }
102 
124 int gs_calc_normals(geosurf * gs)
125 {
126  int row, col;
127  int xcnt, ycnt;
128  int xmod, ymod;
129 
130  if (!gs->norm_needupdate || !gs->norms) {
131  return (0);
132  }
133 
134  gs->norm_needupdate = 0;
135  gs_update_curmask(gs);
136 
137  xmod = gs->x_mod;
138  ymod = gs->y_mod;
139 
140  xcnt = VCOLS(gs);
141  ycnt = VROWS(gs);
142 
143  init_vars(gs);
144 
145  G_debug(5, "gs_calc_normals(): id=%d", gs->gsurf_id);
146 
147  /* first row - just use single cell */
148  /* first col - use bottom & right neighbors */
149  calc_norm(gs, 0, 0, NBR);
150 
151  for (col = 1; col < xcnt; col++) {
152  /* turn off top neighbor for first row */
153  calc_norm(gs, 0, col * xmod, ~NTOP);
154  }
155 
156  /* use bottom & left neighbors for last col */
157  calc_norm(gs, 0, col * xmod, NBL);
158 
159  /* now use four neighboring points for rows 1 - (n-1) */
160  for (row = 1; row < ycnt; row++) {
161  if (!(row % 100))
162  G_debug(5, "gs_calc_normals(): row=%d", row);
163 
164  /* turn off left neighbor for first col */
165  calc_norm(gs, row * ymod, 0, ~NLFT);
166 
167  /* use all 4 neighbors until last col */
168  for (col = 1; col < xcnt; col++) {
169  calc_norm(gs, row * ymod, col * xmod, NALL);
170  }
171 
172  /* turn off right neighbor for last col */
173  calc_norm(gs, row * ymod, col * xmod, ~NRGT);
174  }
175 
176  /* last row */
177  /* use top & right neighbors for first col */
178  calc_norm(gs, row * ymod, 0, NTR);
179 
180  for (col = 1; col < xcnt; col++) {
181  /* turn off bottom neighbor for last row */
182  calc_norm(gs, row * ymod, col * xmod, ~NBOT);
183  }
184 
185  /* use top & left neighbors for last column */
186  calc_norm(gs, row * ymod, col * xmod, NTL);
187 
188  return (1);
189 }
190 
206 int calc_norm(geosurf * gs, int drow, int dcol, unsigned int neighbors)
207 {
208  long noffset;
209  float temp[3], normalizer, dz1, dz2, z0, z1, z2, z3, z4;
210 
211  if (gs->curmask) {
212  /* need to check masked neighbors */
213  /* NOTE: this should automatically eliminate nullvals */
214  if (neighbors & NTOP) {
215  if (BM_get(gs->curmask, dcol, drow - gs->y_mod)) {
216  /* masked */
217  neighbors &= ~NTOP;
218  }
219  }
220 
221  if (neighbors & NBOT) {
222  if (BM_get(gs->curmask, dcol, drow + gs->y_mod)) {
223  /* masked */
224  neighbors &= ~NBOT;
225  }
226  }
227 
228  if (neighbors & NLFT) {
229  if (BM_get(gs->curmask, dcol - gs->x_mod, drow)) {
230  /* masked */
231  neighbors &= ~NLFT;
232  }
233  }
234 
235  if (neighbors & NRGT) {
236  if (BM_get(gs->curmask, dcol + gs->x_mod, drow)) {
237  /* masked */
238  neighbors &= ~NRGT;
239  }
240  }
241  }
242 
243  if (!neighbors) {
244  /* none */
245  return (0);
246  }
247 
248  noffset = DRC2OFF(gs, drow, dcol);
249 
250  if (!GET_MAPATT(elbuf, noffset, z0)) {
251  return (0);
252  }
253 
254  z1 = z2 = z3 = z4 = z0;
255 
256  /* we know these aren't null now, maybe use faster GET_MAPATT? */
257  if (neighbors & NRGT) {
258  GET_MAPATT(elbuf, noffset + gs->x_mod, z1);
259  if (!(neighbors & NLFT)) {
260  z2 = z0 + (z0 - z1);
261  }
262  }
263 
264  if (neighbors & NLFT) {
265  GET_MAPATT(elbuf, noffset - gs->x_mod, z2);
266 
267  if (!(neighbors & NRGT)) {
268  z1 = z0 + (z0 - z2);
269  }
270  }
271 
272  if (neighbors & NTOP) {
273  GET_MAPATT(elbuf, noffset - slice, z4);
274 
275  if (!(neighbors & NBOT)) {
276  z3 = z0 + (z0 - z4);
277  }
278  }
279 
280  if (neighbors & NBOT) {
281  GET_MAPATT(elbuf, noffset + slice, z3);
282 
283  if (!(neighbors & NTOP)) {
284  z4 = z0 + (z0 - z3);
285  }
286  }
287 
288  SET_NORM(norm[noffset]);
289 
290  return (1);
291 }
int BM_get(struct BM *map, int x, int y)
Gets &#39;val&#39; from the bitmap.
Definition: bitmap.c:220
#define NALL
Definition: gs_norms.c:32
#define DRC2OFF(gs, drow, dcol)
Definition: rowcol.h:15
#define SET_NORM(i)
This macro is only used in the function calc_norm()
Definition: gs_norms.c:42
#define VROWS(gs)
Definition: rowcol.h:11
#define VCOLS(gs)
Definition: rowcol.h:12
int gs_calc_normals(geosurf *gs)
Calculate normals.
Definition: gs_norms.c:124
void init_vars(geosurf *gs)
Init variables.
Definition: gs_norms.c:72
#define NTR
Definition: gs_norms.c:35
typbuff * gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
Get attribute data buffer.
Definition: gs.c:681
#define NTOP
Definition: gs_norms.c:27
#define NBR
Definition: gs_norms.c:37
#define NRGT
Definition: gs_norms.c:30
#define NBL
Definition: gs_norms.c:36
#define NTL
Definition: gs_norms.c:34
#define NLFT
Definition: gs_norms.c:29
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
#define NBOT
Definition: gs_norms.c:28
int calc_norm(geosurf *gs, int drow, int dcol, unsigned int neighbors)
Calculate normals.
Definition: gs_norms.c:206
float GS_global_exag(void)
Get global z-exag value.
Definition: GS2.c:1996
int gs_update_curmask(geosurf *surf)
Update current maps.
Definition: gs_bm.c:232
void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
Get axis scale.
Definition: GS2.c:3238
#define GET_MAPATT(buff, offset, att)
Definition: gsget.h:27