~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/gis/reclass.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <string.h>
2
 
#include <grass/gis.h>
3
 
#include <grass/glocale.h>
4
 
 
5
 
static char *NULL_STRING = "null";
6
 
static int reclass_type(FILE *, char **, char **);
7
 
static FILE *fopen_cellhd_old(const char *, const char *);
8
 
static FILE *fopen_cellhd_new(const char *);
9
 
static int get_reclass_table(FILE *, struct Reclass *);
10
 
 
11
 
 
12
 
/*!
13
 
 * \brief reclass file?
14
 
 *
15
 
 * This function determines if the raster map
16
 
 * <b>name</b> in <b>mapset</b> is a reclass file.
17
 
 * If it is, then the name and mapset of the referenced 
18
 
 * raster map are copied into the <b>r_name</b> and <b>r_mapset</b> 
19
 
 * buffers.
20
 
 * Returns 1 if <b>name</b> is a reclass file, 0 if it is not, and -1 if 
21
 
 * there was a problem reading the raster header for <b>name.</b>
22
 
 *
23
 
 *  \param name
24
 
 *  \param mapset
25
 
 *  \param r_name
26
 
 *  \param r_mapset
27
 
 *  \return int
28
 
 */
29
 
 
30
 
int G_is_reclass(const char *name, const char *mapset, char *rname,
31
 
                 char *rmapset)
32
 
{
33
 
    FILE *fd;
34
 
    int type;
35
 
 
36
 
    fd = fopen_cellhd_old(name, mapset);
37
 
    if (fd == NULL)
38
 
        return -1;
39
 
 
40
 
    type = reclass_type(fd, &rname, &rmapset);
41
 
    fclose(fd);
42
 
    if (type < 0)
43
 
        return -1;
44
 
    else
45
 
        return type != 0;
46
 
}
47
 
 
48
 
 
49
 
/*!
50
 
 * \brief get child reclass maps list
51
 
 *
52
 
 * This function generates a
53
 
 * child reclass maps list from the cell_misc/reclassed_to file which stores 
54
 
 * this list. The cell_misc/reclassed_to file is written by 
55
 
 * G_put_reclass().
56
 
 * G_is_reclassed_to() is used by g.rename, g.remove and r.reclass to
57
 
 * prevent accidentally deleting the parent map of a reclassed raster map.
58
 
 *
59
 
 *  \param name
60
 
 *  \param mapset
61
 
 *  \param nrmaps
62
 
 *  \param rmaps
63
 
 *  \return int
64
 
 */
65
 
 
66
 
int G_is_reclassed_to(const char *name, const char *mapset, int *nrmaps,
67
 
                      char ***rmaps)
68
 
{
69
 
    FILE *fd;
70
 
    int i, j, k, l;
71
 
    char buf2[256], buf3[256];
72
 
 
73
 
    fd = G_fopen_old_misc("cell_misc", "reclassed_to", name, mapset);
74
 
 
75
 
    if (fd == NULL) {
76
 
        return -1;
77
 
    }
78
 
 
79
 
    if (rmaps)
80
 
        *rmaps = NULL;
81
 
    for (i = 0; !feof(fd) && fgets(buf2, 255, fd);) {
82
 
        l = strlen(buf2);
83
 
        for (j = 0, k = 0; j < l; j++) {
84
 
            if (buf2[j] == '#' ||
85
 
                ((buf2[j] == ' ' || buf2[j] == '\t' || buf2[j] == '\n') && k))
86
 
                break;
87
 
            else if (buf2[j] != ' ' && buf2[j] != '\t')
88
 
                buf3[k++] = buf2[j];
89
 
        }
90
 
 
91
 
        if (k) {
92
 
            buf3[k] = 0;
93
 
            i++;
94
 
            if (rmaps) {
95
 
                *rmaps = (char **)G_realloc(*rmaps, i * sizeof(char *));
96
 
                (*rmaps)[i - 1] = (char *)G_malloc(k + 1);
97
 
                strncpy((*rmaps)[i - 1], buf3, k);
98
 
                (*rmaps)[i - 1][k] = 0;
99
 
            }
100
 
        }
101
 
    }
102
 
 
103
 
    if (nrmaps)
104
 
        *nrmaps = i;
105
 
 
106
 
    if (i && rmaps) {
107
 
        i++;
108
 
        *rmaps = (char **)G_realloc(*rmaps, i * sizeof(char *));
109
 
        (*rmaps)[i - 1] = NULL;
110
 
    }
111
 
 
112
 
    fclose(fd);
113
 
 
114
 
    return i;
115
 
}
116
 
 
117
 
int G_get_reclass(const char *name, const char *mapset,
118
 
                  struct Reclass *reclass)
119
 
{
120
 
    FILE *fd;
121
 
    int stat;
122
 
 
123
 
    fd = fopen_cellhd_old(name, mapset);
124
 
    if (fd == NULL)
125
 
        return -1;
126
 
    reclass->name = NULL;
127
 
    reclass->mapset = NULL;
128
 
    reclass->type = reclass_type(fd, &reclass->name, &reclass->mapset);
129
 
    if (reclass->type <= 0) {
130
 
        fclose(fd);
131
 
        return reclass->type;
132
 
    }
133
 
 
134
 
    switch (reclass->type) {
135
 
    case RECLASS_TABLE:
136
 
        stat = get_reclass_table(fd, reclass);
137
 
        break;
138
 
    default:
139
 
        stat = -1;
140
 
    }
141
 
 
142
 
    fclose(fd);
143
 
    if (stat < 0) {
144
 
        if (stat == -2)
145
 
            G_warning(_("Too many reclass categories for [%s in %s]"),
146
 
                      name, mapset);
147
 
        else
148
 
            G_warning(_("Illegal reclass format in header file for [%s in %s]"),
149
 
                      name, mapset);
150
 
        stat = -1;
151
 
    }
152
 
    return stat;
153
 
}
154
 
 
155
 
int G_free_reclass(struct Reclass *reclass)
156
 
{
157
 
    switch (reclass->type) {
158
 
    case RECLASS_TABLE:
159
 
        if (reclass->num > 0)
160
 
            G_free(reclass->table);
161
 
        reclass->num = 0;
162
 
        if (reclass->name)
163
 
            G_free(reclass->name);
164
 
        if (reclass->mapset)
165
 
            G_free(reclass->mapset);
166
 
        reclass->name = NULL;
167
 
        reclass->mapset = NULL;
168
 
        break;
169
 
    default:
170
 
        break;
171
 
    }
172
 
 
173
 
    return 0;
174
 
}
175
 
 
176
 
static int reclass_type(FILE * fd, char **rname, char **rmapset)
177
 
{
178
 
    char buf[128];
179
 
    char label[128], arg[128];
180
 
    int i;
181
 
    int type;
182
 
 
183
 
    /* Check to see if this is a reclass file */
184
 
    if (fgets(buf, sizeof(buf), fd) == NULL)
185
 
        return 0;
186
 
    if (strncmp(buf, "reclas", 6))
187
 
        return 0;
188
 
    /* later may add other types of reclass */
189
 
    type = RECLASS_TABLE;
190
 
 
191
 
    /* Read the mapset and file name of the REAL cell file */
192
 
    if (*rname)
193
 
        **rname = '\0';
194
 
    if (*rmapset)
195
 
        **rmapset = '\0';
196
 
    for (i = 0; i < 2; i++) {
197
 
        if (fgets(buf, sizeof buf, fd) == NULL)
198
 
            return -1;
199
 
        if (sscanf(buf, "%[^:]:%s", label, arg) != 2)
200
 
            return -1;
201
 
        if (strncmp(label, "maps", 4) == 0) {
202
 
            if (*rmapset)
203
 
                strcpy(*rmapset, arg);
204
 
            else
205
 
                *rmapset = G_store(arg);
206
 
        }
207
 
        else if (strncmp(label, "name", 4) == 0) {
208
 
            if (*rname)
209
 
                strcpy(*rname, arg);
210
 
            else
211
 
                *rname = G_store(arg);
212
 
        }
213
 
        else
214
 
            return -1;
215
 
    }
216
 
    if (**rmapset && **rname)
217
 
        return type;
218
 
    else
219
 
        return -1;
220
 
}
221
 
 
222
 
static FILE *fopen_cellhd_old(const char *name, const char *mapset)
223
 
{
224
 
    return G_fopen_old("cellhd", name, mapset);
225
 
}
226
 
 
227
 
int G_put_reclass(const char *name, const struct Reclass *reclass)
228
 
{
229
 
    FILE *fd;
230
 
    long min, max;
231
 
    int found;
232
 
    char buf1[GPATH_MAX], buf2[GNAME_MAX], *p;
233
 
    char *xname;
234
 
 
235
 
    switch (reclass->type) {
236
 
    case RECLASS_TABLE:
237
 
        if (reclass->min > reclass->max || reclass->num <= 0) {
238
 
            G_fatal_error(_("Illegal reclass request"));
239
 
            return -1;
240
 
        }
241
 
        break;
242
 
    default:
243
 
        G_fatal_error(_("Illegal reclass type"));
244
 
        return -1;
245
 
    }
246
 
 
247
 
    fd = fopen_cellhd_new(name);
248
 
    if (fd == NULL) {
249
 
        G_warning(_("Unable to create header file for [%s in %s]"),
250
 
                  name, G_mapset());
251
 
        return -1;
252
 
    }
253
 
 
254
 
    fprintf(fd, "reclass\n");
255
 
    fprintf(fd, "name: %s\n", reclass->name);
256
 
    fprintf(fd, "mapset: %s\n", reclass->mapset);
257
 
 
258
 
    /* find first non-null entry */
259
 
    for (min = 0; min < reclass->num; min++)
260
 
        if (!G_is_c_null_value(&reclass->table[min]))
261
 
            break;
262
 
    /* find last non-zero entry */
263
 
    for (max = reclass->num - 1; max >= 0; max--)
264
 
        if (!G_is_c_null_value(&reclass->table[max]))
265
 
            break;
266
 
 
267
 
    /*
268
 
     * if the resultant table is empty, write out a dummy table
269
 
     * else write out the table
270
 
     *   first entry is #min
271
 
     *   rest are translations for cat min+i
272
 
     */
273
 
    if (min > max)
274
 
        fprintf(fd, "0\n");
275
 
    else {
276
 
        fprintf(fd, "#%ld\n", (long)reclass->min + min);
277
 
        while (min <= max) {
278
 
            if (G_is_c_null_value(&reclass->table[min]))
279
 
                fprintf(fd, "%s\n", NULL_STRING);
280
 
            else
281
 
                fprintf(fd, "%ld\n", (long)reclass->table[min]);
282
 
            min++;
283
 
        }
284
 
    }
285
 
    fclose(fd);
286
 
 
287
 
    strcpy(buf2, reclass->name);
288
 
    if ((p = strchr(buf2, '@')))
289
 
        *p = 0;
290
 
 
291
 
    G__file_name_misc(buf1, "cell_misc", "reclassed_to", reclass->name,
292
 
                      reclass->mapset);
293
 
 
294
 
    fd = fopen(buf1, "a+");
295
 
    if (fd == NULL) {
296
 
#if 0
297
 
        G_warning(_("Unable to create dependency file in [%s in %s]"),
298
 
                  buf2, reclass->mapset);
299
 
#endif
300
 
        return 1;
301
 
    }
302
 
 
303
 
    fseek(fd, 0L, SEEK_SET);
304
 
 
305
 
    xname = G_fully_qualified_name(name, G_mapset());
306
 
    found = 0;
307
 
    for (;;) {
308
 
        char buf[GNAME_MAX + GMAPSET_MAX];
309
 
        if (!G_getl2(buf, sizeof(buf), fd))
310
 
            break;
311
 
        if (strcmp(xname, buf) == 0) {
312
 
            found = 1;
313
 
            break;
314
 
        }
315
 
    }
316
 
 
317
 
    if (!found)
318
 
        fprintf(fd, "%s\n", xname);
319
 
 
320
 
    G_free(xname);
321
 
    fclose(fd);
322
 
 
323
 
    return 1;
324
 
}
325
 
 
326
 
static FILE *fopen_cellhd_new(const char *name)
327
 
{
328
 
    return G_fopen_new("cellhd", name);
329
 
}
330
 
 
331
 
static int get_reclass_table(FILE * fd, struct Reclass *reclass)
332
 
{
333
 
    char buf[128];
334
 
    int n;
335
 
    int first, null_str_size;
336
 
    CELL cat;
337
 
    long len;
338
 
 
339
 
    /*
340
 
     * allocate the table, expanding as each entry is read
341
 
     * note that G_realloc() will become G_malloc() if ptr in
342
 
     * NULL
343
 
     */
344
 
    reclass->min = 0;
345
 
    reclass->table = NULL;
346
 
    null_str_size = strlen(NULL_STRING);
347
 
    n = 0;
348
 
    first = 1;
349
 
    while (fgets(buf, sizeof buf, fd)) {
350
 
        if (first) {
351
 
            first = 0;
352
 
            if (sscanf(buf, "#%d", &cat) == 1) {
353
 
                reclass->min = cat;
354
 
                continue;
355
 
            }
356
 
        }
357
 
        if (strncmp(buf, NULL_STRING, null_str_size) == 0)
358
 
            G_set_c_null_value(&cat, 1);
359
 
        else {
360
 
            if (sscanf(buf, "%d", &cat) != 1)
361
 
                return -1;
362
 
        }
363
 
        n++;
364
 
        len = (long)n *sizeof(CELL);
365
 
 
366
 
        if (len != (int)len) {  /* check for int overflow */
367
 
            if (reclass->table != NULL)
368
 
                G_free(reclass->table);
369
 
            return -2;
370
 
        }
371
 
        reclass->table = (CELL *) G_realloc((char *)reclass->table, (int)len);
372
 
        reclass->table[n - 1] = cat;
373
 
    }
374
 
    reclass->max = reclass->min + n - 1;
375
 
    reclass->num = n;
376
 
    return 1;
377
 
}