// A .gml file describes a list of clouds inside a rectangular bounding box. // Each cloud is described by the polygon at its boundary. // There is some XML metadata that is not relevant for this program. // // Example of a typical .gml file: // // ...XML cruft... // <gml:lowerCorner>1 1</gml:lowerCorner> // <gml:upperCorner>38345 34532</gml:upperCorner> // ...XML cruft... // <gml:posList>273.385334 9214.094585 ...</gml:posList> // ...XML cruft... // <gml:posList>4532.908842 7330.118945 4532.92079 ...</gml:posList> // ...XML cruft... // int read_cloud_mask_from_gml_file(struct cloud_mask *m, char *filename) { m->n = 0; m->t = NULL; FILE *f = xfopen(filename, "r"); int n = 0x100, nf; while(1) { char line[n], *sl = fgets_until(line, n, f, '>'); if (!sl) break; if (0 == strhas(line, "lowerCorner")) { double *ff = read_ascii_doubles(f, &nf); if (nf == 2) for (int i = 0; i < 2; i++) m->low[i] = ff[i]; free(ff); } if (0 == strhas(line, "upperCorner")) { double *ff = read_ascii_doubles(f, &nf); if (nf == 2) for (int i = 0; i < 2; i++) m->up[i] = ff[i]; free(ff); } if (0 == strhas(line, "posList")) { struct cloud_polygon p; p.v = read_ascii_doubles(f, &p.n); p.n /= 2; cloud_add_polygon(m, p); } read_until_newline(f); } xfclose(f); return 0; }
inline static double *read_ascii_doubles_fn(const char *fname, int *no) { FILE *f = fopen(fname, "r"); if (!f) { *no = 0; return NULL; } double *r = read_ascii_doubles(f, no); fclose(f); return r; }
// Obtain n numbers from string. // The string contains a list of ascii numbers // or the name of a file containing a list of ascii numbers. // In case of failure, unread numbers are set to zero. // Returns the number of read numbers. inline static int read_n_doubles_from_string(double *out, char *string, int n) { for (int i = 0; i < n; i++) out[i] = 0; int no; double *buf = NULL; FILE *f = fopen(string, "r"); if (f) { buf = read_ascii_doubles(f, &no); fclose(f); } else { buf = alloc_parse_doubles(n, string, &no); } if (no > n) no = n; for (int i = 0; i < no; i++) out[i] = buf[i]; free(buf); return no; }