Bitmap/Bresenham's line algorithm: Difference between revisions

Content deleted Content added
No edit summary
m →‎version 1: added/changed whitespace and comments, optimized a subroutine.
Line 2,591: Line 2,591:
===version 1===
===version 1===
This REXX version has automatic scaling (for displaying the plot) and handles multiple line segments.
This REXX version has automatic scaling (for displaying the plot) and handles multiple line segments.
<lang rexx>/*REXX program plots/draws line(s) using the Bresenham's line algorithm.*/
<lang rexx>/*REXX program plots/draws line segments using the Bresenham's line algorithm.*/
@.='·' /*fill the array with middle─dots*/
@.='·' /*fill the array with middle─dots chars*/
parse arg data /*allow data point specifications*/
parse arg data /*allow the data point specifications. */
if data='' then data= '(1,8) (8,16) (16,8) (8,1) (1,8)' /*rhombus*/
if data='' then data= '(1,8) (8,16) (16,8) (8,1) (1,8)' /*◄────rhombus.*/
data=translate(data,,'()[]{}/,:;') /*elide chaff from data points. */
data=translate(data,,'()[]{}/,:;') /*elide chaff from the data points. */
/* [↓] data pt pairs ──► !.array.*/
/* [↓] data point pairs ───► !.array. */
do points=1 while data\='' /*put data points into an array. */
do points=1 while data\='' /*put the data points into an array (!)*/
parse var data x y data; !.points=x y /*extract line segments.*/
parse var data x y data; !.points=x y /*extract the line segments. */
if points==1 then do; minX=x; maxX=x; minY=y; maxY=y; end /*1st case*/
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)
minX=min(minX,x); maxX=max(maxX,x); minY=min(minY,y); maxY=max(maxY,y)
end /*points*/ /* [↑] data points pairs in !. */
end /*points*/ /* [↑] data points pairs in array !. */


border=2 /*border=extra space around plot.*/
border=2 /*border: is extra space around plot. */
minX=minX-border*2; maxX=maxX+border*2 /*min,max X for the plot display.*/
minX=minX-border*2; maxX=maxX+border*2 /*min and max X for the plot display.*/
minY=minY-border ; maxY=maxY+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 a 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 a pipe from lowest ───► highest*/
@.0.0='┼' /*define the plot's axis point. */
@.0.0='┼' /*define the plot's origin axis point. */
do seg=2 to points-1; _=seg-1 /*obtain the X,Y line coördinates*/
do seg=2 to points-1; _=seg-1 /*obtain the X and Y line coördinates*/
call draw_line !._, !.seg /*draw (plot) a line segment. */
call draw_line !._, !.seg /*draw (plot) a line segment. */
end /*seg*/ /* [↑] drawing the line segments*/
end /*seg*/ /* [↑] drawing the line segments. */
/* [↓] display the plot to term.*/
/* [↓] display the plot to terminal. */
do y=maxY to minY by -1; _= /*display plot one line at a time*/
do y=maxY to minY by -1; _= /*display the plot one line at a time. */
do x=minX to maxX /*traipse throught the X axis. */
do x=minX to maxX /*build line by examining the X axis.*/
_=_ || @.x.y /*construct a "line" of the plot.*/
_=_ || @.x.y /*construct/build a line of the plot. */
end /*x*/ /*(a line is a "row" of points.) */
end /*x*/ /* (a line is a "row" of points.) */
say _ /*display a "line" of the plot. */
say _ /*display a line of the plot──►terminal*/
end /*y*/ /* [↑] all done ploting the pts.*/
end /*y*/ /* [↑] all done plotting the points. */
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're all done. */
/*────────────────────────────────────────────────────────────────────────────*/
/*────────────────────────────────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); if x<xf then sx=+1 /*obtain X range, determine slope*/
dx=abs(xf-x); if x<xf then sx=+1 /*obtain X range, determine the slope*/
else sx=-1
else sx=-1
dy=abs(yf-y); if y<yf then sy=+1 /*obtain Y range, determine slope*/
dy=abs(yf-y); if y<yf then sy=+1 /*obtain Y range, determine the slope*/
else sy=-1
else sy=-1
err=dx-dy /*calc error between adjustments.*/
err=dx-dy /*calculate error between adjustments. */
do forever; @.x.y=plotChar /*plot the points until complete.*/
do forever; @.x.y=plotChar /*plot the points until it's complete. */
if x=xf & y=yf then leave /*are plot points at the finish? */
if x=xf & y=yf then return /*are the plot points at the finish? */
err2=err+err /*this is faster than err*2. */
err2=err+err /*addition is faster than: err*2. */
if err2 > -dy then do; err=err-dy; x=x+sx; 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
if err2 < dx then do; err=err+dx; y=y+sy; end
end /*forever*/
end /*forever*/</lang>
'''output''' &nbsp; when using the default input:
return</lang>
'''output''' when using the default input:
<pre>
<pre>
···│····················
···│····················