/* See {gmo.h}. */ /* Last edited on 2020-10-03 21:17:51 by jstolfi */ #define _GNU_SOURCE_ #include #include #include #include #include #include #include #include #include #include #define FILE_VERSION "2005-08-21" void gmo_write(FILE *wr, gmo_t *P) { auto void write_point(hr3_point_t *p); auto void write_plane(hr3_plane_t *p); auto void write_opto(gmo_opto_t *o); auto void write_knot(gmo_knot_t *p); auto void write_frgb(frgb_t *f); auto void write_item(gmo_item_kind_t iknd, gmo_item_addr_t t); auto void write_item_dot(gmo_item_dot_t *t); auto void write_item_slug(gmo_item_slug_t *t); auto void write_item_tri(gmo_item_tri_t *t); int ix; filefmt_write_header(wr, "gmo_t", FILE_VERSION); fprintf(wr, "npoints = %d\n", P->npoints); fprintf(wr, "nplanes = %d\n", P->nplanes); fprintf(wr, "noptos = %d\n", P->noptos); fprintf(wr, "nknots = %d\n", P->nknots); fprintf(wr, "nitems = %d\n", P->nitems); fprintf(wr, "points:\n"); for (ix = 0; ix < P->npoints; ix++) { fprintf(wr, "%d: ", ix); write_point(&(P->point[ix])); fputc('\n', wr); } fprintf(wr, "planes:\n"); for (ix = 0; ix < P->nplanes; ix++) { fprintf(wr, "%d: ", ix); write_plane(&(P->plane[ix])); fputc('\n', wr); } fprintf(wr, "optos:\n"); for (ix = 0; ix < P->noptos; ix ++) { fprintf(wr, "%d: ", ix); write_opto(&(P->opto[ix])); fputc('\n', wr); } fprintf(wr, "knots:\n"); for (ix = 0; ix < P->nknots; ix ++) { fprintf(wr, "%d: ", ix); write_knot(&(P->knot[ix])); fputc('\n', wr); } fprintf(wr, "items:\n"); for (ix = 0; ix < P->nitems; ix++) { fprintf(wr, "%d: ", ix); write_item(P->iknd[ix], P->item[ix]); fputc('\n', wr); } filefmt_write_footer(wr, "gmo_t"); fflush(wr); void write_point(hr3_point_t *p) { int i; fputc('[', wr); for (i = 0; i < 4; i++) { if (i != 0){ fputc(' ', wr); } double ci = p->c.c[i]; fprintf(wr, "%.16g", ci); } fputc(']', wr); } void write_plane(hr3_plane_t *p) { int i; fputc('<', wr); for (i = 0; i < 4; i++) { if (i != 0){ fputc(' ', wr); } double ci = p->f.c[i]; fprintf(wr, "%.16g", ci); } fputc('>', wr); } void write_opto(gmo_opto_t *o) { write_frgb(&(o->color)); fputc(' ', wr); fprintf(wr, "%c", gmo_opto_kind_to_char(o->kind)); fputc(' ', wr); fprintf(wr, "%.8g", o->sigma); fputc(' ', wr); fprintf(wr, "%d", o->next); } void write_frgb(frgb_t *f) { int i; for (i = 0; i < 3; i++) { if (i != 0){ fputc(' ', wr); } double ci = f->c[i]; fprintf(wr, "%5.3f", ci); } } void write_knot(gmo_knot_t *kn) { fprintf(wr, "%d", kn->pt); fputc(' ', wr); fprintf(wr, "%d", kn->tp); fputc(' ', wr); fprintf(wr, "%d", kn->opto); fputc(' ', wr); fprintf(wr, "%5.3f", kn->radius); } void write_item(gmo_item_kind_t iknd, gmo_item_addr_t t) { fprintf(wr, "%c", gmo_item_kind_to_char(iknd)); fputc(' ', wr); switch (iknd) { case gmo_item_kind_DOT: write_item_dot((gmo_item_dot_t *)t); break; case gmo_item_kind_SLUG: write_item_slug((gmo_item_slug_t *)t); break; case gmo_item_kind_TRI: write_item_tri((gmo_item_tri_t *)t); break; default: affirm(FALSE, "bad gmo_item_kind_t"); } } void write_item_dot(gmo_item_dot_t *t) { fprintf(wr, "%d", t->kn); } void write_item_slug(gmo_item_slug_t *t) { int i; for (i = 0; i < 2; i++) { if (i != 0){ fputc(' ', wr); } fprintf(wr, "%d", t->kn[i]); } } void write_item_tri(gmo_item_tri_t *t) { int i; for (i = 0; i < 3; i++) { if (i != 0){ fputc(' ', wr); } fprintf(wr, "%d", t->kn[i]); } } } gmo_t *gmo_read(FILE *rd) { auto hr3_point_t read_point(void); auto hr3_plane_t read_plane(void); auto frgb_t read_frgb(void); auto gmo_opto_t read_opto(void); auto gmo_knot_t read_knot(void); auto gmo_item_kind_t read_item_kind(void); auto gmo_item_addr_t read_item(gmo_item_kind_t iknd); auto gmo_item_dot_t *read_item_dot(void); auto gmo_item_slug_t *read_item_slug(void); auto gmo_item_tri_t *read_item_tri(void); gmo_t *P = (gmo_t*)notnull(malloc(sizeof(gmo_t)), "no mem"); filefmt_read_header(rd, "gmo_t", FILE_VERSION); P->npoints = nget_int(rd, "npoints"); fget_eol(rd); affirm(P->npoints >= 0, "bad P->npoints"); P->nplanes = nget_int(rd, "nplanes"); fget_eol(rd); affirm(P->nplanes >= 0, "bad P->nplanes"); P->noptos = nget_int(rd, "noptos"); fget_eol(rd); affirm(P->noptos >= 0, "bad P->noptos"); P->nknots = nget_int(rd, "nknots"); fget_eol(rd); affirm(P->nknots >= 0, "bad P->nknots"); P->nitems = nget_int(rd, "nitems"); fget_eol(rd); affirm(P->nitems >= 0, "bad P->nitems"); P->point = (hr3_point_t *)notnull(malloc(P->npoints*sizeof(hr3_point_t)), "no mem"); P->plane = (hr3_plane_t *)notnull(malloc(P->nplanes*sizeof(hr3_plane_t)), "no mem"); P->opto = (gmo_opto_t *)notnull(malloc(P->noptos*sizeof(gmo_opto_t)), "no mem"); P->knot = (gmo_knot_t *)notnull(malloc(P->nknots*sizeof(gmo_knot_t)), "no mem"); P->iknd = (gmo_item_kind_t *)notnull(malloc(P->nitems*sizeof(gmo_item_kind_t)), "no mem"); P->item = (gmo_item_addr_t *)notnull(malloc(P->nitems*sizeof(gmo_item_addr_t)), "no mem"); int ix; /* Read points: */ fget_match(rd, "points:"); fget_eol(rd); for (ix = 0; ix < P->npoints; ix++) { int j = fget_int(rd); affirm(j == ix, "inconsistent point number"); fget_skip_spaces(rd); fget_match(rd, ":"); fget_skip_spaces(rd); P->point[ix] = read_point(); fget_eol(rd); } /* Read planes: */ fget_match(rd, "planes:"); fget_eol(rd); for (ix = 0; ix < P->nplanes; ix++) { int j = fget_int(rd); affirm(j == ix, "inconsistent plane number"); fget_skip_spaces(rd); fget_match(rd, ":"); fget_skip_spaces(rd); P->plane[ix] = read_plane(); fget_eol(rd); } /* Read optos: */ fget_match(rd, "optos:"); fget_eol(rd); for (ix = 0; ix < P->noptos; ix++) { int j = fget_int(rd); affirm(j == ix, "inconsistent opto number"); fget_skip_spaces(rd); fget_match(rd, ":"); fget_skip_spaces(rd); P->opto[ix] = read_opto(); fget_eol(rd); } /* Read knots: */ fget_match(rd, "knots:"); fget_eol(rd); for (ix = 0; ix < P->nknots; ix++) { int j = fget_int(rd); affirm(j == ix, "inconsistent knot number"); fget_skip_spaces(rd); fget_match(rd, ":"); fget_skip_spaces(rd); P->knot[ix] = read_knot(); fget_eol(rd); } /* Read item data: */ fget_match(rd, "items:"); fget_eol(rd); for (ix = 0; ix < P->nitems; ix++) { int j = fget_int(rd); affirm(j == ix, "inconsistent item number"); fget_skip_spaces(rd); fget_match(rd, ":"); fget_skip_spaces(rd); P->iknd[ix] = read_item_kind(); fget_skip_spaces(rd); P->item[ix] = read_item(P->iknd[ix]); fget_eol(rd); } filefmt_read_footer(rd, "gmo_t"); return P; hr3_point_t read_point(void) { hr3_point_t p; int i; fget_skip_spaces(rd); fget_match(rd, "["); for (i = 0; i < 3; i++) { p.c.c[i] = fget_double(rd); } fget_skip_spaces(rd); fget_match(rd, "]"); return p; } hr3_plane_t read_plane(void) { hr3_plane_t p; int i; fget_skip_spaces(rd); fget_match(rd, "<"); for (i = 0; i < 3; i++) { p.f.c[i] = fget_double(rd); } fget_skip_spaces(rd); fget_match(rd, ">"); return p; } frgb_t read_frgb(void) { frgb_t f; int i; for (i = 0; i < 3; i++) { fget_skip_spaces(rd); f.c[i] = (float)fget_double(rd); } return f; } gmo_opto_t read_opto(void) { gmo_opto_t o; o.color = read_frgb(); fget_skip_spaces(rd); o.kind = gmo_opto_kind_from_char(fget_char(rd)); o.sigma = (float)fget_double(rd); o.next = fget_int(rd); return o; } gmo_knot_t read_knot(void) { gmo_knot_t kn; kn.pt = fget_int(rd); affirm((kn.pt >= -1) && (kn.pt < P->npoints), "bad point index"); kn.tp = fget_int(rd); affirm((kn.tp >= -1) && (kn.tp < P->nplanes), "bad plane index"); kn.opto = fget_int(rd); affirm((kn.opto >= 0) && (kn.opto < P->noptos), "bad opto index"); kn.radius = fget_double(rd); return kn; } gmo_item_kind_t read_item_kind(void) { fget_skip_spaces(rd); return gmo_item_kind_from_char(fget_char(rd)); } gmo_item_addr_t read_item(gmo_item_kind_t iknd) { switch (iknd) { case gmo_item_kind_DOT: return (gmo_item_addr_t)read_item_dot(); case gmo_item_kind_SLUG: return (gmo_item_addr_t)read_item_slug(); case gmo_item_kind_TRI: return (gmo_item_addr_t)read_item_tri(); default: affirm(FALSE, "bad gmo_item_kind_t"); return NULL; /* To pacify the compiler. */ } } gmo_item_dot_t *read_item_dot(void) { gmo_item_dot_t *t = (gmo_item_dot_t *)notnull(malloc(sizeof(gmo_item_dot_t)), "no mem"); t->kn = fget_int(rd); affirm((t->kn >= 0) && (t->kn < P->nknots), "bad knot index"); return t; } gmo_item_slug_t *read_item_slug(void) { gmo_item_slug_t *t = (gmo_item_slug_t *)notnull(malloc(sizeof(gmo_item_slug_t)), "no mem"); int i; for (i = 0; i < 2; i++) { t->kn[i] = fget_int(rd); affirm((t->kn[i] >= 0) && (t->kn[i] < P->nknots), "bad knot index"); } return t; } gmo_item_tri_t *read_item_tri(void) { gmo_item_tri_t *t = (gmo_item_tri_t *)notnull(malloc(sizeof(gmo_item_tri_t)), "no mem"); int i; for (i = 0; i < 3; i++) { t->kn[i] = fget_int(rd); affirm((t->kn[i] >= 0) && (t->kn[i] < P->nknots), "bad knot index"); } return t; } } gmo_item_ix_t gmo_enum_items ( gmo_t *P, gmo_item_dot_proc_t visit_dot, gmo_item_slug_proc_t visit_slug, gmo_item_tri_proc_t visit_tri ) { int ix; for (ix = 0; ix < P->nitems; ix++) { gmo_item_kind_t iknd = P->iknd[ix]; gmo_item_addr_t item = P->item[ix]; bool_t res; switch(iknd) { case gmo_item_kind_DOT: res = visit_dot(ix, (gmo_item_dot_t *)item); break; case gmo_item_kind_SLUG: res = visit_slug(ix, (gmo_item_slug_t *)item); break; case gmo_item_kind_TRI: res = visit_tri(ix, (gmo_item_tri_t *)item); break; default: affirm(FALSE, "bad gmo_opto_kind_t"); res = TRUE; /* To pacify the compiler. */ } if(res) { return ix; } } return -1; } gmo_item_kind_t gmo_item_kind_from_char(char c) { if (c == 'D') { return gmo_item_kind_DOT; } else if (c == 'B') { return gmo_item_kind_SLUG; } else if (c == 'T') { return gmo_item_kind_TRI; } else { affirm(FALSE, "bad gmo_item_kind_t character"); return gmo_item_kind_DOT; /* To pacify the compiler. */ } } char gmo_item_kind_to_char(gmo_item_kind_t iknd) { switch (iknd) { case gmo_item_kind_DOT: return 'D'; case gmo_item_kind_SLUG: return 'B'; case gmo_item_kind_TRI: return 'T'; default: affirm(FALSE, "bad gmo_item_kind_t"); return '?'; } }