ICC-Profile

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

- 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



( run in 0.731 second using v1.01-cache-2.11-cpan-524268b4103 )