Curve that touches three points: Difference between revisions

Content added Content deleted
(adding lambdatalk contribution)
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];


# General case quadratic line equation
# Evaluate quadratic equation
sub f (\x) { a*x² + b*x + c }
sub f (\x) { a×x² + b×x + c }


my ($w, $h) = 500, 500; # image size
# Scale it up a bit for display
my $scale = 2;
my $scale = 2; # scaling factor


my ($w, $h) = (500, 500);
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 3 defining points
# Highlight the defining points
dot(|$_, $png, 2) for (10,10,[255,0,0]), (100,200,[255,0,0]), (200,10,[255,0,0]);
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, +@m, +@m[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;
my $lv = @m[$r;$lead];
@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;$lead] // 0);
@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) »*=» $scale;
($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 >= 0.5 {
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) »*=» $scale;
($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) * i ).abs <= $radius;
$png.set($x, $y, |@rgb) if ( $X - $x + ($Y - $y) × i ).abs <= $radius;
}
}
}</lang>
}</lang>