Math-BSpline-Curve

 view release on metacpan or  search on metacpan

lib/Math/BSpline/Curve/Role/Approximation.pm  view on Meta::CPAN

package Math::BSpline::Curve::Role::Approximation;
$Math::BSpline::Curve::Role::Approximation::VERSION = '0.002';
# ABSTRACT: fitting a B-spline curve to a point set

use 5.014;
use warnings;

use Moo::Role;
use List::Util 1.26 ('sum0');
use Scalar::Util 1.26 ('blessed');
use Ref::Util 0.010 ('is_plain_arrayref');
use Module::Runtime 0.012 ('require_module');
use Math::BSpline::Basis 0.001;
use Math::Matrix::Banded 0.004;

requires (
    'new',
);


sub fit {
    my ($class, @args) = @_;

    # We support both a hash and a hashref as args.
    my $args = @args == 1 ? $args[0] : {@args};
    $args ||= {};

    foreach ('degree', 'n_control_points', 'points') {
        if (!exists($args->{$_})) {
            $Math::BSpline::Curve::logger->error(
                "Missing required arguments: $_",
            );
            return undef;
        }
    }

    my $apr = $class->_fit_approximate_unbounded($args);
    if ($apr) {
        return $class->new(
            degree         => $args->{degree},
            knot_vector    => $apr->{knot_vector},
            control_points => $apr->{control_points},
        );
    }
    else {
        return undef;
    }
}


sub calculate_parameters {
    my ($class, $points, $lengths, $total_length) = @_;

    # We support omission of $lengths/$total_length or only of
    # $total_length.
    ($lengths, $total_length) = $class->_fit_calculate_lengths($points)
        if (!$lengths);
    $total_length //= sum0(@$lengths);

    my $phi      = [0];
    my $cur_phi  = 0;
    for (my $i=1;$i<@$points-1;$i++) {
        $cur_phi += $lengths->[$i-1] / $total_length;
        push(@$phi, $cur_phi);
    }
    push(@$phi, 1);

    return $phi;
}




( run in 1.300 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )