#define PROG_NAME "makefigs" #define PROG_DESC "generate figures for the Jornada PUC 2007 talk" #define PROG_VERS "1.0" /* Copyright © 2007 by the State University of Campinas (UNICAMP). */ /* See the copyright, authorship, and warranty notice at end of file. */ /* Last edited on 2024-12-21 14:02:38 by stolfi */ /* Created apr/2007 by Jorge Stolfi, UNICAMP */ #include #include #include #include #include #include #include #include #include #include #include /* INTERNAL PROTOTYPES */ int main(int argc, char **argv); void figs_1d(PlotOptions *o); /* Outputs all 1D figures. */ double forg(double x); /* The original signal to be approximated. */ char *make_basis_tag(b1d_basis_t *bas); /* Creates a file/figure name specific for basis {bas}. */ void parse_options(int argc, char **argv, PlotOptions **op); void get_arg_double(double *varp, int *argnp, int argc, char **argv, char *usage); void get_arg_string(char **varp, int *argnp, int argc, char **argv, char *usage); void arg_error(char *msg, char *arg, char *pname, char *usage); /* IMPLEMENTATIONS */ int main(int argc, char **argv) { PlotOptions *o; parse_options(argc, argv, &o); start_document(o); figs_1d(o); fprintf(stderr, "OK so far...\n"); finish_document(o); return(0); } #define NX 8 /* Number of intervals in domain mesh. */ void figs_1d(PlotOptions *o) { /* Domain for spline bases: */ interval_t dom_sp; dom_sp = (interval_t){{ 0, NX }}; /* Domain for continuous bases: */ interval_t dom_ct; dom_ct = (interval_t){{ 0, 1 }}; /* Bases to plot: */ int nb = 3; b1d_basis_t bas[nb]; bas[0] = (b1d_basis_t){ (b1d_family_t){b1d_kind_POLY, 0, 0}, NX, dom_sp, FALSE }; bas[1] = (b1d_basis_t){ (b1d_family_t){b1d_kind_POLY, 3, 0}, 1, dom_ct, FALSE }; bas[2] = (b1d_basis_t){ (b1d_family_t){b1d_kind_TRIG, 3, 0}, 1, dom_ct, FALSE }; int ib; for (ib = 0; ib < nb; ib++) { /* Plot figures for basis of kind {ib}: */ b1d_basis_t *bi = &(bas[ib]); char *btag = make_basis_tag(bi); /* Plot basis: */ figs_1d_basis(o, btag, bi); /* Plot function and approximation: */ figs_1d_approx(o, btag, forg, bi); } } double forg(double x) { /* Frequency, phase, and amplitude of each component: */ double f1 = 1.300, p1 = 0.300, a1 = 1.000; double f2 = 4.330, p2 = 0.560, a2 = 0.750; double f3 = 12.240, p3 = 0.820, a3 = 0.350; double f4 = 15.550, p4 = 0.940, a4 = 0.325; double f5 = 20.200, p5 = 0.110, a5 = 0.300; double f6 = 31.900, p6 = 0.590, a6 = 0.283; double f7 = 55.300, p7 = 0.203, a7 = 0.453; /* The raw signal: */ double atot = a1+a2+a3+a4+a5+a6+a7; return ( atot + a1 * sin((f1*x + p1)*2*M_PI) + a2 * sin((f2*x + p2)*2*M_PI) + a3 * sin((f3*x + p3)*2*M_PI) + a4 * sin((f4*x + p4)*2*M_PI) + a5 * sin((f5*x + p5)*2*M_PI) + a6 * sin((f6*x + p6)*2*M_PI) + a7 * sin((f7*x + p7)*2*M_PI) ) / atot / 2; } char *make_basis_tag(b1d_basis_t *bas) { char *bt = b1d_basis_tag(bas); char *tag = jsprintf("d1-%s", bt); free(bt); return tag; } #define ARG_ERROR(Msg,Arg) arg_error((Msg),(Arg),argv[0],usage) #define GET_STRING(Var) get_arg_string(&(Var), &argn, argc, argv, usage) #define GET_DOUBLE(Var) get_arg_double(&(Var), &argn, argc, argv, usage) void parse_options(int argc, char **argv, PlotOptions **op) { PlotOptions *o = (PlotOptions *)malloc(sizeof(PlotOptions)); char* usage = "\n [ -help ] [ -outName PREFIX ] [ -eps | -ps ]"; int argn; /* Defaults: */ o->outName = "dg"; o->eps = FALSE; o->paperSize = "letter"; o->color = TRUE; o->scale = 25.4; o->margin[0] = 1.0; o->margin[1] = 1.0; o->meshSize = 1.0; /* Default depends on {color} option: */ Color defColorFill = (Color){{1.00, 0.95, 0.85}}; Color defGrayFill = (Color){{0.90, 0.90, 0.90}}; o->fill = (Color){{-1.0, -1.0, -1.0}}; argn = 1; /* Scan command line options. */ while ((argn < argc) && (argv[argn][0] == '-') && (argv[argn][1] != '\0')) { char *key = argv[argn]; if ((key[0] == '-') && (key[1] == '-') && (key[2] != '\0')) { key++; } if (strcmp(key, "-help") == 0) { fprintf(stderr, "usage: %s %s\n", argv[0], usage); exit(0); } else if (strcmp(key, "-outName") == 0) { GET_STRING(o->outName); } else if (strcmp(key, "-eps") == 0) { o->eps = TRUE; } else if (strcmp(key, "-ps") == 0) { o->eps = FALSE; } else if (strcmp(key, "-paperSize") == 0) { GET_STRING(o->paperSize); } else if (strcmp(key, "-color") == 0) { o->color = TRUE; } else if ((strcmp(key, "-gray") == 0) || (strcmp(key, "-grey") == 0)) { o->color = FALSE; } else if (strcmp(key, "-fill") == 0) { GET_DOUBLE(o->fill.c[0]); GET_DOUBLE(o->fill.c[1]); GET_DOUBLE(o->fill.c[2]); } else if (strcmp(key, "-scale") == 0) { GET_DOUBLE(o->scale); } else if (strcmp(key, "-margin") == 0) { GET_DOUBLE(o->margin[0]); GET_DOUBLE(o->margin[1]); } else if (strcmp(key, "-meshSize") == 0) { GET_DOUBLE(o->meshSize); } else { ARG_ERROR("unknown option", argv[argn]); } ++argn; } if (argn != argc) { ARG_ERROR("extraneous arguments", argv[argn]); } if (o->fill.c[0] == -1) { o->fill = (o->color ? defColorFill : defGrayFill); } (*op) = o; } void get_arg_string(char **varp, int *argnp, int argc, char **argv, char *usage) /* Stores the next command line argument (as a string) into "*varp" */ { int argn = *argnp; if (argn+1 >= argc) { ARG_ERROR("missing arg value", argv[argn]); } (*varp) = argv[argn+1]; (*argnp) = argn+1; } void get_arg_double(double *varp, int *argnp, int argc, char **argv, char *usage) /* Stores the next command line argument (as a double) into "*varp" */ { int argn = *argnp; char *end; if (argn+1 >= argc) { ARG_ERROR("missing arg value", argv[argn]); } (*varp) = strtod(argv[argn+1], &end); if ((*end) != '\0') { ARG_ERROR("invalid numeric argument", argv[argn+1]); } (*argnp) = argn+1; } void arg_error(char *msg, char *arg, char *pname, char *usage) /* Prints "msg", "arg", the "usage" message, and exits. Handy while parsing the command line arguments. */ { fprintf(stderr, "%s %s\n", msg, arg); fprintf(stderr, "usage: %s %s\n", pname, usage); exit(1); }