228 lines
5.8 KiB
C
228 lines
5.8 KiB
C
|
|
/*
|
|
* Argyll Color Management System
|
|
* Multi-dimensional multilevel spline data fitter
|
|
* mlbs base version.
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 2000/11/10
|
|
*
|
|
* Copyright 1996 - 2000 Graeme W. Gill
|
|
* All rights reserved.
|
|
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
|
|
* see the License.txt file for licencing details.
|
|
*/
|
|
|
|
/* This file contains the scattered data solution specific code */
|
|
|
|
/* TTBD:
|
|
*
|
|
* mlbs code doesn't work. Results are rubbish.
|
|
*
|
|
* Fix bugs ?
|
|
* merge stest.c into this file.
|
|
*
|
|
* Get rid of error() calls - return status instead
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include "rspl_imp.h"
|
|
#include "numlib.h"
|
|
#include "mlbs.h"
|
|
|
|
extern void error(char *fmt, ...), warning(char *fmt, ...);
|
|
|
|
#undef DEBUG
|
|
|
|
#undef NEVER
|
|
#define ALWAYS
|
|
|
|
/* Implemented in rspl.c: */
|
|
extern void alloc_grid(rspl *s);
|
|
|
|
extern int is_mono(rspl *s);
|
|
|
|
/* ============================================ */
|
|
void set_from_mlbs(void *cbctx, double *out, double *in) {
|
|
mlbs *p = (mlbs *)cbctx;
|
|
co tp;
|
|
int i;
|
|
|
|
for (i = 0; i < p->di; i++)
|
|
tp.p[i] = in[i];
|
|
|
|
if (p->lookup(p, &tp))
|
|
error("Internal, set_from_mlbs failed!");
|
|
|
|
for (i = 0; i < p->di; i++)
|
|
out[i] = tp.v[i];
|
|
}
|
|
|
|
/* Initialise the regular spline from scattered data */
|
|
/* Return non-zero if non-monotonic */
|
|
static int
|
|
fit_rspl_imp(
|
|
rspl *s, /* this */
|
|
int flags, /* Combination of flags */
|
|
void *d, /* Array holding position and function values of data points */
|
|
int dtp, /* Flag indicating data type, 0 = (co *), 1 = (cow *) */
|
|
int dno, /* Number of data points */
|
|
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, /* Spline grid resolution */
|
|
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 */
|
|
) {
|
|
int di = s->di, fdi = s->fdi;
|
|
int i, n, e, f;
|
|
int rv;
|
|
int nigc;
|
|
int bres;
|
|
mlbs *p;
|
|
|
|
/* set debug level */
|
|
s->debug = (flags >> 24);
|
|
|
|
/* Init other flags */
|
|
if (flags & RSPL_NONMON) /* Enable elimination of non-monoticities */
|
|
s->nm = 1;
|
|
else
|
|
s->nm = 0;
|
|
|
|
if (flags & RSPL_VERBOSE) /* Turn on progress messages to stdout */
|
|
s->verbose = 1;
|
|
else
|
|
s->verbose = 0;
|
|
|
|
/* Save smoothing factor */
|
|
s->smooth = smooth;
|
|
|
|
/* Stash the data points away */
|
|
s->d.no = dno; /* Number of data points */
|
|
|
|
/* Allocate the scattered data space */
|
|
if ((s->d.a = (dpnts *) malloc(sizeof(dpnts) * s->d.no)) == NULL)
|
|
error("rspl malloc failed - data points");
|
|
|
|
if (dtp == 0) { /* Default weight */
|
|
co *dp = (co *)d;
|
|
|
|
/* Copy the list into data points */
|
|
for (n = 0; n < s->d.no; n++) {
|
|
for (e = 0; e < s->di; e++)
|
|
s->d.a[n].p[e] = dp[n].p[e];
|
|
for (f = 0; f < s->fdi; f++)
|
|
s->d.a[n].v[f] = dp[n].v[f];
|
|
s->d.a[n].k = 1.0; /* Assume all data points have same weight */
|
|
}
|
|
} else { /* Per data point weight */
|
|
cow *dp = (cow *)d;
|
|
|
|
/* Copy the list into data points */
|
|
for (n = 0; n < s->d.no; n++) {
|
|
for (e = 0; e < s->di; e++)
|
|
s->d.a[n].p[e] = dp[n].p[e];
|
|
for (f = 0; f < s->fdi; f++)
|
|
s->d.a[n].v[f] = dp[n].v[f];
|
|
s->d.a[n].k = dp[n].w; /* Weight specified */
|
|
}
|
|
}
|
|
|
|
/* Compute target B-Spline resolution */
|
|
/* Make it worst case half the target rspl resolution */
|
|
for (bres = 2; (2 * bres) < gres; bres = 2 * bres -1)
|
|
;
|
|
|
|
/* Create multilevel B-Spline fit */
|
|
p = new_mlbs(di, fdi, bres, s->d.a, s->d.no, glow, ghigh, smooth);
|
|
if (p == NULL)
|
|
error("new_mlbs() failed");
|
|
|
|
/* Create rspl grid points by looking up the B-Spline values */
|
|
rv = s->set_rspl(s, 0, (void *)p, set_from_mlbs, glow, ghigh, gres, vlow, vhigh);
|
|
|
|
/* Don't need B-Spline any more */
|
|
p->del(p);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* Initialise the regular spline from scattered data */
|
|
/* Return non-zero if non-monotonic */
|
|
int
|
|
fit_rspl(
|
|
rspl *s, /* this */
|
|
int flags, /* Combination of flags */
|
|
co *d, /* Array holding position and function values of data points */
|
|
int dno, /* Number of data points */
|
|
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, /* Spline grid resolution */
|
|
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 */
|
|
) {
|
|
/* Call implementation with (co *) data */
|
|
return fit_rspl_imp(s, flags, (void *)d, 0, dno, glow, ghigh, gres, vlow, vhigh, smooth);
|
|
}
|
|
|
|
/* Initialise the regular spline from scattered data with weights */
|
|
/* Return non-zero if non-monotonic */
|
|
int
|
|
fit_rspl_w(
|
|
rspl *s, /* this */
|
|
int flags, /* Combination of flags */
|
|
cow *d, /* Array holding position, function and weight values of data points */
|
|
int dno, /* Number of data points */
|
|
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, /* Spline grid resolution */
|
|
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 */
|
|
) {
|
|
/* Call implementation with (cow *) data */
|
|
return fit_rspl_imp(s, flags, (void *)d, 1, dno, glow, ghigh, gres, vlow, vhigh, smooth);
|
|
}
|
|
|
|
/* Init scattered data elements in rspl */
|
|
void
|
|
init_data(rspl *s) {
|
|
s->d.no = 0;
|
|
s->d.a = NULL;
|
|
s->fit_rspl = fit_rspl;
|
|
s->fit_rspl_w = fit_rspl_w;
|
|
}
|
|
|
|
/* Free the scattered data allocation */
|
|
void
|
|
free_data(rspl *s) {
|
|
if (s->d.a != NULL) {
|
|
free((void *)s->d.a);
|
|
s->d.a = NULL;
|
|
}
|
|
}
|
|
|
|
/* ============================================ */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|