Bitmap/Bresenham's line algorithm: Difference between revisions

Content added Content deleted
(→‎version 1: simplified the program, eliminated the re-calculating of the min and max point values, removed the STYLE from the PRE html tag.)
(→‎version 1: re-worked program to handle multiple-line segments.)
Line 1,978: Line 1,978:
=={{header|REXX}}==
=={{header|REXX}}==
===version 1===
===version 1===
This REXX version has automatic scaling (for displaying the plot).
This REXX version has automatic scaling (for displaying the plot) and handles multiple line segments.
<lang rexx>/*REXX program plots/draws a line using the Bresenham's line algorithm.*/
<lang rexx>/*REXX program plots/draws line(s) using the Bresenham's line algorithm.*/
@.='·' /*fill the array with middle─dots*/
@.='·' /*fill the array with middle─dots*/
parse arg x1 y1 x2 y2 . /*allow specifying line─end pts. */
parse arg data /*allow data point specifications*/
if x1=='' | x1==',' then x1 = -1 /*if not specified, use default. */
if data='' then data= '(1,8) (8,16) (16,8) (8,1) (1,8)'
data=translate(data,,'()[]{}/,:;') /*elide chaff from data points. */
if y1=='' | y1==',' then y1 = -3 /* " " " " " */
if x2=='' | x2==',' then x2 = 6 /* " " " " " */
/* [↓] data pt pairs ──► !.array.*/
if y2=='' | y2==',' then y2 = 10 /* " " " " " */
do points=1 while data\='' /*put data points into an array. */
parse var data x y data; !.points=x y /*extract line segments.*/
if points==1 then do; minX=x; maxX=x; minY=y; maxY=y; end /*1st case*/
minX=min(minX,x); maxX=max(maxX,x); minY=min(minY,y); maxY=max(maxY,y)
end /*points*/ /* [↑] data points pairs in !. */

border=2 /*border=extra space around plot.*/
border=2 /*border=extra space around plot.*/
minX=min(x1,x2)-border*2; maxX=max(x1,x2)+border*2 /*min,max X display*/
minX=minX-border*2; maxX=maxX+border*2 /*min,max X for the plot display.*/
minY=min(y1,y2)-border ; maxY=max(y1,y2)+border /* " " Y " */
minY=minY-border ; maxY=maxY+border /* " " Y " " " " */
do x=minX to maxX; @.x.0='─'; end /*draw dash from left──► right.*/
do x=minX to maxX; @.x.0='─'; end /*draw dash from left──► right.*/
do y=minY to maxY; @.0.y='│'; end /*draw pipe from lowest──►highest*/
do y=minY to maxY; @.0.y='│'; end /*draw pipe from lowest──►highest*/
@.0.0='┼' /*define the plot's axis point. */
@.0.0='┼' /*define the plot's axis point. */
call draw_line x1, y1, x2, y2 /*call subroutine and draw line. */
do seg=2 to points-1; _=seg-1 /*obtain the X,Y line coördinates*/
call draw_line !._, !.seg /*draw (plot) a line segment. */
end /*seg*/ /* [↑] drawing the line segments*/
/* [↓] display the plot to term.*/
/* [↓] display the plot to term.*/
do y=maxY to minY by -1; _= /*display plot one line at a time*/
do y=maxY to minY by -1; _= /*display plot one line at a time*/
Line 2,002: Line 2,009:
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're done.*/
/*────────────────────────────────DRAW_LINE subroutine──────────────────*/
/*────────────────────────────────DRAW_LINE subroutine──────────────────*/
draw_line: procedure expose @.; parse arg x,y,xf,yf; plotChar='Θ'
draw_line: procedure expose @.; parse arg x y,xf yf; plotChar='Θ'
dx=abs(xf-x); dy=abs(yf-y)
dx=abs(xf-x); if x<xf then sx=+1 /*obtain X range, determine slope*/
else sx=-1
if x<xf then sx=+1
dy=abs(yf-y); if y<yf then sy=+1 /*obtain Y range, determine slope*/
else sx=-1
else sy=-1
if y<yf then sy=+1
err=dx-dy /*calc error between adjustments.*/
else sy=-1
err=dx-dy
do forever; @.x.y=plotChar /*plot the points until complete.*/
do forever; @.x.y=plotChar /*plot the points until complete.*/
if x=xf & y=yf then leave /*are plot points at the finish? */
if x=xf & y=yf then leave /*are plot points at the finish? */
if 2*err > -dy then do; err=err-dy; x=x+sx; end
err2=err+err /*this is faster than err*2. */
if 2*err < dx then do; err=err+dx; y=y+sy; end
if err2 > -dy then do; err=err-dy; x=x+sx; end
if err2 < dx then do; err=err+dx; y=y+sy; end
end /*while ··· */
end /*while ··· */
return</lang>
return</lang>
'''output''' when using the default input:
'''output''' when using the default input:
<pre>
<pre>
···············
···│····················
···············
···│····················
··········Θ····
··········Θ············
·········Θ·····
·········Θ·Θ···········
·········Θ·····
········Θ···Θ··········
········Θ······
···│····Θ·····Θ·········
········Θ······
···│···Θ·······Θ········
·······Θ·······
···│···Θ········Θ·······
·····│··Θ·······
···│··Θ··········Θ······
·····│·Θ········
···│·Θ············Θ·····
······Θ········
···│Θ··············Θ····
·····│Θ·········
····Θ············Θ·····
···│··Θ··········Θ······
─────┼Θ─────────
·····Θ··········
···│···Θ·······ΘΘ·······
·····Θ··········
···│····Θ·····Θ·········
····Θ│··········
········Θ···Θ··········
···············
·········Θ·Θ···········
···············
···│·······Θ············
───┼────────────────────
···│····················
</pre>
</pre>