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 )