Xiaolin Wu's line algorithm: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
|||
Line 2,315: | Line 2,315: | ||
img.drawLine(400, 700, x1.toFloat, 100) |
img.drawLine(400, 700, x1.toFloat, 100) |
||
img.savePNG("xiaoling_wu.png", compression = 9)</syntaxhighlight> |
img.savePNG("xiaoling_wu.png", compression = 9)</syntaxhighlight> |
||
=={{header|ObjectIcon}}== |
|||
The program puts up a window. In the window you can draw a line by left-mouse-button-push for one endpoint, and then right-mouse-button-push for the other endpoint. You can draw multiple lines. When you leave (by pressing "q", for instance, or closing the window), the program stores the image as a PNG. |
|||
Rather than vary the color as such, I vary the opacity. |
|||
<syntaxhighlight lang="objecticon"> |
|||
import |
|||
graphics, |
|||
ipl.graphics, |
|||
io |
|||
procedure main () |
|||
local width, height |
|||
local done, w, event |
|||
local x1, y1, x2, y2 |
|||
width := 640 |
|||
height := 480 |
|||
w := Window(). |
|||
set_size(width, height). |
|||
set_bg("white"). |
|||
set_canvas("normal") | stop(&why) |
|||
done := &no |
|||
while /done do |
|||
{ |
|||
if *w.pending() ~= 0 then |
|||
{ |
|||
event := w.event() |
|||
case event[1] of |
|||
{ |
|||
QuitEvents() : done := &yes |
|||
Mouse.LEFT_PRESS: |
|||
{ |
|||
x1 := event[2]; y1 := event[3] |
|||
} |
|||
Mouse.RIGHT_PRESS: |
|||
{ |
|||
x2 := event[2]; y2 := event[3] |
|||
draw_line (w, x1, y1, x2, y2) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
w.get_pixels().to_file("xiaolin_wu_line_algorithm_OI.png") |
|||
end |
|||
procedure draw_line (w, x0, y0, x1, y1) |
|||
local steep |
|||
local dx, dy, gradient |
|||
local xend, yend, xgap, intery |
|||
local xpxl1, ypxl1 |
|||
local xpxl2, ypxl2 |
|||
local x |
|||
x0 := real (x0) |
|||
y0 := real (y0) |
|||
x1 := real (x1) |
|||
y1 := real (y1) |
|||
# In Object Icon (as in Icon), comparisons DO NOT return boolean |
|||
# values! They either SUCCEED or they FAIL. Thus the need for an |
|||
# "if-then-else" here. |
|||
steep := if abs (y1 - y0) > abs (x1 - x0) then &yes else &no |
|||
if \steep then { x0 :=: y0; x1 :=: y1 } |
|||
if x0 > x1 then { x0 :=: x1; y0 :=: y1 } |
|||
dx := x1 - x0; dy := y1 - y0 |
|||
gradient := if dx = 0 then 1.0 else dy / dx |
|||
# Handle the first endpoint. |
|||
xend := round (x0); yend := y0 + (gradient * (xend - x0)) |
|||
xgap := rfpart (x0 + 0.5) |
|||
xpxl1 := xend; ypxl1 := ipart (yend) |
|||
if \steep then |
|||
{ |
|||
plot (w, ypxl1, xpxl2, rfpart (yend) * xgap) |
|||
plot (w, ypxl1 + 1, xpxl1, fpart(yend) * xgap) |
|||
} |
|||
else |
|||
{ |
|||
plot (w, xpxl1, ypxl1, rfpart (yend) * xgap) |
|||
plot (w, xpxl1, ypxl1 + 1, fpart (yend) * xgap) |
|||
} |
|||
# The first y-intersection. |
|||
intery := yend + gradient |
|||
# Handle the second endpoint. |
|||
xend := round (x1); yend := y1 + (gradient * (xend - x1)) |
|||
xgap := fpart (x1 + 0.5) |
|||
xpxl2 := xend; ypxl2 := ipart (yend) |
|||
if \steep then |
|||
{ |
|||
plot (w, ypxl2, xpxl2, rfpart (yend) * xgap) |
|||
plot (w, ypxl2 + 1, xpxl2, fpart (yend) * xgap) |
|||
} |
|||
else |
|||
{ |
|||
plot (w, xpxl2, ypxl2, rfpart (yend) * xgap) |
|||
plot (w, xpxl2, ypxl2 + 1, fpart (yend) * xgap) |
|||
} |
|||
if \steep then |
|||
every x := xpxl1 + 1 to xpxl2 - 1 do |
|||
{ |
|||
plot (w, ipart (intery), x, rfpart (intery)) |
|||
plot (w, ipart (intery) + 1, x, fpart (intery)) |
|||
intery := intery + gradient |
|||
} |
|||
else |
|||
every x := xpxl1 + 1 to xpxl2 - 1 do |
|||
{ |
|||
plot(w, x, ipart (intery), rfpart (intery)) |
|||
plot(w, x, ipart (intery) + 1, fpart (intery)) |
|||
intery := intery + gradient |
|||
} |
|||
return |
|||
end |
|||
procedure plot (w, x, y, c) |
|||
w.set_fg ("black " || round (100.0 * c) || "%") |
|||
w.draw_point (x, y) |
|||
return |
|||
end |
|||
procedure ipart (x) |
|||
local i |
|||
i := integer (x) |
|||
return (if i = x then i else if x < 0 then i - 1 else i) |
|||
end |
|||
procedure round (x) |
|||
return ipart (x + 0.5) |
|||
end |
|||
procedure fpart (x) |
|||
return x - ipart (x) |
|||
end |
|||
procedure rfpart (x) |
|||
return 1.0 - fpart (x) |
|||
end |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
An example: |
|||
[[File:Xiaolin wu line algorithm OI.2023.04.26.17.23.18.png|thumb|none|alt=Some straight lines, antialiased. Black on white.]] |
|||
=={{header|Pascal}}== |
=={{header|Pascal}}== |