Nubs.evaluate
. I'm going to repeat that code here, as I've added one of the Nubs.evaluate
functions to the mix.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
multi method KnotVector.N0_index(Int $p, $u, KnotBasisDirection $direction = Left) | |
{ | |
given $direction | |
{ | |
when Left { UpperBound(@.knots, $u) - $p - 1; } | |
when Right { LowerBound(@.knots, $u) - $p - 1; } | |
when Reasonable { die "Must specify Left or Right for KnotBasisDirection"; } | |
} | |
} | |
multi method Nubs.Direction($t, KnotBasisDirection $direction) | |
{ | |
return $t < ([+] self.ParameterRange) / 2 ?? Left !! Right | |
if ($direction == Reasonable); | |
return $direction; | |
} | |
multi method Nubs.evaluate($t, KnotBasisDirection $direction = Reasonable) | |
{ | |
my $n0 = $.knot_vector.N0_index($.degree, $t, Direction($t, $direction)); | |
return [+] ($.knot_vector.N_local($n0, $.degree, $t) | |
>>*<< @.control_points[$n0 .. ($n0 + $.degree)]); | |
} |
These functions became overly complex because I tried to overload the KnotBasisDirection enum with an extra layer of meaning. Pulling that extra layer out and rearranging things a tad gives you vastly better code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
multi method KnotVector.N0_index(Int $p, $u, KnotBasisDirection $direction = Left) | |
{ | |
given $direction | |
{ | |
when Left { UpperBound(@.knots, $u) - $p - 1; } | |
when Right { LowerBound(@.knots, $u) - $p - 1; } | |
} | |
} | |
multi method Nubs.Direction($t) | |
{ | |
$t < ([+] self.ParameterRange) / 2 ?? Left !! Right; | |
} | |
multi method Nubs.evaluate($t, KnotBasisDirection $direction = self.Direction($t)) | |
{ | |
my $n0 = $.knot_vector.N0_index($.degree, $t, $direction); | |
return [+] ($.knot_vector.N_local($n0, $.degree, $t) | |
>>*<< @.control_points[$n0 .. ($n0 + $.degree)]); | |
} |
Notice that we've eliminated an enum value here, two cases that needed to be checked for, and simplified a third line of code. The "trick" (almost too obvious to be called a trick) is to make the default value of
$direction
be determined by a called to Direction
, rather than calling Direction with a special value that indicates it needs to do work.It's the best of both worlds. By default, if you don't specify
$direction
it will do something reasonable. And for those rare weird cases where it is important (discontinuities in the curve), you can specify the direction to use for the evaluation.Tomorrow: On the road to SVG in Perl 6.
No comments:
Post a Comment