GRASS 8 Programmer's Manual
8.5.0(2026)-8d6ceba290
Toggle main menu visibility
Loading...
Searching...
No Matches
gs_norms.c
Go to the documentation of this file.
1
/*!
2
\file lib/ogsf/gs_norms.c
3
4
\brief OGSF library - calculation normals (lower level functions)
5
6
GRASS OpenGL gsurf OGSF Library
7
8
(C) 1999-2008 by the GRASS Development Team
9
10
This program is free software under the
11
GNU General Public License (>=v2).
12
Read the file COPYING that comes with GRASS
13
for details.
14
15
\author Bill Brown USACERL
16
\author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
17
*/
18
19
#include <math.h>
20
21
#include <grass/gis.h>
22
#include <grass/ogsf.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
39
/*!
40
\brief This macro is only used in the function calc_norm()
41
*/
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) \
50
normalizer = 1.0; \
51
temp[X] /= normalizer; \
52
temp[Y] /= normalizer; \
53
temp[Z] /= normalizer; \
54
PNORM(i, temp);
55
56
static
long
slice;
57
static
float
x_res_z2, y_res_z2;
58
static
float
c_z2, c_z2_sq;
59
static
typbuff *elbuf;
60
static
unsigned
long
*norm;
61
62
/*
63
#define USE_GL_NORMALIZE
64
*/
65
66
/*!
67
\brief Init variables
68
69
for optimization
70
71
\param gs surface (geosurf)
72
*/
73
void
init_vars
(geosurf *gs)
74
{
75
/* optimized - these are static - global to this file */
76
norm = gs->norms;
77
elbuf =
gs_get_att_typbuff
(gs, ATT_TOPO, 0);
78
79
#ifdef USE_GL_NORMALIZE
80
c_z2 = 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
103
/*!
104
\brief Calculate normals
105
106
OPTIMIZED for constant dy & dx
107
108
The norm array is always the same size, but diff resolutions
109
force resampled data points to have their normals recalculated,
110
then only those norms are passed to n3f during drawing.
111
Norms are converted to a packed unsigned int for storage,
112
must be converted back at time of use.
113
114
\todo fix to correctly calculate norms when mapped to sphere!
115
116
Uses the previous and next cells (when available) for normal
117
calculations to produce smoother normals
118
119
\param gs surface (geosurf)
120
121
\return 1 on success
122
\return 0 on failure
123
*/
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
191
/*!
192
\brief Calculate normals
193
194
Need either four neighbors or two non-linear neighbors
195
passed initial state of neighbors known from array position
196
and data row & col
197
198
\param gs surface (geosurf)
199
\param drow data row
200
\param dcol data col
201
\param neighbors neighbors id
202
203
\return 0 no normals
204
\return 1 on success
205
*/
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
}
BM_get
int BM_get(struct BM *map, int x, int y)
Gets 'val' from the bitmap.
Definition
bitmap.c:213
G_debug
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition
debug.c:66
GS_get_scale
void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
Get axis scale.
Definition
gs2.c:3239
GS_global_exag
float GS_global_exag(void)
Get global z-exag value.
Definition
gs2.c:2000
gs_get_att_typbuff
typbuff * gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
Get attribute data buffer.
Definition
gs.c:681
gs_update_curmask
int gs_update_curmask(geosurf *surf)
Update current maps.
Definition
gs_bm.c:228
NLFT
#define NLFT
Definition
gs_norms.c:29
NBOT
#define NBOT
Definition
gs_norms.c:28
NTOP
#define NTOP
Definition
gs_norms.c:27
SET_NORM
#define SET_NORM(i)
This macro is only used in the function calc_norm().
Definition
gs_norms.c:42
NBR
#define NBR
Definition
gs_norms.c:37
NRGT
#define NRGT
Definition
gs_norms.c:30
NBL
#define NBL
Definition
gs_norms.c:36
gs_calc_normals
int gs_calc_normals(geosurf *gs)
Calculate normals.
Definition
gs_norms.c:124
NTL
#define NTL
Definition
gs_norms.c:34
NALL
#define NALL
Definition
gs_norms.c:32
calc_norm
int calc_norm(geosurf *gs, int drow, int dcol, unsigned int neighbors)
Calculate normals.
Definition
gs_norms.c:206
NTR
#define NTR
Definition
gs_norms.c:35
init_vars
void init_vars(geosurf *gs)
Init variables.
Definition
gs_norms.c:73
gsget.h
GET_MAPATT
#define GET_MAPATT(buff, offset, att)
Definition
gsget.h:29
rowcol.h
VCOLS
#define VCOLS(gs)
Definition
rowcol.h:14
VROWS
#define VROWS(gs)
Definition
rowcol.h:13
DRC2OFF
#define DRC2OFF(gs, drow, dcol)
Definition
rowcol.h:17
ogsf
gs_norms.c
Generated on
for GRASS 8 Programmer's Manual by
1.17.0