diff options
Diffstat (limited to 'rspl')
-rw-r--r-- | rspl/Jamfile | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/c1.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/c1df.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/cw1.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/cw3.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/gam.c | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/gam.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/mlbs.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/mlbs.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/opt.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rev.c | 963 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rev.h | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/revbench.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rspl.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rspl.h | 35 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rspl1.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rspl1.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/rspl_imp.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/scat.c | 127 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/scat2.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/sm1.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/sm2.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/sm3.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/smtmpp.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/smtnd.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/spline.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/stest.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/t2d.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/t2ddf.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/t3d.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/t3ddf.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/tnd.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | rspl/trnd.c | 0 |
33 files changed, 917 insertions, 242 deletions
diff --git a/rspl/Jamfile b/rspl/Jamfile index 0d93acc..6f80f9f 100644 --- a/rspl/Jamfile +++ b/rspl/Jamfile @@ -27,6 +27,8 @@ HDRS = ../h ../numlib ../plot $(TIFFINC) ; LINKLIBS = librspl ../plot/libplot ../numlib/libnum ../numlib/libui ../plot/libvrml ../icc/libicc $(TIFFLIB) $(JPEGLIB) ; # Test programs +LINKFLAGS += $(GUILINKFLAGS) ; + MainsFromSources revbench.c c1.c cw1.c cw3.c c1df.c t2d.c t2ddf.c t3d.c t3ddf.c tnd.c trnd.c ; BUILD_TESTS = false ; diff --git a/rspl/c1.c b/rspl/c1.c index 31849ee..31849ee 100644..100755 --- a/rspl/c1.c +++ b/rspl/c1.c diff --git a/rspl/c1df.c b/rspl/c1df.c index 4020d7a..4020d7a 100644..100755 --- a/rspl/c1df.c +++ b/rspl/c1df.c diff --git a/rspl/cw1.c b/rspl/cw1.c index 2a026c8..2a026c8 100644..100755 --- a/rspl/cw1.c +++ b/rspl/cw1.c diff --git a/rspl/cw3.c b/rspl/cw3.c index e26cb7a..e26cb7a 100644..100755 --- a/rspl/cw3.c +++ b/rspl/cw3.c diff --git a/rspl/gam.c b/rspl/gam.c index 0765e05..2a9a63b 100644..100755 --- a/rspl/gam.c +++ b/rspl/gam.c @@ -21,9 +21,14 @@ /* This probably needs re-writing, since (I think) it doesn't take gamut - self intersection into account. Outline would be: + self intersection into account. The rspl/rec.c code works more + reliably, but doesn't cope with concavities that cross the line + to the focal point. So can this "surface following" code be + adapted to solve this type of problem ? - Have a spactial cache structure that contains list of potentialy + Outline would be: + + Have a spatial cache structure that contains list of potentialy intersecting triangles for any point. Create this incrementally. Each triangle can be replaced by a list of fragment triangles sharing the same plane. @@ -61,6 +66,9 @@ Each intersection adds new nodes, and splits a triangle into about 8 smaller triangles. Trick is to avoid slivers and numerical issues with triangles. + + Alternative would be to not split triangles, but just track + the line of intersection ? */ @@ -72,6 +80,7 @@ Add ink limit support. This be done by breaking a cell into a fixed geometry of smaller simplexes by dividing the cell into two on each axis. + (rspl/rev.c has code for this ??) Need to then add scan that detects areas to prune, that then ties in with rev code to mark such diff --git a/rspl/gam.h b/rspl/gam.h index 0892e4d..0892e4d 100644..100755 --- a/rspl/gam.h +++ b/rspl/gam.h diff --git a/rspl/mlbs.c b/rspl/mlbs.c index bbe3865..bbe3865 100644..100755 --- a/rspl/mlbs.c +++ b/rspl/mlbs.c diff --git a/rspl/mlbs.h b/rspl/mlbs.h index 4678cfd..4678cfd 100644..100755 --- a/rspl/mlbs.h +++ b/rspl/mlbs.h diff --git a/rspl/opt.c b/rspl/opt.c index d5a70ce..d5a70ce 100644..100755 --- a/rspl/opt.c +++ b/rspl/opt.c diff --git a/rspl/rev.c b/rspl/rev.c index f2f717b..017943b 100644..100755 --- a/rspl/rev.c +++ b/rspl/rev.c @@ -72,7 +72,6 @@ a particular aux target that lies within that segment. (1150 near black, k ~= 0.4). - */ #include <stdio.h> @@ -109,9 +108,13 @@ //#undef DMALLOC_GLOBALS #define DOSORT /* [def] Cell sort for better speed */ +#undef EN_UNTWIST /* [und] Force attempt to try and untwist gamut surface */ + /* - Seems to improve some, make some worse ?? (i.e Bonet) */ + /* By default this is controlled using ARGYLL_UNTWIST_GAMUT_SURFACE */ + /* environment variable. */ #undef REVTABLESTATS /* [und] Reverse table stats */ -#undef REVVRML /* [und] Reverse table plots */ +#undef REVVRML /* [und] Reverse table 3D plots */ #undef DEBUG1 /* [und] Higher level code */ #undef DEBUG2 /* [und] Lower level code */ @@ -172,16 +175,16 @@ int thissz, lastsz = -1; #endif #ifdef REVTABLESTATS -#pragma message("!!!!!!!!! REVTABLESTATS set in rspl/rev.c !!!!!!!!!!!") +# pragma message("!!!!!!!!! REVTABLESTATS set in rspl/rev.c !!!!!!!!!!!") #endif #ifdef REVVRML -#pragma message("!!!!!!!!! REVVRML set in rspl/rev.c !!!!!!!!!!!") -#include "vrml.h" +# pragma message("!!!!!!!!! REVVRML set in rspl/rev.c !!!!!!!!!!!") +# include "vrml.h" #endif #ifdef CHECK_NNLU -#pragma message("!!!!!!!!! CHECK_NNLU set in rspl/rspl.h !!!!!!!!!!!") +# pragma message("!!!!!!!!! CHECK_NNLU set in rspl/rspl.h !!!!!!!!!!!") #endif /* Do an arbitrary printf */ @@ -356,7 +359,7 @@ static void rev_test_vram(size_t size) { static void *rev_malloc(rspl *s, size_t size) { void *rv; - if ((size + 1 * 1024 * 1204) > g_test_ram) + if ((size + 1 * 1024 * 1024) > g_test_ram) rev_test_vram(size); if ((rv = malloc(size)) == NULL) { rev_reduce_cache(size); @@ -371,7 +374,7 @@ static void *rev_malloc(rspl *s, size_t size) { static void *rev_calloc(rspl *s, size_t num, size_t size) { void *rv; - if (((num * size) + 1 * 1024 * 1204) > g_test_ram) + if (((num * size) + 1 * 1024 * 1024) > g_test_ram) rev_test_vram(size); if ((rv = calloc(num, size)) == NULL) { rev_reduce_cache(num * size); @@ -386,7 +389,7 @@ static void *rev_calloc(rspl *s, size_t num, size_t size) { static void *rev_realloc(rspl *s, void *ptr, size_t size) { void *rv; - if ((size + 1 * 1024 * 1204) > g_test_ram) + if ((size + 1 * 1024 * 1024) > g_test_ram) rev_test_vram(size); if ((rv = realloc(ptr, size)) == NULL) { rev_reduce_cache(size); /* approximation */ @@ -1323,7 +1326,7 @@ set_search_limit( /* should evaluate in[0..di-1], and return number that is not to exceed */ /* limitv. NULL if not used */ void *lcntx, /* Context passed to limit() */ - double limitv /* Value that limit() is not to exceed */ + double limitv /* Value that limitf() is not to exceed */ ) { schbase *b = NULL; /* Pointer to search base information structure */ @@ -4025,10 +4028,11 @@ double *err /* Output error (weighted) distance at solution point */ } #ifdef DEBUG - if (wsrv2) + if (wsrv2) { DBG(("Got second ink limit triangle in tetrahedron\n")); - else if (wsrv) + } else if (wsrv) { DBG(("Got first ink limit triangle in tetrahedron\n")); + } #endif *err = dist; return wsrv; @@ -6820,7 +6824,7 @@ static void free_surfhash(rspl *s, int del) { /* vertex status */ typedef enum { - vtx_norm = 0, /* Normal vertex in primary bxcell */ + vtx_norm = 0, /* Normal vertex in primary bxcell - initial value */ vtx_sha = 1, /* Vertex has been shadowed */ vtx_del = 2, /* Vertex has been deleted because it's shadowed */ vtx_oil = 3 /* Vertex is over ink limit */ @@ -6828,8 +6832,9 @@ typedef enum { struct _vtxrec { int ix; /* fwd index of vertex */ - int cix; /* Cell index for this vertex */ - double v[MXRO]; /* Output value of vertex */ + int cix; /* Fwd cell vertex is in index */ + double vv[MXRO]; /* Output value of vertex */ + double vl[MXRO]; /* Log compressed output value of vertex */ double dist; /* Distance from center point squared */ int tcount; /* Touch count for converting to fwd cells */ int acount; /* Actual count for converting to fwd cells */ @@ -6866,7 +6871,7 @@ struct _vtxcache { }; typedef struct _vtxcache vtxcache; -/* Create the vertex list & hash */ +/* Create the (empty) vertex list & hash */ static void create_vtxrec_list(rspl *s, vtxcache *vc) { vc->hash_size = primes[3]; /* 3373 */ if ((vc->hash = (vtxrec **) rev_calloc(s, vc->hash_size, sizeof(vtxrec *))) == NULL) @@ -6949,16 +6954,67 @@ static vtxrec *get_vtxrec(vtxcache *vc, int ix) { hash = ix % vc->hash_size; - for (vx = vc->hash[hash]; vx != NULL; vx = vx->hlink) { + for (vx = vc->hash[hash]; vx != NULL; vx = vx->hlink) { if (vx->ix == ix) return vx; } return NULL; } +/* Log compress an output value wrt to center point */ +static void logcomp( + rspl *s, + double *out, + double *in, + double *cent +) { + int f, fdi = s->fdi; + double len; + + if (s->rev.surflin_en) { +#ifdef NEVER + /* (This doesn't seem to improve things) */ + /* Calculate vector length */ + for (len = 0.0, f = 0; f < fdi; f++) { + double tt= in[f] - cent[f]; + len += tt * tt; + } + len = sqrt(len); + + /* change length to log length */ + if (len > DBL_EPSILON) { + + len = 20.0 * pow(len, 0.25)/len; /* Ratio */ + + for (f = 0; f < fdi; f++) { + double tt = in[f] - cent[f]; + out[f] = len * tt + cent[f]; + } + } +#else + if (s->rev.surflin != NULL) { + co p; + + for (f = 0; f < fdi; f++) + p.p[f] = in[f]; + s->rev.surflin->interp(s->rev.surflin, &p); + for (f = 0; f < fdi; f++) + out[f] = p.v[f] - s->rev.linoff[f]; + } else { + for (f = 0; f < fdi; f++) + out[f] = in[f]; + } +#endif + } else { + for (f = 0; f < fdi; f++) + out[f] = in[f]; + } +} + /* Create a new vtxrec or return the current one. */ /* Allocates it, adds it to cache. */ /* DOESN"T add it to vtxlist. */ +/* If new, sets status = vtx_norm */ static vtxrec *new_vtxrec( rspl *s, vtxcache *vc, @@ -7005,12 +7061,15 @@ static vtxrec *new_vtxrec( /* Get the output value */ for (f = 0; f < fdi; f++) - vx->v[f] = gp[f]; + vx->vv[f] = gp[f]; + + /* Set vl[] */ + logcomp(s, vx->vl, vx->vv, s->rev.ocent); /* Compute distance to overall center point squared */ vx->dist = 0.0; for (f = 0; f < fdi; f++) { - double tt = gp[f] - s->rev.ocent[f]; + double tt = vx->vl[f] - s->rev.ocent[f]; vx->dist += tt * tt; } @@ -7020,7 +7079,7 @@ static vtxrec *new_vtxrec( int mi; double gw = s->rev.gw[f]; double gl = s->rev.gl[f]; - t = (vx->v[f] - gl)/gw; + t = (vx->vv[f] - gl)/gw; mi = (int)floor(t); /* Grid coordinate */ if (mi < 0) /* Limit to valid cube base index range */ mi = 0; @@ -7442,7 +7501,7 @@ static void extend_bxcell_shadow_group( /* vertex length from gamut center */ for (vlen= 0.0, f = 0; f < fdi; f++) { - double tt = vx->v[f] - s->rev.ocent[f]; + double tt = vx->vl[f] - s->rev.ocent[f]; vlen += tt * tt; } vlen = sqrt(vlen); @@ -7453,7 +7512,7 @@ static void extend_bxcell_shadow_group( scale = 1.0; for (f = 0; f < fdi; f++) - sv[f] = (scale * (vx->v[f] - s->rev.ocent[f])) + s->rev.ocent[f]; + sv[f] = (scale * (vx->vl[f] - s->rev.ocent[f])) + s->rev.ocent[f]; /* Distance from scaled vertex to group center */ for (w = 0.0, f = 0; f < fdi; f++) { @@ -8389,13 +8448,13 @@ static void plot_fxcell_surface(rspl *s, int dofclabels, int dobxcells, int dowa is inside or on the surface of the gamut. A simple and definitive topological rule hasn't been forthcoming, so a simpler heursitic of visiblilty from a singe internal "focal" point is currently used. - calc_ocent() attempts to choose a point with best visibilit of + calc_ocent() attempts to choose a point with best visibility of all the gamut surfaces, since any self-shadowing results in gamut surface holes. Improvements would be to create per-axis mappings (and separate the shadow vertex locations from the real ones) to re-shape - the gamut into a squere as much as possible. + the gamut into a square as much as possible. Multiple external focal points could be used, a vertex being shadowed only when it can't be "seen" by any external focal point. It's hard to figure how to make the latter @@ -8408,12 +8467,19 @@ static void plot_fxcell_surface(rspl *s, int dofclabels, int dobxcells, int dowa accelleration structure for shadow testing (BSP tree ??), and build the gamut surface incrementally from existing furthest points. + + (Have loop re-orderings been exausted ? i.e. can overlap + triangle processing "Do a first pass for each test vertex, + testing against just the triangles that are associated with + it's triangle" be used for main shadowing testing ?) */ /* Struct to slice locus points */ struct _slpoint { double v[MXRO]; /* Point location */ - double rad; /* Distance from ccent */ + double wrad; /* Weighted radius */ + double rad; /* Distance from ccent along slice */ + double minrad; /* Minimum distance from ccent */ double cvec[MXRO]; /* Vector from this point to ccent */ double len; /* Length of segment, -1 if no good */ @@ -8426,12 +8492,15 @@ struct _ocenctx { int ares; /* angle resolution */ slpoint *p[MXRO]; /* Slice locus points */ double ccent[MXRO]; /* Construction center point */ + double ret; /* return value */ + int oog; /* flag set if center is out of gamut */ int debug; }; typedef struct _ocenctx ocenctx; /* Given a set of slice locus points and a proposed center point, */ -/* compute the weighted averag of the orthogonality of the point */ +/* compute the weighted average of the orthogonality of the point */ /* to each locus line segment. (smaller is better) */ +/* (Used for optimizing the focal/center point.) */ static double aorthog(void *_ctx, double *cent) { ocenctx *ctx = (ocenctx *) _ctx; rspl *s = ctx->s; @@ -8441,6 +8510,8 @@ static double aorthog(void *_ctx, double *cent) { double ang, aang = 0.0; int naang = 0; + ctx->oog = 0; + if (ctx->debug) printf("aorthog called with cent %s\n",debPdv(fdi,cent)); for (ff = 0; ff < fdi; ff++) { @@ -8480,7 +8551,10 @@ static double aorthog(void *_ctx, double *cent) { /* Normalized difference in distance over length */ /* Compute dot product of cv and segment vector */ + /* (ang range 0.0 .. 1.0 */ ang = fabs(trad - nrad)/ctx->p[ff][aa].len; + if (ang > 1.0) + ang = 1.0; if (ctx->debug) printf(" aa %d: trad %f nrad %f, diff %f, len %f, ang %f\n",aa,trad,nrad,fabs(trad - nrad),ctx->p[ff][aa].len,ang); @@ -8493,14 +8567,11 @@ static double aorthog(void *_ctx, double *cent) { if (dot < 0.0) { if (ctx->debug) printf(" dot is %f\n",dot); - ang = 50.0; /* Big value */ + ang = 50.0; /* Big value */ + ctx->oog = 1; } else { ang = pow(ang, 50.0); /* Weight high angles */ } - - if (ang > aang) - aang = ang; - aang += ang; naang++; } @@ -8509,6 +8580,8 @@ static double aorthog(void *_ctx, double *cent) { if (ctx->debug) printf(" returning %f\n",aang); + ctx->ret = aang; + return aang; } @@ -8518,6 +8591,7 @@ static double aorthog(void *_ctx, double *cent) { /* surface of the gamut. */ static void calc_ocent(rspl *s) { int i, j, aa, mm; + int e, ee, di = s->di; int f, ff, fdi = s->fdi; int rgres = s->rev.res; /* number of bwd cells */ double minmax[2][MXRO][MXRO]; /* Range min/max points for each axis */ @@ -8527,14 +8601,15 @@ static void calc_ocent(rspl *s) { double ss[MXRO]; ocenctx ctx; /* Context */ double atanscale; + int ici, nici; /* Scan the forward array for the min and max points of each axis */ for (f = 0; f < fdi; f++) { - minmax[0][f][f] = 1e30; - minmax[1][f][f] = -1e30; + minmax[0][f][f] = 1e200; + minmax[1][f][f] = -1e200; } - /* Scan the Grid for min/max values */ + /* Scan the fwd Grid for min/max values */ for (gp = s->g.a, ep = s->g.a + s->g.no * s->g.pss; gp < ep; gp += s->g.pss) { for (ff = 0; ff < fdi; ff++) { if (minmax[0][ff][ff] > gp[ff]) { @@ -8550,8 +8625,8 @@ static void calc_ocent(rspl *s) { if (fdi == 1) { for (f = 0; f < fdi; f++) - s->rev.ocent[f] = 0.5 * (minmax[0][0][f] + minmax[1][0][f]); - DBG(("calc_ocent: got ocent = %s\n",debPdv(fdi,s->rev.ocent))); + s->rev.ocent[f] = 0.5 * (minmax[0][f][f] + minmax[1][f][f]); + DBG(("calc_ocent: got 1d ocent = %s\n",debPdv(fdi,s->rev.ocent))); return; } @@ -8569,7 +8644,8 @@ static void calc_ocent(rspl *s) { for (f = 0; f < fdi; f++) s->rev.ocent[f] = ctx.ccent[f] /= ((fdi-1) * 2.0); - DBG(("calc_ocent: ccent = %s\n",debPdv(fdi,ctx.ccent))); + DBG(("calc_ocent: initial ccent = %s\n",debPdv(fdi,ctx.ccent))); +//printf("calc_ocent: initial ccent = %s\n",debPdv(fdi,ctx.ccent)); /* If it's all to hard ... */ if (fdi != 3) { @@ -8581,11 +8657,17 @@ static void calc_ocent(rspl *s) { midix[f] = (int)((ctx.ccent[f] - s->rev.gl[f])/s->rev.gw[f] + 0.5); mid[f] = (midix[f]+0.5) * s->rev.gw[f] + s->rev.gl[f]; } +//printf("calc_ocent: mid point = %s\n",debPdv(fdi,mid)); /* Array for each slice values at angle (+ repeat at end) */ ctx.debug = 0; ctx.s = s; - ctx.ares = 20; + ctx.ares = (rgres + 1) & ~1; /* Make even so that there is an opposite angle */ + if (ctx.ares < 6) + ctx.ares = 6; + else if (ctx.ares > 20) + ctx.ares = 20; +//printf(" ocent ares %d\n",ctx.ares); atanscale = ctx.ares/(2.0 * DBL_PI); for (ff = 0; ff < fdi; ff++) { if ((ctx.p[ff] = (slpoint *)rev_calloc(s, ctx.ares+1,sizeof(slpoint))) == NULL) @@ -8593,96 +8675,201 @@ static void calc_ocent(rspl *s) { INCSZ(s, (ctx.ares+1) * sizeof(slpoint)); } -//printf("~1 locating center point\n"); + /* Use 5 passes to locate a more reliable initial center point */ + for (nici = 10, ici = 0; ici < nici; ici++) { +//printf(" locating center point iter %d\n",ici); - /* Set initial radius values */ - for (aa = 0; aa < ctx.ares; aa++) { - for (ff = 0; ff < fdi; ff++) - ctx.p[ff][aa].rad = -1.0; - } - - /* Take three slices through the rev[] array, plotting */ - /* the maximum circumference for the slice */ + /* Set initial radius values */ + for (ff = 0; ff < fdi; ff++) { + for (aa = 0; aa < ctx.ares; aa++) { + ctx.p[ff][aa].wrad = -1.0; + ctx.p[ff][aa].rad = -1.0; + ctx.p[ff][aa].minrad = 1e38; + } + } + + /* Take three slices through the rev[] array, plotting */ + /* the maximum circumference for the slice */ - /* For the axis we're slicing */ - for (ff = 0; ff < fdi; ff++) { - DCOUNT(cc, MXRO, 2, 0, 0, rgres); /* Counter through bwd cells */ - double vv[MXRO]; - int aa; - + /* For the axis we're slicing */ + for (ff = 0; ff < fdi; ff++) { + FCOUNT(cc, MXRO, 3); /* Counter through bwd cells */ + int start[3], endp1[3]; + double vv[MXRO]; + int aa; + //printf(" slice axis %d\n",ff); - /* Scan this slice of rev[] */ - DC_INIT(cc); - while (!DC_DONE(cc)) { - int ix; - int slix[2]; /* Indexes in slice direction */ - int *rp; - int co[MXRO]; - - /* Compute bx index */ - ix = 0; - for (j = f = 0; f < fdi; f++) { - if (f == ff) - co[f] = midix[f]; - else { - slix[j] = f; - co[f] = cc[j++]; + /* Setup "fat" slice range */ + for (f = 0; f < fdi; f++) { + if (f == ff) { + start[f] = midix[f]-1; + if (start[f] < 0) + start[f] = 0; + endp1[f] = midix[f]+2; + if (endp1[f] > rgres) + endp1[f] = rgres; + } else { + start[f] = 0; + endp1[f] = rgres; } - ix += co[f] * s->rev.coi[f]; } -//printf(" bx %d, %d ix %d\n",co[0],co[1],co[2],ix); + FRECONFA(cc, start, endp1); + +//printf(" slice range %d - %d, %d - %d, %d - %d\n", start[0], endp1[0]-1, start[1], endp1[1]-1, start[2], endp1[2]-1); + + /* Scan this 3 thick, 2D slice of rev[] */ + FC_INIT(cc); + while (!FC_DONE(cc)) { + int ix; + int slix[MXRO]; /* Indexes in slice direction + orthogonal */ + int *rp; + + /* Compute bx index */ + ix = 0; + for (j = f = 0; f < fdi; f++) { + ix += cc[f] * s->rev.coi[f]; + if (f != ff) + slix[j++] = f; + } + slix[j++] = ff; +//printf(" bx %d, %d ix %d\n",cc[0],cc[1],cc[2],ix); - if (s->rev.rev[ix] == NULL) { + if (s->rev.rev[ix] == NULL) { //printf(" rev is empty\n"); - goto next_bx; - } + goto next_bx; + } - /* For all the vertex values in bx rev[] */ - for (rp = s->rev.rev[ix]+3; *rp != -1; rp++) { - float *fcb = s->g.a + *rp * s->g.pss; - double x, y, rad, ang; + /* For all the cubes bx rev[] */ + for (rp = s->rev.rev[ix]+3; *rp != -1; rp++) { -//printf(" vtx %d\n",*rp); - /* Ignore over ink limit values */ - if (s->limiten && fcb[-1] > s->limitv) - continue; - - /* Compute radius and normalize */ - x = fcb[slix[0]] - ctx.ccent[slix[0]]; - y = fcb[slix[1]] - ctx.ccent[slix[1]]; - rad = sqrt(x * x + y * y); - if (rad < EPS) - continue; + /* For each vertx of this cube */ + for (ee = 0; ee < (1<<di); ee++) { + int vix = *rp + s->g.hi[ee]; + float *gp = s->g.a + vix * s->g.pss; /* Pointer to float of fwd vertex */ + double fcb[MXRO]; + double x, y, z, wrad, rad, ang; - /* Quantized angle this point is at */ - ang = atanscale * atan2(y, x); - aa = (int)floor(ang); - if (aa < 0) - aa += ctx.ares; - if (aa >= ctx.ares) - aa -= ctx.ares; + /* Don't add over ink limit vertexes */ + if (s->limiten && gp[-1] > s->limitv) { + continue; + } + + for (f = 0; f < fdi; f++) + fcb[f] = gp[f]; + + /* (Don't) Convert output values to log values */ + /* logcomp(s, fcb, fcb, ctx.ccent); */ + + /* Compute 2D radius and normalize */ + x = fcb[slix[0]] - ctx.ccent[slix[0]]; + y = fcb[slix[1]] - ctx.ccent[slix[1]]; + z = fcb[slix[2]] - ctx.ccent[slix[2]]; + /* wrad is "elipsoid" weighted radius in slice */ + wrad = x * x + y * y - 1.5 * z * z; + wrad = sqrt(wrad < 0.0 ? 0.0 : wrad); + rad = sqrt(x * x + y * y); + if (rad < EPS || wrad < EPS) + continue; + + /* Quantized angle this point is at */ + ang = atanscale * atan2(y, x); + aa = (int)floor(ang); + if (aa < 0) + aa += ctx.ares; + if (aa >= ctx.ares) + aa -= ctx.ares; //printf(" slice %d vtx %f %f %f rad %f, ang %f aa %d\n", ff, fcb[0], fcb[1], fcb[2], rad, ang, aa); - if (rad > ctx.p[ff][aa].rad) { - ctx.p[ff][aa].rad = rad; + if (wrad > ctx.p[ff][aa].wrad) { + ctx.p[ff][aa].wrad = wrad; + ctx.p[ff][aa].rad = rad; - for (f = 0; f < fdi; f++) { - ctx.p[ff][aa].v[f] = fcb[f]; + /* Copy far point */ + for (f = 0; f < fdi; f++) + ctx.p[ff][aa].v[f] = fcb[f]; + + /* (don't) Flatten the points to lie on the notional center */ + /* ctx.p[ff][aa].v[ff] = ctx.ccent[ff]; */ + } + + /* Track min in case ccent is not within slice */ + if (rad < ctx.p[ff][aa].minrad) { + ctx.p[ff][aa].minrad = rad; + } } - /* Flatten the points to lie on the notional center */ - ctx.p[ff][aa].v[ff] = ctx.ccent[ff]; } + next_bx:; + FC_INC(cc); } - next_bx:; - DC_INC(cc); + + /* Repeat first in extra at end */ + ctx.p[ff][ctx.ares] = ctx.p[ff][0]; /* Structure copy */ } - /* Repeat first in extra at end */ - ctx.p[ff][ctx.ares] = ctx.p[ff][0]; /* Structure copy */ + /* Check if center point is within slice by looking for empty entries. */ + { + double ccvec[MXRO]; /* Center correction vector */ + double ccount = 0.0; + + for (f = 0; f < fdi; f++) + ccvec[f] = 0.0; + + for (ff = 0; ff < fdi; ff++) { + for (aa = 0; aa < ctx.ares; aa++) { + +//printf(" slice %d aa %d, vtx %s rad %f, irad %f\n", ff, aa, debPdv(fdi,ctx.p[ff][aa].v), ctx.p[ff][aa].rad, ctx.p[ff][aa].minrad); + + /* Either the grid is very sparse, or our center */ + /* is outside */ + if (ctx.p[ff][aa].rad < 0.0) { + int oaa = aa + (ctx.ares/2); + if (oaa >= ctx.ares) + oaa -= ctx.ares; + +//printf(" oaa %d, vtx %s rad %f, irad %f\n", oaa, debPdv(fdi,ctx.p[ff][oaa].v), ctx.p[ff][oaa].rad, ctx.p[ff][oaa].minrad); + + /* If oposite side has an entry */ + if (ctx.p[ff][oaa].rad > 0.0) { + double cor[MXRO]; + double prop = (3.0 * ctx.p[ff][oaa].minrad + + ctx.p[ff][oaa].rad)/4.0; + + prop /= ctx.p[ff][oaa].rad; /* Proportion of distance to v[] */ + + for (f = 0; f < fdi; f++) + cor[f] = prop * (ctx.p[ff][oaa].v[f] - ctx.ccent[f]); +//printf(" prop %f, corr %s\n",prop,debPdv(fdi,cor)); + for (f = 0; f < fdi; f++) + ccvec[f] += cor[f]; + ccount++; + } + } + } + } + +//printf("ccount %f\n",ccount); + if (ccount > 0.0) { /* Make adjustment */ + if (ici < (nici-1)) { + for (f = 0; f < fdi; f++) + ccvec[f] /= ccount; +//printf("Corecting center by %s\n",debPdv(fdi,ccvec)); + for (f = 0; f < fdi; f++) + ctx.ccent[f] += ccvec[f]; +//printf("cceny now %s\n",debPdv(fdi,ctx.ccent)); + } else { /* Last round and correction needed */ + if (0.0 && s->verbose) + fprintf(stdout, "%cFailed to locate aprox. gamut center\n",cr_char); + } + } else { + break; /* We're done */ + } + } } +//printf("calc_ocent: refined ccent = %s\n",debPdv(fdi,ctx.ccent)); + /* Pre-compute point to point info to speed optimization */ for (ff = 0; ff < fdi; ff++) { for (aa = 0; aa < ctx.ares; aa++) { @@ -8706,7 +8893,9 @@ static void calc_ocent(rspl *s) { /* slice segment. This should maximize visibility of the inner of the */ /* gamut surface, for shadow testing. */ for (f = 0; f < fdi; f++) - ss[f] = 5.0; + ss[f] = fabs(0.1 * (minmax[1][f][f] - minmax[0][f][f])); + +//ctx.debug = 1; /* return 0 on sucess, 1 on failure due to excessive itterations */ if (powell(NULL, fdi, s->rev.ocent, ss, 1e-3, 500, aorthog, (void *)&ctx, NULL, NULL)) { @@ -8715,8 +8904,16 @@ static void calc_ocent(rspl *s) { s->rev.ocent[f] = ctx.ccent[f]; } -// ctx.debug = 1; -// printf("Final angle = %f\n", aorthog(&ctx, ctx.ccent)); +//ctx.debug = 1; + + /* Check result */ + aorthog(&ctx, ctx.ccent); + + /* Hmm. This isn't very reliable in detecting failure. */ + if (ctx.oog) + printf("calc_ocent failed to return in-gamut focal point!\n"); + +//printf("Final angle = %f\n", ctx.ret); #ifdef REVVRML /* Plotting routine declarations */ /* Diagnostic - dump the gamut slice locii */ @@ -8729,7 +8926,7 @@ static void calc_ocent(rspl *s) { double blue[3] = { 0.1, 0.1, 0.8 }; double *rgb[3] = { red, green, blue }; - wrl = new_vrml("section", 0, vrml_lab); + wrl = new_vrml("section", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); wrl->add_marker(wrl, s->rev.ocent, NULL, 1.0); /* Show vertex labels */ @@ -8772,7 +8969,384 @@ static void calc_ocent(rspl *s) { DECSZ(s, (ctx.ares+1) * sizeof(slpoint)); } - DBG(("calc_ocent: got ocent = %s\n",debPdv(fdi,s->rev.ocent))); + DBG(("calc_ocent: final ocent = %s\n",debPdv(fdi,s->rev.ocent))); +//printf("calc_ocent: final ocent = %s\n",debPdv(fdi,s->rev.ocent)); +} + +/* Create gamut surface linearization (surflin) transform. */ +/* This is used by logcomp() to try and straighten out the */ +/* device response so that the ocent is "visible" from */ +/* any point on the surface. */ +/* (We assume we are called at the correct point when bx->status == bx_uninit) */ +static int calc_surflin( +rspl *s, +vtxcache *vc, /* Vertexes */ +assdire *edgdir /* Edge lookup for vertex */ +) { + int i, j, g; + int e, ee, di = s->di; + int f, ff, fdi = s->fdi; + vtxrec *vx, *nvx; + int nitter, itter; + + double vxv[POW2MXRI][MXRO]; /* Overal fwd interp vertex values */ + int nvtx; + cow *mpoints; + int gres[MXDO]; + double min[MXDO], max[MXDO]; + double vmin[MXDO], vmax[MXDO]; + + for (f = 0; f < fdi; f++) + gres[f] = s->g.bres; // ?? + +//printf("calc_surflin: rspl res %d\n",gres[0]); + DBG(("calc_surflin: rspl res %d\n",gres[0])); + +//printf("~1 gres = %d %d %d\n", s->g.res[0], s->g.res[1], s->g.res[2]); +//printf("~1 ci = %d %d %d\n", s->g.ci[0], s->g.ci[1], s->g.ci[2]); + + /* Lookup interpolation cube corners */ + for (ee = 0; ee < (1<<di); ee++) { + int ix; + float *fcb; + for (ix = e = 0; e < di; e++) { + if (ee & (1<<e)) + ix += s->g.ci[e] * (s->g.res[e] - 1); + } + fcb = s->g.a + ix * s->g.pss; + for (f = 0; f < fdi; f++) + vxv[ee][f] = fcb[f]; +//printf("~1 cube corners %d = %f %f %f\n",ee, vxv[ee][0], vxv[ee][1], vxv[ee][2]); + } + +//printf("calc_surflin: counting number of vertexes:\n"); + /* Count the number of vertexes we may need */ + nvtx = 0; + for (i = 0; i < vc->hash_size; i++) { + for (vx = vc->hash[i]; vx != NULL; vx = vx->hlink) { + nvtx++; + } + } + DBG(("calc_surflin: %d mapping points\n",nvtx)); +//printf("calc_surflin: %d mapping points\n",nvtx); + +//printf("calc_surflin: computing goal values:\n"); + /* Currently the vertex vl = vv = output value of vertex. */ + /* Temporarily replace vv with the idealize (linear interp) output "goal" values. */ + for (i = 0; i < vc->hash_size; i++) { + for (vx = vc->hash[i]; vx != NULL; vx = vx->hlink) { + int tix; /* Temp fwd cell index */ + double we[MXRI]; /* Vertex input position == 1.0 - Weight */ + double gw[POW2MXRI]; /* weight for each grid cube corner */ + double w; + + /* Compute this vertexes relative input position */ + for (tix = vx->ix, e = 0; e < di; e++) { + int dix; + dix = tix % s->g.res[e]; + tix /= s->g.res[e]; + we[e] = (double)dix/(s->g.res[e]-1.0); + } + + /* Compute corner weights needed for interpolation */ + gw[0] = 1.0; + for (e = 0, g = 1; e < di; g *= 2, e++) { + for (j = 0; j < g; j++) { + gw[g+j] = gw[j] * we[e]; + gw[j] *= (1.0 - we[e]); + } + } + + /* Linear interpolated output values */ + w = gw[0]; + for (f = 0; f < fdi; f++) /* Base of cube */ + vx->vv[f] = w * vxv[0][f]; + + for (g = 1; g < (1<<di); g++) { /* For all other corners of cube */ + w = gw[g]; + for (f = 0; f < fdi; f++) + vx->vv[f] += w * vxv[g][f]; + } + } + } + + /* Now itteratively adjust the vl values to better match the scaled */ + /* relative positions of the goal values. */ + + /* Go through them again to get every line they are part of */ + /* (We're assuming we need exponentially more itters with finer point */ + /* spacing ?) */ + nitter = (int)(0.06 * s->g.bres * s->g.bres + 0.5); + if (nitter < 1) + nitter = 1; + for (itter = 0; itter < nitter; itter++) { + + DBG(("calc_surflin: maping itter %d\n",itter)); +//printf("calc_surflin: maping itter %d\n",itter); + + for (i = 0; i < vc->hash_size; i++) { + for (vx = vc->hash[i]; vx != NULL; vx = vx->hlink) { + assdire *edg; /* Edge table */ + float *fp; + int fl; + double agrad, aorad; + int nn; + double scale; + + fp = s->g.a + vx->ix * s->g.pss; /* This vertex in fwd grid */ + fl = FLV(fp); /* Edge flags for this vertex */ + edg = edgdir + fl; + + /* For vertexes at the end of all possible edges common with this vertex, */ + /* compute average radius */ + agrad = aorad = 0.0; + for (j = 0; j < edgdir[fl].no; j++) { + int eix; + + /* Index number of vertex other than the one we got it from */ + if (edg->ti[j].goffs[0] != 0) + eix = vx->ix + edg->ti[j].goffs[0]; + else + eix = vx->ix + edg->ti[j].goffs[1]; + + if ((nvx = get_vtxrec(vc, eix)) != NULL) { + double glen, olen; + glen = olen = 0.0; + for (f = 0; f < fdi; f++) { + double tt; + + tt = vx->vv[f] - nvx->vv[f]; + glen += tt * tt; + + tt = vx->vl[f] - nvx->vl[f]; + olen += tt * tt; + } + glen = sqrt(glen); + olen = sqrt(olen); + agrad += glen; + aorad += olen; + nn++; + } + } + + if (nn == 0) { /* Hmm. No neighors ? */ + vx->status = vtx_del; /* Mark it as isolated */ + continue; + } + + scale = aorad/agrad; /* Local scale factor from goal to output */ + + /* Reset the current vertex output value based on the relative */ + /* position of it in goal space */ + for (f = 0; f < fdi; f++) + vx->vl[f] = 0.0; + + nn = 0; + for (j = 0; j < edgdir[fl].no; j++) { + int eix; + + /* Index number of vertex other than the one we got it from */ + if (edg->ti[j].goffs[0] != 0) + eix = vx->ix + edg->ti[j].goffs[0]; + else + eix = vx->ix + edg->ti[j].goffs[1]; + + if ((nvx = get_vtxrec(vc, eix)) != NULL) { + for (f = 0; f < fdi; f++) + vx->vl[f] += nvx->vl[f] + scale * (vx->vv[f] - nvx->vv[f]); + nn++; + } + } + for (f = 0; f < fdi; f++) + vx->vl[f] /= (double)nn; + } + } + } + + DBG(("calc_surflin: creating rspl\n")); +//printf("calc_surflin: creating rspl\n"); + + /* Now construct rspl setup mapping points from vertex normal output values */ + /* to adjusted vl values */ + + if ((s->rev.surflin = new_rspl(RSPL_NOFLAGS, fdi, fdi)) == NULL) + error("calc_surflin: new_rspl failed"); + + nvtx++; /* One for center point */ + + /* Allocate rspl setup points */ + if ((mpoints = malloc(sizeof(cow) * 2 * nvtx)) == NULL) +// if ((mpoints = malloc(sizeof(cow) * nvtx)) == NULL) + error("calc_surflin: malloc of %d rspl setup points failed",nvtx); + + nvtx = 0; + +#ifndef NEVER + /* Center point */ + for (f = 0; f < fdi; f++) { + mpoints[nvtx].p[f] = s->rev.ocent[f]; + mpoints[nvtx].v[f] = s->rev.ocent[f]; + } + mpoints[nvtx].w = 10.0; + nvtx++; +#endif + + /* Set the surface mapping points and restore vertexes values */ + for (i = 0; i < vc->hash_size; i++) { + for (vx = vc->hash[i]; vx != NULL; vx = vx->hlink) { + float *fcb; + + fcb = s->g.a + vx->ix * s->g.pss; /* This vertex in fwd grid */ + + /* Actual output value as source of mapping */ + for (f = 0; f < fdi; f++) + mpoints[nvtx].p[f] = vx->vv[f] = fcb[f]; + + if (vx->status != vtx_norm) { /* Skip isolated values */ + vx->status = vtx_norm; /* Restore vtx contents */ + for (f = 0; f < fdi; f++) + vx->vl[f] = vx->vv[f]; + continue; + } + + for (f = 0; f < fdi; f++) + mpoints[nvtx].v[f] = vx->vl[f]; + mpoints[nvtx].w = 1.0; + nvtx++; + + vx->status = vtx_norm; /* Restore vtx contents */ + for (f = 0; f < fdi; f++) + vx->vl[f] = vx->vv[f]; + +//printf("Map[%d] %f %f %f -> %f %f %f\n", nvtx-1, mpoints[nvtx-1].p[0], mpoints[nvtx-1].p[1], mpoints[nvtx-1].p[2], mpoints[nvtx-1].v[0], mpoints[nvtx-1].v[1], mpoints[nvtx-1].v[2]); + +#ifndef NEVER + /* Add intermediate "fixed" point */ + for (f = 0; f < fdi; f++) { + mpoints[nvtx].p[f] = mpoints[nvtx].v[f] + = 0.5 * mpoints[nvtx-1].p[f] + 0.5 * s->rev.ocent[f]; + } + mpoints[nvtx].w = 0.5; + nvtx++; +#endif + } + } + + for (f = 0; f < fdi; f++) { + min[f] = 1e38; + max[f] = -1e38; + vmin[f] = 1e38; + vmax[f] = -1e38; + } + for (i = 0; i < nvtx; i++) { + +#ifdef NEVER + /* Blend with original values */ + for (f = 0; f < fdi; f++) + mpoints[i].v[f] = 0.5 * mpoints[i].p[f] + 0.5 * mpoints[i].v[f]; +#endif + + for (f = 0; f < fdi; f++) { + if (mpoints[i].p[f] < min[f]) + min[f] = mpoints[i].p[f]; + if (mpoints[i].p[f] > max[f]) + max[f] = mpoints[i].p[f]; + + if (mpoints[i].v[f] < vmin[f]) + vmin[f] = mpoints[i].v[f]; + if (mpoints[i].v[f] > vmax[f]) + vmax[f] = mpoints[i].v[f]; + } + } + +#ifdef REVVRML /* Plot mapping vectors red->green */ + { + vrml *wrl; + double red[3] = { 1.0, 0.0, 0.0 }; + double green[3] = { 0.0, 1.0, 0.0 }; + + wrl = new_vrml("suflinvecss", 0, vrml_lab); + wrl->start_line_set(wrl, 0); + + for (i = 0; i < nvtx; i++) { + wrl->add_col_vertex(wrl, 0, mpoints[i].p, red); + wrl->add_col_vertex(wrl, 0, mpoints[i].v, green); + + } + + wrl->make_lines(wrl, 0, 2); + wrl->del(wrl); + } +#endif + + DBG(("calc_surflin: mapping points set, about to creat rspl:\n")); +//printf("calc_surflin: mapping points set, about to creat rspl:\n"); + + /* Fit the rspl */ + s->rev.surflin->fit_rspl_w(s->rev.surflin, RSPL_NOFLAGS, mpoints, nvtx, + min, max, gres, vmin, vmax, 4.0, NULL, NULL); + + DBG(("calc_surflin: mapping created\n")); +//printf("calc_surflin: mapping created\n"); + +#ifdef NEVER + { + double de; + co p; + extern double icmNorm33(double *, double *); + + /* Check fit */ + de = 0.0; + + for (i = 0; i < nvtx; i++) { + for (f = 0; f < fdi; f++) + p.p[f] = mpoints[i].p[f]; + + s->rev.surflin->interp(s->rev.surflin, &p); + + de += icmNorm33(mpoints[i].v, p.v); + } + de = de/(double)nvtx; + + printf("Avg fit error = %f\n",de); + } +#endif + + free(mpoints); + + /* Lookup ocent mapping offset */ + { + co p; + + for (f = 0; f < fdi; f++) + p.p[f] = s->rev.ocent[f]; + s->rev.surflin->interp(s->rev.surflin, &p); +//printf("opoint mapping %f %f %f -> %f %f %f\n", p.p[0], p.p[1], p.p[2], p.v[0], p.v[1], p.v[2]); + for (f = 0; f < fdi; f++) + s->rev.linoff[f] = p.v[f] - s->rev.ocent[f]; + } + + +#ifndef NEVER + /* Put the transform into use */ + s->rev.surflin_en = 1; + + /* Transform all the vertexes */ + for (i = 0; i < vc->hash_size; i++) { + for (vx = vc->hash[i]; vx != NULL; vx = vx->hlink) { + logcomp(s, vx->vl, vx->vv, s->rev.ocent); + + /* Compute distance to overall center point squared */ + vx->dist = 0.0; + for (f = 0; f < fdi; f++) { + double tt = vx->vl[f] - s->rev.ocent[f]; + vx->dist += tt * tt; + } + } + } +#endif + + return 0; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -8800,6 +9374,7 @@ rspl *s /* Note that bit 1 can be set for cells that are not */ /* to be explored because they are in the gamut interior, */ /* and because they have already been added to the seedlist. */ + int pass; /* Construction pass */ float *gp; /* Pointer to fwd grid points */ DCOUNT(gg, MXRO, fdi, 0, 0, rgres); /* Track the prime seed coordinate */ @@ -8835,9 +9410,24 @@ rspl *s int nnmxrevcelldepth = 0; /* Maximum nnrev[] list lengths */ int nnrevshare = 0; /* Sum of nnrev[] list reference counts */ #endif + datao rgmin, rgmax; DBG(("init_revaccell called, di = %d, fdi = %d, mgres = %d\n",di,fdi,(int)s->g.mres)); + /* To help VRML diagnostics, make a guess as to whether the output */ + /* space is XYZ like, or L*a*b* like */ + + s->get_out_range(s, rgmin, rgmax); /* overall output min/max */ + + if (fdi >= 3 + && rgmin[0] >= -1.0 && rgmax[0] < 3.0 + && rgmin[1] >= -1.0 && rgmax[1] < 3.0 + && rgmin[2] >= -1.0 && rgmax[2] < 3.0) { + s->rev.probxyz = 1; + if (s->verbose) + fprintf(stdout, "%cLooks like an XYZ space\n",cr_char); + } + if (fdi > 1 && s->verbose) fprintf(stdout, "%cInitializing nnrev arrays...\n",cr_char); @@ -8885,7 +9475,7 @@ rspl *s /* * The rev[] and nnrev[] grids contain pointers to lists of grid cube base indexes. * If the pointer is NULL, then there are no base indexes in that list. - * A non NULL list uses element [0] to indicate the alocation size of the list, + * A non NULL list uses element [0] to indicate the allocation size of the list, * [1] contains the index of the next free location, [2] contains the reference * count (lists may be shared), the list starts at [3]. The last entry is marked with -1. */ @@ -8897,6 +9487,8 @@ rspl *s double iv[MXDI]; /* Input value corresponding to grid */ DBG(("Looking up fwd vertex ink limit values\n")); +//printf("Looking up fwd vertex ink limit values\n"); +//printf("s->limitv = %f\n",s->limitv); /* Calling the limit function for each fwd vertex could be bad */ /* if the limit function is slow. Maybe an octree type algorithm */ /* could be used if this is a problem ? */ @@ -8906,7 +9498,9 @@ rspl *s for (e = 0; e < di; e++) iv[e] = s->g.l[e] + gc[e] * s->g.w[e]; /* Input sample values */ gp[-1] = (float)(INKSCALE * s->limitf(s->lcntx, iv)); +//printf("~1 set ix %d limitv to %f\n",i,gp[-1]); } +//else printf("~1 ix %d limitv is %f\n",i,gp[-1]); EC_INC(gc); } s->g.limitv_cached = 1; @@ -8958,6 +9552,7 @@ rspl *s uil = oil = 0; for (f = 0; f < fdi; f++) /* Init output min/max */ min[f] = max[f] = gp[f]; + if (!s->limiten || gp[-1] <= s->limitv) uil = 1; else @@ -9065,7 +9660,7 @@ rspl *s } /* Next reverse grid point in intersecting cube */ } /* Next base grid point */ - DBG(("We skipped %d cells that were over the limit\n",nskcells)); + DBG(("We skipped %d/%d cells that were over the limit\n",nskcells,gno)); #ifdef CHECK_NNLU if (fdi > 1) { @@ -9180,7 +9775,6 @@ rspl *s cc[f] += (ff & 1) ? 1 : -1; vflagp += (ff & 1) ? s->rev.coi[f] : -s->rev.coi[f]; - /* Out of bounds or empty */ if (cc[f] < 0 || cc[f] >= rgres || ((*vflagp & 0xf) == 0)) { vflag[i] = (vflag[i] & ~0xf) | 2; /* Convert this one to empty surface cell */ @@ -9256,7 +9850,7 @@ rspl *s } } - } else { + } else { /* di >= 3 gamut surface finding */ #ifdef REVVRML /* Plot the initial surface bxcells & their fwd cells. */ @@ -9289,7 +9883,7 @@ rspl *s /* - - - - - - - - - - - - - - */ /* fill, thin and add, until */ /* there is no more work to do. */ - for (;;) { + for (pass = 0;; pass++) { int phase; int morevtxadded = 0; #if defined(REVTABLESTATS) || defined(DEBUG) @@ -9301,7 +9895,7 @@ rspl *s /* For each surface bxcell, convert the corresponding */ /* rev[] fwd cubes into vertices. */ - /* (Musk keep bxcells even if none of their verticies */ + /* (Must keep bxcells even if none of their verticies */ /* are physically in them, so that those verticies get thinned. */ /* could only remove them if vertex was not in any surface cell ?) */ for (pbx = &s->rev.surflist, bx = *pbx; bx != NULL; bx = nbx) { @@ -9368,10 +9962,10 @@ rspl *s /* Expand a bxcell's shadow testing group values based on it's vertex list */ /* so that shadow testing works correctly for vertexes that don't */ /* actually lie within the bxcell. (Note that in fact the triangle */ - /* testing creates triangles that are mode of vertexes that may not */ - /* be in this bx's list, so the shadow size doesn't accturatly reprsent */ + /* testing creates triangles that are made of vertexes that may not */ + /* be in this bx's list, so the shadow size doesn't accuratly reprsent */ /* the possible shadow area. It's not clear what consequences this has, */ - /* if any. If we extanded the group to cover this, we would need to have ) */ + /* if any. If we extanded the group to cover this, we would need to have */ /* two groups, a shadower group including those vertexes, and a shadowee */ /* goup for just those vertexes that are part of the bx. */ extend_bxcell_shadow_group(s, &vc, bx); @@ -9380,6 +9974,19 @@ rspl *s morevtxadded = 1; } + /* Compute transform rspl that helps "unfold" any regions of the surface */ + /* that overlap from the perspective of ocent, to try and avoid gaps in */ + /* the final gamut surface. Existing vtxrec are converted to have vl */ + /* in the unfolded space. */ + if (pass == 0 /* && function flag set */) { +#ifndef EN_UNTWIST /* Control using an environment variable */ + if (getenv("ARGYLL_UNTWIST_GAMUT_SURFACE") != NULL) +#endif + { + calc_surflin(s, &vc, edgdir); + } + } + DBG(("thinning surface vertex lists and converting to cells\n")); /* (Sorting bxcells doesn't seem to make any performace difference.) */ @@ -9440,8 +10047,8 @@ rspl *s /* If any of bx is further from nbx and their bounding */ /* cylinders overlap in perspective from rev.ocenter, */ /* assume nbx is a shadow */ - if (shadow_group_group(s, s->rev.ocent, bx->g.bcent, bx->cc, bx->dw, - nbx->g.bcent, nbx->cc, nbx->dw)) { + if (shadow_group_group(s, s->rev.ocent, bx->g.bcent, bx->cc, + bx->dw, nbx->g.bcent, nbx->cc, nbx->dw)) { nbx->wlist = bx->wlist; bx->wlist = nbx; //printf("~1 adding shadow nnrev[%d] from xlist\n",nbx->ix); @@ -9511,8 +10118,8 @@ rspl *s /* marked deleted ??) */ if ( // vx->status == vtx_norm && - shadow_group_vertex(s, s->rev.ocent, bx->g.bcent, bx->cc, bx->dw, - vx->v)) { + shadow_group_vertex(s, s->rev.ocent, bx->g.bcent, bx->cc, + bx->dw, vx->vl)) { add_vtxrec_list(&vc, vx, 0); /* Add if not deleted */ //printf(" Added ix %d from bx %d\n",vx->ix,nbx->ix); } @@ -9529,7 +10136,8 @@ rspl *s error("Failed to find vertex %s in cache",*rp); if (vx->status == vtx_norm && - shadow_group_vertex(s, s->rev.ocent, bx->g.bcent, bx->cc, bx->dw, vx->v)) { + shadow_group_vertex(s, s->rev.ocent, bx->g.bcent, bx->cc, + bx->dw, vx->vl)) { add_vtxrec_list(&vc, vx, 1); /* Add if not hidden/deleted */ } } @@ -9543,7 +10151,7 @@ rspl *s /* For vertexes of this bxcell and shadowers, */ /* in order from largst to smallest distance from center. */ for (vx = vc.vtxlist; vx != NULL; vx = vx->tlist) { - float *vp; /* Vertex being tested */ + float *fcb; /* Vertex being tested */ int fl; assdire *tri; /* Triangle table */ @@ -9556,8 +10164,8 @@ rspl *s //printf("~1 doing vertex %d at %s dist %f\n",vx->ix, debPdv(fdi,vx->v), sqrt(vx->dist)); - vp = s->g.a + vx->ix * s->g.pss; /* This vertex in fwd grid */ - fl = FLV(vp); /* Edge flags for this vertex */ + fcb = s->g.a + vx->ix * s->g.pss; /* This vertex in fwd grid */ + fl = FLV(fcb); /* Edge flags for this vertex */ tri = tridir + fl; //printf("~1 fl %d = 0o%o, no triangles %d\n",fl, fl, tri->no); @@ -9597,7 +10205,7 @@ rspl *s for (e = 0; e <= sdi; e++) { for (f = 0; f < fdi; f++) - v[e][f] = trivx[e]->v[f]; + v[e][f] = trivx[e]->vl[f]; } /* Compute shadow group params of triangle for quick vertex test */ @@ -9633,7 +10241,7 @@ rspl *s /* Do quick check against triangle */ if (!shadow_group_vertex(s, - s->rev.ocent, gc, cc, dw, nvx->v)) { + s->rev.ocent, gc, cc, dw, nvx->vl)) { //printf("~1 shadow group check shows no intersection\n"); continue; } @@ -9644,11 +10252,14 @@ rspl *s shdwd = wsrv = 0; /* Compute line delta */ - vp = s->g.a + nvx->ix * s->g.pss; - for (f = 0; f < fdi; f++) { - pv[f] = vp[f]; + fcb = s->g.a + nvx->ix * s->g.pss; + for (f = 0; f < fdi; f++) + pv[f] = fcb[f]; + + logcomp(s, pv, pv, s->rev.ocent); + + for (f = 0; f < fdi; f++) de[f] = pv[f] - s->rev.ocent[f]; - } /* Setup line cla and clb */ init_line_eq_imp(s, NULL, &cla, clb, s->rev.ocent, de, 0); @@ -9773,13 +10384,13 @@ rspl *s /* Check all of its neighbor vertexes, to see if */ /* it's safe to actually delete them. */ if (vx->status >= vtx_sha) { /* vertex to delete ? */ - float *vp; + float *fcb; int fl; assdire *edg; /* Edge table */ //printf("Checking vx %d neighbors\n",vx->ix); - vp = s->g.a + vx->ix * s->g.pss; /* This vertex in fwd grid */ - fl = FLV(vp); /* Edge flags for this vertex */ + fcb = s->g.a + vx->ix * s->g.pss; /* This vertex in fwd grid */ + fl = FLV(fcb); /* Edge flags for this vertex */ edg = edgdir + fl; /* For all possible edges that use this vertex */ @@ -9972,7 +10583,7 @@ rspl *s /* Struct to hold test vertex locations */ struct _tvxrec { - double v[MXRO]; + double v[MXRO]; /* Log output vertex value */ double dist; /* Distance from center point squared */ int ix[MXRO+1]; /* Indexes of the triangle verticies */ int shad; /* Test result */ @@ -10082,10 +10693,10 @@ rspl *s for (j = 0; j <= sdi; j++) { if (trivx[j]->status == vtx_norm) { for (f = 0; f < fdi; f++) - tvx->v[f] += 0.95/nntvsh * trivx[j]->v[f]; + tvx->v[f] += 0.95/nntvsh * trivx[j]->vl[f]; } else { for (f = 0; f < fdi; f++) - tvx->v[f] += 0.05/ntvsh * trivx[j]->v[f]; + tvx->v[f] += 0.05/ntvsh * trivx[j]->vl[f]; trivx[j]->cross = 1; /* For diagnostics */ } } @@ -10202,7 +10813,7 @@ rspl *s for (j = 0; j <= sdi; j++) { for (f = 0; f < fdi; f++) - v[j][f] = trivx[j]->v[f]; + v[j][f] = trivx[j]->vl[f]; } /* Compute shadow group params of triangle for quick vertex test */ @@ -10380,7 +10991,7 @@ rspl *s for (j = 0; j <= sdi; j++) { for (f = 0; f < fdi; f++) - v[j][f] = trivx[j]->v[f]; + v[j][f] = trivx[j]->vl[f]; } /* Compute shadow group params of triangle for quick vertex test */ @@ -10570,7 +11181,7 @@ rspl *s vtxrec *vx; if ((vx = get_vtxrec(&vc, *rp)) == NULL) - continue; /* Hmm. */ + continue; /* Hmm. Delete it.*/ /* Keep all the un-shadowed or preserved vertexes */ if (vx->status == vtx_norm @@ -10618,9 +11229,9 @@ rspl *s /* Add extra over ink limit vertexes. */ for (bx = s->rev.surflist; bx != NULL; bx = bx->slist) { int sdi = 1; /* sub-simplexes are edges */ - int *crp, *rp, *nrp; - int ttouch; + int *rp; vtxrec *vx, *nvx; + int *exlist = NULL; /* Add over ink limit vertexes, so that fwd cells will straddle */ /* the ink limit boundary. */ @@ -10630,8 +11241,8 @@ rspl *s /* over ink limit verticies.) */ if (s->limiten && vflag[bx->ix] & 0x10) { int *rp; -//printf("~1 ink limitin is enabled bx %d\n", bx->ix); +//printf("~1 ink limitin is enabled bx %d\n", bx->ix); for (rp = bx->sl+3; *rp != -1; rp++) { float *vp, *evp; int fl; @@ -10671,7 +11282,7 @@ rspl *s //printf(" Checking edge %d (%f) -> %d (%f)\n", vx->ix, vp[-1], eix, evp[-1]); - /* If over limit, add it to the list */ + /* If over limit, add it to the expansion list */ if (evp[-1] > s->limitv) { //printf("~1 added over ink limit vertex %d\n",eix); @@ -10679,10 +11290,18 @@ rspl *s continue; /* Added by another bx */ nvx = new_vtxrec(s, &vc, eix); nvx->status = vtx_oil; - add2indexlist(s, &bx->sl, eix, 0); + add2indexlist(s, &exlist, eix, 0); } } } + + /* If we found over ink limit verticies, add them to our list */ + if (exlist != NULL) { + for (rp = exlist+3; *rp != -1; rp++) { + add2indexlist(s, &bx->sl, *rp, 0); + } + free_indexlist(s, &exlist); + } } } @@ -10808,6 +11427,11 @@ rspl *s bx->status = bx_conv; } + if (s->rev.surflin != NULL) { /* Don't need surflin anymore */ + s->rev.surflin->del(s->rev.surflin); + s->rev.surflin = NULL; + s->rev.surflin_en = 0; + } if (cla != NULL) free_dmatrix(cla, 0, fdi-1, 0, fdi); free_trirec(s, &stc); @@ -11911,7 +12535,7 @@ int dofwlabels /* Plot fwd cell base indexs */ double grey[3] = { 0.5, 0.5, 0.5 }; double white[3] = { 1.0, 1.0, 1.0 }; - wrl = new_vrml("raw_bxfwcells", 0, vrml_lab); + wrl = new_vrml("raw_bxfwcells", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); wrl->add_marker(wrl, s->rev.ocent, NULL, 1.0); if (dofwlabels) { @@ -12080,7 +12704,7 @@ double xv[MXRO] /* Intersection point */ double blue[3] = { 0.1, 0.1, 0.8 }; double yellow[3] = { 0.8, 0.8, 0.1 }; - wrl = new_vrml("tri_check", 0, vrml_lab); + wrl = new_vrml("tri_check", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); /* Gamut center point marker */ wrl->add_marker(wrl, s->rev.ocent, NULL, 1.0); @@ -12166,6 +12790,8 @@ double xv[MXRO] /* Intersection point */ /* Main summary plot at each thinning round and at end. */ /* Show vertex surface & optional added or deleted vertexes, */ /* + optional bxcells. */ +#define VV vv /* Actual surface values */ +//#define VV vl /* Logf mapped surface values */ static void plot_vtx_surface( rspl *s, int dovtxlabels, /* Show vertex index numbers */ @@ -12193,9 +12819,9 @@ assdire *edgdir /* Edge lookup for vertex */ bxcell *vbx; if (dopres) - wrl = new_vrml("final_surface", 0, vrml_lab); + wrl = new_vrml("last_surface", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); else - wrl = new_vrml("thinned_surface", 0, vrml_lab); + wrl = new_vrml("thinned_surface", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); wrl->add_marker(wrl, s->rev.ocent, NULL, 1.0); if (dovtxlabels) { @@ -12209,7 +12835,7 @@ assdire *edgdir /* Edge lookup for vertex */ || (dopres && vx->pres) || (dooil && vx->status == vtx_oil)) { sprintf(index, "%d",vx->ix); - wrl->add_text(wrl, index, vx->v, cyan, 0.3); + wrl->add_text(wrl, index, vx->VV, cyan, 0.3); } } } @@ -12218,20 +12844,25 @@ assdire *edgdir /* Edge lookup for vertex */ /* Go through the vertex hash to set every vertex value */ for (i = 0; i < vc->hash_size; i++) { for (vx = vc->hash[i]; vx != NULL; vx = vx->hlink) { + double *col = NULL; if (vx->status != vtx_norm && vx->addvtx) error ("Found vertex that is both deleted and cause of added bxcell"); if (doadded && vx->addvtx) /* Cause of added bxcell */ - vx->vrmlix = wrl->add_col_vertex(wrl, 0, vx->v, green); + col = green; else if (dopres && vx->pres) /* Preserved vertex */ - vx->vrmlix = wrl->add_col_vertex(wrl, 0, vx->v, yellow); + col = yellow; else if (dodeleted && (vx->status == vtx_sha || vx->status == vtx_del)) - vx->vrmlix = wrl->add_col_vertex(wrl, 0, vx->v, red); + col = red; else if (dooil && vx->status == vtx_oil) - vx->vrmlix = wrl->add_col_vertex(wrl, 0, vx->v, blue); + col = blue; else if (vx->status == vtx_norm) - vx->vrmlix = wrl->add_col_vertex(wrl, 0, vx->v, white); + col = white; + + if (col != NULL) { + vx->vrmlix = wrl->add_col_vertex(wrl, 0, vx->VV, col); + } } } @@ -12304,26 +12935,26 @@ assdire *edgdir /* Edge lookup for vertex */ col = white; for (f = 0; f < fdi; f++) - vv[f] = vx->v[f] + off; + vv[f] = vx->VV[f] + off; lix[0] = wrl->add_vertex(wrl, 2, vv); for (f = 0; f < fdi; f++) - vv[f] = vx->v[f] - off; + vv[f] = vx->VV[f] - off; lix[1] = wrl->add_vertex(wrl, 2, vv); wrl->add_col_line(wrl, 2, lix, col); for (f = 0; f < fdi; f++) - vv[f] = vx->v[f] + ((f & 1) ? off : -off); + vv[f] = vx->VV[f] + ((f & 1) ? off : -off); lix[0] = wrl->add_vertex(wrl, 2, vv); for (f = 0; f < fdi; f++) - vv[f] = vx->v[f] - ((f & 1) ? off : -off); + vv[f] = vx->VV[f] - ((f & 1) ? off : -off); lix[1] = wrl->add_vertex(wrl, 2, vv); wrl->add_col_line(wrl, 2, lix, col); for (f = 0; f < fdi; f++) - vv[f] = vx->v[f] + ((f & 2) ? off : -off); + vv[f] = vx->VV[f] + ((f & 2) ? off : -off); lix[0] = wrl->add_vertex(wrl, 2, vv); for (f = 0; f < fdi; f++) - vv[f] = vx->v[f] - ((f & 2) ? off : -off); + vv[f] = vx->VV[f] - ((f & 2) ? off : -off); lix[1] = wrl->add_vertex(wrl, 2, vv); wrl->add_col_line(wrl, 2, lix, col); } @@ -12396,7 +13027,7 @@ int bxix /* Index of bx cell causing touches */ double white[3] = { 1.0, 1.0, 1.0 }; double red[3] = { 0.8, 0.1, 0.1 }; - wrl = new_vrml("add_touch_bxcells", 0, vrml_lab); + wrl = new_vrml("add_touch_bxcells", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); /* Gamut center point marker */ wrl->add_marker(wrl, s->rev.ocent, NULL, 1.0); @@ -12461,7 +13092,7 @@ int dowait /* Wait for a return key */ double grey[3] = { 0.5, 0.5, 0.5 }; double white[3] = { 1.0, 1.0, 1.0 }; - wrl = new_vrml("thinned_fwcells", 0, vrml_lab); + wrl = new_vrml("thinned_fwcells", 0, s->rev.probxyz ? vrml_xyz : vrml_lab); wrl->add_marker(wrl, s->rev.ocent, NULL, 1.0); if (dofclabels) { diff --git a/rspl/rev.h b/rspl/rev.h index 6fc79cb..80b9fa9 100644..100755 --- a/rspl/rev.h +++ b/rspl/rev.h @@ -62,10 +62,10 @@ * Reversing the Parameter -> Baricentric equations gives the * following interpolation equation using Parameter coordinates: * - * VV0 - VV1 * P0 - * + VV1 - VV2 * P1 - * + VV2 - VV3 * P2 - * + VV3 + * (VV0 - VV1) * P0 + * + (VV1 - VV2) * P1 + * + (VV2 - VV3) * P2 + * + VV3 * * Note that withing the simplex, 0 <= P0 && P0 <= P1 && P1 <= P2 && P2 <= 1 * @@ -270,6 +270,7 @@ struct _bxcell{ bxstat status; /* State of sl list */ int *sl; /* fwd vertex seed list for surface bxcells */ + /* or cell list after conversion to cells */ int *dl; /* deleted fwd vertex list for this bxcell */ int *scell; /* If non-NULL, this is a (non-surface) */ @@ -441,6 +442,8 @@ struct _rev_struct { /* All other sections depend on this. */ int fastsetup; /* Flag - NZ if fast setup at cost of slow throughput */ + int probxyz; /* Flag - NZ - guess if XYZ for VRML diagnostics use */ + int lchweighted; /* Non-zero if nearest search is LCh weighted */ double lchw[MXRO]; /* LCh nearest weighting */ double lchw_sq[MXRO]; /* LCh nearest weighting squared */ @@ -465,7 +468,7 @@ struct _rev_struct { int rev_valid; /* nz if this information in rev[] and nnrev[] is valid */ int **rev; /* Exact reverse lookup starting list. */ int **nnrev; /* Nearest reverse lookup starting list. */ - /* These lists are of fwd grid indexes. */ + /* These lists are of fwd grid base indexes. */ /* [0] is allocation length */ /* [1] is the next free entry index (length + 3, not counting -1) */ /* [2] is index into share lists, -1 if not shared. */ @@ -474,6 +477,10 @@ struct _rev_struct { double ocent[MXRO]; /* rev cell gamut "center" point for thinning and shadow testing. */ + int surflin_en; /* Flag set when suflin is enabled */ + struct _rspl *surflin; /* gamut surface linearization transform used by logcomp() */ + double linoff[MXRO]; /* ocent offset after surflin mapping */ + bxcell *surflist; /* Linked list of rev[] bwd cells that contain gamut surface fwd cells. */ /* Used to speed up fill_nncell() when rev.fastsetup is set, else NULL */ int surf_hash_size; /* Current size of bxcell hash list */ diff --git a/rspl/revbench.c b/rspl/revbench.c index f61ff2e..f61ff2e 100644..100755 --- a/rspl/revbench.c +++ b/rspl/revbench.c diff --git a/rspl/rspl.c b/rspl/rspl.c index db63a47..db63a47 100644..100755 --- a/rspl/rspl.c +++ b/rspl/rspl.c diff --git a/rspl/rspl.h b/rspl/rspl.h index 7d096f9..dc4e14d 100644..100755 --- a/rspl/rspl.h +++ b/rspl/rspl.h @@ -24,13 +24,15 @@ /** General Limits **/ -#define MXDI 10 /* Maximum input dimensionality */ -#define MXDO 10 /* Maximum output dimensionality (Is not fully tested!!!) */ -#define LOG2MXDI 4 /* log2 MXDI */ -#define DEF2MXDI 16 /* Default allocation size for 2^di (di=4) */ -#define POW2MXDI 1024 /* 2 ^ MXDI */ -#define DEF3MXDI 81 /* Default allocation size for 3^di (di=4) */ -#define POW3MXDI 59049 /* 3 ^ MXDI */ +#define MXDI 10 /* Maximum input dimensionality */ +#define MXDO 10 /* Maximum output dimensionality (Is not fully tested!!!) */ +#define LOG2MXDI 4 /* log2 MXDI */ +#define DEF2MXDI 16 /* Default allocation size for 2^di (di=4) */ +#define POW2MXDI 1024 /* 2 ^ MXDI */ +#define DEF3MXDI 81 /* Default allocation size for 3^di (di=4) */ +#define POW3MXDI 59049 /* 3 ^ MXDI */ +#define HACOMPS ((POW3MXDI + 2 * MXDI + 1)/2) /* Maximum number of array components */ + /* 295255 - not used ? */ #if MXDI > MXDO /* Maximum of either DI or DO */ # define MXDIDO MXDI @@ -38,14 +40,13 @@ # define MXDIDO MXDO #endif -/* RESTRICTED SIZE Limits, used for reverse, spline and scattered interpolation */ +/* RESTRICTED SIZE Limits, used for reverse and spline */ #define MXRI 4 /* Maximum input dimensionality */ #define MXRO 10 /* Maximum output dimensionality (Is not fully tested!!!) */ #define LOG2MXRI 2 /* log2 MXRI */ #define POW2MXRI 16 /* 2 ^ MXRI */ #define POW3MXRI 81 /* 3 ^ MXRI */ -#define HACOMPS ((POW3MXRI + 2 * MXRI + 1)/2) /* Maximum number of array components */ #define POW2MXRO 1024 /* 2 ^ MXRO */ #if MXRI > MXRO /* Maximum of either RI or RO */ @@ -93,9 +94,9 @@ typedef struct { /* Scattered data Per data point data (internal) */ struct _rpnts { - double p[MXRI]; /* Data position [di] */ - double v[MXRO]; /* Data value [fdi] */ - double k[MXRO]; /* Weight factor (nominally 1.0, less for lower confidence data point) */ + double p[MXDI]; /* Data position [di] */ + double v[MXDO]; /* Data value [fdi] */ + double k[MXDO]; /* Weight factor (nominally 1.0, less for lower confidence data point) */ // double fe; /* Fit error in output pass (ausm) */ }; typedef struct _rpnts rpnts; @@ -114,7 +115,7 @@ typedef struct { typedef struct { int niters; /* Number of multigrid itterations needed */ int **ires; /* Resolution for each itteration and dimension */ - void **mgtmps[MXRO]; /* Store pointers to re-usable mgtmp when incremental */ + void **mgtmps[MXDO]; /* Store pointers to re-usable mgtmp when incremental */ /* (These don't seem to be used anymore. was incremental removed ?) */ } it_info; @@ -260,7 +261,7 @@ struct _rspl { #define RSPL_VERBOSE 0x8000 /* Turn on print progress messages */ #define RSPL_NOVERBOSE 0x4000 /* Turn off print progress messages */ - /* Initialise from scattered data. RESTRICTED SIZE */ + /* Initialise from scattered data. */ /* Return non-zero if result is non-monotonic */ int (*fit_rspl)( @@ -282,7 +283,7 @@ struct _rspl { /* gres[] entries per dimension. Used to scale smoothness criteria */ ); - /* Initialise from scattered data, with per point weighting. RESTRICTED SIZE */ + /* Initialise from scattered data, with per point weighting. */ /* Return non-zero if result is non-monotonic */ int (*fit_rspl_w)( @@ -305,7 +306,7 @@ struct _rspl { ); /* Initialise from scattered data, with per point individual out weighting. */ - /* RESTRICTED SIZE Return non-zero if result is non-monotonic */ + /* Return non-zero if result is non-monotonic */ int (*fit_rspl_ww)( struct _rspl *s, /* this */ @@ -327,7 +328,6 @@ struct _rspl { ); /* Initialise from scattered data, with weak default function. */ - /* RESTRICTED SIZE */ /* Return non-zero if result is non-monotonic */ int (*fit_rspl_df)( @@ -353,7 +353,6 @@ struct _rspl { ); /* Initialise from scattered data, with per point weighting and weak default function. */ - /* RESTRICTED SIZE */ /* Return non-zero if result is non-monotonic */ int (*fit_rspl_w_df)( diff --git a/rspl/rspl1.c b/rspl/rspl1.c index 3996269..3996269 100644..100755 --- a/rspl/rspl1.c +++ b/rspl/rspl1.c diff --git a/rspl/rspl1.h b/rspl/rspl1.h index 63be428..63be428 100644..100755 --- a/rspl/rspl1.h +++ b/rspl/rspl1.h diff --git a/rspl/rspl_imp.h b/rspl/rspl_imp.h index 0cd8805..0cd8805 100644..100755 --- a/rspl/rspl_imp.h +++ b/rspl/rspl_imp.h diff --git a/rspl/scat.c b/rspl/scat.c index f94e074..87835ea 100644..100755 --- a/rspl/scat.c +++ b/rspl/scat.c @@ -221,20 +221,24 @@ struct _mgtmp { int bres, brix; /* Biggest resolution and its index */ double mres; /* Geometric mean res[] */ int no; /* Total number of points in grid = res ^ di */ - ratai l,h,w; /* Grid low, high, grid cell width */ + datai l,h,w; /* Grid low, high, grid cell width */ double *ipos[MXDI]; /* Optional relative grid cell position for each input dim cell */ /* Grid array offset lookups */ - int ci[MXRI]; /* Grid coordinate increments for each dimension */ - int hi[POW2MXRI]; /* Combination offset for sequence through cube. */ + int ci[MXDI]; /* Grid coordinate increments for each dimension */ + int hi[POW2MXDI]; /* Combination offset for sequence through cube. */ } g; - /* Data point grid dependent information */ + /* Data point grid dependent information - allocate for size of 2^di */ struct mgdat { int b; /* Index for associated base grid point, in grid points */ - double w[POW2MXRI]; /* Weight for surrounding gridpoints [2^di] */ + double w[0]; /* Weight for surrounding gridpoints [2^di] */ } *d; + int sizeof_mgdat; /* sizeof(mgdat) + sizeof(double) * (1<<di) */ + + /* Address of mgdat at index N from given mgtmp *M */ +#define MGDAT_N(M,N) ((struct mgdat *)(((char *)&(M)->d[0]) + (N) * (M)->sizeof_mgdat)) /* Equation Solution related (Grid point solutions) */ struct { @@ -245,8 +249,7 @@ struct _mgtmp { /* and +/-1 offset in all dimensions, but only the +ve offset */ /* half of the sparse matrix is stored, due to equations */ /* being symetrical. */ -#define XCOLPMAX (HACOMPS+8) - int xcol[XCOLPMAX]; /* A array column translation from packed to sparse index */ + int *xcol; /* A array column translation from packed to sparse index */ int *ixcol; /* A array column translation from sparse to packed index */ double *b; /* b vector for RHS of simultabeous equation b[g.no] */ double normb; /* normal of b vector */ @@ -408,11 +411,11 @@ fit_rspl_imp( void *d, /* Array holding position and function values of data points */ int dtp, /* Flag indicating data type, 0 = (co *), 1 = (cow *), 2 = (coww *) */ int dno, /* Number of data points */ - ratai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ - ratai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ + datai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ + datai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ int gres[MXDI], /* Spline grid resolution */ - ratao vlow, /* Data value low normalize, NULL = default 0.0 */ - ratao vhigh, /* Data value high normalize - NULL = default 1.0 */ + datao vlow, /* Data value low normalize, NULL = default 0.0 */ + datao vhigh, /* Data value high normalize - NULL = default 1.0 */ double smooth, /* Smoothing factor, 0.0 = default 1.0 */ /* (if -ve, overides optimised smoothing, and sets raw smoothing */ /* typically between 1e-7 .. 1e-1) */ @@ -430,12 +433,11 @@ fit_rspl_imp( int i, e, f; #ifdef NEVER -printf("~1 rspl: gres = %d %d %d %d, smooth = %f, avgdev = %f %f %f\n", -gres[0], gres[1], gres[2], gres[3], smooth, avgdev[0], avgdev[1], avgdev[2]); -printf("~1 rspl: glow = %f %f %f %f ghigh = %f %f %f %f\n", -glow[0], glow[1], glow[2], glow[3], ghigh[0], ghigh[1], ghigh[2], ghigh[3]); -printf("~1 rspl: vlow = %f %f %f vhigh = %f %f %f\n", -vlow[0], vlow[1], vlow[2], vhigh[0], vhigh[1], vhigh[2]); +printf("~1 rspl: di %d, fdi %d\n",fdi); +printf("~1 rspl: gres = %s, smooth = %f, avgdev = %s\n", +debPiv(di, gres),smooth, debPdv(fdi,avgdev)); +printf("~1 rspl: glow = %s ghigh = %s\n", debPdv(di,glow), debPdv(di,ghigh)); +printf("~1 rspl: vlow = %s vhigh = %s\n",debPdv(fdi,vlow), debPdv(fdi,vhigh)); printf("~1 rspl: flags = 0x%x\n",flags); #endif @@ -444,9 +446,9 @@ printf("~1 rspl: flags = 0x%x\n",flags); #endif /* This is a restricted size function */ - if (di > MXRI) + if (di > MXDI) error("rspl: fit can't handle di = %d",di); - if (fdi > MXRO) + if (fdi > MXDO) error("rspl: fit can't handle fdi = %d",fdi); /* set debug level */ @@ -528,8 +530,9 @@ printf("~1 rspl: flags = 0x%x\n",flags); for (i = 0; i < dno; i++) { for (e = 0; e < s->di; e++) { - if (dp[i].p[e] > s->g.h[e]) + if (dp[i].p[e] > s->g.h[e]) { s->g.h[e] = dp[i].p[e]; + } if (dp[i].p[e] < s->g.l[e]) s->g.l[e] = dp[i].p[e]; } @@ -882,11 +885,11 @@ fit_rspl( int flags, /* Combination of flags */ co *d, /* Array holding position and function values of data points */ int dno, /* Number of data points */ - ratai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ - ratai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ + datai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ + datai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ int gres[MXDI], /* Spline grid resolution */ - ratao vlow, /* Data value low normalize, NULL = default 0.0 */ - ratao vhigh, /* Data value high normalize - NULL = default 1.0 */ + datao vlow, /* Data value low normalize, NULL = default 0.0 */ + datao vhigh, /* Data value high normalize - NULL = default 1.0 */ double smooth, /* Smoothing factor, nominal = 1.0 */ double avgdev[MXDO], /* Average Deviation of function values as proportion of function range. */ @@ -906,11 +909,11 @@ fit_rspl_w( int flags, /* Combination of flags */ cow *d, /* Array holding position, function and weight values of data points */ int dno, /* Number of data points */ - ratai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ - ratai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ + datai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ + datai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ int gres[MXDI], /* Spline grid resolution */ - ratao vlow, /* Data value low normalize, NULL = default 0.0 */ - ratao vhigh, /* Data value high normalize - NULL = default 1.0 */ + datao vlow, /* Data value low normalize, NULL = default 0.0 */ + datao vhigh, /* Data value high normalize - NULL = default 1.0 */ double smooth, /* Smoothing factor, nominal = 1.0 */ double avgdev[MXDO], /* Average Deviation of function values as proportion of function range. */ @@ -930,11 +933,11 @@ fit_rspl_ww( int flags, /* Combination of flags */ coww *d, /* Array holding position, function and weight values of data points */ int dno, /* Number of data points */ - ratai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ - ratai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ + datai glow, /* Grid low scale - will be expanded to enclose data, NULL = default 0.0 */ + datai ghigh, /* Grid high scale - will be expanded to enclose data, NULL = default 1.0 */ int gres[MXDI], /* Spline grid resolution */ - ratao vlow, /* Data value low normalize, NULL = default 0.0 */ - ratao vhigh, /* Data value high normalize - NULL = default 1.0 */ + datao vlow, /* Data value low normalize, NULL = default 0.0 */ + datao vhigh, /* Data value high normalize - NULL = default 1.0 */ double smooth, /* Smoothing factor, nominal = 1.0 */ double avgdev[MXDO], /* Average Deviation of function values as proportion of function range. */ @@ -1530,15 +1533,17 @@ static mgtmp *new_mgtmp( #endif /* Allocate space for auiliary data point related info */ - if ((m->d = (struct mgdat *) calloc(dno, sizeof(struct mgdat))) == NULL) + m->sizeof_mgdat = sizeof(struct mgdat) + sizeof(double) * (1 << di); + if ((m->d = (struct mgdat *) calloc(dno, m->sizeof_mgdat)) == NULL) error("rspl: malloc failed - mgtmp"); /* fill in the aux data point info */ /* (We're assuming N-linear interpolation here. */ /* Perhaps we should try simplex too ?) */ for (n = 0; n < dno; n++) { - double we[MXRI]; /* 1.0 - Weight in each dimension */ + double we[MXDI]; /* 1.0 - Weight in each dimension */ int ix = 0; /* Index to base corner of surrounding cube in grid points */ + struct mgdat *dd; /* Figure out which grid cell the point falls into */ for (e = 0; e < di; e++) { @@ -1557,21 +1562,22 @@ static mgtmp *new_mgtmp( ix += mi * m->g.ci[e]; /* Add Index offset for grid cube base in dimen */ we[e] = t - (double)mi; /* 1.0 - weight */ } - m->d[n].b = ix; + dd = MGDAT_N(m, n); + dd->b = ix; /* Compute corner weights needed for interpolation */ - m->d[n].w[0] = 1.0; + dd->w[0] = 1.0; for (e = 0, g = 1; e < di; g *= 2, e++) { for (i = 0; i < g; i++) { - m->d[n].w[g+i] = m->d[n].w[i] * we[e]; - m->d[n].w[i] *= (1.0 - we[e]); + dd->w[g+i] = dd->w[i] * we[e]; + dd->w[i] *= (1.0 - we[e]); } } #ifdef DEBUG printf("Data point %d weighting factors = \n",n); for (e = 0; e < (1 << di); e++) { - printf("%d: %f\n",e,m->d[n].w[e]); + printf("%d: %f\n",e,dd->w[e]); } #endif /* DEBUG */ @@ -1588,6 +1594,7 @@ static mgtmp *new_mgtmp( /* Set the solution matricies to unalocated */ m->q.A = NULL; + m->q.xcol = NULL; m->q.ixcol = NULL; m->q.b = NULL; m->q.x = NULL; @@ -1620,6 +1627,7 @@ static void free_mgtmp(mgtmp *m) { } free_dvector(m->q.x,0,gno-1); free_dvector(m->q.b,0,gno-1); + free((void *)m->q.xcol); free((void *)m->q.ixcol); free_dmatrix(m->q.A,0,gno-1,0,m->q.acols-1); free((void *)m->d); @@ -1770,8 +1778,24 @@ mgtmp *sm /* Optional smoothing map for ausm mode */ DCOUNT(gc, MXDIDO, di, -2, -2, 3); /* Step through +/- 2 cube offset */ #endif int ix; /* Grid point offset in grid points */ + int xcolpmax; acols = 0; + /* Allocate xcol[] */ + if (xcol == NULL) { + /* Comput used dimensions XCOLPMAX, */ + /* = number of array components, */ + /* = HACOMPS + 8 */ + xcolpmax = 1; + for (k = 0; k < di; k++) + xcolpmax *= 3; + xcolpmax += 2 * di + 1; + xcolpmax /= 2; + xcolpmax += 8; + if ((xcol = (int *) malloc(xcolpmax * sizeof(int))) == NULL) + error("rspl malloc failed - xcol"); + } + DC_INIT(gc); while (!DC_DONE(gc)) { @@ -1796,7 +1820,7 @@ mgtmp *sm /* Optional smoothing map for ausm mode */ for (ix = 0, k = 0; k < di; k++) ix += gc[k] * gci[k]; /* Multi-dimension grid offset */ if (ix >= 0) { - if (acols >= XCOLPMAX) + if (acols >= xcolpmax) error("rspl internal: exceeded xcol bounds"); xcol[acols++] = ix; /* We only store half, due to symetry */ } @@ -1849,6 +1873,7 @@ mgtmp *sm /* Optional smoothing map for ausm mode */ m->q.b = b; m->q.x = x; m->q.acols = acols; + m->q.xcol = xcol; m->q.ixcol = ixcol; } else { /* re-initializing, zero matrices */ @@ -2264,7 +2289,8 @@ mgtmp *sm /* Optional smoothing map for ausm mode */ /* Accumulate data point dependent factors */ for (n = 0; n < dno; n++) { /* Go through all the data points */ int j,k; - int bp = m->d[n].b; /* index to base grid point in grid points */ + struct mgdat *dd = MGDAT_N(m, n); + int bp = dd->b; /* index to base grid point in grid points */ /* For each point in the cube as the base grid point, */ /* add in the appropriate weighting for its weighted neighbors. */ @@ -2274,7 +2300,7 @@ mgtmp *sm /* Optional smoothing map for ausm mode */ ai = bp + m->g.hi[j]; /* A matrix index */ - w = m->d[n].w[j]; /* Base point grid weight */ + w = dd->w[j]; /* Base point grid weight */ d = 2.0 * s->d.a[n].k[f] * w; /* (2.0, w are derivtv factors, k data pnt wgt) */ tt = d * s->d.a[n].v[f]; /* Change in data component */ @@ -2287,7 +2313,7 @@ mgtmp *sm /* Optional smoothing map for ausm mode */ for (k = j+1; k < (1 << di); k++) { /* Binary sequence */ int ii; ii = ixcol[m->g.hi[k] - m->g.hi[j]]; /* A matrix column index */ - A[ai][ii] += d * m->d[n].w[k]; /* dui component due to ui+1 */ + A[ai][ii] += d * dd->w[k]; /* dui component due to ui+1 */ } } } @@ -2337,14 +2363,15 @@ static void comp_fit_errors( /* Compute error for each data point */ for (n = 0; n < dno; n++) { int j; - int bp = m->d[n].b; /* index to base grid point in grid points */ + struct mgdat *dd = MGDAT_N(m, n); + int bp = dd->b; /* index to base grid point in grid points */ double val; /* Current interpolated value */ double err; double gain = 1.0; /* Compute the interpolated grid value for this data point */ for (val = 0.0, j = 0; j < (1 << di); j++) /* Binary sequence */ - val += m->d[n].w[j] * x[bp + m->g.hi[j]]; + val += dd->w[j] * x[bp + m->g.hi[j]]; err = s->d.a[n].v[f] - val; err *= 0.8; @@ -2367,8 +2394,8 @@ static double mgtmp_interp( rspl *s = m->s; int di = s->di; int e, n; - double we[MXRI]; /* 1.0 - Weight in each dimension */ - double gw[POW2MXRI]; /* weight for each grid cube corner */ + double we[MXDI]; /* 1.0 - Weight in each dimension */ + double gw[POW2MXDI]; /* weight for each grid cube corner */ double *gp; /* Pointer to x2[] grid cube base */ double val; @@ -2428,7 +2455,7 @@ static void init_soln( /* For all output grid points */ EC_INIT(gc); for (n = 0; n < gno; n++) { - double p[MXRI]; /* Grid relative location */ + double p[MXDI]; /* Grid relative location */ for (e = 0; e < di; e++) p[e] = (double)gc[e]/(m1->g.res[e] - 1.0); @@ -2645,7 +2672,7 @@ one_itter1( /* For each dimension */ for (d = 0; d < di; d++) { int ld = d == 0 ? 1 : 0; /* lowest dim */ - int sof, gc[MXRI]; + int sof, gc[MXDI]; //printf("~1 doing one_itter1 for dim %d\n",d); for (e = 0; e < di; e++) @@ -2713,7 +2740,7 @@ one_itter2( double ovsh /* Overshoot to use, 1.0 for none */ ) { int e,i,k; - int gc[MXRI]; + int gc[MXDI]; for (i = e = 0; e < di; e++) gc[e] = 0; /* init coords */ diff --git a/rspl/scat2.c b/rspl/scat2.c index 7579366..7579366 100644..100755 --- a/rspl/scat2.c +++ b/rspl/scat2.c diff --git a/rspl/sm1.c b/rspl/sm1.c index 5bcf26e..5bcf26e 100644..100755 --- a/rspl/sm1.c +++ b/rspl/sm1.c diff --git a/rspl/sm2.c b/rspl/sm2.c index 84bc8cf..84bc8cf 100644..100755 --- a/rspl/sm2.c +++ b/rspl/sm2.c diff --git a/rspl/sm3.c b/rspl/sm3.c index 9307787..9307787 100644..100755 --- a/rspl/sm3.c +++ b/rspl/sm3.c diff --git a/rspl/smtmpp.c b/rspl/smtmpp.c index 1264d4b..1264d4b 100644..100755 --- a/rspl/smtmpp.c +++ b/rspl/smtmpp.c diff --git a/rspl/smtnd.c b/rspl/smtnd.c index f105429..355d20b 100644..100755 --- a/rspl/smtnd.c +++ b/rspl/smtnd.c @@ -1031,7 +1031,7 @@ static void do_test( if (verb) printf("Measured noise average deviation = %f%%\n",tnoise * 100.0); /* Fit to scattered data */ - if (verb) printf("Fitting the scattered data, smooth = %f, avgdev = %f\n",smooth,avgdev != NULL ? avgdev[0] : 0.0); + if (verb) printf("Fitting the scattered data, smooth = %f, avgdev = %f\n",smooth, avgdev[0]); avgdev[0] = 0.25 * noise; rss->fit_rspl(rss, flags, /* Non-mon and clip flags */ diff --git a/rspl/spline.c b/rspl/spline.c index dabeb0f..dabeb0f 100644..100755 --- a/rspl/spline.c +++ b/rspl/spline.c diff --git a/rspl/stest.c b/rspl/stest.c index d1cf2da..d1cf2da 100644..100755 --- a/rspl/stest.c +++ b/rspl/stest.c diff --git a/rspl/t2d.c b/rspl/t2d.c index e3f304c..e3f304c 100644..100755 --- a/rspl/t2d.c +++ b/rspl/t2d.c diff --git a/rspl/t2ddf.c b/rspl/t2ddf.c index 115d5f5..115d5f5 100644..100755 --- a/rspl/t2ddf.c +++ b/rspl/t2ddf.c diff --git a/rspl/t3d.c b/rspl/t3d.c index c526669..c526669 100644..100755 --- a/rspl/t3d.c +++ b/rspl/t3d.c diff --git a/rspl/t3ddf.c b/rspl/t3ddf.c index 4a43f0d..4a43f0d 100644..100755 --- a/rspl/t3ddf.c +++ b/rspl/t3ddf.c diff --git a/rspl/tnd.c b/rspl/tnd.c index 89718d9..89718d9 100644..100755 --- a/rspl/tnd.c +++ b/rspl/tnd.c diff --git a/rspl/trnd.c b/rspl/trnd.c index 2676182..2676182 100644..100755 --- a/rspl/trnd.c +++ b/rspl/trnd.c |