Curve that touches three points: Difference between revisions
Content added Content deleted
(adding lambdatalk contribution) |
SqrtNegInf (talk | contribs) m (→{{header|Raku}}: sync up 'rref', factor out points) |
||
Line 659: | Line 659: | ||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
{{works with|Rakudo|2018.10}} |
|||
Kind of bogus. There are an infinite number of curves that pass through those three points. I'll assume a quadratic curve. Lots of bits and pieces borrowed from other tasks to avoid relying on library functions. |
Kind of bogus. There are an infinite number of curves that pass through those three points. I'll assume a quadratic curve. Lots of bits and pieces borrowed from other tasks to avoid relying on library functions. |
||
Line 665: | Line 665: | ||
<lang perl6>use Image::PNG::Portable; |
<lang perl6>use Image::PNG::Portable; |
||
# the points of interest |
|||
my @points = (10,10), (100,200), (200,10); |
|||
# Solve for a quadratic line that passes through those points |
# Solve for a quadratic line that passes through those points |
||
my (\a, \b, \c) = |
my (\a, \b, \c) = (rref (.[0]², .[0], 1, .[1] for @points) )[*;*-1]; |
||
rref([[10², 10, 1, 10],[100², 100, 1, 200],[200², 200, 1, 10]])[*;*-1]; |
|||
# |
# Evaluate quadratic equation |
||
sub f (\x) { |
sub f (\x) { a×x² + b×x + c } |
||
⚫ | |||
# Scale it up a bit for display |
|||
my $scale = 2; |
my $scale = 2; # scaling factor |
||
⚫ | |||
my $png = Image::PNG::Portable.new: :width($w), :height($h); |
my $png = Image::PNG::Portable.new: :width($w), :height($h); |
||
Line 686: | Line 687: | ||
} |
} |
||
# Highlight the |
# Highlight the defining points |
||
dot(|$_, $ |
dot( | $_, $(255,0,0), $png, 2) for @points; |
||
$png.write: 'Curve-3-points-perl6.png'; |
$png.write: 'Curve-3-points-perl6.png'; |
||
Line 694: | Line 695: | ||
sub rref (@m) { |
sub rref (@m) { |
||
return unless @m; |
return unless @m; |
||
my ($lead, $rows, $cols) = 0, |
my ($lead, $rows, $cols) = 0, @m, @m[0]; |
||
for ^$rows -> $r { |
for ^$rows -> $r { |
||
$lead < $cols or return @m; |
$lead < $cols or return @m; |
||
Line 704: | Line 705: | ||
} |
} |
||
@m[$i, $r] = @m[$r, $i] if $r != $i; |
@m[$i, $r] = @m[$r, $i] if $r != $i; |
||
@m[$r] »/=» $ = @m[$r;$lead]; |
|||
@m[$r] »/=» $lv; |
|||
for ^$rows -> $n { |
for ^$rows -> $n { |
||
next if $n == $r; |
next if $n == $r; |
||
@m[$n] »-=» @m[$r] » |
@m[$n] »-=» @m[$r] »×» (@m[$n;$lead] // 0); |
||
} |
} |
||
++$lead; |
++$lead; |
||
Line 717: | Line 717: | ||
sub line($x0 is copy, $y0 is copy, $x1 is copy, $y1 is copy, $png, @rgb) { |
sub line($x0 is copy, $y0 is copy, $x1 is copy, $y1 is copy, $png, @rgb) { |
||
my $steep = abs($y1 - $y0) > abs($x1 - $x0); |
my $steep = abs($y1 - $y0) > abs($x1 - $x0); |
||
($x0,$y0,$x1,$y1) » |
($x0,$y0,$x1,$y1) »×=» $scale; |
||
if $steep { |
if $steep { |
||
($x0, $y0) = ($y0, $x0); |
($x0, $y0) = ($y0, $x0); |
||
Line 741: | Line 741: | ||
} |
} |
||
$error += $Δerror; |
$error += $Δerror; |
||
if $error |
if $error ≥ 0.5 { |
||
$y += $y-step; |
$y += $y-step; |
||
$error -= 1.0; |
$error -= 1.0; |
||
Line 749: | Line 749: | ||
sub dot ($X is copy, $Y is copy, @rgb, $png, $radius = 3) { |
sub dot ($X is copy, $Y is copy, @rgb, $png, $radius = 3) { |
||
($X, $Y) » |
($X, $Y) »×=» $scale; |
||
for ($X X+ -$radius .. $radius) X ($Y X+ -$radius .. $radius) -> ($x, $y) { |
for ($X X+ -$radius .. $radius) X ($Y X+ -$radius .. $radius) -> ($x, $y) { |
||
$png.set($x, $y, |@rgb) if ( $X - $x + ($Y - $y) |
$png.set($x, $y, |@rgb) if ( $X - $x + ($Y - $y) × i ).abs <= $radius; |
||
} |
} |
||
}</lang> |
}</lang> |