Bitmap/Bézier curves/Quadratic: Difference between revisions
Content deleted Content added
Added Julia language |
Thundergnat (talk | contribs) →{{header|Perl6}}: Add Perl6 example |
||
Line 607: | Line 607: | ||
by_pair pts (fun p0 p1 -> line ~p0 ~p1); |
by_pair pts (fun p0 p1 -> line ~p0 ~p1); |
||
;;</lang> |
;;</lang> |
||
=={{header|Perl 6}}== |
|||
{{works with|Rakudo|2017.09}} |
|||
Uses pieces from [[Bitmap#Perl_6| Bitmap]], and [[Bitmap/Bresenham's_line_algorithm#Perl_6| Bresenham's line algorithm]] tasks. They are included here to make a complete, runnable program. |
|||
<lang perl6>class Pixel { has UInt ($.R, $.G, $.B) } |
|||
class Bitmap { |
|||
has UInt ($.width, $.height); |
|||
has Pixel @!data; |
|||
method fill(Pixel $p) { |
|||
@!data = $p.clone xx ($!width*$!height) |
|||
} |
|||
method pixel( |
|||
$i where ^$!width, |
|||
$j where ^$!height |
|||
--> Pixel |
|||
) is rw { @!data[$i + $j * $!width] } |
|||
method set-pixel ($i, $j, Pixel $p) { |
|||
return if $j >= $!height; |
|||
self.pixel($i, $j) = $p.clone; |
|||
} |
|||
method get-pixel ($i, $j) returns Pixel { |
|||
self.pixel($i, $j); |
|||
} |
|||
method line($x0 is copy, $y0 is copy, $x1 is copy, $y1 is copy, $pix) { |
|||
my $steep = abs($y1 - $y0) > abs($x1 - $x0); |
|||
if $steep { |
|||
($x0, $y0) = ($y0, $x0); |
|||
($x1, $y1) = ($y1, $x1); |
|||
} |
|||
if $x0 > $x1 { |
|||
($x0, $x1) = ($x1, $x0); |
|||
($y0, $y1) = ($y1, $y0); |
|||
} |
|||
my $Δx = $x1 - $x0; |
|||
my $Δy = abs($y1 - $y0); |
|||
my $error = 0; |
|||
my $Δerror = $Δy / $Δx; |
|||
my $y-step = $y0 < $y1 ?? 1 !! -1; |
|||
my $y = $y0; |
|||
for $x0 .. $x1 -> $x { |
|||
if $steep { |
|||
self.set-pixel($y, $x, $pix); |
|||
} else { |
|||
self.set-pixel($x, $y, $pix); |
|||
} |
|||
$error += $Δerror; |
|||
if $error >= 0.5 { |
|||
$y += $y-step; |
|||
$error -= 1.0; |
|||
} |
|||
} |
|||
} |
|||
method dot ($px, $py, $pix, $radius = 2) { |
|||
for $px - $radius .. $px + $radius -> $x { |
|||
for $py - $radius .. $py + $radius -> $y { |
|||
self.set-pixel($x, $y, $pix) if ( $px - $x + ($py - $y) * i ).abs <= $radius; |
|||
} |
|||
} |
|||
} |
|||
method quadratic ( $x1, $y1, $x2, $y2, $x3, $y3, $pix, $segments = 30 ) { |
|||
my @line-segments = map -> $t { |
|||
my \a = (1-$t)²; |
|||
my \b = $t * (1-$t) * 2; |
|||
my \c = $t²; |
|||
(a*$x1 + b*$x2 + c*$x3).round(1),(a*$y1 + b*$y2 + c*$y3).round(1) |
|||
}, (0, 1/$segments, 2/$segments ... 1); |
|||
for @line-segments.rotor(2=>-1) -> (($x1,$y1),($x2,$y2)){ self.line($x1,$y1,$x2,$y2, $pix) }; |
|||
} |
|||
method data { @!data } |
|||
} |
|||
role PPM { |
|||
method P6 returns Blob { |
|||
"P6\n{self.width} {self.height}\n255\n".encode('ascii') |
|||
~ Blob.new: flat map { .R, .G, .B }, self.data |
|||
} |
|||
} |
|||
sub color( $r, $g, $b) { Pixel.new(R => $r, G => $g, B => $b) } |
|||
my Bitmap $b = Bitmap.new( width => 600, height => 400) but PPM; |
|||
$b.fill( color(62,63,63) ); |
|||
my @points = (65,25, 85,380, 570,15); |
|||
$b.quadratic( |@points, color(0,255,0) ); |
|||
@points.map: { $b.dot( $^x, $^y, color(255,255,0) )} |
|||
$*OUT.write: $b.P6;</lang> |
|||
See [https://github.com/thundergnat/rc/blob/master/img/Bezier-quadratic-perl6.png example image here], (converted to a .png as .ppm format is not widely supported). |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |