diff options
Diffstat (limited to 'rspl/cw3.c')
-rw-r--r-- | rspl/cw3.c | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/rspl/cw3.c b/rspl/cw3.c new file mode 100644 index 0000000..03c9b81 --- /dev/null +++ b/rspl/cw3.c @@ -0,0 +1,325 @@ + +/************************************************/ +/* Investigate various curve approximations */ +/************************************************/ + +/* Discrete regularized spline versions */ +/* Test variable grid spacing in 3D + +/* Author: Graeme Gill + * Date: 28/11/2013 + * + * Copyright 1995, 2013 Graeme W. Gill + * + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +#undef DIAG +#undef DIAG2 +#undef GLOB_CHECK +#define AVGDEV 0.0 /* Average deviation of function data */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <math.h> +#include "copyright.h" +#include "aconfig.h" +#include "counters.h" +#include "numlib.h" +#include "plot.h" +#include "rspl.h" + +double lin(); +void usage(void); + +#define TRIALS 1 /* Number of random trials */ +#define XRES 100 /* Plotting res */ + + +#define PNTS1 20 +#define GRES1 33 + +/* Function that we're approximating */ +static double func(double val) { + double out; + int sgn = 0; + + if (val < 0.0) { + sgn = 1; + val = -val; + } + + out = pow(val, 2.4); + + if (sgn) + out = -out; + + return out; +} + +/* Grid spacing power */ +#define GRIDPOW 1.8 + +/* Scattered data sample spacing power */ +#define SAMPPOW 1.3 + + +co test_points[PNTS1 * PNTS1 * PNTS1]; + +double ipos[GRES1]; +double *iposes[3] = { ipos, ipos, ipos }; + +double powlike(double vv, double pp); + +void usage(void) { + fprintf(stderr,"Test 3D rspl interpolation variable grid spacing\n"); + fprintf(stderr,"Author: Graeme W. Gill\n"); + fprintf(stderr,"usage: c1 [options]\n"); + fprintf(stderr," -s smooth Use given smoothness (default 1.0)\n"); + exit(1); +} + +int main(int argc, char *argv[]) { + int fa,nfa; /* argument we're looking at */ + int i, j, e, f, n; + double x; + double xx1[XRES]; + double yy1[6][XRES]; + double xx2[XRES]; + double yy2[6][XRES]; + rspl *rss; /* incremental solution version */ + datai low,high; + int gres[MXDI]; + double smooth = 1.0; + double avgdev[MXDO]; + + low[0] = 0.0; + low[1] = 0.0; + low[2] = 0.0; + high[0] = 1.0; + high[1] = 1.0; + high[2] = 1.0; + avgdev[0] = AVGDEV; + avgdev[1] = AVGDEV; + avgdev[2] = AVGDEV; + + error_program = "c1"; + check_if_not_interactive(); + + /* Process the arguments */ + for(fa = 1;fa < argc;fa++) { + nfa = fa; /* skip to nfa if next argument is used */ + if (argv[fa][0] == '-') { /* Look for any flags */ + char *na = NULL; /* next argument after flag, null if none */ + + if (argv[fa][2] != '\000') + na = &argv[fa][2]; /* next is directly after flag */ + else { + if ((fa+1) < argc) { + if (argv[fa+1][0] != '-') { + nfa = fa + 1; + na = argv[nfa]; /* next is seperate non-flag argument */ + } + } + } + + if (argv[fa][1] == '?') + usage(); + + /* smoothness */ + else if (argv[fa][1] == 's' || argv[fa][1] == 'S') { + fa = nfa; + if (na == NULL) usage(); + smooth = atof(na); + } + else + usage(); + } else + break; + } + + for (n = 0; n < TRIALS; n++) { + double lrand = 0.0; /* Amount of level randomness */ + int di = 3; + int pnts = PNTS1; + int tpnts = PNTS1 * PNTS1 * PNTS1; + int fres; + + fres = GRES1; + gres[0] = fres; + gres[1] = fres; + gres[2] = fres; + + /* Create the object */ + rss = new_rspl(RSPL_NOFLAGS, + 3, /* di */ + 3); /* fdi */ + + /* For each grid spacing test */ + for (j = 0; j < 2; j++) { + DCOUNT(gc, MXDIDO, di, 0, 0, pnts); + + /* Set the scattered data points (actually grid) */ + DC_INIT(gc); + for (i = 0; !DC_DONE(gc); i++) { + + for (f = 0; f < 3; f++) { + double val, out; + + val = gc[f]/(pnts - 1.0); + + if (j == 0) { /* Linear */ +// out = func(val + d_rand(-0.001, 0.001)); + out = func(val); + test_points[i].p[f] = val; + test_points[i].v[f] = out; + + } else { /* power 2.0 grid spacing */ + val = pow(val, SAMPPOW); /* sample point spacing */ + +// out = func(val + d_rand(-0.001, 0.001)); + out = func(val); + val = powlike(val, 1.0/GRIDPOW); /* To grid spacing */ + test_points[i].p[f] = val; + test_points[i].v[f] = out; + } + } + DC_INC(gc); + } + + /* Set grid position info. This is the same for each input axis */ + for (i = 0; i < gres[0]; i++) { + double val, out; + + val = i/(gres[0] - 1.0); + if (j == 1) + val = powlike(val, 1.0/GRIDPOW); /* To grid spacing */ + ipos[i] = val; + } + + printf("Fitting rspl....\n"); + rss->fit_rspl(rss, + 0, + test_points, /* Test points */ + tpnts, /* Number of test points */ + low, high, gres, /* Low, high, resolution of grid */ + NULL, NULL, /* Default data scale */ + smooth, /* Smoothing */ + avgdev, /* Average deviation */ + j == 0 ? NULL : iposes); /* iwidth */ + + /* Show the result full scale of one axis and corresponding output */ + for (i = 0; i < XRES; i++) { + co tp; /* Test point */ + x = i/(double)(XRES-1); + xx1[i] = x; + yy1[0][i] = func(x); + tp.p[0] = x; + tp.p[1] = tp.p[2] = 0.0; + if (j == 1) + tp.p[0] = powlike(tp.p[0], 1.0/GRIDPOW); /* Grid spacing input */ + rss->interp(rss, &tp); + yy1[1+j][i] = tp.v[0]; + if (yy1[1+j][i] < -0.2) + yy1[1+j][i] = -0.2; + else if (yy1[1+j][i] > 1.2) + yy1[1+j][i] = 1.2; + } + + /* Show the result magnified */ + for (i = 0; i < XRES; i++) { + co tp; /* Test point */ + x = i/(double)(XRES-1); + x *= 0.1; + xx2[i] = x; + yy2[0][i] = func(x); + tp.p[0] = x; + tp.p[1] = tp.p[2] = 0.0; + if (j == 1) + tp.p[0] = powlike(tp.p[0], 1.0/GRIDPOW); /* Grid spacing input */ + rss->interp(rss, &tp); + yy2[1+j][i] = tp.v[0]; + if (yy2[1+j][i] < -0.2) + yy2[1+j][i] = -0.2; + else if (yy2[1+j][i] > 1.2) + yy2[1+j][i] = 1.2; + } + } + + printf("Full scale: Black = lin, Red = even, Green = pow2\n"); + do_plot6(xx1,yy1[0],yy1[1],yy1[2],NULL,NULL,NULL,XRES); + + printf("Magnified: Black = lin, Red = even, Green = pow2\n"); + do_plot6(xx2,yy2[0],yy2[1],yy2[2],NULL,NULL,NULL,XRES); + } + return 0; +} + +/* A power-like function, based on Graphics Gems adjustment curve. */ +/* Avoids "toe" problem of pure power. */ +/* Adjusted so that "power" 2 and 0.5 agree with real power at 0.5 */ + +double powlike(double vv, double pp) { + double tt, g; + + if (pp >= 1.0) { + g = 2.0 * (pp - 1.0); + vv = vv/(g - g * vv + 1.0); + } else { + g = 2.0 - 2.0/pp; + vv = (vv - g * vv)/(1.0 - g * vv); + } + + return vv; +} + + +/******************************************************************/ +/* Error/debug output routines */ +/******************************************************************/ + +/* Next u function done with optimization */ + +/* Structure to hold data for optimization function */ +struct _edatas { + rspl *rss; + int j; + }; typedef struct _edatas edatas; + +#ifdef GLOB_CHECK +/* Overall Global optimization method */ +/* Definition of the optimization function handed to powell() */ +double efunc2(void *edata, double p[]) + { + int j; + double rv; + rspl *rss = (rspl *)edata; + for (j = 0; j < rss->nig; j++) /* Ugg */ + rss->u[j].v = p[j]; + rv = rss->efactor(rss); +#ifdef DIAG2 + /* printf("%c%e",cr_char,rv); */ + printf("%e\n",rv); +#endif + return rv; + } + +solveu(rss) +rspl *rss; + { + int j; + double *cp; + double *s; + + cp = dvector(0,rss->nig); + s = dvector(0,rss->nig); + for (j = 0; j < rss->nig; j++) /* Ugg */ + { + cp[j] = rss->u[j].v; + s[j] = 0.1; + } + powell(rss->nig,cp,s,1e-7,1000,efunc2,(void *)rss); + } +#endif /* GLOB_CHECK */ |