view release on metacpan or search on metacpan
- modified 'Curve_test.plx' to test 'akima' based curves.
2012-04-13
- added snippet 'linear_least_squares.txt'.
- modified subroutine '_endslope' of 'akima.pm' to fit a quadratic equation using least squares, instead of linear equation.
2012-04-14
- modified '_endslope' to use weighted cubic function, and renamed '_endpoint'.
- modified '_objderv' to compute endpoint slopes and derivatives using standard Akima method, then call '_endpoint' to overwrite the endpoint derivatives.
- added several tests to 'akima_test.plx'.
- added '_parametric' method to 'akima.pm', prints error message if called.
- modified 'array' method of 'akima.pm' to get/save an array containing x-values, y-values and derivatives.
2012-04-15
- modified 'new' method of 'akima.pm' by adding optional endpoint flag parameter.
- modified '_objderv' to use endpoint flag.
- modified the '_makeCWF' subroutine of 'Chart.pm' to use 'akima.pm' objects, instead of 'Math::Akima' objects.
- added 'normalize' method to 'akima.pm'.
- modified 'add_set' method of 'Chart.pm' to handle '[]' as a column slice.
- added 'press_curve_8_example.plx' to generate TVI curves.
2012-04-16
lib/ICC/Javascripts/rgraph/RGraph.common.core.js view on Meta::CPAN
return ret;
};
/**
* This function gets the end point (X/Y coordinates) of a given radius.
* You pass it the center X/Y and the radius and this function will return
* the endpoint X/Y coordinates.
*
* @param number cx The center X coord
* @param number cy The center Y coord
* @param number r The lrngth of the radius
*/
RG.getRadiusEndPoint = function (cx, cy, angle, radius)
{
var x = cx + (ma.cos(angle) * radius);
var y = cy + (ma.sin(angle) * radius);
lib/ICC/Javascripts/rgraph/RGraph.pie.js view on Meta::CPAN
/**
* Coords for the text
*/
var x = cx + explosion_offsetx + ((r + 10)* Math.cos(a)) + (prop['chart.labels.sticks'] ? (a < RG.HALFPI || a > (RG.TWOPI + RG.HALFPI) ? 2 : -2) : 0),
y = cy + explosion_offsety + (((r + 10) * Math.sin(a)));
/**
* If sticks are enabled use the endpoints that have been saved
*/
if (this.coordsSticks && this.coordsSticks[i]) {
var x = this.coordsSticks[i][4][0] + (x < cx ? -5 : 5),
y = this.coordsSticks[i][4][1];
}
/**
* Alignment
*/
lib/ICC/Javascripts/rgraph/RGraph.pie.js view on Meta::CPAN
//
// Draw the right hand side labels first
//
for (var i=0; i<this.angles.length; ++i) {
var angle = this.angles[i][0] + ((this.angles[i][1] - this.angles[i][0]) / 2), // Midpoint
endpoint_inner = RG.getRadiusEndPoint(centerx, centery, angle, radius + 5),
endpoint_outer = RG.getRadiusEndPoint(centerx, centery, angle, radius + 10),
explosion = [
(typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i]),
(ma.cos(angle) * (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i])),
(ma.sin(angle) * (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i]))
]
//
// Work out the color
//
lib/ICC/Javascripts/rgraph/RGraph.pie.js view on Meta::CPAN
}
if (angle > (-1 * RG.HALFPI) && angle < RG.HALFPI) {
labels_right.push([
i,
angle,
labels[i] ? labels[i] : '',
endpoint_inner,
endpoint_outer,
color,
RG.arrayClone(explosion)
]);
} else {
labels_left.push([
i,
angle,
labels[i] ? labels[i] : '',
endpoint_inner,
endpoint_outer,
color,
RG.arrayClone(explosion)
]);
}
}
//
lib/ICC/Javascripts/rgraph/RGraph.svg.common.core.js view on Meta::CPAN
/**
* This function gets the end point (X/Y coordinates) of a given radius.
* You pass it the center X/Y and the radius and this function will return
* the endpoint X/Y coordinates.
*
* @param number cx The center X coord
* @param number cy The center Y coord
* @param number r The length of the radius
* @param number angle The anle to use
*/
RG.SVG.TRIG.getRadiusEndPoint = function (opt)
{
// Allow for two arguments style
if (arguments.length === 1) {
lib/ICC/Javascripts/rgraph/RGraph.svg.pie.js view on Meta::CPAN
// Draw the labels
//
this.drawLabels = function ()
{
var angles = this.angles,
prop = this.properties,
labels = prop.labels;
for (var i=0; i<angles.length; ++i) {
var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
angle: angles[i].halfway - RG.SVG.TRIG.HALFPI,
r: angles[i].radius + 15
});
var x = endpoint[0] + angles[i].cx,
y = endpoint[1] + angles[i].cy,
valign,
halign;
// Figure out the valign and halign based on the quadrant
// the the center of the sgement is in.
if (angles[i].halfway > 0 && angles[i].halfway < RG.SVG.TRIG.HALFPI) {
halign = 'left';
valign = 'bottom';
} else if (angles[i].halfway > RG.SVG.TRIG.HALFPI && angles[i].halfway < RG.SVG.TRIG.PI) {
halign = 'left';
lib/ICC/Javascripts/rgraph/RGraph.svg.pie.js view on Meta::CPAN
this.drawLabelsSticks = function ()
{
var labels_right = [],
labels_left = [],
labels_coords = [];
for (var i=0; i<this.angles.length; ++i) {
var angle = (this.angles[i].start + ((this.angles[i].end - this.angles[i].start) / 2)) - RGraph.SVG.TRIG.HALFPI, // Midpoint
endpoint_inner = RG.SVG.TRIG.getRadiusEndPoint({angle: angle, r: this.radius + 5}),
endpoint_outer = RG.SVG.TRIG.getRadiusEndPoint({angle: angle, r: this.radius + 20}),
explosion = [
(typeof prop.exploded === 'number' ? prop.exploded : prop.exploded[i]),
ma.cos(angle) * (typeof prop.exploded === 'number' ? prop.exploded : prop.exploded[i]),
ma.sin(angle) * (typeof prop.exploded === 'number' ? prop.exploded : prop.exploded[i])
];
// Initialise this array
labels_coords[i] = [];
lib/ICC/Javascripts/rgraph/RGraph.svg.pie.js view on Meta::CPAN
labels_coords[i].halign = 'left';
}
endpoint_inner[0] += (explosion[1] || 0);
endpoint_inner[1] += (explosion[2] || 0);
endpoint_outer[0] += (explosion[1] || 0);
endpoint_outer[1] += (explosion[2] || 0);
var x,y;
if (labels[index].text) {
var stick = RG.SVG.create({
svg: this.svg,
parent: this.svg.all,
type: 'path',
attr: {
d: 'M {1} {2} L {3} {4}'.format(
this.centerx + endpoint_inner[0],
this.centery + endpoint_inner[1],
this.centerx + endpoint_outer[0],
this.centery + endpoint_outer[1]
),
stroke: '#999',
fill: 'rgba(0,0,0,0)'
}
});
}
// The path is altered later so this needs saving
if (stick) {
labels[index].stick = stick;
}
x = (this.centerx + endpoint_outer[0] + (angle > 1.57 ? -50 : 50));
y = (this.centery + endpoint_outer[1]);
labels_coords[i].x = x ;
labels_coords[i].y = y;
labels_coords[i].text = prop.labels[i];
}
// Calculate the spacing for each side
var vspace_right = (this.height - prop.gutterTop - prop.gutterBottom) / labels_right.length;
var vspace_left = (this.height - prop.gutterTop - prop.gutterBottom) / labels_left.length;
lib/ICC/Javascripts/rgraph/RGraph.svg.radar.js view on Meta::CPAN
var angles = this.angles2,
prop = this.properties,
labels = prop.labels;
for (var i=0,len=labels.length; i<len; ++i) {
if (!labels[i]) {
continue;
}
var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
angle: RG.SVG.TRIG.TWOPI / labels.length * i - RG.SVG.TRIG.HALFPI,
r: this.radius + 15
});
var x = endpoint[0] + this.centerx,
y = endpoint[1] + this.centery;
//
// Horizontal alignment
if ((i / len) < 0.5) {
halign = 'left';
} else {
halign = 'right';
}
lib/ICC/Javascripts/rgraph/RGraph.svg.rose.js view on Meta::CPAN
// Draw the circular labels if necessary
for (var i=0; i<prop.labels.length; ++i) {
if (prop.variant === 'non-equi-angular') {
var angle = ((this.angles2[i][0].end - this.angles2[i][0].start) / 2) + this.angles2[i][0].start - RG.SVG.TRIG.HALFPI;
} else {
var angle = (((RG.SVG.TRIG.TWOPI / prop.labels.length)) * i) - RG.SVG.TRIG.HALFPI + prop.labelsAngleOffset + (RG.SVG.TRIG.TWOPI / (2 * prop.labels.length));
}
var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
r: this.radius + prop.labelsRadialMargin,
angle: angle
});
// Accommodate the explosion for the label
var explosion = this.getExploded({
index: i,
start: this.angles2[i][0].start - RG.SVG.TRIG.HALFPI,
end: this.angles2[i][0].end - RG.SVG.TRIG.HALFPI
});
endpoint[0] += this.centerx + explosion[0];
endpoint[1] += this.centery + explosion[1];
// Do the alignment based on which quadrant the label is in
if (ma.round(endpoint[0]) > this.centerx) {
halign = 'left';
} else if (ma.round(endpoint[0]) === this.centerx) {
halign = 'center';
} else {
halign = 'right';
}
RG.SVG.text({
object: this,
svg: this.svg,
parent: this.svg.all,
tag: 'labels',
text: typeof prop.labels[i] === 'string' ? prop.labels[i] : '',
size: prop.labelsSize,
x: endpoint[0],
y: endpoint[1],
halign: halign,
valign: 'center',
background: 'rgba(255,255,255,0.7)',
padding:2,
color: prop.labelsColor || prop.textColor,
bold: typeof prop.labelsBold === 'boolean' ? prop.labelsBold : prop.textBold,
italic: typeof prop.labelsItalic === 'boolean' ? prop.labelsItalic : prop.textItalic,
font: prop.labelsFont || prop.textFont
});
}
lib/ICC/Shared.pm view on Meta::CPAN
# for each row
for my $i (1 .. $ix - 1) {
# set diagonal values
$rhs->[$i - 1][$i] = 3;
$rhs->[$i + 1][$i] = -3;
}
# set endpoint values
$rhs->[0][0] = -3;
$rhs->[1][0] = -3;
$rhs->[$ix][$ix] = 3;
$rhs->[$ix - 1][$ix] = 3;
# solve for derivative matrix
($info, $derv) = ICC::Support::Lapack::trisolve([(1) x $ix], [2, (4) x ($ix - 1), 2], [(1) x $ix], $rhs);
# make matrix of zeros
$mat = ICC::Support::Lapack::zeros($ox + 1, $ix + 1);
lib/ICC/Shared.pm view on Meta::CPAN
# for each row
for my $i (1 .. $ix - 1) {
# set diagonal values
$rhs->[$i - 1][$i] = 3;
$rhs->[$i + 1][$i] = -3;
}
# set endpoint values
$rhs->[0][0] = -3;
$rhs->[1][0] = -3;
$rhs->[$ix][$ix] = 3;
$rhs->[$ix - 1][$ix] = 3;
# solve for derivative matrix
$derv = Math::Matrix->tridiagonal([2, (4) x ($ix - 1), 2])->concat($rhs)->solve();
# make matrix of zeros
$mat = [map {[(0) x ($ix + 1)]} (0 .. $ox)];
lib/ICC/Support/akima.pm view on Meta::CPAN
# inherit from Shared
use parent qw(ICC::Shared);
# enable static variables
use feature 'state';
# create new akima object
# arrays are sorted so that input values are increasing
# array structure: [[input_values_array], [output_values_array]]
# flag enables setting endpoint derivatives with least-squares fit
# parameters: ([ref_to_array, [endpoint_flag]])
# returns: (ref_to_object)
sub new {
# get object class
my $class = shift();
# create empty akima object
my $self = [
{}, # object header
[], # x-values
lib/ICC/Support/akima.pm view on Meta::CPAN
# get parameters
my ($self, $in) = @_;
# local variable
my ($low);
# if input value <= x-min
if ($in <= $self->[1][0]) {
# return endpoint derivative
return($self->[3][0]);
# if input value >= x-max
} elsif ($in >= $self->[1][-1]) {
# return endpoint derivative
return($self->[3][-1]);
} else {
# if x-value not within current interval
if (! defined($low = $self->[0]{'low'}) || ($in < $self->[1][$low]) || ($in > $self->[1][$low + 1])) {
# locate interval with binary search
$self->[0]{'low'} = _binsearch($self->[1], $in);
lib/ICC/Support/akima.pm view on Meta::CPAN
# return transform
return($self->transform($in));
}
}
# compute object derivatives
# for spline knots using Akima's method
# parameters: (ref_to_object, endpoint_flag)
sub _objderv {
# get parameters
my ($self, $flag) = @_;
# local variables
my ($p, @m, $d, $d1, $d2, $dm);
# get array length
$p = $#{$self->[1]};
lib/ICC/Support/akima.pm view on Meta::CPAN
# otherwise, use average slope of adjoining segments
$self->[3][$i] = ($m[$i + 1] + $m[$i + 2])/2;
}
}
# if four or more points and flag set
if ($p >= 3 && $flag) {
# compute endpoint derivatives using weighted least squares
$self->[3][0] = _endpoint($self, 0);
$self->[3][-1] = _endpoint($self, -1);
}
}
# determine derivative of endpoint
# using weighted least squares method
# endpoint index is either 0 or -1
# parameters: (ref_to_object, endpoint_index)
# returns: (derivative)
sub _endpoint {
# get parameters
my ($self, $ix) = @_;
# local variables
my ($x, $y, $v, $r, $w, $info, $c);
# get x and y references
$x = $self->[1];
$y = $self->[2];
lib/ICC/Support/akima.pm view on Meta::CPAN
# returns: (value_array)
sub _local {
# get parameters
my ($self, $i) = @_;
# local variables
my ($x1, $x2, $y1, $y2, $m1, $m2);
my ($dy, $dx, $t, $a, $b, $c, $d, @s);
# get endpoint values
$x1 = $self->[1][$i];
$x2 = $self->[1][$i + 1];
$y1 = $self->[2][$i];
$y2 = $self->[2][$i + 1];
$m1 = $self->[3][$i];
$m2 = $self->[3][$i + 1];
# compute intermediate values
($dx = $x2 - $x1) || croak('zero interval in spline data');
$dy = $y1 - $y2;
lib/ICC/Support/akima.pm view on Meta::CPAN
# return if constant
return() if ($a == 0 && $b == 0);
# if linear equation
if ($a == 0) {
# compute solution
$t = -$c/$b;
# push if solution within interval (but not endpoints)
push(@s, $t * $dx + $x1) if ($t > 0 && $t < 1);
# if quadratic equation
} else {
# compute discriminant
$d = $b**2 - 4 * $a * $c;
# return if complex solutions
return() if ($d < 0);
# compute first solution
$t = (-$b + sqrt($d))/(2 * $a);
# push if solution within interval (but not endpoints)
push(@s, $t * $dx + $x1) if ($t > 0 && $t < 1);
# if discriminant > 0 (two real solutions)
if ($d > 0) {
# compute second solution
$t = (-$b - sqrt($d))/(2 * $a);
# push if solution within interval (but not endpoints)
push(@s, $t * $dx + $x1) if ($t > 0 && $t < 1);
}
}
# return solution(s)
return (@s);
}
lib/ICC/Support/akima.pm view on Meta::CPAN
# get parameters
my ($self, $in) = @_;
# local variables
my ($i, $x1, $x2, $y1, $y2, $m1, $m2);
my ($dy, $dx, $t, $h1, $h2, $h3);
# get lower index
$i = $self->[0]{'low'};
# get endpoint values
$x1 = $self->[1][$i];
$x2 = $self->[1][$i + 1];
$y1 = $self->[2][$i];
$y2 = $self->[2][$i + 1];
$m1 = $self->[3][$i];
$m2 = $self->[3][$i + 1];
# compute intermediate values
($dx = $x2 - $x1) || croak('zero interval in spline data');
$dy = $y1 - $y2;
lib/ICC/Support/akima.pm view on Meta::CPAN
# get parameters
my ($self, $in) = @_;
# local variables
my ($i, $x1, $x2, $y1, $y2, $m1, $m2);
my ($dy, $dx, $t, $h1, $h2, $h3);
# get lower index
$i = $self->[0]{'low'};
# get endpoint values
$x1 = $self->[1][$i];
$x2 = $self->[1][$i + 1];
$y1 = $self->[2][$i];
$y2 = $self->[2][$i + 1];
$m1 = $self->[3][$i];
$m2 = $self->[3][$i + 1];
# compute intermediate values
($dx = $x2 - $x1) || croak('zero interval in spline data');
$dy = $y1 - $y2;
lib/ICC/Support/akima.pm view on Meta::CPAN
# local variables
my ($i, $x0, $x1, $y0, $y1, $m0, $m1);
my ($dx, $t, $tc, $h00, $h01, $h10, $h11);
# check if ICC::Support::Lapack module is loaded
state $lapack = defined($INC{'ICC/Support/Lapack.pm'});
# get lower index
$i = $self->[0]{'low'};
# get endpoint values
$x0 = $self->[1][$i];
$x1 = $self->[1][$i + 1];
$y0 = $self->[2][$i];
$y1 = $self->[2][$i + 1];
$m0 = $self->[3][$i];
$m1 = $self->[3][$i + 1];
# compute intermediate values
($dx = $x1 - $x0) || croak('zero interval in spline data');
$t = ($in - $x0)/$dx;
lib/ICC/Support/geo2.pm view on Meta::CPAN
} else {
# compute (x0 - x1) x (x2 - x1)
$vx = ICC::Shared::crossProduct($v01, $v21);
# return distance and offset
return(sqrt(($vx->[0]**2 + $vx->[1]**2 + $vx->[2]**2)/$s), $t);
}
# identical endpoints
} else {
# return distance and offset
return(sqrt(($in->[0] - $self->[1][0][0])**2 + ($in->[1] - $self->[1][0][1])**2 + ($in->[2] - $self->[1][0][2])**2), 0);
}
}
# compute Jacobian matrix
lib/ICC/Support/geo2.pm view on Meta::CPAN
[0, $jac->[1][2]/$d, -$jac->[1][1]/$d],
[-$jac->[1][2]/$d, 0, $jac->[1][0]/$d],
[$jac->[1][1]/$d, -$jac->[1][0]/$d, 0]
];
# compute distance partial derivatives
$jac->[0] = ICC::Support::Lapack::vec_xplus($wx, $vx, {'trans' => 'T'});
}
# identical endpoints
} else {
# set offset
$t = 0;
# compute Jacobian vector and radius
($jac->[0], $d) = _radjac($self->[1][0], $in);
# complete Jacobian
$jac->[1] = [0, 0, 0];
lib/ICC/Support/spline.pm view on Meta::CPAN
# parameters: (input_value)
# returns: (derivative_value)
sub derivative {
# get parameters
my ($self, $in) = @_;
# if an extrapolated solution (s < 0)
if (($self->[1][1] > $self->[1][0] && $in < $self->[1][0]) || ($self->[1][1] < $self->[1][0] && $in > $self->[1][0])) {
# return endpoint derivative
return($self->[3][0] * $#{$self->[2]}/($self->[1][1] - $self->[1][0]));
# if an extrapolated solution (s >= 1)
} elsif (($self->[1][1] > $self->[1][0] && $in >= $self->[1][1]) || ($self->[1][1] < $self->[1][0] && $in <= $self->[1][1])) {
# return endpoint derivative
return($self->[3][-1] * $#{$self->[2]}/($self->[1][1] - $self->[1][0]));
} else {
# return interpolated derivative value
return(_derv($self, POSIX::modf($#{$self->[2]} * ($in - $self->[1][0])/($self->[1][1] - $self->[1][0]))) * $#{$self->[2]}/($self->[1][1] - $self->[1][0]));
}
}
lib/ICC/Support/spline.pm view on Meta::CPAN
# returns: (ref_to_curv_object)
sub curv {
# return 'curv' object reference
return(ICC::Profile::curv->new(table(@_)));
}
# normalize transform
# adjusts object values linearly
# so that endpoint values are 0 or 1
# adjusts input-range and output-values by default
# adjusts input-values if format is 'x'
# adjusts output-values if format is 'y'
# parameters: ([format])
sub normalize {
# get parameters
my ($self, $fmt) = @_;
# local variables
lib/ICC/Support/spline.pm view on Meta::CPAN
$rhs = bless([], 'Math::Matrix');
# for each input element
for my $i (1 .. $ix - 1) {
# compute rhs (3 * (y[i + 1] - y[i - 1]))
$rhs->[$i][0] = 3 * ($self->[2][$i + 1] - $self->[2][$i - 1]);
}
# set rhs endpoint values
$rhs->[0][0] = 3 * ($self->[2][1] - $self->[2][0]);
$rhs->[$ix][0] = 3 * ($self->[2][$ix] - $self->[2][$ix - 1]);
# if ICC::Support::Lapack module is loaded
if ($lapack) {
# solve for derivative matrix
($info, $derv) = ICC::Support::Lapack::trisolve([(1) x $ix], [2, (4) x ($ix - 1), 2], [(1) x $ix], $rhs);
# otherwise, use Math::Matrix module
lib/ICC/Support/spline.pm view on Meta::CPAN
# for each row
for my $i (1 .. $ix - 1) {
# set rhs diagonal values
$rhs->[$i - 1][$i] = 3;
$rhs->[$i + 1][$i] = -3;
}
# set rhs endpoint values
$rhs->[0][0] = -3;
$rhs->[1][0] = -3;
$rhs->[$ix][$ix] = 3;
$rhs->[$ix - 1][$ix] = 3;
# if ICC::Support::Lapack module is loaded
if ($lapack) {
# solve for derivative matrix
($info, $derv) = ICC::Support::Lapack::trisolve([(1) x $ix], [2, (4) x ($ix - 1), 2], [(1) x $ix], $rhs);
lib/ICC/Support/spline.pm view on Meta::CPAN
# returns: (t-value_array)
sub _local {
# get parameters
my ($self, $low) = @_;
# local variables
my ($y1, $y2, $m1, $m2);
my ($a, $b, $c, $dscr, @t);
# get endpoint values
$y1 = $self->[2][$low];
$y2 = $self->[2][$low + 1];
$m1 = $self->[3][$low];
$m2 = $self->[3][$low + 1];
# compute coefficients of quadratic equation (at^2 + bt + c = 0)
$a = 6 * ($y1 - $y2) + 3 * ($m1 + $m2);
$b = -6 * ($y1 - $y2) - 2 * $m2 - 4 * $m1;
$c = $m1;
lib/ICC/Support/spline.pm view on Meta::CPAN
sub _rev {
# get parameters
my ($self, $in, $low) = @_;
# local variables
my ($y1, $y2, $m1, $m2);
my ($a, $b, $c, $d, $dscr, @t);
my ($d0, $d1, $cs, $cc, @r, $ccr, $sol, $lim0, $lim1);
# get endpoint values
$y1 = $self->[2][$low];
$y2 = $self->[2][$low + 1];
$m1 = $self->[3][$low];
$m2 = $self->[3][$low + 1];
# compute coefficients of cubic equation (at^3 + bt^2 + ct + d = 0)
$a = 2 * ($y1 - $y2) + $m1 + $m2;
$b = -3 * ($y1 - $y2) -2 * $m1 - $m2;
$c = $m1;
$d = $y1 - $in;
lib/ICC/Support/spline2.pm view on Meta::CPAN
# get parameters
my ($self, $in) = @_;
# local variable
my ($low);
# if an extrapolated solution (s < 0)
if ($in < $self->[1][0]) {
# return endpoint derivative
return($self->[3][0]);
# if an extrapolated solution (s >= 1)
} elsif ($in >= $self->[1][-1]) {
# return endpoint derivative
return($self->[3][-1]);
} else {
# initilize segment
$low = 0;
# while input value > upper knot value
while ($in > $self->[1][$low + 1]) {
lib/ICC/Support/spline2.pm view on Meta::CPAN
# returns: (ref_to_curv_object)
sub curv {
# return 'curv' object reference
return(ICC::Profile::curv->new(table(@_)));
}
# normalize transform !!!!! needs work
# adjusts object values linearly
# so that endpoint values are 0 or 1
# adjusts input-range and output-values by default
# adjusts input-values if format is 'x'
# adjusts output-values if format is 'y'
# parameters: ([format])
sub normalize {
# get parameters
my ($self, $fmt) = @_;
# local variables
lib/ICC/Support/spline2.pm view on Meta::CPAN
$rhs = bless([], 'Math::Matrix');
# for each input element
for my $i (1 .. $ix - 1) {
# compute rhs (6 * (y[i + 1] - y[i - 1])/(x[i + 1] - x[i - 1]))
$rhs->[$i][0] = 6 * ($self->[2][$i + 1] - $self->[2][$i - 1])/($self->[1][$i + 1] - $self->[1][$i - 1]);
}
# set rhs endpoint values
$rhs->[0][0] = 3 * ($self->[2][1] - $self->[2][0])/($self->[1][1] - $self->[1][0]);
$rhs->[$ix][0] = 3 * ($self->[2][$ix] - $self->[2][$ix - 1])/($self->[1][$ix] - $self->[1][$ix - 1]);
# if ICC::Support::Lapack module is loaded
if ($lapack) {
# solve for derivative matrix
($info, $derv) = ICC::Support::Lapack::trisolve([(1) x $ix], [2, (4) x ($ix - 1), 2], [(1) x $ix], $rhs);
# otherwise, use Math::Matrix module
lib/ICC/Support/spline2.pm view on Meta::CPAN
# for each row
for my $i (1 .. $ix - 1) {
# set rhs diagonal values
$rhs->[$i][$i - 1] = $x = 6/($self->[1][$i - 1] - $self->[1][$i + 1]);
$rhs->[$i][$i + 1] = -$x;
}
# set rhs endpoint values
$rhs->[0][0] = $x = 3/($self->[1][0] - $self->[1][1]);
$rhs->[0][1] = -$x;
$rhs->[$ix][$ix] = $x = 3/($self->[1][$ix] - $self->[1][$ix - 1]);
$rhs->[$ix][$ix -1] = -$x;
# if ICC::Support::Lapack module is loaded
if ($lapack) {
# solve for derivative matrix
($info, $derv) = ICC::Support::Lapack::trisolve([(1) x $ix], [2, (4) x ($ix - 1), 2], [(1) x $ix], $rhs);
lib/ICC/Support/spline2.pm view on Meta::CPAN
# get parameters
my ($self, $low) = @_;
# local variables
my ($dx, $y1, $y2, $m1, $m2);
my ($a, $b, $c, $dscr, @t);
# compute delta x-value
$dx = $self->[1][$low + 1] - $self->[1][$low];
# get endpoint values
$y1 = $self->[2][$low];
$y2 = $self->[2][$low + 1];
$m1 = $self->[3][$low] * $dx;
$m2 = $self->[3][$low + 1] * $dx;
# compute coefficients of quadratic equation (at^2 + bt + c = 0)
$a = 6 * ($y1 - $y2) + 3 * ($m1 + $m2);
$b = -6 * ($y1 - $y2) - 2 * $m2 - 4 * $m1;
$c = $m1;
lib/ICC/Support/spline2.pm view on Meta::CPAN
my ($self, $in, $low) = @_;
# local variables
my ($dx, $y1, $y2, $m1, $m2);
my ($a, $b, $c, $d, $dscr, @t);
my ($d0, $d1, $cs, $cc, @r, $ccr, $sol, $lim0, $lim1);
# compute delta x-value
$dx = $self->[1][$low + 1] - $self->[1][$low];
# get endpoint values
$y1 = $self->[2][$low];
$y2 = $self->[2][$low + 1];
$m1 = $self->[3][$low] * $dx;
$m2 = $self->[3][$low + 1] * $dx;
# compute coefficients of cubic equation (at^3 + bt^2 + ct + d = 0)
$a = 2 * ($y1 - $y2) + $m1 + $m2;
$b = -3 * ($y1 - $y2) -2 * $m1 - $m2;
$c = $m1;
$d = $y1 - $in;
pod/ICC/Support/Color.pod view on Meta::CPAN
The Color object provides three different interpolation methods, linear, cubic spline, and Lagrange. Linear interpolation
uses a straight line function between points. Cubic spline interpolation uses a cubic function between points. Lagrange
interpolation uses a polynomial function that passes through some number of points surrounding the interval. The ASTM E 308
and E 2022 standards employ Lagrange interpolation.
In most cases, cubic spline interpolation will provide the best results. A so-called "natural" cubic spline is used, which
has continuous first and second derivatives. Linear interpolation is preferred for fluorescent and gas discharge
illuminants. For illuminants, the appropriate interpolation method is selected based on the "smoothness" of the SPD.
Lagrange interpolation is included for ASTM compatibility.
Wavelengths outside the range of the measuring device are copied from the endpoints. This is the preferred way to extend the
data. Fortunately, the values of the color-matching functions become extremely small as they approach the UV and IR regions.
This minimizes any errors from an abbreviated measurement range.
=head2 Color weight functions
To compute the colorimetry of a single sample using a 1 nm increment requires interpolating 470 values, multiplying them by
the color-matching functions and illuminant, then adding these products together to get X, Y, and Z values. This consumes a
lot of computing power.
This work can be greatly simplified with color-weight functions. Color-weight functions combine the interpolation and