1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/* Copyright (c) 2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
#include <math.h>
/* Problem: find a function f : p -> q (where p is user's curve control
parameter, q is log factor) such that the curves will bend in
a semi-linear way over the p's range of 0..1. The curve function is
then g(x, p) = (exp(f(p) * x) - 1) / (exp(f(p)) - 1), where x is
curve's domain. If, for example, the points g(0.5, p) are to make
a semi-linear pattern, then the solution is a function f that minimizes
the integral of the error function e(p) = sqr(((1-p)/2)-g(.5, p))
over 0..1. Until someone does this analytically, we are left with
a lame formula, which has been tweaked and tested in gnuplot:
f(p) = h(p) / (1 - h(p)), where h(p) = (((p + 1e-20) * 1.2) ** .41) * .91.
The file curve.gp, in the sickle's source directory, may come handy,
in case there is anyone, who fancy tweaking it even further.
To implement this, start from these equations:
nhops = npoints - 1
bb * mm ^ nhops = bb + 1
(bb ^ 2) * (mm ^ nhops) = ((exp(ff/2) - 1) / (exp(ff) - 1)) ^ 2
and calculate:
hh = pow(((p + c1) * c2), c3) * c4
ff = hh / (1 - hh)
eff = exp(ff) - 1
gh = (exp(ff * .5) - 1) / eff
bb = gh * (gh / (1 - (gh + gh)))
mm = ((exp(ff * (1/nhops)) - 1) / (eff * bb)) + 1
The loop is:
for (vv = bb, i = 0; i <= nhops; vv *= mm, i++)
result = (vv - bb) * (y1 - y0) + y0
where y0, y1 are start and destination values
This formula generates curves with < .000004% deviation from the straight
line for p = 0 at half-domain, range 1. There are no nans for -1 <= p <= 1.
*/
#define CLCCURVE_C1 1e-20
#define CLCCURVE_C2 1.2
#define CLCCURVE_C3 0.41
#define CLCCURVE_C4 0.91
void clccurve_coefs(int nhops, double crv, double *bbp, double *mmp)
{
if (nhops > 0)
{
double hh, ff, eff, gh;
if (crv < 0)
{
if (crv < -1.)
crv = -1.;
hh = pow(((CLCCURVE_C1 - crv) * CLCCURVE_C2), CLCCURVE_C3)
* CLCCURVE_C4;
ff = hh / (1. - hh);
eff = exp(ff) - 1.;
gh = (exp(ff * .5) - 1.) / eff;
*bbp = gh * (gh / (1. - (gh + gh)));
*mmp = 1. / (((exp(ff * (1. / (double)nhops)) - 1.) /
(eff * *bbp)) + 1.);
*bbp += 1.;
}
else
{
if (crv > 1.)
crv = 1.;
hh = pow(((crv + CLCCURVE_C1) * CLCCURVE_C2), CLCCURVE_C3)
* CLCCURVE_C4;
ff = hh / (1. - hh);
eff = exp(ff) - 1.;
gh = (exp(ff * .5) - 1.) / eff;
*bbp = gh * (gh / (1. - (gh + gh)));
*mmp = ((exp(ff * (1. / (double)nhops)) - 1.) /
(eff * *bbp)) + 1.;
}
}
else if (crv < 0)
*bbp = 2., *mmp = 1.;
else
*bbp = *mmp = 1.;
}
|