Bitmap/Bresenham's line algorithm: Difference between revisions
Content added Content deleted
(cannot use const with std::swap, the values need to be writable!) |
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
||
Line 219: | Line 219: | ||
...|.................... |
...|.................... |
||
</pre> |
</pre> |
||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
Line 698: | Line 697: | ||
1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY |
1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY |
||
1610 GOTO 1560</lang> |
1610 GOTO 1560</lang> |
||
=={{header|BBC BASIC}}== |
|||
{{works with|BBC BASIC for Windows}} |
|||
<lang bbcbasic> Width% = 200 |
|||
Height% = 200 |
|||
REM Set window size: |
|||
VDU 23,22,Width%;Height%;8,16,16,128 |
|||
REM Draw lines: |
|||
PROCbresenham(50,100,100,190,0,0,0) |
|||
PROCbresenham(100,190,150,100,0,0,0) |
|||
PROCbresenham(150,100,100,10,0,0,0) |
|||
PROCbresenham(100,10,50,100,0,0,0) |
|||
END |
|||
DEF PROCbresenham(x1%,y1%,x2%,y2%,r%,g%,b%) |
|||
LOCAL dx%, dy%, sx%, sy%, e |
|||
dx% = ABS(x2% - x1%) : sx% = SGN(x2% - x1%) |
|||
dy% = ABS(y2% - y1%) : sy% = SGN(y2% - y1%) |
|||
IF dx% > dy% e = dx% / 2 ELSE e = dy% / 2 |
|||
REPEAT |
|||
PROCsetpixel(x1%,y1%,r%,g%,b%) |
|||
IF x1% = x2% IF y1% = y2% EXIT REPEAT |
|||
IF dx% > dy% THEN |
|||
x1% += sx% : e -= dy% : IF e < 0 e += dx% : y1% += sy% |
|||
ELSE |
|||
y1% += sy% : e -= dx% : IF e < 0 e += dy% : x1% += sx% |
|||
ENDIF |
|||
UNTIL FALSE |
|||
ENDPROC |
|||
DEF PROCsetpixel(x%,y%,r%,g%,b%) |
|||
COLOUR 1,r%,g%,b% |
|||
GCOL 1 |
|||
LINE x%*2,y%*2,x%*2,y%*2 |
|||
ENDPROC</lang> |
|||
[[File:bresenham_bbc.gif]] |
|||
=={{header|Batch File}}== |
=={{header|Batch File}}== |
||
Line 866: | Line 827: | ||
) |
) |
||
goto :eof</lang> |
goto :eof</lang> |
||
=={{header|BBC BASIC}}== |
|||
{{works with|BBC BASIC for Windows}} |
|||
<lang bbcbasic> Width% = 200 |
|||
Height% = 200 |
|||
REM Set window size: |
|||
VDU 23,22,Width%;Height%;8,16,16,128 |
|||
REM Draw lines: |
|||
PROCbresenham(50,100,100,190,0,0,0) |
|||
PROCbresenham(100,190,150,100,0,0,0) |
|||
PROCbresenham(150,100,100,10,0,0,0) |
|||
PROCbresenham(100,10,50,100,0,0,0) |
|||
END |
|||
DEF PROCbresenham(x1%,y1%,x2%,y2%,r%,g%,b%) |
|||
LOCAL dx%, dy%, sx%, sy%, e |
|||
dx% = ABS(x2% - x1%) : sx% = SGN(x2% - x1%) |
|||
dy% = ABS(y2% - y1%) : sy% = SGN(y2% - y1%) |
|||
IF dx% > dy% e = dx% / 2 ELSE e = dy% / 2 |
|||
REPEAT |
|||
PROCsetpixel(x1%,y1%,r%,g%,b%) |
|||
IF x1% = x2% IF y1% = y2% EXIT REPEAT |
|||
IF dx% > dy% THEN |
|||
x1% += sx% : e -= dy% : IF e < 0 e += dx% : y1% += sy% |
|||
ELSE |
|||
y1% += sy% : e -= dx% : IF e < 0 e += dy% : x1% += sx% |
|||
ENDIF |
|||
UNTIL FALSE |
|||
ENDPROC |
|||
DEF PROCsetpixel(x%,y%,r%,g%,b%) |
|||
COLOUR 1,r%,g%,b% |
|||
GCOL 1 |
|||
LINE x%*2,y%*2,x%*2,y%*2 |
|||
ENDPROC</lang> |
|||
[[File:bresenham_bbc.gif]] |
|||
=={{header|C}}== |
=={{header|C}}== |
||
Line 1,245: | Line 1,244: | ||
end; |
end; |
||
</lang> |
</lang> |
||
=={{header|E}}== |
|||
{{trans|C}} |
|||
<lang e>def swap(&left, &right) { # From [[Generic swap]] |
|||
def t := left |
|||
left := right |
|||
right := t |
|||
} |
|||
def drawLine(image, var x0, var y0, var x1, var y1, color) { |
|||
def steep := (y1 - y0).abs() > (x1 - x0).abs() |
|||
if (steep) { |
|||
swap(&x0, &y0) |
|||
swap(&x1, &y1) |
|||
} |
|||
if (x0 > x1) { |
|||
swap(&x0, &x1) |
|||
swap(&y0, &y1) |
|||
} |
|||
def deltax := x1 - x0 |
|||
def deltay := (y1 - y0).abs() |
|||
def ystep := if (y0 < y1) { 1 } else { -1 } |
|||
var error := deltax // 2 |
|||
var y := y0 |
|||
for x in x0..x1 { |
|||
if (steep) { image[y, x] := color } else { image[x, y] := color } |
|||
error -= deltay |
|||
if (error < 0) { |
|||
y += ystep |
|||
error += deltax |
|||
} |
|||
} |
|||
}</lang> |
|||
<lang e>def i := makeImage(5, 20) |
|||
drawLine(i, 1, 1, 3, 18, makeColor.fromFloat(0,1,1)) |
|||
i.writePPM(<import:java.io.makeFileOutputStream>(<file:~/Desktop/Bresenham.ppm>))</lang> |
|||
=={{header|Elm}}== |
=={{header|Elm}}== |
||
Line 1,306: | Line 1,344: | ||
</lang> |
</lang> |
||
=={{header|E}}== |
|||
{{trans|C}} |
|||
<lang e>def swap(&left, &right) { # From [[Generic swap]] |
|||
def t := left |
|||
left := right |
|||
right := t |
|||
} |
|||
def drawLine(image, var x0, var y0, var x1, var y1, color) { |
|||
def steep := (y1 - y0).abs() > (x1 - x0).abs() |
|||
if (steep) { |
|||
swap(&x0, &y0) |
|||
swap(&x1, &y1) |
|||
} |
|||
if (x0 > x1) { |
|||
swap(&x0, &x1) |
|||
swap(&y0, &y1) |
|||
} |
|||
def deltax := x1 - x0 |
|||
def deltay := (y1 - y0).abs() |
|||
def ystep := if (y0 < y1) { 1 } else { -1 } |
|||
var error := deltax // 2 |
|||
var y := y0 |
|||
for x in x0..x1 { |
|||
if (steep) { image[y, x] := color } else { image[x, y] := color } |
|||
error -= deltay |
|||
if (error < 0) { |
|||
y += ystep |
|||
error += deltax |
|||
} |
|||
} |
|||
}</lang> |
|||
<lang e>def i := makeImage(5, 20) |
|||
drawLine(i, 1, 1, 3, 18, makeColor.fromFloat(0,1,1)) |
|||
i.writePPM(<import:java.io.makeFileOutputStream>(<file:~/Desktop/Bresenham.ppm>))</lang> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Line 1,427: | Line 1,426: | ||
{Y, E}. |
{Y, E}. |
||
</lang> |
</lang> |
||
=={{header|ERRE}}== |
=={{header|ERRE}}== |
||
Line 1,640: | Line 1,638: | ||
Window(Content=image, Title="Bresenham's line algorithm") |
Window(Content=image, Title="Bresenham's line algorithm") |
||
|> (Application()).Run |> ignore</lang> |
|> (Application()).Run |> ignore</lang> |
||
=={{header|Factor}}== |
|||
A very ugly imperative implementation similar to the wikipedia pseudocode.. |
|||
<lang factor>USING: accessors arrays kernel locals math math.functions |
|||
math.ranges math.vectors rosettacode.raster.display |
|||
rosettacode.raster.storage sequences ui.gadgets ; |
|||
IN: rosettacode.raster.line |
|||
:: line-points ( pt1 pt2 -- points ) |
|||
pt1 first2 :> y0! :> x0! |
|||
pt2 first2 :> y1! :> x1! |
|||
y1 y0 - abs x1 x0 - abs > :> steep |
|||
steep [ |
|||
y0 x0 y0! x0! |
|||
y1 x1 y1! x1! |
|||
] when |
|||
x0 x1 > [ |
|||
x0 x1 x0! x1! |
|||
y0 y1 y0! y1! |
|||
] when |
|||
x1 x0 - :> deltax |
|||
y1 y0 - abs :> deltay |
|||
0 :> current-error! |
|||
deltay deltax / abs :> deltaerr |
|||
0 :> ystep! |
|||
y0 :> y! |
|||
y0 y1 < [ 1 ystep! ] [ -1 ystep! ] if |
|||
x0 x1 1 <range> [ |
|||
y steep [ swap ] when 2array |
|||
current-error deltaerr + current-error! |
|||
current-error 0.5 >= [ |
|||
ystep y + y! |
|||
current-error 1 - current-error! |
|||
] when |
|||
] { } map-as ; |
|||
! Needs rosettacode.raster.storage for the set-pixel function and to create the image |
|||
: draw-line ( {R,G,B} pt1 pt2 image -- ) |
|||
[ line-points ] dip |
|||
[ set-pixel ] curry with each ;</lang> |
|||
=={{header|FBSL}}== |
=={{header|FBSL}}== |
||
Line 1,683: | Line 1,721: | ||
END SUB</lang> |
END SUB</lang> |
||
'''Output:''' [[File:FBSLBresenham.PNG]] |
'''Output:''' [[File:FBSLBresenham.PNG]] |
||
=={{header|Factor}}== |
|||
A very ugly imperative implementation similar to the wikipedia pseudocode.. |
|||
<lang factor>USING: accessors arrays kernel locals math math.functions |
|||
math.ranges math.vectors rosettacode.raster.display |
|||
rosettacode.raster.storage sequences ui.gadgets ; |
|||
IN: rosettacode.raster.line |
|||
:: line-points ( pt1 pt2 -- points ) |
|||
pt1 first2 :> y0! :> x0! |
|||
pt2 first2 :> y1! :> x1! |
|||
y1 y0 - abs x1 x0 - abs > :> steep |
|||
steep [ |
|||
y0 x0 y0! x0! |
|||
y1 x1 y1! x1! |
|||
] when |
|||
x0 x1 > [ |
|||
x0 x1 x0! x1! |
|||
y0 y1 y0! y1! |
|||
] when |
|||
x1 x0 - :> deltax |
|||
y1 y0 - abs :> deltay |
|||
0 :> current-error! |
|||
deltay deltax / abs :> deltaerr |
|||
0 :> ystep! |
|||
y0 :> y! |
|||
y0 y1 < [ 1 ystep! ] [ -1 ystep! ] if |
|||
x0 x1 1 <range> [ |
|||
y steep [ swap ] when 2array |
|||
current-error deltaerr + current-error! |
|||
current-error 0.5 >= [ |
|||
ystep y + y! |
|||
current-error 1 - current-error! |
|||
] when |
|||
] { } map-as ; |
|||
! Needs rosettacode.raster.storage for the set-pixel function and to create the image |
|||
: draw-line ( {R,G,B} pt1 pt2 image -- ) |
|||
[ line-points ] dip |
|||
[ set-pixel ] curry with each ;</lang> |
|||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
Line 1,877: | Line 1,875: | ||
end program BasicImageTests</lang> |
end program BasicImageTests</lang> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
<lang freebasic>' version 16-09-2015 |
<lang freebasic>' version 16-09-2015 |
||
Line 2,736: | Line 2,735: | ||
Images <tt>test0.png</tt> and <tt>test1.png</tt> look different since Imlib2 draw lines with antialiasing. |
Images <tt>test0.png</tt> and <tt>test1.png</tt> look different since Imlib2 draw lines with antialiasing. |
||
=={{header|Perl 6}}== |
|||
{{works with|Rakudo|2018.03}} |
|||
Bitmap class from [[Bitmap#Perl_6|Bitmap]] task. |
|||
<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) { |
|||
self.pixel($i, $j) = $p.clone; |
|||
} |
|||
method get-pixel ($i, $j) returns Pixel { |
|||
self.pixel($i, $j); |
|||
} |
|||
} |
|||
sub line(Bitmap $bitmap, $x0 is copy, $x1 is copy, $y0 is copy, $y1 is copy) { |
|||
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 { |
|||
my $pix = Pixel.new(R => 100, G => 200, B => 0); |
|||
if $steep { |
|||
$bitmap.set-pixel($y, $x, $pix); |
|||
} else { |
|||
$bitmap.set-pixel($x, $y, $pix); |
|||
} |
|||
$error += $Δerror; |
|||
if $error >= 0.5 { |
|||
$y += $y-step; |
|||
$error -= 1.0; |
|||
} |
|||
} |
|||
}</lang> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 3,240: | Line 3,183: | ||
bm |
bm |
||
</lang> |
</lang> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2018.03}} |
|||
Bitmap class from [[Bitmap#Perl_6|Bitmap]] task. |
|||
<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) { |
|||
self.pixel($i, $j) = $p.clone; |
|||
} |
|||
method get-pixel ($i, $j) returns Pixel { |
|||
self.pixel($i, $j); |
|||
} |
|||
} |
|||
sub line(Bitmap $bitmap, $x0 is copy, $x1 is copy, $y0 is copy, $y1 is copy) { |
|||
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 { |
|||
my $pix = Pixel.new(R => 100, G => 200, B => 0); |
|||
if $steep { |
|||
$bitmap.set-pixel($y, $x, $pix); |
|||
} else { |
|||
$bitmap.set-pixel($x, $y, $pix); |
|||
} |
|||
$error += $Δerror; |
|||
if $error >= 0.5 { |
|||
$y += $y-step; |
|||
$error -= 1.0; |
|||
} |
|||
} |
|||
}</lang> |
|||
=={{header|RapidQ}}== |
=={{header|RapidQ}}== |
||
Line 3,880: | Line 3,880: | ||
...|.................... |
...|.................... |
||
</pre> |
</pre> |
||
=={{header|Vedit macro language}}== |
=={{header|Vedit macro language}}== |