GRASS 8 Programmer's Manual
8.5.0(2026)-8d6ceba290
Toggle main menu visibility
Loading...
Searching...
No Matches
sparse.c
Go to the documentation of this file.
1
/*
2
** Bitmap library
3
**
4
** Written by David Gerdes 12 November 1992
5
** US Army Construction Engineering Research Laboratories
6
**
7
**
8
** This library provides basic support for the creation and manipulation
9
** of two dimensional bitmap arrays.
10
**
11
** BM_create (x, y) Create bitmap of specified dimensions
12
**
13
** BM_destroy (map) Destroy bitmap and free memory
14
**
15
** BM_set (map, x, y, val) Set array position to val [TRUE/FALSE]
16
**
17
** BM_get (map, x, y) Return value at array position
18
*/
19
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <grass/linkm.h>
23
#include <grass/bitmap.h>
24
25
#define BM_col_to_byte(x) ((x) >> 3)
/* x / 8 */
26
#define BM_col_to_bit(x) ((x) & 7)
/* x % 8 */
27
28
static
int
depth;
29
30
/*!
31
* \brief
32
*
33
* Create a sparse bitmap of dimension 'x'/'y'
34
*
35
* Returns bitmap structure or NULL on error
36
*
37
* \param x
38
* \param y
39
* \return struct BM
40
*/
41
struct
BM *
BM_create_sparse
(
int
x
,
int
y)
42
{
43
struct
BM *map;
44
int
i;
45
46
if
(
NULL
== (map = (
struct
BM *)malloc(
sizeof
(
struct
BM))))
47
return
(
NULL
);
48
map->bytes = (
x
+ 7) / 8;
49
50
if
(
NULL
==
51
(map->data = (
unsigned
char
*)malloc(
sizeof
(
struct
BMlink *) * y))) {
52
free(map);
53
return
(
NULL
);
54
}
55
56
map->rows = y;
57
map->cols =
x
;
58
map->sparse = 1;
59
60
link_set_chunk_size
(500);
61
map->token =
link_init
(
sizeof
(
struct
BMlink));
62
63
for
(i = 0; i < map->rows; i++) {
64
((
struct
BMlink **)(map->data))[i] =
65
(
struct
BMlink *)
link_new
(map->token);
66
((
struct
BMlink **)(map->data))[i]->
count
=
x
;
67
((
struct
BMlink **)(map->data))[i]->val = 0;
68
((
struct
BMlink **)(map->data))[i]->next =
NULL
;
69
}
70
71
depth++;
72
73
return
map;
74
}
75
76
/*!
77
* \brief
78
*
79
* Destroy sparse bitmap and free all associated memory
80
*
81
* Returns 0
82
*
83
* \param map
84
* \return int
85
*/
86
int
BM_destroy_sparse
(
struct
BM *map)
87
{
88
int
i;
89
struct
BMlink *p, *tmp;
90
91
for
(i = 0; i < map->rows; i++) {
92
p = ((
struct
BMlink **)(map->data))[i];
93
while
(p !=
NULL
) {
94
tmp = p->next;
95
link_dispose
(map->token, (
VOID_T
*)p);
96
p = tmp;
97
}
98
}
99
100
if
(--depth == 0)
101
link_cleanup
(map->token);
102
103
free(map->data);
104
free(map);
105
106
return
0;
107
}
108
109
/*!
110
* \brief
111
*
112
* Set sparse bitmap value to 'val' at location 'x'/'y'
113
*
114
* Returns 0
115
*
116
* \param map
117
* \param x
118
* \param y
119
* \param val
120
* \return int
121
*/
122
int
BM_set_sparse
(
struct
BM *map,
int
x
,
int
y,
int
val)
123
{
124
struct
BMlink *p, *p2, *prev;
125
int
cur_x
= 0;
126
int
Tval;
127
int
dist_a, dist_b;
128
129
val = !(!val);
/* set val == 1 or 0 */
130
131
p = ((
struct
BMlink **)(map->data))[y];
132
prev =
NULL
;
133
while
(p !=
NULL
) {
134
if
(
cur_x
+ p->count >
x
) {
135
if
(p->val == val)
/* no change */
136
return
0;
137
138
Tval = p->val;
139
140
/* if x is on edge, then we probably want to merge it with
141
** its neighbor for efficiency
142
*/
143
144
/* dist_a is how far x is from Left edge of group */
145
/* dist_b is how far x is from right edge of group */
146
147
dist_a =
x
-
cur_x
;
148
dist_b = (
cur_x
+ p->count - 1) -
x
;
149
150
/* if on both edges, then we should be able to merge 3 into one */
151
if
(dist_b == 0 && p->next && p->next->val == val) {
152
if
(dist_a == 0 &&
x
> 0) {
153
if
(prev !=
NULL
&& prev->val == val) {
154
prev->count += p->next->count + 1;
155
prev->next = p->next->next;
156
link_dispose
(map->token, (
VOID_T
*)p->next);
157
link_dispose
(map->token, (
VOID_T
*)p);
158
return
0;
159
}
160
}
161
}
162
163
/* handle right edge merge */
164
if
(dist_b == 0 && p->next && p->next->val == val) {
165
p->count--;
166
p->next->count++;
167
if
(p->count == 0) {
168
if
(prev) {
169
prev->next = p->next;
170
}
171
else
{
172
((
struct
BMlink **)(map->data))[y] = p->next;
173
}
174
link_dispose
(map->token, (
VOID_T
*)p);
175
}
176
return
0;
177
}
178
179
/* handle left edge merge */
180
if
(dist_a == 0 &&
x
> 0) {
181
182
if
(prev !=
NULL
&& prev->val == val) {
183
prev->count++;
184
p->count--;
185
if
(p->count == 0) {
186
prev->next = p->next;
187
link_dispose
(map->token, (
VOID_T
*)p);
188
}
189
return
0;
190
}
191
}
192
193
/* if not on edge, have to add link for each side */
194
if
(dist_a > 0) {
195
p->count = dist_a;
196
p->val = Tval;
197
p2 = (
struct
BMlink *)
link_new
(map->token);
198
p2->next = p->next;
199
p->next = p2;
200
p = p2;
201
}
202
p->count = 1;
203
p->val = val;
204
205
if
(dist_b > 0) {
206
p2 = (
struct
BMlink *)
link_new
(map->token);
207
p2->count = dist_b;
208
p2->val = Tval;
209
210
p2->next = p->next;
211
p->next = p2;
212
}
213
214
return
0;
215
}
216
cur_x
+= p->count;
217
prev = p;
218
p = p->next;
219
}
220
221
return
0;
222
}
223
224
/*!
225
* \brief
226
*
227
* Returns sparse bitmap value at location 'x'/'y'
228
*
229
* Returns value or -1 on error
230
*
231
* \param map
232
* \param x
233
* \param y
234
* \return int
235
*/
236
int
BM_get_sparse
(
struct
BM *map,
int
x
,
int
y)
237
{
238
struct
BMlink *p;
239
int
cur_x
= 0;
240
241
p = ((
struct
BMlink **)(map->data))[y];
242
while
(p !=
NULL
) {
243
if
(
cur_x
+ p->count >
x
)
244
return
(p->val);
245
cur_x
+= p->count;
246
p = p->next;
247
}
248
249
return
-1;
250
}
251
252
/*!
253
* \brief
254
*
255
* Returns size of sparse bitmap in bytes
256
*
257
* \param map
258
* \return int
259
*/
260
size_t
BM_get_map_size_sparse
(
struct
BM *map)
261
{
262
int
i;
263
size_t
size;
264
struct
BMlink *p;
265
266
size = (size_t)map->rows *
sizeof
(
struct
BMlink *);
267
for
(i = 0; i < map->rows; i++) {
268
p = ((
struct
BMlink **)(map->data))[i];
269
while
(p !=
NULL
) {
270
size +=
sizeof
(
struct
BMlink);
271
p = p->next;
272
}
273
}
274
275
return
size;
276
}
277
278
/*!
279
* \brief
280
*
281
* Debugging code to dump out structure of links
282
*
283
* Returns 0
284
*
285
* \param map
286
* \return int
287
*/
288
int
BM_dump_map_sparse
(
struct
BM *map)
289
{
290
int
i;
291
struct
BMlink *p;
292
293
for
(i = 0; i < map->rows; i++) {
294
p = ((
struct
BMlink **)(map->data))[i];
295
while
(p !=
NULL
) {
296
fprintf(stdout,
"(%2d %2d) "
, p->count, p->val);
297
p = p->next;
298
}
299
fprintf(stdout,
"\n"
);
300
}
301
302
return
0;
303
}
304
305
/*!
306
* \brief
307
*
308
* Debugging code to dump out structure of links for single row
309
*
310
* Returns 0
311
*
312
* \param map
313
* \param y
314
* \return int
315
*/
316
int
BM_dump_map_row_sparse
(
struct
BM *map,
int
y)
317
{
318
int
i;
319
struct
BMlink *p;
320
321
i = y;
322
{
323
p = ((
struct
BMlink **)(map->data))[i];
324
while
(p !=
NULL
) {
325
fprintf(stdout,
"(%2d %2d) "
, p->count, p->val);
326
p = p->next;
327
}
328
fprintf(stdout,
"\n"
);
329
}
330
331
return
0;
332
}
333
334
/*!
335
* \brief
336
*
337
* Write sparse bitmap matrix out to disk file 'fp'.
338
* NOTE: 'fp' must already be opened and later closed by user
339
*
340
* Returns 0 on success or -1 on error
341
*
342
* \param fp
343
* \param map
344
* \return int
345
*/
346
int
BM_file_write_sparse
(FILE *fp,
struct
BM *map)
347
{
348
char
c;
349
int
i, y;
350
struct
BMlink *p;
351
352
c = BM_MAGIC;
353
fwrite(&c,
sizeof
(
char
),
sizeof
(
char
), fp);
354
355
fwrite(BM_TEXT, BM_TEXT_LEN,
sizeof
(
char
), fp);
356
357
c = BM_SPARSE;
358
fwrite(&c,
sizeof
(
char
),
sizeof
(
char
), fp);
359
360
fwrite(&(map->rows),
sizeof
(map->rows),
sizeof
(
char
), fp);
361
362
fwrite(&(map->cols),
sizeof
(map->cols),
sizeof
(
char
), fp);
363
364
for
(y = 0; y < map->rows; y++) {
365
/* first count number of links */
366
p = ((
struct
BMlink **)(map->data))[y];
367
int
cnt = 0;
368
369
while
(p !=
NULL
) {
370
cnt++;
371
p = p->next;
372
}
373
374
i = cnt;
375
fwrite(&i,
sizeof
(i),
sizeof
(
char
), fp);
376
377
/* then write them out */
378
p = ((
struct
BMlink **)(map->data))[y];
379
while
(p !=
NULL
) {
380
i = p->count;
381
fwrite(&i,
sizeof
(i),
sizeof
(
char
), fp);
382
383
i = p->val;
384
fwrite(&i,
sizeof
(i),
sizeof
(
char
), fp);
385
386
p = p->next;
387
}
388
}
389
fflush(fp);
390
391
return
0;
392
}
NULL
#define NULL
Definition
ccmath.h:32
link_dispose
void link_dispose(struct link_head *Head, VOID_T *ptr)
Definition
dispose.c:10
cur_x
double cur_x
Definition
driver/init.c:32
count
int count
link_cleanup
void link_cleanup(struct link_head *Head)
Definition
linkm/init.c:67
link_set_chunk_size
void link_set_chunk_size(int size)
Definition
linkm/init.c:32
link_init
struct link_head * link_init(int size)
Definition
linkm/init.c:42
link_new
VOID_T * link_new(struct link_head *Head)
Definition
new.c:12
VOID_T
#define VOID_T
Definition
qtree.h:28
BM_create_sparse
struct BM * BM_create_sparse(int x, int y)
Create a sparse bitmap of dimension 'x'/'y'.
Definition
sparse.c:41
BM_dump_map_row_sparse
int BM_dump_map_row_sparse(struct BM *map, int y)
Debugging code to dump out structure of links for single row.
Definition
sparse.c:316
BM_file_write_sparse
int BM_file_write_sparse(FILE *fp, struct BM *map)
Write sparse bitmap matrix out to disk file 'fp'. NOTE: 'fp' must already be opened and later closed ...
Definition
sparse.c:346
BM_get_sparse
int BM_get_sparse(struct BM *map, int x, int y)
Returns sparse bitmap value at location 'x'/'y'.
Definition
sparse.c:236
BM_get_map_size_sparse
size_t BM_get_map_size_sparse(struct BM *map)
Returns size of sparse bitmap in bytes.
Definition
sparse.c:260
BM_destroy_sparse
int BM_destroy_sparse(struct BM *map)
Destroy sparse bitmap and free all associated memory.
Definition
sparse.c:86
BM_set_sparse
int BM_set_sparse(struct BM *map, int x, int y, int val)
Set sparse bitmap value to 'val' at location 'x'/'y'.
Definition
sparse.c:122
BM_dump_map_sparse
int BM_dump_map_sparse(struct BM *map)
Debugging code to dump out structure of links.
Definition
sparse.c:288
x
#define x
bitmap
sparse.c
Generated on
for GRASS 8 Programmer's Manual by
1.17.0