Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
6
Task/Bitmap-Bresenhams-line-algorithm/00-META.yaml
Normal file
6
Task/Bitmap-Bresenhams-line-algorithm/00-META.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
category:
|
||||
- Graphics algorithms
|
||||
- Geometry
|
||||
from: http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm
|
||||
note: Raster graphics operations
|
||||
4
Task/Bitmap-Bresenhams-line-algorithm/00-TASK.txt
Normal file
4
Task/Bitmap-Bresenhams-line-algorithm/00-TASK.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
;Task:
|
||||
Using the data storage type defined on the [[Bitmap]] page for raster graphics images,
|
||||
<br>draw a line given two points with [[wp:Bresenham's line algorithm|Bresenham's line algorithm]].
|
||||
<br><br>
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
T Colour
|
||||
Byte r, g, b
|
||||
|
||||
F (r, g, b)
|
||||
.r = r
|
||||
.g = g
|
||||
.b = b
|
||||
|
||||
F ==(other)
|
||||
R .r == other.r & .g == other.g & .b == other.b
|
||||
|
||||
V black = Colour(0, 0, 0)
|
||||
V white = Colour(255, 255, 255)
|
||||
|
||||
T Bitmap
|
||||
Int width, height
|
||||
Colour background
|
||||
[[Colour]] map
|
||||
|
||||
F (width = 40, height = 40, background = white)
|
||||
assert(width > 0 & height > 0)
|
||||
.width = width
|
||||
.height = height
|
||||
.background = background
|
||||
.map = (0 .< height).map(h -> (0 .< @width).map(w -> @@background))
|
||||
|
||||
F fillrect(x, y, width, height, colour = black)
|
||||
assert(x >= 0 & y >= 0 & width > 0 & height > 0)
|
||||
L(h) 0 .< height
|
||||
L(w) 0 .< width
|
||||
.map[y + h][x + w] = colour
|
||||
|
||||
F chardisplay()
|
||||
V txt = .map.map(row -> row.map(bit -> (I bit == @@.background {‘ ’} E ‘@’)).join(‘’))
|
||||
txt = txt.map(row -> ‘|’row‘|’)
|
||||
txt.insert(0, ‘+’(‘-’ * .width)‘+’)
|
||||
txt.append(‘+’(‘-’ * .width)‘+’)
|
||||
print(reversed(txt).join("\n"))
|
||||
|
||||
F set(x, y, colour = black)
|
||||
.map[y][x] = colour
|
||||
|
||||
F get(x, y)
|
||||
R .map[y][x]
|
||||
|
||||
F line(x0, y0, x1, y1)
|
||||
‘Bresenham's line algorithm’
|
||||
V dx = abs(x1 - x0)
|
||||
V dy = abs(y1 - y0)
|
||||
V (x, y) = (x0, y0)
|
||||
V sx = I x0 > x1 {-1} E 1
|
||||
V sy = I y0 > y1 {-1} E 1
|
||||
I dx > dy
|
||||
V err = dx / 2.0
|
||||
L x != x1
|
||||
.set(x, y)
|
||||
err -= dy
|
||||
I err < 0
|
||||
y += sy
|
||||
err += dx
|
||||
x += sx
|
||||
E
|
||||
V err = dy / 2.0
|
||||
L y != y1
|
||||
.set(x, y)
|
||||
err -= dx
|
||||
I err < 0
|
||||
x += sx
|
||||
err += dy
|
||||
y += sy
|
||||
.set(x, y)
|
||||
|
||||
V bitmap = Bitmap(17, 17)
|
||||
L(x0, y0, x1, y1) ((1, 8, 8, 16), (8, 16, 16, 8), (16, 8, 8, 1), (8, 1, 1, 8))
|
||||
bitmap.line(x0, y0, x1, y1)
|
||||
bitmap.chardisplay()
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
* Bitmap/Bresenham's line algorithm - 13/05/2019
|
||||
BRESENH CSECT
|
||||
USING BRESENH,R13 base register
|
||||
B 72(R15) skip savearea
|
||||
DC 17F'0' savearea
|
||||
SAVE (14,12) save previous context
|
||||
ST R13,4(R15) link backward
|
||||
ST R15,8(R13) link forward
|
||||
LR R13,R15 set addressability
|
||||
LA R10,DATAXY @dataxy
|
||||
LA R8,1 p=1
|
||||
DO WHILE=(C,R8,LE,=A(POINTS)) do p=1 to points
|
||||
L R6,0(R10) x=dataxy((p-1)*2+1)
|
||||
L R7,4(R10) y=dataxy((p-1)*2+2)
|
||||
IF C,R8,EQ,=F'1' THEN if p=1 then
|
||||
ST R6,MINX minx=x
|
||||
ST R6,MAXX maxx=x
|
||||
ST R7,MINY miny=y
|
||||
ST R7,MAXY maxy=y
|
||||
ENDIF , endif
|
||||
IF C,R6,LT,MINX THEN if x<minx then
|
||||
ST R6,MINX minx=x
|
||||
ENDIF , endif
|
||||
IF C,R6,GT,MAXX THEN if x>maxx then
|
||||
ST R6,MAXX maxx=x
|
||||
ENDIF , endif
|
||||
IF C,R7,LT,MINY THEN if y<miny then
|
||||
ST R7,MINY miny=y
|
||||
ENDIF , endif
|
||||
IF C,R7,GT,MAXY THEN if y>maxy then
|
||||
ST R7,MAXY maxy=y
|
||||
ENDIF , endif
|
||||
LA R10,8(R10) @dataxy+=8
|
||||
LA R8,1(R8) p++
|
||||
ENDDO , enddo p
|
||||
L R1,MINX minx
|
||||
S R1,=A(BORDER*2) -border*2
|
||||
ST R1,MINX minx=minx-border*2
|
||||
L R1,MAXX maxx
|
||||
A R1,=A(BORDER*2) +border*2
|
||||
ST R1,MAXX maxx=maxx+border*2
|
||||
L R1,MINY miny
|
||||
S R1,=A(BORDER) -border
|
||||
ST R1,MINY miny=miny-border
|
||||
L R1,MAXY maxy
|
||||
A R1,=A(BORDER) +border
|
||||
ST R1,MAXY maxy=maxy+border
|
||||
L R1,MINX minx
|
||||
LCR R1,R1 -
|
||||
A R1,=F'1' +1
|
||||
ST R1,OX ox=-minx+1
|
||||
L R1,MINY miny
|
||||
LCR R1,R1 -
|
||||
A R1,=F'1' +1
|
||||
ST R1,OY oy=-miny+1
|
||||
LA R1,HMAPX hbound(map,1)
|
||||
S R1,OX wx=hbound(map,1)-ox
|
||||
IF C,R1,LT,MAXX THEN if maxx>wx then
|
||||
ST R1,MAXX maxx=wx
|
||||
ENDIF , endif
|
||||
LA R1,HMAPY hbound(map,2)
|
||||
S R1,OY wy=hbound(map,2)-oy
|
||||
IF C,R1,LT,MAXY THEN if maxy>wy then
|
||||
ST R1,MAXY maxy=wy
|
||||
ENDIF , endif
|
||||
L R6,MINX x=minx
|
||||
DO WHILE=(C,R6,LE,MAXX) do x=minx to maxx
|
||||
L R1,OY oy
|
||||
BCTR R1,0 1
|
||||
MH R1,=AL2(HMAPX) dim(x)
|
||||
AR R1,R6 x
|
||||
A R1,OX ox
|
||||
LA R1,MAP-1(R1) map(0+oy,x+ox)
|
||||
MVC 0(1,R1),=C'-' map(0+oy,x+ox)='-'
|
||||
A R6,=F'1' x++
|
||||
ENDDO , enddo x
|
||||
L R7,MINY y=miny
|
||||
DO WHILE=(C,R7,LE,MAXY) do y=miny to maxy
|
||||
LR R1,R7 y
|
||||
A R1,OY +oy
|
||||
BCTR R1,0 -1
|
||||
MH R1,=AL2(HMAPX) *dim(x)
|
||||
A R1,OX +ox
|
||||
LA R1,MAP-1(R1) @map(y+oy,0+ox)
|
||||
MVC 0(1,R1),=C'|' map(y+oy,0+ox)='|'
|
||||
A R7,=F'1' y++
|
||||
ENDDO , enddo y
|
||||
L R1,OY +oy
|
||||
BCTR R1,0 -1
|
||||
MH R1,=AL2(HMAPX) *dim(x)
|
||||
A R1,OX +ox
|
||||
LA R1,MAP-1(R1) @map(0+oy,0+ox)
|
||||
MVC 0(1,R1),=C'+' map(0+oy,0+ox)='+'
|
||||
LA R10,POINTS points
|
||||
BCTR R10,0 pn=points-1
|
||||
LA R9,DATAXY @dataxy
|
||||
LA R8,1 p=1
|
||||
DO WHILE=(CR,R8,LE,R10) do p=1 to points-1
|
||||
L R6,0(R9) x=dataxy((p-1)*2+1)
|
||||
L R7,4(R9) y=dataxy((p-1)*2+2)
|
||||
L R4,8(R9) xf=dataxy(p*2+1)
|
||||
L R5,12(R9) yf=dataxy(p*2+2)
|
||||
LR R2,R4 xf
|
||||
SR R2,R6 -x
|
||||
LPR R2,R2 abs()
|
||||
ST R2,DX dx=abs(xf-x)
|
||||
LR R2,R5 xf
|
||||
SR R2,R7 -y
|
||||
LPR R2,R2 abs()
|
||||
ST R2,DY dy=abs(yf-y)
|
||||
IF CR,R6,LT,R4 THEN if x<xf then
|
||||
MVC SX,=F'1' sx=+1
|
||||
ELSE , else
|
||||
MVC SX,=F'-1' sx=-1
|
||||
ENDIF , endif
|
||||
IF CR,R7,LT,R5 THEN if y<yf then
|
||||
MVC SY,=F'1' sy=+1
|
||||
ELSE , else
|
||||
MVC SY,=F'-1' sy=-1
|
||||
ENDIF , endif
|
||||
L R2,DX dx
|
||||
S R2,DY -dy
|
||||
ST R2,ERR err=dx-dy
|
||||
LOOP EQU * loop forever
|
||||
LR R1,R7 y
|
||||
A R1,OY +oy
|
||||
BCTR R1,0 -1
|
||||
MH R1,=AL2(HMAPX) *dim(x)
|
||||
AR R1,R6 +x
|
||||
A R1,OX +ox
|
||||
LA R1,MAP-1(R1) @map(y+oy,x+ox)
|
||||
MVC 0(1,R1),=C'X' map(y+oy,x+ox)='X'
|
||||
CR R6,R4 if x=xf
|
||||
BNE STAYDO ~
|
||||
CR R7,R5 if y=yf
|
||||
BE EXITLOOP if x=xf and y=yf then leave loop
|
||||
STAYDO L R0,ERR err
|
||||
A R0,ERR err+err
|
||||
ST R0,ERR2 err2=err+err
|
||||
L R0,DY dy
|
||||
LCR R0,R0 -dy
|
||||
IF C,R0,LT,ERR2 THEN if err2>-dy then
|
||||
A R0,ERR -dy+err
|
||||
ST R0,ERR err=err-dy
|
||||
A R6,SX x=x+sx
|
||||
ENDIF , endif
|
||||
L R0,DX dx
|
||||
IF C,R0,GT,ERR2 THEN if err2<dx then
|
||||
L R0,ERR err
|
||||
A R0,DX +dx
|
||||
ST R0,ERR err=err+dx
|
||||
A R7,SY y=y+sy
|
||||
ENDIF , endif
|
||||
B LOOP endloop
|
||||
EXITLOOP LA R9,8(R9) @dataxy+=2
|
||||
LA R8,1(R8) p++
|
||||
ENDDO , enddo p
|
||||
LA R9,MAP+(HMAPX*HMAPY)-HMAPX @map
|
||||
L R7,MAXY y=maxy
|
||||
DO WHILE=(C,R7,GE,MINY) do y=maxy to miny by -1
|
||||
MVC PG(HMAPX),0(R9) output map(x,*)
|
||||
XPRNT PG,L'PG print buffer
|
||||
S R9,=A(HMAPX) @pg
|
||||
S R7,=F'1' y--
|
||||
ENDDO , enddo y
|
||||
L R13,4(0,R13) restore previous savearea pointer
|
||||
RETURN (14,12),RC=0 restore registers from calling sav
|
||||
BORDER EQU 2 border size
|
||||
POINTS EQU (MAP-DATAXY)/L'DATAXY/2
|
||||
HMAPX EQU 24 dim(map,1)
|
||||
HMAPY EQU 20 dim(map,2)
|
||||
DATAXY DC F'1',F'8',F'8',F'16',F'16',F'8',F'8',F'1',F'1',F'8'
|
||||
MAP DC (HMAPX*HMAPY)CL1'.' map(hmapx,hmapy)
|
||||
OX DS F
|
||||
OY DS F
|
||||
MINX DS F
|
||||
MAXX DS F
|
||||
MINY DS F
|
||||
MAXY DS F
|
||||
DX DS F
|
||||
DY DS F
|
||||
SX DS F
|
||||
SY DS F
|
||||
ERR DS F
|
||||
ERR2 DS F
|
||||
PG DC CL80' ' buffer
|
||||
REGEQU
|
||||
END BRESENH
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*- #
|
||||
|
||||
line OF class image := (REF IMAGE picture, POINT start, stop, PIXEL color)VOID:
|
||||
BEGIN
|
||||
REAL dx = ABS (x OF stop - x OF start),
|
||||
dy = ABS (y OF stop - y OF start);
|
||||
REAL err;
|
||||
POINT here := start,
|
||||
step := (1, 1);
|
||||
IF x OF start > x OF stop THEN
|
||||
x OF step := -1
|
||||
FI;
|
||||
IF y OF start > y OF stop THEN
|
||||
y OF step := -1
|
||||
FI;
|
||||
IF dx > dy THEN
|
||||
err := dx / 2;
|
||||
WHILE x OF here /= x OF stop DO
|
||||
picture[x OF here, y OF here] := color;
|
||||
err -:= dy;
|
||||
IF err < 0 THEN
|
||||
y OF here +:= y OF step;
|
||||
err +:= dx
|
||||
FI;
|
||||
x OF here +:= x OF step
|
||||
OD
|
||||
ELSE
|
||||
err := dy / 2;
|
||||
WHILE y OF here /= y OF stop DO
|
||||
picture[x OF here, y OF here] := color;
|
||||
err -:= dx;
|
||||
IF err < 0 THEN
|
||||
x OF here +:= x OF step;
|
||||
err +:= dy
|
||||
FI;
|
||||
y OF here +:= y OF step
|
||||
OD
|
||||
FI;
|
||||
picture[x OF here, y OF here] := color # ensure dots to be drawn #
|
||||
END # line #;
|
||||
|
||||
SKIP
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/a68g --script #
|
||||
# -*- coding: utf-8 -*- #
|
||||
|
||||
PR READ "prelude/Bitmap.a68" PR; # c.f. [[rc:Bitmap]] #
|
||||
PR READ "prelude/Bitmap/Bresenhams_line_algorithm.a68" PR;
|
||||
|
||||
### The test program: ###
|
||||
test:(
|
||||
REF IMAGE x = INIT LOC[1:16, 1:16]PIXEL;
|
||||
(fill OF class image)(x, white OF class image);
|
||||
(line OF class image)(x, ( 1, 8), ( 8,16), black OF class image);
|
||||
(line OF class image)(x, ( 8,16), (16, 8), black OF class image);
|
||||
(line OF class image)(x, (16, 8), ( 8, 1), black OF class image);
|
||||
(line OF class image)(x, ( 8, 1), ( 1, 8), black OF class image);
|
||||
(print OF class image)(x)
|
||||
)
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
INCLUDE "H6:RGBLINE.ACT" ;from task Bresenham's line algorithm
|
||||
|
||||
RGB black,yellow,violet,blue
|
||||
|
||||
PROC DrawImage(RgbImage POINTER img BYTE x,y)
|
||||
RGB POINTER ptr
|
||||
BYTE i,j
|
||||
|
||||
ptr=img.data
|
||||
FOR j=0 TO img.h-1
|
||||
DO
|
||||
FOR i=0 TO img.w-1
|
||||
DO
|
||||
IF RgbEqual(ptr,yellow) THEN
|
||||
Color=1
|
||||
ELSEIF RgbEqual(ptr,violet) THEN
|
||||
Color=2
|
||||
ELSEIF RgbEqual(ptr,blue) THEN
|
||||
Color=3
|
||||
ELSE
|
||||
Color=0
|
||||
FI
|
||||
Plot(x+i,y+j)
|
||||
ptr==+RGBSIZE
|
||||
OD
|
||||
OD
|
||||
RETURN
|
||||
|
||||
PROC Main()
|
||||
RgbImage img
|
||||
BYTE CH=$02FC,width=[81],height=[51],st=[5]
|
||||
BYTE ARRAY ptr(12393)
|
||||
BYTE c,i,n
|
||||
INT x,y,nx,ny
|
||||
RGB POINTER col
|
||||
|
||||
Graphics(7+16)
|
||||
SetColor(0,13,12) ;yellow
|
||||
SetColor(1,4,8) ;violet
|
||||
SetColor(2,8,6) ;blue
|
||||
SetColor(4,0,0) ;black
|
||||
|
||||
RgbBlack(black)
|
||||
RgbYellow(yellow)
|
||||
RgbViolet(violet)
|
||||
RgbBlue(blue)
|
||||
|
||||
InitRgbImage(img,width,height,ptr)
|
||||
FillRgbImage(img,black)
|
||||
|
||||
nx=width/st ny=height/st
|
||||
FOR n=0 TO 2*nx+2*ny-1
|
||||
DO
|
||||
IF n MOD 3=0 THEN col=yellow
|
||||
ELSEIF n MOD 3=1 THEN col=violet
|
||||
ELSE col=blue FI
|
||||
|
||||
IF n<nx THEN
|
||||
x=n*st y=0
|
||||
ELSEIF n<nx+ny THEN
|
||||
x=width-1 y=(n-nx)*st
|
||||
ELSEIF n<2*nx+ny THEN
|
||||
x=width-1-(n-nx-ny)*st y=height-1
|
||||
ELSE
|
||||
x=0 y=height-1-(n-2*nx-ny)*st
|
||||
FI
|
||||
RgbLine(img,width/2,height/2,x,y,col)
|
||||
OD
|
||||
|
||||
DrawImage(img,(160-width)/2,(96-height)/2)
|
||||
|
||||
DO UNTIL CH#$FF OD
|
||||
CH=$FF
|
||||
RETURN
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
procedure Line (Picture : in out Image; Start, Stop : Point; Color : Pixel) is
|
||||
DX : constant Float := abs Float (Stop.X - Start.X);
|
||||
DY : constant Float := abs Float (Stop.Y - Start.Y);
|
||||
Err : Float;
|
||||
X : Positive := Start.X;
|
||||
Y : Positive := Start.Y;
|
||||
Step_X : Integer := 1;
|
||||
Step_Y : Integer := 1;
|
||||
begin
|
||||
if Start.X > Stop.X then
|
||||
Step_X := -1;
|
||||
end if;
|
||||
if Start.Y > Stop.Y then
|
||||
Step_Y := -1;
|
||||
end if;
|
||||
if DX > DY then
|
||||
Err := DX / 2.0;
|
||||
while X /= Stop.X loop
|
||||
Picture (X, Y) := Color;
|
||||
Err := Err - DY;
|
||||
if Err < 0.0 then
|
||||
Y := Y + Step_Y;
|
||||
Err := Err + DX;
|
||||
end if;
|
||||
X := X + Step_X;
|
||||
end loop;
|
||||
else
|
||||
Err := DY / 2.0;
|
||||
while Y /= Stop.Y loop
|
||||
Picture (X, Y) := Color;
|
||||
Err := Err - DX;
|
||||
if Err < 0.0 then
|
||||
X := X + Step_X;
|
||||
Err := Err + DY;
|
||||
end if;
|
||||
Y := Y + Step_Y;
|
||||
end loop;
|
||||
end if;
|
||||
Picture (X, Y) := Color; -- Ensure dots to be drawn
|
||||
end Line;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
X : Image (1..16, 1..16);
|
||||
begin
|
||||
Fill (X, White);
|
||||
Line (X, ( 1, 8), ( 8,16), Black);
|
||||
Line (X, ( 8,16), (16, 8), Black);
|
||||
Line (X, (16, 8), ( 8, 1), Black);
|
||||
Line (X, ( 8, 1), ( 1, 8), Black);
|
||||
Print (X);
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
10 HGR :FULLSCREEN = PEEK (49234)
|
||||
20 HCOLOR= 3
|
||||
30 FOR N = 3 TO 279 STEP 4
|
||||
40 X1 = 276:Y1 = 189:X2 = N:Y2 = 1: GOSUB 100"PLOT LINE"
|
||||
50 NEXT N
|
||||
60 FOR N = 3 TO 191 STEP 3
|
||||
70 X1 = 276:Y1 = 190:X2 = 2:Y2 = N: GOSUB 100"PLOT LINE"
|
||||
80 NEXT N
|
||||
90 END
|
||||
100 DX = ABS (X2 - X1)
|
||||
110 SX = SGN (X2 - X1)
|
||||
120 DY = - ABS (Y2 - Y1)
|
||||
130 SY = SGN (Y2 - Y1)
|
||||
140 ERR = DX + DY
|
||||
150 FOR WHILE = 0 TO 1 STEP 0
|
||||
160 HPLOT X1,Y1
|
||||
170 IF X1 = X2 AND Y1 = Y2 THEN RETURN
|
||||
180 E2 = 2 * ERR
|
||||
190 IF E2 > = DY AND X1 = X2 THEN RETURN
|
||||
200 IF E2 > = DY THEN ERR = ERR + DY:X1 = X1 + SX
|
||||
210 IF E2 < = DX AND Y1 = Y2 THEN RETURN
|
||||
220 IF E2 < = DX THEN ERR = ERR + DX:Y1 = Y1 + SY
|
||||
230 NEXT WHILE
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
Blue := Color(0,0,255)
|
||||
White := Color(255,255,255)
|
||||
Bitmap := Bitmap(100,100,Blue) ;create a 100*100 blue bitmap
|
||||
Line(Bitmap,White,5,10,60,80) ;draw a white line from (5,10) to (60,80)
|
||||
Bitmap.Write("Line.ppm") ;write the bitmap to file
|
||||
|
||||
Line(ByRef Bitmap,ByRef Color,PosX1,PosY1,PosX2,PosY2)
|
||||
{
|
||||
DeltaX := Abs(PosX2 - PosX1), DeltaY := -Abs(PosY2 - PosY1) ;calculate deltas
|
||||
StepX := ((PosX1 < PosX2) ? 1 : -1), StepY := ((PosY1 < PosY2) ? 1 : -1) ;calculate steps
|
||||
ErrorValue := DeltaX + DeltaY ;calculate error value
|
||||
Loop ;loop over the pixel values
|
||||
{
|
||||
Bitmap[PosX1,PosX2] := Color
|
||||
If (PosX1 = PosX2 && PosY1 = PosY2)
|
||||
Break
|
||||
Temp1 := ErrorValue << 1, ((Temp1 > DeltaY) ? (ErrorValue += DeltaY, PosX1 += StepX) : ""), ((Temp1 < DeltaX) ? (ErrorValue += DeltaX, PosY1 += StepY) : "") ;move forward
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
Local $var = drawBresenhamLine(2, 3, 2, 6)
|
||||
|
||||
Func drawBresenhamLine($iX0, $iY0, $iX1, $iY1)
|
||||
Local $iDx = Abs($iX1 - $iX0)
|
||||
Local $iSx = $iX0 < $iX1 ? 1 : -1
|
||||
Local $iDy = Abs($iY1 - $iY0)
|
||||
Local $iSy = $iY0 < $iY1 ? 1 : -1
|
||||
Local $iErr = ($iDx > $iDy ? $iDx : -$iDy) / 2, $e2
|
||||
|
||||
While $iX0 <= $iX1
|
||||
ConsoleWrite("plot( $x=" & $iX0 & ", $y=" & $iY0 & " )" & @LF)
|
||||
If ($iX0 = $iX1) And ($iY0 = $iY1) Then Return
|
||||
$e2 = $iErr
|
||||
If ($e2 > -$iDx) Then
|
||||
$iErr -= $iDy
|
||||
$iX0 += $iSx
|
||||
EndIf
|
||||
If ($e2 < $iDy) Then
|
||||
$iErr += $iDx
|
||||
$iY0 += $iSy
|
||||
EndIf
|
||||
WEnd
|
||||
EndFunc ;==>drawBresenhamLine
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
1500 REM === Draw a line. Ported from C version
|
||||
1510 REM Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
|
||||
1520 DX = ABS(X2 - X1):SX = -1:IF X1 < X2 THEN SX = 1
|
||||
1530 DY = ABS(Y2 - Y1):SY = -1:IF Y1 < Y2 THEN SY = 1
|
||||
1540 ER = -DY:IF DX > DY THEN ER = DX
|
||||
1550 ER = INT(ER / 2)
|
||||
1560 PLOT X1,Y1:REM This command may differ depending on BASIC dialect
|
||||
1570 IF X1 = X2 AND Y1 = Y2 THEN RETURN
|
||||
1580 E2 = ER
|
||||
1590 IF E2 > -DX THEN ER = ER - DY:X1 = X1 + SX
|
||||
1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY
|
||||
1610 GOTO 1560
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set width=87
|
||||
set height=51
|
||||
|
||||
mode %width%,%height%
|
||||
|
||||
set "grid="
|
||||
set /a resolution=height*width
|
||||
for /l %%i in (1,1,%resolution%) do (
|
||||
set "grid=!grid! "
|
||||
)
|
||||
call :line 1 1 5 5
|
||||
call :line 9 30 60 7
|
||||
call :line 9 30 60 50
|
||||
call :line 52 50 32 1
|
||||
echo:%grid%
|
||||
pause>nul
|
||||
exit
|
||||
|
||||
:line
|
||||
set x1=%1
|
||||
set y1=%2
|
||||
set x2=%3
|
||||
set y2=%4
|
||||
|
||||
set /a dx=x2-x1
|
||||
set /a dy=y2-y1
|
||||
|
||||
::Clipping done to avoid overflow
|
||||
|
||||
if %dx% neq 0 set /a o=y1 - ( x1 * dy / dx )
|
||||
if %x1% leq %x2% (
|
||||
if %x1% geq %width% goto :eof
|
||||
if %x2% lss 0 goto :eof
|
||||
|
||||
if %x1% lss 0 (
|
||||
if %dx% neq 0 set y1=%o%
|
||||
set x1=0
|
||||
)
|
||||
if %x2% geq %width% (
|
||||
set /a x2= width - 1
|
||||
if %dx% neq 0 set /a "y2= x2 * dy / dx + o"
|
||||
)
|
||||
) else (
|
||||
if %x2% geq %width% goto :eof
|
||||
if %x1% lss 0 goto :eof
|
||||
|
||||
if %x2% lss 0 (
|
||||
if %dx% neq 0 set y2=%o%
|
||||
set x2=0
|
||||
)
|
||||
if %x1% geq %width% (
|
||||
set /a x1=width - 1
|
||||
if %dx% neq 0 set /a "y1= x1 * dy / dx + o"
|
||||
)
|
||||
)
|
||||
if %y1% leq %y2% (
|
||||
if %y1% geq %height% goto :eof
|
||||
if %y2% lss 0 goto :eof
|
||||
|
||||
if %y1% lss 0 (
|
||||
set y1=0
|
||||
if %dx% neq 0 set /a x1= - o * dx /dy
|
||||
)
|
||||
if %y2% geq %height% (
|
||||
set /a y2=height-1
|
||||
if %dx% neq 0 set /a "x2= (y2 - o) * dx /dy"
|
||||
)
|
||||
) else (
|
||||
if %y2% geq %height% goto :eof
|
||||
if %y1% lss 0 goto :eof
|
||||
|
||||
if %y2% lss 0 (
|
||||
set y2=0
|
||||
if %dx% neq 0 set /a "x2= - o * dx /dy"
|
||||
)
|
||||
if %y1% geq %height% (
|
||||
set /a y1=height-1
|
||||
if %dx% neq 0 set /a "x1= (y1 - o) * dx /dy"
|
||||
)
|
||||
)
|
||||
|
||||
:: Start of Bresenham's algorithm
|
||||
|
||||
set stepy=1
|
||||
set stepx=1
|
||||
|
||||
set /a dx=x2-x1
|
||||
set /a dy=y2-y1
|
||||
|
||||
if %dy% lss 0 set /a "dy=-dy","stepy=-1"
|
||||
if %dx% lss 0 set /a "dx=-dx","stepx=-1"
|
||||
|
||||
set /a "dy <<= 1"
|
||||
set /a "dx <<= 1"
|
||||
|
||||
if %dx% gtr %dy% (
|
||||
set /a "fraction=dy-(dx>>1)"
|
||||
set /a "cursor=y1*width + x1"
|
||||
for /l %%x in (%x1%,%stepx%,%x2%) do (
|
||||
set /a cursorP=cursor+1
|
||||
for /f "tokens=1-2" %%g in ("!cursor! !cursorP!") do set "grid=!grid:~0,%%g!Û!grid:~%%h!"
|
||||
if !fraction! geq 0 (
|
||||
set /a y1+=stepy
|
||||
set /a cursor+=stepy*width
|
||||
set /a fraction-=dx
|
||||
)
|
||||
set /a fraction+=dy
|
||||
set /a cursor+=stepx
|
||||
)
|
||||
) else (
|
||||
set /a "fraction=dx-(dy>>1)"
|
||||
set /a "cursor=y1*width + x1"
|
||||
for /l %%y in (%y1%,%stepy%,%y2%) do (
|
||||
set /a cursorP=cursor+1
|
||||
for /f "tokens=1-2" %%g in ("!cursor! !cursorP!") do set "grid=!grid:~0,%%g!Û!grid:~%%h!"
|
||||
if !fraction! geq 0 (
|
||||
set /a x1+=stepx
|
||||
set /a cursor+=stepx
|
||||
set /a fraction-=dy
|
||||
)
|
||||
set /a fraction+=dx
|
||||
set /a cursor+=width*stepy
|
||||
)
|
||||
)
|
||||
goto :eof
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
void Line( float x1, float y1, float x2, float y2, const Color& color )
|
||||
{
|
||||
// Bresenham's line algorithm
|
||||
const bool steep = (fabs(y2 - y1) > fabs(x2 - x1));
|
||||
if(steep)
|
||||
{
|
||||
std::swap(x1, y1);
|
||||
std::swap(x2, y2);
|
||||
}
|
||||
|
||||
if(x1 > x2)
|
||||
{
|
||||
std::swap(x1, x2);
|
||||
std::swap(y1, y2);
|
||||
}
|
||||
|
||||
const float dx = x2 - x1;
|
||||
const float dy = fabs(y2 - y1);
|
||||
|
||||
float error = dx / 2.0f;
|
||||
const int ystep = (y1 < y2) ? 1 : -1;
|
||||
int y = (int)y1;
|
||||
|
||||
const int maxX = (int)x2;
|
||||
|
||||
for(int x=(int)x1; x<=maxX; x++)
|
||||
{
|
||||
if(steep)
|
||||
{
|
||||
SetPixel(y,x, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPixel(x,y, color);
|
||||
}
|
||||
|
||||
error -= dy;
|
||||
if(error < 0)
|
||||
{
|
||||
y += ystep;
|
||||
error += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
static class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
new Bitmap(200, 200)
|
||||
.DrawLine(0, 0, 199, 199, Color.Black).DrawLine(199,0,0,199,Color.Black)
|
||||
.DrawLine(50, 75, 150, 125, Color.Blue).DrawLine(150, 75, 50, 125, Color.Blue)
|
||||
.Save("line.png", ImageFormat.Png);
|
||||
}
|
||||
static Bitmap DrawLine(this Bitmap bitmap, int x0, int y0, int x1, int y1, Color color)
|
||||
{
|
||||
int dx = Math.Abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||
int dy = Math.Abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||
int err = (dx > dy ? dx : -dy) / 2, e2;
|
||||
for(;;) {
|
||||
bitmap.SetPixel(x0, y0, color);
|
||||
if (x0 == x1 && y0 == y1) break;
|
||||
e2 = err;
|
||||
if (e2 > -dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
void line(int x0, int y0, int x1, int y1) {
|
||||
|
||||
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||
int err = (dx>dy ? dx : -dy)/2, e2;
|
||||
|
||||
for(;;){
|
||||
setPixel(x0,y0);
|
||||
if (x0==x1 && y0==y1) break;
|
||||
e2 = err;
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
(defn draw-line
|
||||
"Draw a line from x1,y1 to x2,y2 using Bresenham's, to a java BufferedImage in the colour of pixel."
|
||||
[buffer x1 y1 x2 y2 pixel]
|
||||
(let [dist-x (Math/abs (- x1 x2))
|
||||
dist-y (Math/abs (- y1 y2))
|
||||
steep (> dist-y dist-x)]
|
||||
(let [[x1 y1 x2 y2] (if steep [y1 x1 y2 x2] [x1 y1 x2 y2])]
|
||||
(let [[x1 y1 x2 y2] (if (> x1 x2) [x2 y2 x1 y1] [x1 y1 x2 y2])]
|
||||
(let [delta-x (- x2 x1)
|
||||
delta-y (Math/abs (- y1 y2))
|
||||
y-step (if (< y1 y2) 1 -1)]
|
||||
|
||||
(let [plot (if steep
|
||||
#(.setRGB buffer (int %1) (int %2) pixel)
|
||||
#(.setRGB buffer (int %2) (int %1) pixel))]
|
||||
|
||||
(loop [x x1 y y1 error (Math/floor (/ delta-x 2)) ]
|
||||
(plot x y)
|
||||
(if (< x x2)
|
||||
; Rather then rebind error, test that it is less than delta-y rather than zero
|
||||
(if (< error delta-y)
|
||||
(recur (inc x) (+ y y-step) (+ error (- delta-x delta-y)))
|
||||
(recur (inc x) y (- error delta-y)))))))))))
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
drawBresenhamLine = (x0, y0, x1, y1) ->
|
||||
dx = Math.abs(x1 - x0)
|
||||
sx = if x0 < x1 then 1 else -1
|
||||
dy = Math.abs(y1 - y0)
|
||||
sy = if y0 < y1 then 1 else -1
|
||||
err = (if dx>dy then dx else -dy) / 2
|
||||
|
||||
loop
|
||||
setPixel(x0, y0)
|
||||
break if x0 == x1 && y0 == y1
|
||||
e2 = err
|
||||
if e2 > -dx
|
||||
err -= dy
|
||||
x0 += sx
|
||||
if e2 < dy
|
||||
err += dx
|
||||
y0 += sy
|
||||
null
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
10 rem bresenham line algorihm
|
||||
20 rem translated from purebasic
|
||||
30 x0=10 : rem start x co-ord
|
||||
40 y0=15 : rem start y co-ord
|
||||
50 x1=30 : rem end x co-ord
|
||||
60 y1=20 : rem end y co-ord
|
||||
70 se=0 : rem 0 = steep 1 = !steep
|
||||
80 ns=25 : rem num segments
|
||||
90 dim pt(ns,2) : rem points in line
|
||||
100 sc=1024 : rem start of screen memory
|
||||
110 sw=40 : rem screen width
|
||||
120 sh=25 : rem screen height
|
||||
130 pc=42 : rem plot character '*'
|
||||
140 gosub 1000
|
||||
150 end
|
||||
1000 rem plot line
|
||||
1010 if abs(y1-y0)>abs(x1-x0) then se=1:tp=y0:y0=x0:x0=tp:tp=y1:y1=x1:x1=tp
|
||||
1020 if x0>x1 then tp=x1:x1=x0:x0=tp:tp=y1:y1=y0:y0=tp
|
||||
1030 dx=x1-x0
|
||||
1040 dy=abs(y1-y0)
|
||||
1050 er=dx/2
|
||||
1060 y=y0
|
||||
1070 ys=-1
|
||||
1080 if y0<y1 then ys = 1
|
||||
1090 for x=x0 to x1
|
||||
1100 if se=1 then p0=y: p1=x:gosub 2000:goto 1120
|
||||
1110 p0=x: p1=y: gosub 2000
|
||||
1120 er=er-dy
|
||||
1130 if er<0 then y=y+ys:er=er+dx
|
||||
1140 next x
|
||||
1150 return
|
||||
2000 rem plot individual point
|
||||
2010 rem p0 == plot point x
|
||||
2020 rem p1 == plot point y
|
||||
2030 sl=p0+(p1*sw)
|
||||
2040 rem make sure we dont write beyond screen memory
|
||||
2050 if sl<(sw*sh) then poke sc+sl,pc
|
||||
2060 return
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
(defun draw-line (buffer x1 y1 x2 y2 pixel)
|
||||
(declare (type rgb-pixel-buffer buffer))
|
||||
(declare (type integer x1 y1 x2 y2))
|
||||
(declare (type rgb-pixel pixel))
|
||||
(let* ((dist-x (abs (- x1 x2)))
|
||||
(dist-y (abs (- y1 y2)))
|
||||
(steep (> dist-y dist-x)))
|
||||
(when steep
|
||||
(psetf x1 y1 y1 x1
|
||||
x2 y2 y2 x2))
|
||||
(when (> x1 x2)
|
||||
(psetf x1 x2 x2 x1
|
||||
y1 y2 y2 y1))
|
||||
(let* ((delta-x (- x2 x1))
|
||||
(delta-y (abs (- y1 y2)))
|
||||
(error (floor delta-x 2))
|
||||
(y-step (if (< y1 y2) 1 -1))
|
||||
(y y1))
|
||||
(loop
|
||||
:for x :upfrom x1 :to x2
|
||||
:do (if steep
|
||||
(setf (rgb-pixel buffer x y) pixel)
|
||||
(setf (rgb-pixel buffer y x) pixel))
|
||||
(setf error (- error delta-y))
|
||||
(when (< error 0)
|
||||
(incf y y-step)
|
||||
(incf error delta-x))))
|
||||
buffer))
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
module bitmap_bresenhams_line_algorithm;
|
||||
|
||||
import std.algorithm, std.math, bitmap;
|
||||
|
||||
void drawLine(Color)(Image!Color img,
|
||||
size_t x1, size_t y1,
|
||||
in size_t x2, in size_t y2,
|
||||
in Color color)
|
||||
pure nothrow @nogc {
|
||||
immutable int dx = x2 - x1;
|
||||
immutable int ix = (dx > 0) - (dx < 0);
|
||||
immutable size_t dx2 = abs(dx) * 2;
|
||||
int dy = y2 - y1;
|
||||
immutable int iy = (dy > 0) - (dy < 0);
|
||||
immutable size_t dy2 = abs(dy) * 2;
|
||||
img[x1, y1] = color;
|
||||
|
||||
if (dx2 >= dy2) {
|
||||
int error = dy2 - (dx2 / 2);
|
||||
while (x1 != x2) {
|
||||
if (error >= 0 && (error || (ix > 0))) {
|
||||
error -= dx2;
|
||||
y1 += iy;
|
||||
}
|
||||
|
||||
error += dy2;
|
||||
x1 += ix;
|
||||
img[x1, y1] = color;
|
||||
}
|
||||
} else {
|
||||
int error = dx2 - (dy2 / 2);
|
||||
while (y1 != y2) {
|
||||
if (error >= 0 && (error || (iy > 0))) {
|
||||
error -= dy2;
|
||||
x1 += ix;
|
||||
}
|
||||
|
||||
error += dx2;
|
||||
y1 += iy;
|
||||
img[x1, y1] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
version (bitmap_bresenhams_line_algorithm_main) {
|
||||
void main() {
|
||||
auto img = new Image!RGB(25, 22);
|
||||
img.drawLine(5, 5, 15, 20, RGB.white);
|
||||
img.drawLine(3, 20, 10, 12, RGB.white);
|
||||
img.textualShow();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
procedure drawLine (bitmap : TBitmap; xStart, yStart, xEnd, yEnd : integer; color : TAlphaColor);
|
||||
// Bresenham's Line Algorithm. Byte, March 1988, pp. 249-253.
|
||||
// Modified from http://www.efg2.com/Lab/Library/Delphi/Graphics/Bresenham.txt and tested.
|
||||
var
|
||||
a, b : integer; // displacements in x and y
|
||||
d : integer; // decision variable
|
||||
diag_inc : integer; // d's increment for diagonal steps
|
||||
dx_diag : integer; // diagonal x step for next pixel
|
||||
dx_nondiag : integer; // nondiagonal x step for next pixel
|
||||
dy_diag : integer; // diagonal y step for next pixel
|
||||
dy_nondiag : integer; // nondiagonal y step for next pixel
|
||||
i : integer; // loop index
|
||||
nondiag_inc: integer; // d's increment for nondiagonal steps
|
||||
swap : integer; // temporary variable for swap
|
||||
x,y : integer; // current x and y coordinates
|
||||
begin
|
||||
x := xStart; // line starting point}
|
||||
y := yStart;
|
||||
// Determine drawing direction and step to the next pixel.
|
||||
a := xEnd - xStart; // difference in x dimension
|
||||
b := yEnd - yStart; // difference in y dimension
|
||||
// Determine whether end point lies to right or left of start point.
|
||||
if a < 0 then // drawing towards smaller x values?
|
||||
begin
|
||||
a := -a; // make 'a' positive
|
||||
dx_diag := -1
|
||||
end
|
||||
else
|
||||
dx_diag := 1;
|
||||
|
||||
// Determine whether end point lies above or below start point.
|
||||
if b < 0 then // drawing towards smaller x values?
|
||||
begin
|
||||
b := -b; // make 'a' positive
|
||||
dy_diag := -1
|
||||
end
|
||||
else
|
||||
dy_diag := 1;
|
||||
// Identify octant containing end point.
|
||||
if a < b then
|
||||
begin
|
||||
swap := a;
|
||||
a := b;
|
||||
b := swap;
|
||||
dx_nondiag := 0;
|
||||
dy_nondiag := dy_diag
|
||||
end
|
||||
else
|
||||
begin
|
||||
dx_nondiag := dx_diag;
|
||||
dy_nondiag := 0
|
||||
end;
|
||||
d := b + b - a; // initial value for d is 2*b - a
|
||||
nondiag_inc := b + b; // set initial d increment values
|
||||
diag_inc := b + b - a - a;
|
||||
for i := 0 to a do
|
||||
begin /// draw the a+1 pixels
|
||||
drawPixel (bitmap, x, y, color);
|
||||
if d < 0 then // is midpoint above the line?
|
||||
begin // step nondiagonally
|
||||
x := x + dx_nondiag;
|
||||
y := y + dy_nondiag;
|
||||
d := d + nondiag_inc // update decision variable
|
||||
end
|
||||
else
|
||||
begin // midpoint is above the line; step diagonally}
|
||||
x := x + dx_diag;
|
||||
y := y + dy_diag;
|
||||
d := d + diag_inc
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
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>))
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
PROGRAM BRESENHAM
|
||||
|
||||
!$INCLUDE="PC.LIB"
|
||||
|
||||
PROCEDURE BRESENHAM
|
||||
! === Draw a line using graphic coordinates
|
||||
! Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
|
||||
dx=ABS(x2-x1) sx=-1
|
||||
IF x1<x2 THEN sx=1
|
||||
dy=ABS(y2-y1) sy=-1
|
||||
IF y1<y2 THEN sy=1
|
||||
er=-dy
|
||||
IF dx>dy THEN er=dx
|
||||
er=INT(er/2)
|
||||
LOOP
|
||||
PSET(x1,y1,1)
|
||||
EXIT IF x1=x2 AND y1=y2
|
||||
e2=er
|
||||
IF e2>-dx THEN er=er-dy x1=x1+sx
|
||||
IF e2<dy THEN er=er+dx y1=y1+sy
|
||||
END LOOP
|
||||
END PROCEDURE
|
||||
|
||||
BEGIN
|
||||
SCREEN(2)
|
||||
INPUT(x1,y1,x2,y2)
|
||||
BRESENHAM
|
||||
GET(A$)
|
||||
SCREEN(0)
|
||||
END PROGRAM
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
-- Brensenham Line Algorithm
|
||||
|
||||
type alias Position =
|
||||
{x: Int, y: Int}
|
||||
|
||||
type alias BresenhamStatics =
|
||||
{ finish : Position
|
||||
, sx : Int
|
||||
, sy : Int
|
||||
, dx : Float
|
||||
, dy : Float
|
||||
}
|
||||
|
||||
|
||||
line : Position -> Position -> List Position
|
||||
line p q =
|
||||
let
|
||||
dx = (toFloat << abs) (q.x - p.x)
|
||||
dy = (toFloat << abs) (q.y - p.y)
|
||||
|
||||
sx = if p.x < q.x then 1 else -1
|
||||
sy = if p.y < q.y then 1 else -1
|
||||
|
||||
error =
|
||||
(if dx > dy then dx else -dy) / 2
|
||||
|
||||
statics =
|
||||
BresenhamStatics q sx sy dx dy
|
||||
in
|
||||
bresenhamLineLoop statics error p []
|
||||
|
||||
|
||||
bresenhamLineLoop : BresenhamStatics -> Float -> Position -> List Position -> List Position
|
||||
bresenhamLineLoop statics error p positions =
|
||||
let
|
||||
positions_ = p :: positions
|
||||
{sx, sy, dx, dy, finish} = statics
|
||||
in
|
||||
if (p.x == finish.x) && (p.y == finish.y) then
|
||||
positions_
|
||||
else
|
||||
let
|
||||
(dErrX, x) =
|
||||
if error > -dx then (-dy, sx + p.x)
|
||||
else (0, p.x)
|
||||
|
||||
(dErrY, y) =
|
||||
if error < dy then (dx, sy + p.y)
|
||||
else (0, p.y)
|
||||
|
||||
error_ = error + dErrX + dErrY
|
||||
in
|
||||
bresenhamLineLoop statics error_ (Position x y) positions_
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
build_path({Sx, Sy}, {Tx, Ty}) ->
|
||||
if
|
||||
Tx < Sx -> StepX = -1;
|
||||
true -> StepX = 1
|
||||
end,
|
||||
if
|
||||
Ty < Sy -> StepY = -1;
|
||||
true -> StepY = 1
|
||||
end,
|
||||
|
||||
Dx = abs((Tx-Sx)*2),
|
||||
Dy = abs((Ty-Sy)*2),
|
||||
|
||||
if
|
||||
Dy > Dx -> Path = through_y({Sx, Sy}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, Dx*2-Dy, []);
|
||||
true -> Path = through_x({Sx, Sy}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, Dy*2-Dx, [])
|
||||
end,
|
||||
|
||||
lists:reverse(Path).
|
||||
|
||||
through_x({Tx, _}, {Tx, _}, _, _, _, P) -> P;
|
||||
through_x({Sx, Sy}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F0, P) when F0 >= 0 ->
|
||||
Ny = Sy + StepY,
|
||||
F1 = F0 - Dx,
|
||||
Nx = Sx + StepX,
|
||||
F2 = F1 + Dy,
|
||||
through_x({Nx, Ny}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F2, [{Nx, Ny}|P]);
|
||||
through_x({Sx, Sy}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F0, P) when F0 < 0 ->
|
||||
Ny = Sy,
|
||||
Nx = Sx + StepX,
|
||||
F2 = F0 + Dy,
|
||||
through_x({Nx, Ny}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F2, [{Nx, Ny}|P]).
|
||||
|
||||
through_y({_, Ty}, {_, Ty}, _, _, _, P) -> P;
|
||||
through_y({Sx, Sy}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F0, P) when F0 >= 0 ->
|
||||
Nx = Sx + StepX,
|
||||
F1 = F0 - Dy,
|
||||
Ny = Sy + StepY,
|
||||
F2 = F1 + Dx,
|
||||
through_y({Nx, Ny}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F2, [{Nx, Ny}|P]);
|
||||
through_y({Sx, Sy}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F0, P) when F0 < 0 ->
|
||||
Nx = Sx,
|
||||
Ny = Sy + StepY,
|
||||
F2 = F0 + Dx,
|
||||
through_y({Nx, Ny}, {Tx, Ty}, {StepX, StepY}, {Dx, Dy}, F2, [{Nx, Ny}|P]).
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
line({X0, Y0}, {X1, Y1}) ->
|
||||
SX = step(X0, X1),
|
||||
SY = step(Y0, Y1),
|
||||
DX = abs(X1 - X0),
|
||||
DY = abs(Y1 - Y0),
|
||||
Err = DX - DY,
|
||||
line({X0, Y0}, {X1, Y1}, {SX, SY}, {DX, DY}, Err, []).
|
||||
|
||||
line({X1, Y1}, {X1, Y1}, _, _, _, Acc) ->
|
||||
lists:reverse([{X1, Y1} | Acc]);
|
||||
line({X, Y}, {X1, Y1}, {SX, SY}, {DX, DY}, Err, Acc) ->
|
||||
DE = 2 * Err,
|
||||
{X0, Err0} = next_x(X, SX, DY, Err, DE),
|
||||
{Y0, Err1} = next_y(Y, SY, DX, Err0, DE),
|
||||
line({X0, Y0}, {X1, Y1}, {SX, SY}, {DX, DY}, Err1, [{X, Y} | Acc]).
|
||||
|
||||
step(P0, P1) when P0 < P1 ->
|
||||
1;
|
||||
step(_, _) ->
|
||||
-1.
|
||||
|
||||
next_x(X, SX, DY, E, DE) when DE > -DY ->
|
||||
{X + SX, E - DY};
|
||||
next_x(X, _SX, _DY, E, _DE) ->
|
||||
{X, E}.
|
||||
|
||||
next_y(Y, SY, DX, E, DE) when DE < DX ->
|
||||
{Y + SY, E + DX};
|
||||
next_y(Y, _SY, _DX, E, _DE) ->
|
||||
{Y, E}.
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
include std/console.e
|
||||
include std/graphics.e
|
||||
include std/math.e
|
||||
|
||||
-- the new_image function and related code in the 25 or so
|
||||
-- lines below are from http://rosettacode.org/wiki/Basic_bitmap_storage#Euphoria
|
||||
-- as of friday, march 2, 2012
|
||||
|
||||
-- Some color constants:
|
||||
constant
|
||||
black = #000000,
|
||||
white = #FFFFFF,
|
||||
red = #FF0000,
|
||||
green = #00FF00,
|
||||
blue = #0000FF
|
||||
|
||||
-- Create new image filled with some color
|
||||
function new_image(integer width, integer height, atom fill_color)
|
||||
return repeat(repeat(fill_color,height),width)
|
||||
end function
|
||||
|
||||
--grid used for drawing lines in this program
|
||||
sequence screenData = new_image(16,16,black)
|
||||
|
||||
--the line algorithm
|
||||
function bresLine(sequence screenData, integer x0, integer y0, integer x1, integer y1, integer color)
|
||||
|
||||
integer deltaX = abs(x1 - x0), deltaY = abs(y1 - y0)
|
||||
integer stepX, stepY, lineError, error2
|
||||
|
||||
if x0 < x1 then
|
||||
stepX = 1
|
||||
else
|
||||
stepX = -1
|
||||
end if
|
||||
|
||||
if y0 < y1 then
|
||||
stepY = 1
|
||||
else
|
||||
stepY = -1
|
||||
end if
|
||||
|
||||
if deltaX > deltaY then
|
||||
lineError = deltaX
|
||||
else
|
||||
lineError = -deltaY
|
||||
end if
|
||||
|
||||
lineError = round(lineError / 2, 1)
|
||||
|
||||
while 1 do
|
||||
|
||||
screenData[x0][y0] = color
|
||||
|
||||
if (x0 = x1 and y0 = y1) then
|
||||
exit
|
||||
end if
|
||||
|
||||
error2 = lineError
|
||||
|
||||
if error2 > -deltaX then
|
||||
lineError -= deltaY
|
||||
x0 += stepX
|
||||
end if
|
||||
if error2 < deltaY then
|
||||
lineError += deltaX
|
||||
y0 += stepY
|
||||
end if
|
||||
end while
|
||||
return screenData -- return modified version of the screenData sequence
|
||||
end function
|
||||
|
||||
--prevents console output wrapping to next line if it is too big for the screen
|
||||
wrap(0)
|
||||
--outer diamond
|
||||
screenData = bresLine(screenData,8,1,16,8,white)
|
||||
screenData = bresLine(screenData,16,8,8,16,white)
|
||||
screenData = bresLine(screenData,8,16,1,8,white)
|
||||
screenData = bresLine(screenData,1,8,8,1,white)
|
||||
--inner diamond
|
||||
screenData = bresLine(screenData,8,4,12,8,white)
|
||||
screenData = bresLine(screenData,12,8,8,12,white)
|
||||
screenData = bresLine(screenData,8,12,4,8,white)
|
||||
screenData = bresLine(screenData,4,8,8,4,white)
|
||||
-- center lines drawing from left to right, and the next from right to left.
|
||||
screenData = bresLine(screenData,7,7,9,7,white)
|
||||
screenData = bresLine(screenData,9,9,7,9,white)
|
||||
--center dot
|
||||
screenData = bresLine(screenData,8,8,8,8,white)
|
||||
|
||||
--print to the standard console output
|
||||
for i = 1 to 16 do
|
||||
puts(1,"\n")
|
||||
for j = 1 to 16 do
|
||||
if screenData[j][i] = black then
|
||||
printf(1, "%s", ".")
|
||||
else
|
||||
printf(1, "%s", "#")
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
|
||||
puts(1,"\n\n")
|
||||
any_key()
|
||||
|
||||
--/*
|
||||
--output was edited to replace the color's hex digits for clearer output graphics.
|
||||
--to output all the hex digits, use printf(1,"%06x", screenData[j][i])
|
||||
--to output 'shortened' hex digits, use :
|
||||
--printf(1, "%x", ( abs( ( (screenData[j][i] / #FFFFF) - 1 ) ) - 1 ) )
|
||||
--and
|
||||
--printf(1,"%x", abs( ( (screenData[j][i] / #FFFFF) - 1 ) ) )
|
||||
--
|
||||
--,respectively in the last if check.
|
||||
--*/
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
let inline bresenham fill (x0, y0) (x1, y1) =
|
||||
let steep = abs(y1 - y0) > abs(x1 - x0)
|
||||
let x0, y0, x1, y1 =
|
||||
if steep then y0, x0, y1, x1 else x0, y0, x1, y1
|
||||
let x0, y0, x1, y1 =
|
||||
if x0 > x1 then x1, y1, x0, y0 else x0, y0, x1, y1
|
||||
let dx, dy = x1 - x0, abs(y1 - y0)
|
||||
let s = if y0 < y1 then 1 else -1
|
||||
let rec loop e x y =
|
||||
if x <= x1 then
|
||||
if steep then fill y x else fill x y
|
||||
if e < dy then
|
||||
loop (e-dy+dx) (x+1) (y+s)
|
||||
else
|
||||
loop (e-dy) (x+1) y
|
||||
loop (dx/2) x0 y0
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
open System.Windows
|
||||
open System.Windows.Media.Imaging
|
||||
|
||||
[<System.STAThread>]
|
||||
do
|
||||
let rand = System.Random()
|
||||
let n = 256
|
||||
let pixel = Array.create (n*n) 0uy
|
||||
let rand = System.Random().Next
|
||||
for _ in 1..100 do
|
||||
bresenham (fun x y -> pixel.[x+y*n] <- 255uy) (rand n, rand n) (rand n, rand n)
|
||||
let image = Controls.Image(Stretch=Media.Stretch.Uniform)
|
||||
let format = Media.PixelFormats.Gray8
|
||||
image.Source <-
|
||||
BitmapSource.Create(n, n, 1.0, 1.0, format, null, pixel, n)
|
||||
Window(Content=image, Title="Bresenham's line algorithm")
|
||||
|> (Application()).Run |> ignore
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#DEFINE WM_LBUTTONDOWN 513
|
||||
#DEFINE WM_CLOSE 16
|
||||
|
||||
FBSLSETTEXT(ME, "Bresenham") ' Set form caption
|
||||
FBSLSETFORMCOLOR(ME, RGB(0, 255, 255)) ' Cyan: set persistent background color
|
||||
DRAWWIDTH(5) ' Adjust point size
|
||||
FBSL.GETDC(ME) ' Use volatile FBSL.GETDC below to avoid extra assignments
|
||||
|
||||
RESIZE(ME, 0, 0, 200, 235)
|
||||
CENTER(ME)
|
||||
SHOW(ME)
|
||||
|
||||
BEGIN EVENTS
|
||||
SELECT CASE CBMSG
|
||||
CASE WM_LBUTTONDOWN: Rhombus() ' Draw
|
||||
CASE WM_CLOSE: FBSL.RELEASEDC(ME, FBSL.GETDC) ' Clean up
|
||||
END SELECT
|
||||
END EVENTS
|
||||
|
||||
SUB Rhombus()
|
||||
Bresenham(50, 100, 100, 190)(100, 190, 150, 100)(150, 100, 100, 10)(100, 10, 50, 100)
|
||||
|
||||
SUB Bresenham(x0, y0, x1, y1)
|
||||
DIM dx = ABS(x0 - x1), sx = SGN(x0 - x1)
|
||||
DIM dy = ABS(y0 - y1), sy = SGN(y0 - y1)
|
||||
DIM tmp, er = IIF(dx > dy, dx, -dy) / 2
|
||||
|
||||
WHILE NOT (x0 = x1 ANDALSO y0 = y1)
|
||||
PSET(FBSL.GETDC, x0, y0, &HFF) ' Red: Windows stores colors in BGR order
|
||||
tmp = er
|
||||
IF tmp > -dx THEN: er = er - dy: x0 = x0 + sx: END IF
|
||||
IF tmp < +dy THEN: er = er + dx: y0 = y0 + sy: END IF
|
||||
WEND
|
||||
END SUB
|
||||
END SUB
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
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 ;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
defer steep \ noop or swap
|
||||
defer ystep \ 1+ or 1-
|
||||
|
||||
: line ( x0 y0 x1 y1 color bmp -- )
|
||||
{ color bmp }
|
||||
rot swap
|
||||
( x0 x1 y0 y1 )
|
||||
2dup - abs >r
|
||||
2over - abs r> <
|
||||
if ['] swap \ swap use of x and y
|
||||
else 2swap ['] noop
|
||||
then is steep
|
||||
( y0 y1 x0 x1 )
|
||||
2dup >
|
||||
if swap 2swap swap \ ensure x1 > x0
|
||||
else 2swap
|
||||
then
|
||||
( x0 x1 y0 y1 )
|
||||
2dup >
|
||||
if ['] 1-
|
||||
else ['] 1+
|
||||
then is ystep
|
||||
over - abs { y deltay }
|
||||
swap 2dup - dup { deltax }
|
||||
2/ rot 1+ rot
|
||||
( error x1+1 x0 )
|
||||
do color i y steep bmp b!
|
||||
deltay -
|
||||
dup 0<
|
||||
if y ystep to y
|
||||
deltax +
|
||||
then
|
||||
loop
|
||||
drop ;
|
||||
|
||||
5 5 bitmap value test
|
||||
0 test bfill
|
||||
1 0 4 1 red test line
|
||||
4 1 3 4 red test line
|
||||
3 4 0 3 red test line
|
||||
0 3 1 0 red test line
|
||||
test bshow cr
|
||||
**
|
||||
* **
|
||||
* *
|
||||
** *
|
||||
**
|
||||
ok
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
module RCImagePrimitive
|
||||
use RCImageBasic
|
||||
|
||||
implicit none
|
||||
|
||||
type point
|
||||
integer :: x, y
|
||||
end type point
|
||||
|
||||
private :: swapcoord
|
||||
|
||||
contains
|
||||
|
||||
subroutine swapcoord(p1, p2)
|
||||
integer, intent(inout) :: p1, p2
|
||||
integer :: t
|
||||
|
||||
t = p2
|
||||
p2 = p1
|
||||
p1 = t
|
||||
end subroutine swapcoord
|
||||
|
||||
subroutine draw_line(img, from, to, color)
|
||||
type(rgbimage), intent(inout) :: img
|
||||
type(point), intent(in) :: from, to
|
||||
type(rgb), intent(in) :: color
|
||||
|
||||
type(point) :: rfrom, rto
|
||||
integer :: dx, dy, error, ystep, x, y
|
||||
logical :: steep
|
||||
|
||||
rfrom = from
|
||||
rto = to
|
||||
steep = (abs(rto%y - rfrom%y) > abs(rto%x - rfrom%x))
|
||||
if ( steep ) then
|
||||
call swapcoord(rfrom%x, rfrom%y)
|
||||
call swapcoord(rto%x, rto%y)
|
||||
end if
|
||||
if ( rfrom%x > rto%x ) then
|
||||
call swapcoord(rfrom%x, rto%x)
|
||||
call swapcoord(rfrom%y, rto%y)
|
||||
end if
|
||||
|
||||
dx = rto%x - rfrom%x
|
||||
dy = abs(rto%y - rfrom%y)
|
||||
error = dx / 2
|
||||
y = rfrom%y
|
||||
|
||||
if ( rfrom%y < rto%y ) then
|
||||
ystep = 1
|
||||
else
|
||||
ystep = -1
|
||||
end if
|
||||
|
||||
do x = rfrom%x, rto%x
|
||||
if ( steep ) then
|
||||
call put_pixel(img, y, x, color)
|
||||
else
|
||||
call put_pixel(img, x, y, color)
|
||||
end if
|
||||
error = error - dy
|
||||
if ( error < 0 ) then
|
||||
y = y + ystep
|
||||
error = error + dx
|
||||
end if
|
||||
end do
|
||||
|
||||
end subroutine draw_line
|
||||
|
||||
end module RCImagePrimitive
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
program BasicImageTests
|
||||
use RCImageBasic
|
||||
use RCImageIO
|
||||
use RCImagePrimitive
|
||||
|
||||
implicit none
|
||||
|
||||
type(rgbimage) :: animage
|
||||
integer :: x, y
|
||||
|
||||
call alloc_img(animage, 200, 200)
|
||||
call fill_img(animage, rgb(255,255,255))
|
||||
|
||||
call draw_line(animage, point(0,0), point(199,199), rgb(0,0,0))
|
||||
|
||||
do y=0,219,20
|
||||
call draw_line(animage, point(0,0), point(199, y), &
|
||||
rgb(0,0,0))
|
||||
end do
|
||||
|
||||
open(unit=10, file='outputimage.ppm', status='new')
|
||||
call output_ppm(10, animage)
|
||||
close(10)
|
||||
|
||||
call free_img(animage)
|
||||
|
||||
end program BasicImageTests
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
' version 16-09-2015
|
||||
' compile with: fbc -s console
|
||||
' OR compile with: fbc -s gui
|
||||
|
||||
' Ported from the C version
|
||||
Sub Br_line(x0 As Integer, y0 As Integer, x1 As Integer, y1 As Integer, Col As Integer = &HFFFFFF)
|
||||
|
||||
Dim As Integer dx = Abs(x1 - x0), dy = Abs(y1 - y0)
|
||||
Dim As Integer sx = IIf(x0 < x1, 1, -1)
|
||||
Dim As Integer sy = IIf(y0 < y1, 1, -1)
|
||||
Dim As Integer er = IIf(dx > dy, dx, -dy) \ 2, e2
|
||||
|
||||
Do
|
||||
PSet(x0, y0), col
|
||||
If (x0 = x1) And (y0 = y1) Then Exit Do
|
||||
e2 = er
|
||||
If e2 > -dx Then Er -= dy : x0 += sx
|
||||
If e2 < dy Then Er += dx : y0 += sy
|
||||
Loop
|
||||
|
||||
End Sub
|
||||
|
||||
' ------=< MAIN >=------
|
||||
|
||||
Dim As Double x0, y0, x1, y1
|
||||
|
||||
ScreenRes 400, 400, 32
|
||||
WindowTitle" Press key to end demo"
|
||||
Randomize Timer
|
||||
|
||||
Do
|
||||
Cls
|
||||
For a As Integer = 1 To 20
|
||||
Br_line(Rnd*380+10, Rnd*380+10, Rnd*380+10, Rnd*380+10, Rnd*&hFFFFFF)
|
||||
Next
|
||||
Sleep 2000
|
||||
Loop Until InKey <> "" ' loop until a key is pressed
|
||||
|
||||
End
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package raster
|
||||
|
||||
// Line draws line by Bresenham's algorithm.
|
||||
func (b *Bitmap) Line(x0, y0, x1, y1 int, p Pixel) {
|
||||
// implemented straight from WP pseudocode
|
||||
dx := x1 - x0
|
||||
if dx < 0 {
|
||||
dx = -dx
|
||||
}
|
||||
dy := y1 - y0
|
||||
if dy < 0 {
|
||||
dy = -dy
|
||||
}
|
||||
var sx, sy int
|
||||
if x0 < x1 {
|
||||
sx = 1
|
||||
} else {
|
||||
sx = -1
|
||||
}
|
||||
if y0 < y1 {
|
||||
sy = 1
|
||||
} else {
|
||||
sy = -1
|
||||
}
|
||||
err := dx - dy
|
||||
|
||||
for {
|
||||
b.SetPx(x0, y0, p)
|
||||
if x0 == x1 && y0 == y1 {
|
||||
break
|
||||
}
|
||||
e2 := 2 * err
|
||||
if e2 > -dy {
|
||||
err -= dy
|
||||
x0 += sx
|
||||
}
|
||||
if e2 < dx {
|
||||
err += dx
|
||||
y0 += sy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bitmap) LineRgb(x0, y0, x1, y1 int, c Rgb) {
|
||||
b.Line(x0, y0, x1, y1, c.Pixel())
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package main
|
||||
|
||||
// Files required to build supporting package raster are found in:
|
||||
// * This task (immediately above)
|
||||
// * Bitmap
|
||||
// * Write a PPM file
|
||||
|
||||
import (
|
||||
"raster"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
b := raster.NewBitmap(400, 300)
|
||||
b.FillRgb(0xdfefff)
|
||||
blue := raster.Rgb(0x8fcfff)
|
||||
b.LineRgb(7, 12, 307, 122, blue)
|
||||
b.LineRgb(177, 12, 127, 222, blue)
|
||||
err := b.WritePpmFile("bresenham.ppm")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
module Bitmap.Line(line) where
|
||||
|
||||
import Bitmap
|
||||
import Control.Monad
|
||||
import Control.Monad.ST
|
||||
import qualified Data.STRef
|
||||
|
||||
var = Data.STRef.newSTRef
|
||||
get = Data.STRef.readSTRef
|
||||
mutate = Data.STRef.modifySTRef
|
||||
|
||||
line :: Color c => Image s c -> Pixel -> Pixel -> c -> ST s ()
|
||||
line i (Pixel (xa, ya)) (Pixel (xb, yb)) c = do
|
||||
yV <- var y1
|
||||
errorV <- var $ deltax `div` 2
|
||||
forM_ [x1 .. x2] (\x -> do
|
||||
y <- get yV
|
||||
setPix i (Pixel $ if steep then (y, x) else (x, y)) c
|
||||
mutate errorV $ subtract deltay
|
||||
error <- get errorV
|
||||
when (error < 0) (do
|
||||
mutate yV (+ ystep)
|
||||
mutate errorV (+ deltax)))
|
||||
where steep = abs (yb - ya) > abs (xb - xa)
|
||||
(xa', ya', xb', yb') = if steep
|
||||
then (ya, xa, yb, xb)
|
||||
else (xa, ya, xb, yb)
|
||||
(x1, y1, x2, y2) = if xa' > xb'
|
||||
then (xb', yb', xa', ya')
|
||||
else (xa', ya', xb', yb')
|
||||
deltax = x2 - x1
|
||||
deltay = abs $ y2 - y1
|
||||
ystep = if y1 < y2 then 1 else -1
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
thru=: <./ + -~ i.@+ _1 ^ > NB. integers from x through y
|
||||
|
||||
NB.*getBresenhamLine v Returns points for a line given start and end points
|
||||
NB. y is: y0 x0 ,: y1 x1
|
||||
getBresenhamLine=: monad define
|
||||
steep=. ([: </ |@-~/) y
|
||||
points=. |."1^:steep y
|
||||
slope=. %~/ -~/ points
|
||||
ypts=. thru/ {."1 points
|
||||
xpts=. ({: + 0.5 <.@:+ slope * ypts - {.) {.points
|
||||
|."1^:steep ypts,.xpts
|
||||
)
|
||||
|
||||
NB.*drawLines v Draws lines (x) on image (y)
|
||||
NB. x is: 2-item list (start and end points) ; (color)
|
||||
drawLines=: (1&{:: ;~ [: ; [: <@getBresenhamLine"2 (0&{::))@[ setPixels ]
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
myimg=: 0 255 0 makeRGB 20 32 NB. 32 by 20 green image
|
||||
myimg=: ((1 1 ,: 5 11) ; 255 0 0 ) drawLines myimg NB. draw red line from xy point 1 1 to 11 5
|
||||
|
||||
NB. Works for lists of 2 by 2 arrays each defining a line's start and end point.
|
||||
Diamond=: _2]\ _2]\ 9 5 5 15 , 5 15 9 25 , 9 25 13 15 , 13 15 9 5
|
||||
Square =: _2]\ _2]\ 5 5 5 25 , 5 25 13 25 , 13 25 13 5 , 13 5 5 5
|
||||
viewRGB myimg=: (Diamond;255 0 0) drawLines myimg NB. draw 4 red lines to form a diamond
|
||||
viewRGB myimg=: (Square;0 0 255) drawLines myimg NB. draw 4 blue lines to form a square
|
||||
viewRGB (Diamond;255 0 0) drawLines (Square;0 0 255) drawLines myimg
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.WindowConstants;
|
||||
|
||||
public class Bresenham {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(Bresenham::run);
|
||||
}
|
||||
|
||||
private static void run() {
|
||||
JFrame f = new JFrame();
|
||||
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
f.setTitle("Bresenham");
|
||||
|
||||
f.getContentPane().add(new BresenhamPanel());
|
||||
f.pack();
|
||||
|
||||
f.setLocationRelativeTo(null);
|
||||
f.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
class BresenhamPanel extends JPanel {
|
||||
|
||||
private final int pixelSize = 10;
|
||||
|
||||
BresenhamPanel() {
|
||||
setPreferredSize(new Dimension(600, 500));
|
||||
setBackground(Color.WHITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
|
||||
int w = (getWidth() - 1) / pixelSize;
|
||||
int h = (getHeight() - 1) / pixelSize;
|
||||
int maxX = (w - 1) / 2;
|
||||
int maxY = (h - 1) / 2;
|
||||
int x1 = -maxX, x2 = maxX * -2 / 3, x3 = maxX * 2 / 3, x4 = maxX;
|
||||
int y1 = -maxY, y2 = maxY * -2 / 3, y3 = maxY * 2 / 3, y4 = maxY;
|
||||
|
||||
drawLine(g, 0, 0, x3, y1); // NNE
|
||||
drawLine(g, 0, 0, x4, y2); // ENE
|
||||
drawLine(g, 0, 0, x4, y3); // ESE
|
||||
drawLine(g, 0, 0, x3, y4); // SSE
|
||||
drawLine(g, 0, 0, x2, y4); // SSW
|
||||
drawLine(g, 0, 0, x1, y3); // WSW
|
||||
drawLine(g, 0, 0, x1, y2); // WNW
|
||||
drawLine(g, 0, 0, x2, y1); // NNW
|
||||
}
|
||||
|
||||
private void plot(Graphics g, int x, int y) {
|
||||
int w = (getWidth() - 1) / pixelSize;
|
||||
int h = (getHeight() - 1) / pixelSize;
|
||||
int maxX = (w - 1) / 2;
|
||||
int maxY = (h - 1) / 2;
|
||||
|
||||
int borderX = getWidth() - ((2 * maxX + 1) * pixelSize + 1);
|
||||
int borderY = getHeight() - ((2 * maxY + 1) * pixelSize + 1);
|
||||
int left = (x + maxX) * pixelSize + borderX / 2;
|
||||
int top = (y + maxY) * pixelSize + borderY / 2;
|
||||
|
||||
g.setColor(Color.black);
|
||||
g.drawOval(left, top, pixelSize, pixelSize);
|
||||
}
|
||||
|
||||
private void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
|
||||
// delta of exact value and rounded value of the dependent variable
|
||||
int d = 0;
|
||||
|
||||
int dx = Math.abs(x2 - x1);
|
||||
int dy = Math.abs(y2 - y1);
|
||||
|
||||
int dx2 = 2 * dx; // slope scaling factors to
|
||||
int dy2 = 2 * dy; // avoid floating point
|
||||
|
||||
int ix = x1 < x2 ? 1 : -1; // increment direction
|
||||
int iy = y1 < y2 ? 1 : -1;
|
||||
|
||||
int x = x1;
|
||||
int y = y1;
|
||||
|
||||
if (dx >= dy) {
|
||||
while (true) {
|
||||
plot(g, x, y);
|
||||
if (x == x2)
|
||||
break;
|
||||
x += ix;
|
||||
d += dy2;
|
||||
if (d > dx) {
|
||||
y += iy;
|
||||
d -= dx2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (true) {
|
||||
plot(g, x, y);
|
||||
if (y == y2)
|
||||
break;
|
||||
y += iy;
|
||||
d += dx2;
|
||||
if (d > dy) {
|
||||
x += ix;
|
||||
d -= dy2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
function bline(x0, y0, x1, y1) {
|
||||
|
||||
var dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||
var dy = Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||
var err = (dx>dy ? dx : -dy)/2;
|
||||
|
||||
while (true) {
|
||||
setPixel(x0,y0);
|
||||
if (x0 === x1 && y0 === y1) break;
|
||||
var e2 = err;
|
||||
if (e2 > -dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
function drawline!(img::Matrix{T}, x0::Int, y0::Int, x1::Int, y1::Int, col::T) where T
|
||||
δx = abs(x1 - x0)
|
||||
δy = abs(y1 - y0)
|
||||
δe = abs(δy / δx)
|
||||
er = 0.0
|
||||
|
||||
y = y0
|
||||
for x in x0:x1
|
||||
img[x, y] = col
|
||||
er += δe
|
||||
if er > 0.5
|
||||
y += 1
|
||||
er -= 1.0
|
||||
end
|
||||
end
|
||||
|
||||
return img
|
||||
end
|
||||
|
||||
using Images
|
||||
|
||||
img = fill(Gray(255.0), 5, 5);
|
||||
println("\nImage:")
|
||||
display(img); println()
|
||||
drawline!(img, 1, 1, 5, 5, Gray(0.0));
|
||||
println("\nModified image:")
|
||||
display(img); println()
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
-----------------------------------------------
|
||||
-- Bitmap replacement
|
||||
-- (why? current Lua impl lacks a "set" method)
|
||||
-----------------------------------------------
|
||||
local Bitmap = {
|
||||
new = function(self, width, height)
|
||||
local instance = setmetatable({ width=width, height=height }, self)
|
||||
instance:alloc()
|
||||
return instance
|
||||
end,
|
||||
alloc = function(self)
|
||||
self.pixels = {}
|
||||
for y = 1, self.height do
|
||||
self.pixels[y] = {}
|
||||
for x = 1, self.width do
|
||||
self.pixels[y][x] = 0x00000000
|
||||
end
|
||||
end
|
||||
end,
|
||||
clear = function(self, c)
|
||||
for y = 1, self.height do
|
||||
for x = 1, self.width do
|
||||
self.pixels[y][x] = c or 0x00000000
|
||||
end
|
||||
end
|
||||
end,
|
||||
get = function(self, x, y)
|
||||
x, y = math.floor(x+1), math.floor(y+1)
|
||||
if ((x>=1) and (x<=self.width) and (y>=1) and (y<=self.height)) then
|
||||
return self.pixels[y][x]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end,
|
||||
set = function(self, x, y, c)
|
||||
x, y = math.floor(x+1), math.floor(y+1)
|
||||
if ((x>=1) and (x<=self.width) and (y>=1) and (y<=self.height)) then
|
||||
self.pixels[y][x] = c or 0x00000000
|
||||
end
|
||||
end,
|
||||
}
|
||||
Bitmap.__index = Bitmap
|
||||
setmetatable(Bitmap, { __call = function (t, ...) return t:new(...) end })
|
||||
|
||||
------------------------------
|
||||
-- Bresenham's Line Algorithm:
|
||||
------------------------------
|
||||
Bitmap.line = function(self, x1, y1, x2, y2, c)
|
||||
local dx, sx = math.abs(x2-x1), x1<x2 and 1 or -1
|
||||
local dy, sy = math.abs(y2-y1), y1<y2 and 1 or -1
|
||||
local err = math.floor((dx>dy and dx or -dy)/2)
|
||||
while(true) do
|
||||
self:set(x1, y1, c or 0xFFFFFFFF)
|
||||
if (x1==x2 and y1==y2) then break end
|
||||
if (err > -dx) then
|
||||
err, x1 = err-dy, x1+sx
|
||||
if (x1==x2 and y1==y2) then
|
||||
self:set(x1, y1, c or 0xFFFFFFFF)
|
||||
break
|
||||
end
|
||||
end
|
||||
if (err < dy) then
|
||||
err, y1 = err+dx, y1+sy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------
|
||||
-- Demo:
|
||||
--------
|
||||
Bitmap.render = function(self, charmap)
|
||||
for y = 1, self.height do
|
||||
local rowtab = {}
|
||||
for x = 1, self.width do
|
||||
rowtab[x] = charmap[self.pixels[y][x]]
|
||||
end
|
||||
print(table.concat(rowtab))
|
||||
end
|
||||
end
|
||||
local bitmap = Bitmap(61,21)
|
||||
bitmap:clear()
|
||||
bitmap:line(0,10,30,0)
|
||||
bitmap:line(30,0,60,10)
|
||||
bitmap:line(60,10,30,20)
|
||||
bitmap:line(30,20,0,10)
|
||||
bitmap:render({[0x000000]='.', [0xFFFFFFFF]='X'})
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
%screen = Bitmap object
|
||||
%startPoint = [x0,y0]
|
||||
%endPoint = [x1,y1]
|
||||
%color = [red,green,blue]
|
||||
|
||||
function bresenhamLine(screen,startPoint,endPoint,color)
|
||||
|
||||
if( any(color > 255) )
|
||||
error 'RGB colors must be between 0 and 255';
|
||||
end
|
||||
|
||||
%Check for vertical line, x0 == x1
|
||||
if( startPoint(1) == endPoint(1) )
|
||||
%Draw vertical line
|
||||
for i = (startPoint(2):endPoint(2))
|
||||
setPixel(screen,[startPoint(1) i],color);
|
||||
end
|
||||
end
|
||||
|
||||
%Simplified Bresenham algorithm
|
||||
dx = abs(endPoint(1) - startPoint(1));
|
||||
dy = abs(endPoint(2) - startPoint(2));
|
||||
|
||||
if(startPoint(1) < endPoint(1))
|
||||
sx = 1;
|
||||
else
|
||||
sx = -1;
|
||||
end
|
||||
|
||||
if(startPoint(2) < endPoint(2))
|
||||
sy = 1;
|
||||
else
|
||||
sy = -1;
|
||||
end
|
||||
|
||||
err = dx - dy;
|
||||
pixel = startPoint;
|
||||
|
||||
while(true)
|
||||
|
||||
screen.setPixel(pixel,color); %setPixel(x0,y0)
|
||||
|
||||
if( pixel == endPoint )
|
||||
break;
|
||||
end
|
||||
|
||||
e2 = 2*err;
|
||||
|
||||
if( e2 > -dy )
|
||||
err = err - dy;
|
||||
pixel(1) = pixel(1) + sx;
|
||||
end
|
||||
|
||||
if( e2 < dx )
|
||||
err = err + dx;
|
||||
pixel(2) = pixel(2) + sy;
|
||||
end
|
||||
end
|
||||
|
||||
assignin('caller',inputname(1),screen); %saves the changes to the object
|
||||
end
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
>> img = Bitmap(800,600);
|
||||
>> img.bresenhamLine([400 550],[200 400],[255 255 255]);
|
||||
>> img.bresenhamLine([400 550],[600 400],[255 255 255]);
|
||||
>> img.bresenhamLine([200 400],[350 150],[255 255 255]);
|
||||
>> img.bresenhamLine([600 400],[450 150],[255 255 255]);
|
||||
>> img.bresenhamLine([350 150],[450 150],[255 255 255]);
|
||||
>> img.bresenhamLine([400 550],[400 150],[255 255 255]);
|
||||
>> disp(img)
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
fn plot img coord steep col =
|
||||
(
|
||||
if steep then
|
||||
(
|
||||
swap coord[1] coord[2]
|
||||
)
|
||||
setPixels img coord col
|
||||
)
|
||||
|
||||
fn drawLine img start end col =
|
||||
(
|
||||
local steep = (abs (end.y - start.y)) > (abs (end.x - start.x))
|
||||
|
||||
if steep then
|
||||
(
|
||||
swap start.x start.y
|
||||
swap end.x end.y
|
||||
)
|
||||
|
||||
if start.x > end.x then
|
||||
(
|
||||
swap start.x end.x
|
||||
swap start.y end.y
|
||||
)
|
||||
|
||||
local deltaX = end.x - start.x
|
||||
local deltaY = abs (end.y - start.y)
|
||||
local error = deltaX / 2.0
|
||||
local yStep = -1
|
||||
local y = start.y
|
||||
|
||||
if start.y < end.y then
|
||||
(
|
||||
yStep = 1
|
||||
)
|
||||
|
||||
for x in start.x to end.x do
|
||||
(
|
||||
plot img [x, y] steep col
|
||||
error -= deltaY
|
||||
if error < 0 then
|
||||
(
|
||||
y += yStep
|
||||
error += deltaX
|
||||
)
|
||||
)
|
||||
img
|
||||
)
|
||||
|
||||
myBitmap = bitmap 512 512 color:(color 0 0 0)
|
||||
myBitmap = drawLine myBitmap [0, 511] [511, 0] #((color 255 255 255))
|
||||
display myBitmap
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
SegmentBresenham := proc (img, x0, y0, x1, y1)
|
||||
local deltax, deltay, x, y, ystep, steep, err, img2, x02, y02, x12, y12;
|
||||
x02, x12, y02, y12 := y0, y1, x0, x1;
|
||||
steep := abs(x12 - x02) < abs(y12 - y02);
|
||||
img2 := copy(img);
|
||||
if steep then
|
||||
x02, y02 := y02, x02;
|
||||
x12, y12 := y12, x12;
|
||||
end if;
|
||||
if x12 < x02 then
|
||||
x02, x12 := x12, x02;
|
||||
y02, y12 := y12, y02;
|
||||
end if;
|
||||
deltax := x12 - x02;
|
||||
deltay := abs(y12 - y02);
|
||||
err := deltax / 2;
|
||||
y := y02;
|
||||
if y02 < y12 then
|
||||
ystep := 1
|
||||
else
|
||||
ystep := -1
|
||||
end if;
|
||||
for x from x02 to x12 do
|
||||
if steep then
|
||||
img2[y, x] := 0
|
||||
else
|
||||
img2[x, y] := 0
|
||||
end if;
|
||||
err := err - deltay;
|
||||
if err < 0 then
|
||||
y := y + ystep;
|
||||
err := err + deltax
|
||||
end if;
|
||||
end do;
|
||||
return img2;
|
||||
end proc:
|
||||
|
|
@ -0,0 +1 @@
|
|||
Rasterize[Style[Graphics[Line[{{0, 0}, {20, 10}}]], Antialiasing -> False]]
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import bitmap
|
||||
|
||||
proc drawLine*(img: Image; p, q: Point; color: Color) =
|
||||
let
|
||||
dx = abs(q.x - p.x)
|
||||
sx = if p.x < q.x: 1 else: -1
|
||||
dy = abs(q.y - p.y)
|
||||
sy = if p.y < q.y: 1 else: -1
|
||||
|
||||
var
|
||||
p = p
|
||||
q = q
|
||||
err = (if dx > dy: dx else: -dy) div 2
|
||||
e2 = 0
|
||||
|
||||
while true:
|
||||
img[p.x, p.y] = color
|
||||
if p == q:
|
||||
break
|
||||
e2 = err
|
||||
if e2 > -dx:
|
||||
err -= dy
|
||||
p.x += sx
|
||||
if e2 < dy:
|
||||
err += dx
|
||||
p.y += sy
|
||||
|
||||
when isMainModule:
|
||||
var img = newImage(16, 16)
|
||||
img.fill(White)
|
||||
img.drawLine((0, 7), (7, 15), Black)
|
||||
img.drawLine((7, 15), (15, 7), Black)
|
||||
img.drawLine((15, 7), (7, 0), Black)
|
||||
img.drawLine((7, 0), (0, 7), Black)
|
||||
img.print()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
let draw_line ~img ~color ~p0:(x0,y0) ~p1:(x1,y1) =
|
||||
|
||||
let steep = abs(y1 - y0) > abs(x1 - x0) in
|
||||
|
||||
let plot =
|
||||
if steep
|
||||
then (fun x y -> put_pixel img color y x)
|
||||
else (fun x y -> put_pixel img color x y)
|
||||
in
|
||||
|
||||
let x0, y0, x1, y1 =
|
||||
if steep
|
||||
then y0, x0, y1, x1
|
||||
else x0, y0, x1, y1
|
||||
in
|
||||
let x0, x1, y0, y1 =
|
||||
if x0 > x1
|
||||
then x1, x0, y1, y0
|
||||
else x0, x1, y0, y1
|
||||
in
|
||||
|
||||
let delta_x = x1 - x0
|
||||
and delta_y = abs(y1 - y0) in
|
||||
let error = -delta_x / 2
|
||||
and y_step =
|
||||
if y0 < y1 then 1 else -1
|
||||
in
|
||||
let rec loop x y error =
|
||||
plot x y;
|
||||
if x <= x1 then
|
||||
let error = error + delta_y in
|
||||
let y, error =
|
||||
if error > 0
|
||||
then (y + y_step), (error - delta_x)
|
||||
else y, error
|
||||
in
|
||||
loop (succ x) y error
|
||||
in
|
||||
loop x0 y0 error
|
||||
;;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/* Draw a line from (x0, y0) to (x1, y1). 13 May 2010 */
|
||||
/* Based on Rosetta code proforma. */
|
||||
|
||||
/* Declarations for image and selected color, for 4-bit colors. */
|
||||
declare image(40,40) bit (4), color bit (4) static initial ('1000'b);
|
||||
|
||||
draw_line: procedure (xi, yi, xf, yf );
|
||||
declare (xi, yi, xf, yf) fixed binary (31) nonassignable;
|
||||
declare (x0, y0, x1, y1) fixed binary (31);
|
||||
declare (deltax, deltay, x, y, ystep) fixed binary;
|
||||
declare (error initial (0), delta_error) float;
|
||||
declare steep bit (1);
|
||||
|
||||
x0 = xi; y = YI; y0 = yi; x1 = xf; y1 = yf;
|
||||
steep = abs(y1 - y0) > abs (x1 - x0);
|
||||
if steep then
|
||||
do; call swap (x0, y0); call swap (x1, y1); end;
|
||||
if x0 > x1 then
|
||||
do; call swap (x0, x1); call swap (y0, y1); end;
|
||||
deltax = x1 - x0; deltay = abs(y1 - y0);
|
||||
delta_error = deltay/deltax;
|
||||
if y0 < y1 then ystep = 1; else ystep = -1;
|
||||
do x = x0 to x1;
|
||||
if steep then image(y, x) = color; else image(x, y) = color;
|
||||
if steep then put skip list (y, x); else put skip list (x, y);
|
||||
error = error + delta_error;
|
||||
if error >= 0.5 then do; y = y + ystep; error = error - 1; end;
|
||||
end;
|
||||
|
||||
swap: procedure (a, b);
|
||||
declare (a, b) fixed binary (31);
|
||||
declare t fixed binary (31);
|
||||
t = a; a = b; b = t;
|
||||
end swap;
|
||||
|
||||
end draw_line;
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|.........*
|
||||
..........|.......**.
|
||||
..........|.....**...
|
||||
..........|...**.....
|
||||
----------+-**-------
|
||||
..........**.........
|
||||
........**|..........
|
||||
.......*..|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
..........|..........
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
*process source xref or(!);
|
||||
brbn:Proc Options(main);
|
||||
/*********************************************************************
|
||||
* 21.05.2014 Walter Pachl
|
||||
* Implementing the pseudo code of
|
||||
* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
|
||||
* under 'Simplification' (see also REXX version 2)
|
||||
*********************************************************************/
|
||||
grid.=
|
||||
dcl image(-2:7,-4:11) char(1);
|
||||
image='.';
|
||||
image(*,0)='-';
|
||||
image(0,*)='|';
|
||||
image(0,0)='+';
|
||||
call draw_line(-1,-3,6,10);
|
||||
Dcl (i,j) Bin Fixed(31);
|
||||
Do j=11 To -4 By -1;
|
||||
Put Edit(j,' ')(Skip,f(2),a);
|
||||
Do i=-2 To 7;
|
||||
Put Edit(image(i,j))(a);
|
||||
End;
|
||||
End;
|
||||
Put Edit(' 2101234567')(Skip,a);
|
||||
|
||||
draw_line: procedure (x0,y0,x1,y1);
|
||||
dcl (x0,y0,x1,y1) fixed binary(31);
|
||||
dcl (dx,dy,sx,sy,err,e2) fixed binary(31);
|
||||
|
||||
dx = abs(x1-x0);
|
||||
dy = abs(y1-y0);
|
||||
if x0 < x1 then sx = 1;
|
||||
else sx = -1;
|
||||
if y0 < y1 then sy = 1;
|
||||
else sy = -1;
|
||||
err = dx-dy;
|
||||
|
||||
Do Until(x0=x1&y0=y1);
|
||||
image(x0,y0)='X';
|
||||
e2=err*2;
|
||||
if e2>-dy then do;
|
||||
err=err-dy;
|
||||
x0=x0+sx;
|
||||
End;
|
||||
if e2<dx then do;
|
||||
err=err+dx;
|
||||
y0=y0+sy;
|
||||
End;
|
||||
End;
|
||||
image(x0,y0)='X';
|
||||
end;
|
||||
end;
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#! /usr/bin/perl
|
||||
use strict;
|
||||
use Image::Imlib2;
|
||||
|
||||
sub my_draw_line
|
||||
{
|
||||
my ( $img, $x0, $y0, $x1, $y1) = @_;
|
||||
|
||||
my $steep = (abs($y1 - $y0) > abs($x1 - $x0));
|
||||
if ( $steep ) {
|
||||
( $y0, $x0 ) = ( $x0, $y0);
|
||||
( $y1, $x1 ) = ( $x1, $y1 );
|
||||
}
|
||||
if ( $x0 > $x1 ) {
|
||||
( $x1, $x0 ) = ( $x0, $x1 );
|
||||
( $y1, $y0 ) = ( $y0, $y1 );
|
||||
}
|
||||
my $deltax = $x1 - $x0;
|
||||
my $deltay = abs($y1 - $y0);
|
||||
my $error = $deltax / 2;
|
||||
my $ystep;
|
||||
my $y = $y0;
|
||||
my $x;
|
||||
$ystep = ( $y0 < $y1 ) ? 1 : -1;
|
||||
for( $x = $x0; $x <= $x1; $x += 1 ) {
|
||||
if ( $steep ) {
|
||||
$img->draw_point($y, $x);
|
||||
} else {
|
||||
$img->draw_point($x, $y);
|
||||
}
|
||||
$error -= $deltay;
|
||||
if ( $error < 0 ) {
|
||||
$y += $ystep;
|
||||
$error += $deltax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# test
|
||||
my $img = Image::Imlib2->new(160, 160);
|
||||
$img->set_color(255, 255, 255, 255); # white
|
||||
$img->fill_rectangle(0,0,160,160);
|
||||
|
||||
$img->set_color(0,0,0,255); # black
|
||||
my_draw_line($img, 10, 80, 80, 160);
|
||||
my_draw_line($img, 80, 160, 160, 80);
|
||||
my_draw_line($img, 160, 80, 80, 10);
|
||||
my_draw_line($img, 80, 10, 10, 80);
|
||||
|
||||
$img->save("test0.png");
|
||||
|
||||
# let's try the same using its internal algo
|
||||
$img->set_color(255, 255, 255, 255); # white
|
||||
$img->fill_rectangle(0,0,160,160);
|
||||
$img->set_color(0,0,0,255); # black
|
||||
$img->draw_line(10, 80, 80, 160);
|
||||
$img->draw_line(80, 160, 160, 80);
|
||||
$img->draw_line(160, 80, 80, 10);
|
||||
$img->draw_line(80, 10, 10, 80);
|
||||
|
||||
$img->save("test1.png");
|
||||
|
||||
exit 0;
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
-- demo\rosetta\Bresenham_line.exw (runnable version)
|
||||
|
||||
global function bresLine(sequence image, integer x0, y0, x1, y1, colour)
|
||||
-- The line algorithm
|
||||
integer dimx = length(image),
|
||||
dimy = length(image[1]),
|
||||
deltaX = abs(x1-x0),
|
||||
deltaY = abs(y1-y0),
|
||||
stepX = iff(x0<x1,1,-1),
|
||||
stepY = iff(y0<y1,1,-1),
|
||||
lineError = iff(deltaX>deltaY,deltaX,-deltaY),
|
||||
prevle
|
||||
lineError = round(lineError/2, 1)
|
||||
while true do
|
||||
if x0>=1 and x0<=dimx
|
||||
and y0>=1 and y0<=dimy then
|
||||
image[x0][y0] = colour
|
||||
end if
|
||||
if x0=x1 and y0=y1 then exit end if
|
||||
prevle = lineError
|
||||
if prevle>-deltaX then
|
||||
lineError -= deltaY
|
||||
x0 += stepX
|
||||
end if
|
||||
if prevle<deltaY then
|
||||
lineError += deltaX
|
||||
y0 += stepY
|
||||
end if
|
||||
end while
|
||||
return image
|
||||
end function
|
||||
|
||||
--include ppm.e -- red, green, blue, white, new_image(), write_ppm(), bresLine() (as distributed, instead of the above)
|
||||
|
||||
sequence screenData = new_image(400,300,black)
|
||||
screenData = bresLine(screenData,100,1,50,300,red)
|
||||
screenData = bresLine(screenData,1,180,400,240,green)
|
||||
screenData = bresLine(screenData,200,1,400,150,white)
|
||||
screenData = bresLine(screenData,195,1,205,300,blue)
|
||||
write_ppm("bresenham.ppm",screenData)
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
(de brez (Img X Y DX DY)
|
||||
(let SX
|
||||
(cond
|
||||
((=0 DX) 0)
|
||||
((gt0 DX) 1)
|
||||
(T (setq DX (- DX)) -1) )
|
||||
(let SY
|
||||
(cond
|
||||
((=0 DY) 0)
|
||||
((gt0 DY) 1)
|
||||
(T (setq DY (- DY)) -1) )
|
||||
(if (>= DX DY)
|
||||
(let E (- (* 2 DY) DX)
|
||||
(do DX
|
||||
(set (nth Img Y X) 1)
|
||||
(when (ge0 E)
|
||||
(inc 'Y SY)
|
||||
(dec 'E (* 2 DX)) )
|
||||
(inc 'X SX)
|
||||
(inc 'E (* 2 DY)) ) )
|
||||
(let E (- (* 2 DX) DY)
|
||||
(do DY
|
||||
(set (nth Img Y X) 1)
|
||||
(when (ge0 E)
|
||||
(inc 'X SX)
|
||||
(dec 'E (* 2 DY)) )
|
||||
(inc 'Y SY)
|
||||
(inc 'E (* 2 DX)) ) ) ) ) ) )
|
||||
|
||||
(let Img (make (do 90 (link (need 120 0)))) # Create image 120 x 90
|
||||
(brez Img 10 10 100 30) # Draw five lines
|
||||
(brez Img 10 10 100 50)
|
||||
(brez Img 10 10 100 70)
|
||||
(brez Img 10 10 60 70)
|
||||
(brez Img 10 10 20 70)
|
||||
(out "img.pbm" # Write to bitmap file
|
||||
(prinl "P1")
|
||||
(prinl 120 " " 90)
|
||||
(mapc prinl Img) ) )
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
:- use_module(bitmap).
|
||||
:- use_module(bitmapIO).
|
||||
:- use_module(library(clpfd)).
|
||||
|
||||
% ends when X1 = X2 and Y1 = Y2
|
||||
draw_recursive_line(NPict,Pict,Color,X,X,_DX,_DY,Y,Y,_E,_Sx,_Sy):-
|
||||
set_pixel0(NPict,Pict,[X,Y],Color).
|
||||
draw_recursive_line(NPict,Pict,Color,X,X2,DX,DY,Y,Y2,E,Sx,Sy):-
|
||||
set_pixel0(TPict,Pict,[X,Y],Color),
|
||||
E2 #= 2*E,
|
||||
% because we can't accumulate error we set Ey or Ex to 1 or 0
|
||||
% depending on whether we need to add dY or dX to the error term
|
||||
( E2 >= DY ->
|
||||
Ey = 1, NX #= X + Sx;
|
||||
Ey = 0, NX = X),
|
||||
( E2 =< DX ->
|
||||
Ex = 1, NY #= Y + Sy;
|
||||
Ex = 0, NY = Y),
|
||||
NE #= E + DX*Ex + DY*Ey,
|
||||
draw_recursive_line(NPict,TPict,Color,NX,X2,DX,DY,NY,Y2,NE,Sx,Sy).
|
||||
|
||||
draw_line(NPict,Pict,Color,X1,Y1,X2,Y2):-
|
||||
DeltaY #= Y2-Y1,
|
||||
DeltaX #= X2-X1,
|
||||
( DeltaY < 0 -> Sy = -1; Sy = 1),
|
||||
( DeltaX < 0 -> Sx = -1; Sx = 1),
|
||||
DX #= abs(DeltaX),
|
||||
DY #= -1*abs(DeltaY),
|
||||
E #= DY+DX,
|
||||
draw_recursive_line(NPict,Pict,Color,X1,X2,DX,DY,Y1,Y2,E,Sx,Sy).
|
||||
|
||||
|
||||
init:-
|
||||
new_bitmap(B,[100,100],[255,255,255]),
|
||||
draw_line(NB,B,[0,0,0],2,2,10,90),
|
||||
write_ppm_p6('line.ppm',NB).
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
Procedure BresenhamLine(x0 ,y0 ,x1 ,y1)
|
||||
If Abs(y1 - y0) > Abs(x1 - x0);
|
||||
steep =#True
|
||||
Swap x0, y0
|
||||
Swap x1, y1
|
||||
EndIf
|
||||
If x0 > x1
|
||||
Swap x0, x1
|
||||
Swap y0, y1
|
||||
EndIf
|
||||
deltax = x1 - x0
|
||||
deltay = Abs(y1 - y0)
|
||||
error = deltax / 2
|
||||
y = y0
|
||||
If y0 < y1
|
||||
ystep = 1
|
||||
Else
|
||||
ystep = -1
|
||||
EndIf
|
||||
For x = x0 To x1
|
||||
If steep
|
||||
Plot(y,x)
|
||||
Else
|
||||
Plot(x,y)
|
||||
EndIf
|
||||
error - deltay
|
||||
If error < 0
|
||||
y + ystep
|
||||
error + deltax
|
||||
EndIf
|
||||
Next
|
||||
EndProcedure
|
||||
|
||||
#Window1 = 0
|
||||
#Image1 = 0
|
||||
#ImgGadget = 0
|
||||
#width = 300
|
||||
#height = 300
|
||||
|
||||
Define.i Event
|
||||
Define.f Angle
|
||||
|
||||
If OpenWindow(#Window1, 0, 0, #width, #height, "Bresenham's Line PureBasic Example", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
|
||||
If CreateImage(#Image1, #width, #height)
|
||||
ImageGadget(#ImgGadget, 0, 0, #width, #height, ImageID(#Image1))
|
||||
StartDrawing(ImageOutput(#Image1))
|
||||
FillArea(0,0,-1,$FFFFFF) :FrontColor(0)
|
||||
While Angle < 2*#PI
|
||||
BresenhamLine(150,150,150+Cos(Angle)*120,150+Sin(Angle)*120)
|
||||
Angle + #PI/60
|
||||
Wend
|
||||
|
||||
StopDrawing()
|
||||
SetGadgetState(#ImgGadget, ImageID(#Image1))
|
||||
Repeat
|
||||
Event = WaitWindowEvent()
|
||||
Until Event = #PB_Event_CloseWindow
|
||||
EndIf
|
||||
EndIf
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
def line(self, x0, y0, x1, y1):
|
||||
"Bresenham's line algorithm"
|
||||
dx = abs(x1 - x0)
|
||||
dy = abs(y1 - y0)
|
||||
x, y = x0, y0
|
||||
sx = -1 if x0 > x1 else 1
|
||||
sy = -1 if y0 > y1 else 1
|
||||
if dx > dy:
|
||||
err = dx / 2.0
|
||||
while x != x1:
|
||||
self.set(x, y)
|
||||
err -= dy
|
||||
if err < 0:
|
||||
y += sy
|
||||
err += dx
|
||||
x += sx
|
||||
else:
|
||||
err = dy / 2.0
|
||||
while y != y1:
|
||||
self.set(x, y)
|
||||
err -= dx
|
||||
if err < 0:
|
||||
x += sx
|
||||
err += dy
|
||||
y += sy
|
||||
self.set(x, y)
|
||||
Bitmap.line = line
|
||||
|
||||
bitmap = Bitmap(17,17)
|
||||
for points in ((1,8,8,16),(8,16,16,8),(16,8,8,1),(8,1,1,8)):
|
||||
bitmap.line(*points)
|
||||
bitmap.chardisplay()
|
||||
|
||||
'''
|
||||
The origin, 0,0; is the lower left, with x increasing to the right,
|
||||
and Y increasing upwards.
|
||||
|
||||
The chardisplay above produces the following output :
|
||||
+-----------------+
|
||||
| @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @|
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @@ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ @ |
|
||||
| @ |
|
||||
| |
|
||||
+-----------------+
|
||||
'''
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from fractions import Fraction
|
||||
|
||||
def line(self, x0, y0, x1, y1):
|
||||
rev = reversed
|
||||
if abs(y1 - y0) <= abs(x1 - x0):
|
||||
x0, y0, x1, y1 = y0, x0, y1, x1
|
||||
rev = lambda x: x
|
||||
if x1 < x0:
|
||||
x0, y0, x1, y1 = x1, y1, x0, y0
|
||||
leny = abs(y1 - y0)
|
||||
for i in range(leny + 1):
|
||||
self.set(*rev((round(Fraction(i, leny) * (x1 - x0)) + x0, (1 if y1 > y0 else -1) * i + y0)))
|
||||
|
||||
Bitmap.line = line
|
||||
|
||||
# see test code above
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*REXX program plots/draws line segments using the Bresenham's line (2D) algorithm. */
|
||||
parse arg data /*obtain optional arguments from the CL*/
|
||||
if data='' then data= "(1,8) (8,16) (16,8) (8,1) (1,8)" /* ◄──── a rhombus.*/
|
||||
data= translate(data, , '()[]{}/,:;') /*elide chaff from the data points. */
|
||||
@.= '·' /*use mid─dots chars (plot background).*/
|
||||
do points=1 while data\='' /*put the data points into an array (!)*/
|
||||
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 /*1st case.*/
|
||||
end
|
||||
minX= min(minX,x); maxX= max(maxX,x); minY= min(minY,y); maxY= max(maxY,y)
|
||||
end /*points*/ /* [↑] data points pairs in array !. */
|
||||
border= 2 /*border: is extra space around plot. */
|
||||
minX= minX - border*2; maxX= maxX + border*2 /*min and max X for the plot display.*/
|
||||
minY= minY - border ; maxY= maxY + border /* " " " Y " " " " */
|
||||
|
||||
do x=minX to maxX; @.x.0= '─'; end /*draw a dash from left ───► right.*/
|
||||
do y=minY to maxY; @.0.y= '│'; end /*draw a pipe from lowest ───► highest*/
|
||||
@.0.0= '┼' /*define the plot's origin axis point. */
|
||||
do seg=2 to points-1; _= seg - 1 /*obtain the X and Y line coördinates*/
|
||||
call drawLine !._, !.seg /*draw (plot) a line segment. */
|
||||
end /*seg*/ /* [↑] drawing the line segments. */
|
||||
/* [↓] display the plot to terminal. */
|
||||
do y=maxY to minY by -1; _= /*display the plot one line at a time. */
|
||||
do x=minX to maxX; _= _ || @.x.y /*construct/build a line of the plot. */
|
||||
end /*x*/ /* (a line is a "row" of points.) */
|
||||
say _ /*display a line of the plot──►terminal*/
|
||||
end /*y*/ /* [↑] all done plotting the points. */
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
drawLine: procedure expose @.; parse arg x y,xf yf; parse value '-1 -1' with sx sy
|
||||
dx= abs(xf-x); if x<xf then sx= 1 /*obtain X range, determine the slope*/
|
||||
dy= abs(yf-y); if y<yf then sy= 1 /* " Y " " " " */
|
||||
err= dx - dy /*calculate error between adjustments. */
|
||||
/*Θ is the plot character for points. */
|
||||
do forever; @.x.y= 'Θ' /*plot the points until it's complete. */
|
||||
if x=xf & y=yf then return /*are the plot points at the finish? */
|
||||
err2= err + err /*calculate double the error value. */
|
||||
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 /*forever*/
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* REXX ***************************************************************
|
||||
* 21.05.2014 Walter Pachl
|
||||
* Implementing the pseudo code of
|
||||
* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
|
||||
* under 'Simplification'
|
||||
**********************************************************************/
|
||||
grid.='.'
|
||||
Do i=-2 To 7; grid.i.0='-'; End
|
||||
Do j=-4 To 11; grid.0.j='|'; End
|
||||
grid.0.0='+'
|
||||
Call line -1,-3,6,10
|
||||
Do j=11 To -4 By -1
|
||||
ol=format(j,2)' '
|
||||
Do i=-2 To 7
|
||||
ol=ol||grid.i.j
|
||||
End
|
||||
Say ol
|
||||
End
|
||||
Say ' 2101234567'
|
||||
Exit
|
||||
line: Procedure Expose grid.
|
||||
Parse Arg x0, y0, x1, y1
|
||||
dx = abs(x1-x0)
|
||||
dy = abs(y1-y0)
|
||||
if x0 < x1 then sx = 1
|
||||
else sx = -1
|
||||
if y0 < y1 then sy = 1
|
||||
else sy = -1
|
||||
err = dx-dy
|
||||
|
||||
Do Forever
|
||||
grid.x0.y0='X'
|
||||
if x0 = x1 & y0 = y1 Then Leave
|
||||
e2 = 2*err
|
||||
if e2 > -dy then do
|
||||
err = err - dy
|
||||
x0 = x0 + sx
|
||||
end
|
||||
if e2 < dx then do
|
||||
err = err + dx
|
||||
y0 = y0 + sy
|
||||
end
|
||||
end
|
||||
Return
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#lang racket
|
||||
(require racket/draw)
|
||||
|
||||
(define (draw-line dc x0 y0 x1 y1)
|
||||
(define dx (abs (- x1 x0)))
|
||||
(define dy (abs (- y1 y0)))
|
||||
(define sx (if (> x0 x1) -1 1))
|
||||
(define sy (if (> y0 y1) -1 1))
|
||||
(cond
|
||||
[(> dx dy)
|
||||
(let loop ([x x0] [y y0] [err (/ dx 2.0)])
|
||||
(unless (= x x1)
|
||||
(send dc draw-point x y)
|
||||
(define newerr (- err dy))
|
||||
(if (< newerr 0)
|
||||
(loop (+ x sx) (+ y sy) (+ newerr dx))
|
||||
(loop (+ x sx) y newerr))))]
|
||||
[else
|
||||
(let loop ([x x0] [y y0] [err (/ dy 2.0)])
|
||||
(unless (= y y1)
|
||||
(send dc draw-point x y)
|
||||
(define newerr (- err dy))
|
||||
(if (< newerr 0)
|
||||
(loop (+ x sx) (+ y sy) newerr)
|
||||
(loop x (+ y sy) (+ newerr dy)))))]))
|
||||
|
||||
(define bm (make-object bitmap% 17 17))
|
||||
(define dc (new bitmap-dc% [bitmap bm]))
|
||||
(send dc set-smoothing 'unsmoothed)
|
||||
(send dc set-pen "red" 1 'solid)
|
||||
(for ([points '((1 8 8 16) (8 16 16 8) (16 8 8 1) (8 1 1 8))])
|
||||
(apply draw-line (cons dc points)))
|
||||
bm
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
SUB draw_line(x1, y1, x2, y2, colour)
|
||||
x_dist = abs(x2-x1)
|
||||
y_dist = abs(y2-y1)
|
||||
IF y2-y1 < -x_dist OR x2-x1 <= -y_dist THEN
|
||||
SWAP x1, x2 ' Swap start and end points
|
||||
SWAP y1, y2
|
||||
END IF
|
||||
IF x1 < x2 THEN x_step = 1 ELSE x_step = -1
|
||||
IF y1 < y2 THEN y_step = 1 ELSE y_step = -1
|
||||
|
||||
IF y_dist > x_dist THEN ' steep angle, step by y
|
||||
error = y_dist/2
|
||||
x = x1
|
||||
FOR y = y1 TO y2
|
||||
canvas.Pset(x, y, colour)
|
||||
error = error - x_dist
|
||||
IF error < 0 THEN
|
||||
x = x + x_step
|
||||
error = error + y_dist
|
||||
END IF
|
||||
NEXT y
|
||||
ELSE ' not steep, step by x
|
||||
error = x_dist/2
|
||||
y = y1
|
||||
FOR x = x1 TO x2
|
||||
canvas.Pset(x, y, colour)
|
||||
error = error - y_dist
|
||||
IF error < 0 THEN
|
||||
y = y + y_step
|
||||
error = error + x_dist
|
||||
END IF
|
||||
NEXT y
|
||||
END IF
|
||||
|
||||
END SUB
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
SUB PaintCanvas
|
||||
draw_line 200, 10, 100, 200, &H00ff00
|
||||
draw_line 100, 200, 200, 400, &H00ff00
|
||||
draw_line 200, 400, 300, 200, &H00ff00
|
||||
draw_line 300, 200, 200, 10, &H00ff00
|
||||
END SUB
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
load "guilib.ring"
|
||||
load "stdlib.ring"
|
||||
|
||||
new qapp
|
||||
{
|
||||
win1 = new qwidget() {
|
||||
setwindowtitle("drawing using qpainter")
|
||||
setwinicon(self,"c:\ring\bin\image\browser.png")
|
||||
setgeometry(100,100,500,600)
|
||||
label1 = new qlabel(win1) {
|
||||
setgeometry(10,10,400,400)
|
||||
settext("")
|
||||
}
|
||||
new qpushbutton(win1) {
|
||||
setgeometry(200,400,100,30)
|
||||
settext("draw")
|
||||
setclickevent("draw()")
|
||||
}
|
||||
show()
|
||||
}
|
||||
exec()
|
||||
}
|
||||
|
||||
func draw
|
||||
p1 = new qpicture()
|
||||
color = new qcolor() {
|
||||
setrgb(0,0,255,255)
|
||||
}
|
||||
pen = new qpen() {
|
||||
setcolor(color)
|
||||
setwidth(1)
|
||||
}
|
||||
new qpainter() {
|
||||
begin(p1)
|
||||
setpen(pen)
|
||||
|
||||
line = [[50,100,100,190], [100,190,150,100], [150,100,100,10], [100,10,50,100]]
|
||||
|
||||
for n = 1 to 4
|
||||
x1=line[n][1] y1=line[n][2] x2=line[n][3] y2=line[n][4]
|
||||
dx = fabs(x2 - x1) sx = sign(x2 - x1)
|
||||
dy = fabs(y2 - y1) sy = sign(y2 - y1)
|
||||
if dx < dy e = dx / 2 else e = dy / 2 ok
|
||||
while true
|
||||
drawline (x1*2,y1*2,x2*2,y2*2)
|
||||
if x1 = x2 if y1 = y2 exit ok ok
|
||||
if dx > dy
|
||||
x1 += sx e -= dy if e < 0 e += dx y1 += sy ok
|
||||
else
|
||||
y1 += sy e -= dx if e < 0 e += dy x1 += sx ok ok
|
||||
end
|
||||
next
|
||||
|
||||
endpaint()
|
||||
}
|
||||
label1 { setpicture(p1) show() }
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
Pixel = Struct.new(:x, :y)
|
||||
|
||||
class Pixmap
|
||||
|
||||
def draw_line(p1, p2, colour)
|
||||
validate_pixel(p1.x, p2.y)
|
||||
validate_pixel(p2.x, p2.y)
|
||||
|
||||
x1, y1 = p1.x, p1.y
|
||||
x2, y2 = p2.x, p2.y
|
||||
|
||||
steep = (y2 - y1).abs > (x2 - x1).abs
|
||||
|
||||
if steep
|
||||
x1, y1 = y1, x1
|
||||
x2, y2 = y2, x2
|
||||
end
|
||||
|
||||
if x1 > x2
|
||||
x1, x2 = x2, x1
|
||||
y1, y2 = y2, y1
|
||||
end
|
||||
|
||||
deltax = x2 - x1
|
||||
deltay = (y2 - y1).abs
|
||||
error = deltax / 2
|
||||
ystep = y1 < y2 ? 1 : -1
|
||||
|
||||
y = y1
|
||||
x1.upto(x2) do |x|
|
||||
pixel = steep ? [y,x] : [x,y]
|
||||
self[*pixel] = colour
|
||||
error -= deltay
|
||||
if error < 0
|
||||
y += ystep
|
||||
error += deltax
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
bitmap = Pixmap.new(500, 500)
|
||||
bitmap.fill(RGBColour::BLUE)
|
||||
10.step(430, 60) do |a|
|
||||
bitmap.draw_line(Pixel[10, 10], Pixel[490,a], RGBColour::YELLOW)
|
||||
bitmap.draw_line(Pixel[10, 10], Pixel[a,490], RGBColour::YELLOW)
|
||||
end
|
||||
bitmap.draw_line(Pixel[10, 10], Pixel[490,490], RGBColour::YELLOW)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
struct Point {
|
||||
x: i32,
|
||||
y: i32
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut points: Vec<Point> = Vec::new();
|
||||
points.append(&mut get_coordinates(1, 20, 20, 28));
|
||||
points.append(&mut get_coordinates(20, 28, 69, 0));
|
||||
draw_line(points, 70, 30);
|
||||
}
|
||||
|
||||
fn get_coordinates(x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<Point> {
|
||||
let mut coordinates: Vec<Point> = vec![];
|
||||
let dx:i32 = i32::abs(x2 - x1);
|
||||
let dy:i32 = i32::abs(y2 - y1);
|
||||
let sx:i32 = { if x1 < x2 { 1 } else { -1 } };
|
||||
let sy:i32 = { if y1 < y2 { 1 } else { -1 } };
|
||||
|
||||
let mut error:i32 = (if dx > dy { dx } else { -dy }) / 2 ;
|
||||
let mut current_x:i32 = x1;
|
||||
let mut current_y:i32 = y1;
|
||||
loop {
|
||||
coordinates.push(Point { x : current_x, y: current_y });
|
||||
|
||||
if current_x == x2 && current_y == y2 { break; }
|
||||
|
||||
let error2:i32 = error;
|
||||
|
||||
if error2 > -dx {
|
||||
error -= dy;
|
||||
current_x += sx;
|
||||
}
|
||||
if error2 < dy {
|
||||
error += dx;
|
||||
current_y += sy;
|
||||
}
|
||||
}
|
||||
coordinates
|
||||
}
|
||||
|
||||
fn draw_line(line: std::vec::Vec<Point>, width: i32, height: i32) {
|
||||
for col in 0..height {
|
||||
for row in 0..width {
|
||||
let is_point_in_line = line.iter().any(| point| point.x == row && point.y == col);
|
||||
match is_point_in_line {
|
||||
true => print!("@"),
|
||||
_ => print!(".")
|
||||
};
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
object BitmapOps {
|
||||
def bresenham(bm:RgbBitmap, x0:Int, y0:Int, x1:Int, y1:Int, c:Color)={
|
||||
val dx=math.abs(x1-x0)
|
||||
val sx=if (x0<x1) 1 else -1
|
||||
val dy=math.abs(y1-y0)
|
||||
val sy=if (y0<y1) 1 else -1
|
||||
|
||||
def it=new Iterator[Tuple2[Int,Int]]{
|
||||
var x=x0; var y=y0
|
||||
var err=(if (dx>dy) dx else -dy)/2
|
||||
def next={
|
||||
val res=(x,y)
|
||||
val e2=err;
|
||||
if (e2 > -dx) {err-=dy; x+=sx}
|
||||
if (e2<dy) {err+=dx; y+=sy}
|
||||
res;
|
||||
}
|
||||
def hasNext = (sx*x <= sx*x1 && sy*y <= sy*y1)
|
||||
}
|
||||
|
||||
for((x,y) <- it)
|
||||
bm.setPixel(x, y, c)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
func my_draw_line(img, x0, y0, x1, y1) {
|
||||
|
||||
var steep = (abs(y1 - y0) > abs(x1 - x0))
|
||||
|
||||
if (steep) {
|
||||
(y0, x0) = (x0, y0)
|
||||
(y1, x1) = (x1, y1)
|
||||
}
|
||||
if (x0 > x1) {
|
||||
(x1, x0) = (x0, x1)
|
||||
(y1, y0) = (y0, y1)
|
||||
}
|
||||
|
||||
var deltax = (x1 - x0)
|
||||
var deltay = abs(y1 - y0)
|
||||
var error = (deltax / 2)
|
||||
var y = y0
|
||||
var ystep = (y0 < y1 ? 1 : -1)
|
||||
|
||||
x0.to(x1).each { |x|
|
||||
img.draw_point(steep ? ((y, x)) : ((x, y)))
|
||||
error -= deltay
|
||||
if (error < 0) {
|
||||
y += ystep
|
||||
error += deltax
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require('Image::Imlib2')
|
||||
|
||||
var img = %s'Image::Imlib2'.new(160, 160)
|
||||
img.set_color(255, 255, 255, 255) # white
|
||||
img.fill_rectangle(0,0,160,160)
|
||||
|
||||
img.set_color(0,0,0,255) # black
|
||||
my_draw_line(img, 10, 80, 80, 160)
|
||||
my_draw_line(img, 80, 160, 160, 80)
|
||||
my_draw_line(img, 160, 80, 80, 10)
|
||||
my_draw_line(img, 80, 10, 10, 80)
|
||||
|
||||
img.save("test0.png");
|
||||
|
||||
# let's try the same using its internal algo
|
||||
img.set_color(255, 255, 255, 255) # white
|
||||
img.fill_rectangle(0,0,160,160)
|
||||
img.set_color(0,0,0,255) # black
|
||||
img.draw_line(10, 80, 80, 160)
|
||||
img.draw_line(80, 160, 160, 80)
|
||||
img.draw_line(160, 80, 80, 10)
|
||||
img.draw_line(80, 10, 10, 80)
|
||||
|
||||
img.save("test1.png")
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/local/bin/spar
|
||||
pragma annotate( summary, "DrawLine" )
|
||||
@( description, "Draw a line given 2 points with the Bresenham's algorithm." )
|
||||
@( see_also, "http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm" )
|
||||
@( author, "Ken O. Burtch" );
|
||||
pragma license( unrestricted );
|
||||
|
||||
pragma restriction( no_external_commands );
|
||||
|
||||
procedure drawline is
|
||||
|
||||
-- Spar 1.x has only single-dimensional arrays but we can simulate a
|
||||
-- two dimensional array that has been folded into a 1D array
|
||||
|
||||
width : constant positive := 20;
|
||||
height : constant positive := 20;
|
||||
type image_array is array(1..400) of character;
|
||||
Picture : image_array;
|
||||
|
||||
-- Line
|
||||
-- Draw a line between two coordinates using the given character
|
||||
|
||||
procedure Line ( Start_X : positive; Start_Y : positive; Stop_X : positive; Stop_Y : positive; Color : character) is
|
||||
|
||||
-- at this point, formal parameters are defined but the actual values aren't defined!
|
||||
-- but creating a dummy Line in a test script works?
|
||||
|
||||
DX : constant float := abs( float( Stop_X ) - float( Start_X ) );
|
||||
DY : constant float := abs( float( Stop_Y ) - float( Start_Y ) );
|
||||
Err : float;
|
||||
X : positive := Start_X;
|
||||
Y : positive := Start_Y;
|
||||
Step_X : integer := 1;
|
||||
Step_Y : integer := 1;
|
||||
begin
|
||||
if Start_X > Stop_X then
|
||||
Step_X := -1;
|
||||
end if;
|
||||
if Start_Y > Stop_Y then
|
||||
Step_Y := -1;
|
||||
end if;
|
||||
if DX > DY then
|
||||
Err := DX / 2.0;
|
||||
while X /= Stop_X loop
|
||||
Picture (X + width*(Y-1)) := Color;
|
||||
Err := @ - DY;
|
||||
if Err < 0.0 then
|
||||
Y := positive( integer(@) + Step_Y);
|
||||
Err := @ + DX;
|
||||
end if;
|
||||
X := positive( integer(@) + Step_X );
|
||||
end loop;
|
||||
else
|
||||
Err := DY / 2.0;
|
||||
while Y /= Stop_Y loop
|
||||
Picture (X + height*(Y-1)) := Color;
|
||||
Err := @ - DX;
|
||||
if Err < 0.0 then
|
||||
X := positive( integer(@) + Step_X );
|
||||
Err := @ + DY;
|
||||
end if;
|
||||
Y := positive( integer(@) + Step_Y );
|
||||
end loop;
|
||||
end if;
|
||||
Picture (X + width*(Y-1)) := Color;
|
||||
end Line;
|
||||
|
||||
-- new_picture
|
||||
-- Erase the picture by filling it with spaces.
|
||||
|
||||
procedure new_picture is
|
||||
begin
|
||||
for i in arrays.first( Picture )..arrays.last( Picture ) loop
|
||||
Picture(i) := ' ';
|
||||
end loop;
|
||||
end new_picture;
|
||||
|
||||
-- render
|
||||
-- Draw the contents of the picture area.
|
||||
|
||||
procedure render is
|
||||
begin
|
||||
for i in arrays.first( Picture )..arrays.last( Picture ) loop
|
||||
put( Picture(i) );
|
||||
if i mod width = 0 then
|
||||
new_line;
|
||||
end if;
|
||||
end loop;
|
||||
end render;
|
||||
|
||||
begin
|
||||
new_picture;
|
||||
Line( 1, 8, 8, 16, 'X' );
|
||||
Line( 8,16,16, 8, 'X' );
|
||||
Line(16, 8, 8, 1, 'X' );
|
||||
Line( 8, 1, 1, 8, 'X' );
|
||||
render;
|
||||
end drawline;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
(lx0, ly0, lx1, ly1)
|
||||
Prgm
|
||||
Local steep, x, y, dx, dy, ystep, error, tmp
|
||||
abs(ly1 - ly0) > abs(lx1 - lx0) → steep
|
||||
If steep Then
|
||||
lx0 → tmp
|
||||
ly0 → lx0
|
||||
tmp → ly0
|
||||
lx1 → tmp
|
||||
ly1 → lx1
|
||||
tmp → ly1
|
||||
EndIf
|
||||
If lx0 > lx1 Then
|
||||
lx0 → tmp
|
||||
lx1 → lx0
|
||||
tmp → lx1
|
||||
ly0 → tmp
|
||||
ly1 → ly0
|
||||
tmp → ly1
|
||||
EndIf
|
||||
lx1 - lx0 → dx
|
||||
abs(ly1 - ly0) → dy
|
||||
when(ly0 < ly1, 1, –1) → ystep
|
||||
intDiv(dx, 2) → error
|
||||
ly0 → y
|
||||
For x,lx0,lx1
|
||||
If steep Then: PxlChg x, y :Else: PxlChg y, x :EndIf
|
||||
error - dy → error
|
||||
If error < 0 Then
|
||||
y + ystep → y
|
||||
error + dx → error
|
||||
EndIf
|
||||
EndFor
|
||||
EndPrgm
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package require Tcl 8.5
|
||||
package require Tk
|
||||
|
||||
proc drawLine {image colour point0 point1} {
|
||||
lassign $point0 x0 y0
|
||||
lassign $point1 x1 y1
|
||||
|
||||
set steep [expr {abs($y1 - $y0) > abs($x1 - $x0)}]
|
||||
if {$steep} {
|
||||
lassign [list $x0 $y0] y0 x0
|
||||
lassign [list $x1 $y1] y1 x1
|
||||
}
|
||||
if {$x0 > $x1} {
|
||||
lassign [list $x0 $x1] x1 x0
|
||||
lassign [list $y0 $y1] y1 y0
|
||||
}
|
||||
set deltax [expr {$x1 - $x0}]
|
||||
set deltay [expr {abs($y1 - $y0)}]
|
||||
set error [expr {$deltax / 2}]
|
||||
set ystep [expr {$y0 < $y1 ? 1 : -1}]
|
||||
|
||||
for {set x $x0; set y $y0} {$x <= $x1} {incr x} {
|
||||
setPixel $image $colour [expr {$steep ? [list $y $x] : [list $x $y]}]
|
||||
incr error -$deltay
|
||||
if {$error < 0} {
|
||||
incr y $ystep
|
||||
incr error $deltax
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# create the image and display it
|
||||
set img [newImage 200 100]
|
||||
label .l -image $img
|
||||
pack .l
|
||||
|
||||
fill $img black
|
||||
drawLine $img yellow {20 20} {180 80}
|
||||
drawLine $img yellow {180 20} {20 80}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#! /bin/bash
|
||||
|
||||
function line {
|
||||
x0=$1
|
||||
y0=$2
|
||||
x1=$3
|
||||
y1=$4
|
||||
|
||||
if (( x0 > x1 ))
|
||||
then
|
||||
(( dx = x0 - x1 ))
|
||||
(( sx = -1 ))
|
||||
else
|
||||
(( dx = x1 - x0 ))
|
||||
(( sx = 1 ))
|
||||
fi
|
||||
|
||||
if (( y0 > y1 ))
|
||||
then
|
||||
(( dy = y0 - y1 ))
|
||||
(( sy = -1 ))
|
||||
else
|
||||
(( dy = y1 - y0 ))
|
||||
(( sy = 1 ))
|
||||
fi
|
||||
|
||||
if (( dx > dy ))
|
||||
then
|
||||
(( err = dx ))
|
||||
else
|
||||
(( err = -dy ))
|
||||
fi
|
||||
(( err /= 2 ))
|
||||
(( e2 = 0 ))
|
||||
|
||||
while :
|
||||
do
|
||||
echo -en "\e[${y0};${x0}H#\e[K"
|
||||
(( x0 == x1 && y0 == y1 )) && return
|
||||
(( e2 = err ))
|
||||
if (( e2 > -dx ))
|
||||
then
|
||||
(( err -= dy ))
|
||||
(( x0 += sx ))
|
||||
fi
|
||||
if (( e2 < dy ))
|
||||
then
|
||||
(( err += dx ))
|
||||
(( y0 += sy ))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Draw a full screen diamond
|
||||
COLS=$( tput cols )
|
||||
LINS=$( tput lines )
|
||||
LINS=$((LINS-1))
|
||||
clear
|
||||
line $((COLS/2)) 1 $((COLS/4)) $((LINS/2))
|
||||
line $((COLS/4)) $((LINS/2)) $((COLS/2)) $LINS
|
||||
line $((COLS/2)) $LINS $((COLS/4*3)) $((LINS/2))
|
||||
line $((COLS/4*3)) $((LINS/2)) $((COLS/2)) 1
|
||||
echo -e "\e[${LINS}H"
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
'Bitmap/Bresenham's line algorithm - VBScript - 13/05/2019
|
||||
Dim map(48,40), list(10), ox, oy
|
||||
data=Array(1,8, 8,16, 16,8, 8,1, 1,8)
|
||||
For i=0 To UBound(map,1): For j=0 To UBound(map,2)
|
||||
map(i,j)="."
|
||||
Next: Next 'j, i
|
||||
points=(UBound(data)+1)/2
|
||||
For p=1 To points
|
||||
x=data((p-1)*2)
|
||||
y=data((p-1)*2+1)
|
||||
list(p)=Array(x,y)
|
||||
If p=1 Then minX=x: maxX=x: minY=y: maxY=y
|
||||
If x<minX Then minX=x
|
||||
If x>maxX Then maxX=x
|
||||
If y<minY Then minY=y
|
||||
If y>maxY Then maxY=y
|
||||
Next 'p
|
||||
border=2
|
||||
minX=minX-border*2 : maxX=maxX+border*2
|
||||
minY=minY-border : maxY=maxY+border
|
||||
ox =-minX : oy =-minY
|
||||
wx=UBound(map,1)-ox : If maxX>wx Then maxX=wx
|
||||
wy=UBound(map,2)-oy : If maxY>wy Then maxY=wy
|
||||
For x=minX To maxX: map(x+ox,0+oy)="-": Next 'x
|
||||
For y=minY To maxY: map(0+ox,y+oy)="|": Next 'y
|
||||
map(ox,oy)="+"
|
||||
For p=1 To points-1
|
||||
draw_line list(p), list(p+1)
|
||||
Next 'p
|
||||
For y=maxY To minY Step -1
|
||||
line=""
|
||||
For x=minX To maxX
|
||||
line=line & map(x+ox,y+oy)
|
||||
Next 'x
|
||||
Wscript.Echo line
|
||||
Next 'y
|
||||
|
||||
Sub draw_line(p1, p2)
|
||||
Dim x,y,xf,yf,dx,dy,sx,sy,err,err2
|
||||
x =p1(0) : y =p1(1)
|
||||
xf=p2(0) : yf=p2(1)
|
||||
dx=Abs(xf-x) : dy=Abs(yf-y)
|
||||
If x<xf Then sx=+1: Else sx=-1
|
||||
If y<yf Then sy=+1: Else sy=-1
|
||||
err=dx-dy
|
||||
Do
|
||||
map(x+ox,y+oy)="X"
|
||||
If x=xf And y=yf Then Exit Do
|
||||
err2=err+err
|
||||
If err2>-dy Then err=err-dy: x=x+sx
|
||||
If err2< dx Then err=err+dx: y=y+sy
|
||||
Loop
|
||||
End Sub 'draw_line
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Daw a line using Bresenham's line algorithm.
|
||||
// #1=x1, #2=y1; #3=x2, #4=y2
|
||||
|
||||
:DRAW_LINE:
|
||||
Num_Push(31,35)
|
||||
#31 = abs(#3-#1) // x distance
|
||||
#32 = abs(#4-#2) // y distance
|
||||
if (#4-#2 < -#31 || #3-#1 <= -#32) {
|
||||
#99=#1; #1=#3; #3=#99 // swap start and end points
|
||||
#99=#2; #2=#4; #4=#99
|
||||
}
|
||||
if (#1 < #3) { #34=1 } else { #34=-1 } // x step
|
||||
if (#2 < #4) { #35=1 } else { #35=-1 } // y step
|
||||
|
||||
if (#32 > #31) { // steep angle, step by Y
|
||||
#33 = #32 / 2 // error distance
|
||||
while (#2 <= #4) {
|
||||
Call("DRAW_PIXEL")
|
||||
#33 -= #31
|
||||
if (#33 < 0) {
|
||||
#1 += #34 // move right
|
||||
#33 += #32
|
||||
}
|
||||
#2++ // move up
|
||||
}
|
||||
} else { // not steep, step by X
|
||||
#33 = #31 / 2
|
||||
while (#1 <= #3) {
|
||||
Call("DRAW_PIXEL")
|
||||
#33 -= #32
|
||||
if (#33 < 0) {
|
||||
#2 += #35 // move up
|
||||
#33 += #31
|
||||
}
|
||||
#1++ // move right
|
||||
}
|
||||
}
|
||||
Num_Pop(31,35)
|
||||
return
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# doesn't handle vertical lines
|
||||
def (line x0 y0 x1 y1)
|
||||
let steep ((> abs) y1-y0 x1-x0)
|
||||
when steep
|
||||
swap! x0 y0
|
||||
swap! x1 y1
|
||||
when (x0 > x1)
|
||||
swap! x0 x1
|
||||
swap! y0 y1
|
||||
withs (deltax x1-x0
|
||||
deltay (abs y1-y0)
|
||||
error deltax/2
|
||||
ystep (if (y0 < y1) 1 -1)
|
||||
y y0)
|
||||
for x x0 (x <= x1) ++x
|
||||
if steep
|
||||
plot y x
|
||||
plot x y
|
||||
error -= deltay
|
||||
when (error < 0)
|
||||
y += ystep
|
||||
error += deltax
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import "graphics" for Canvas, ImageData, Color
|
||||
import "dome" for Window
|
||||
|
||||
class Game {
|
||||
static bmpCreate(name, w, h) { ImageData.create(name, w, h) }
|
||||
|
||||
static bmpFill(name, col) {
|
||||
var image = ImageData[name]
|
||||
for (x in 0...image.width) {
|
||||
for (y in 0...image.height) image.pset(x, y, col)
|
||||
}
|
||||
}
|
||||
|
||||
static bmpPset(name, x, y, col) { ImageData[name].pset(x, y, col) }
|
||||
|
||||
static bmpPget(name, x, y) { ImageData[name].pget(x, y) }
|
||||
|
||||
static bmpLine(name, x0, y0, x1, y1, col) {
|
||||
var dx = (x1 - x0).abs
|
||||
var dy = (y1 - y0).abs
|
||||
var sx = (x0 < x1) ? 1 : -1
|
||||
var sy = (y0 < y1) ? 1 : -1
|
||||
var err = ((dx > dy ? dx : - dy) / 2).floor
|
||||
while (true) {
|
||||
bmpPset(name, x0, y0, col)
|
||||
if (x0 == x1 && y0 == y1) break
|
||||
var e2 = err
|
||||
if (e2 > -dx) {
|
||||
err = err - dy
|
||||
x0 = x0 + sx
|
||||
}
|
||||
if (e2 < dy) {
|
||||
err = err + dx
|
||||
y0 = y0 + sy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static init() {
|
||||
Window.title = "Bresenham's line algorithm"
|
||||
var size = 200
|
||||
Window.resize(size, size)
|
||||
Canvas.resize(size, size)
|
||||
var name = "bresenham"
|
||||
var bmp = bmpCreate(name, size, size)
|
||||
bmpFill(name, Color.white)
|
||||
bmpLine(name, 50, 100, 100, 190, Color.black)
|
||||
bmpLine(name, 100, 190, 150, 100, Color.black)
|
||||
bmpLine(name, 150, 100, 100, 10, Color.black)
|
||||
bmpLine(name, 100, 10, 50, 100, Color.black)
|
||||
bmp.draw(0, 0)
|
||||
}
|
||||
|
||||
static update() {}
|
||||
|
||||
static draw(alpha) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
include c:\cxpl\codes; \intrinsic 'code' declarations
|
||||
[SetVid($112); \set 640x480 graphics in 24-bit color
|
||||
Move(10, 20); \set start of line segment
|
||||
Line(600, 400, $123456);\draw line segment, red=$12, green=$34, blue=$56
|
||||
if ChIn(1) then []; \wait for keystroke while viewing graphic screen
|
||||
SetVid(3); \restore normal text mode
|
||||
]
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
ppm:=PPM(200,200,0xFF|FF|FF);
|
||||
ppm.line(50,100, 100,190, 0);
|
||||
ppm.line(100,190, 150,100, 0);
|
||||
ppm.line(150,100, 100,10, 0);
|
||||
ppm.line(100,10, 50,100, 0);
|
||||
|
||||
ppm.writeJPGFile("line.jpg");
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
class PPM{ // (0,0) is logically bottom left
|
||||
fcn init(width,height,rgb=0){
|
||||
sz:=width*height;
|
||||
var [const]
|
||||
data=Data(sz*3).fill(rgb.toBigEndian(3).toData()), // initialize to 24bit Black (RGB=000)
|
||||
w=width, h=height;
|
||||
}
|
||||
fcn fill(rgb){ data.fill(rgb.toBigEndian(3).toData()) }
|
||||
fcn __sGet(x,y) { data.toBigEndian(3*y*w + 3*x,3); } //ppm[x,y]
|
||||
fcn __sSet(rgb,x,y){ data[3*y*w + x*3,3]=rgb.toBigEndian(3); rgb } //ppm[x,y]=rgb
|
||||
fcn write(out,raw=False){ // write bottom to top to move (0,0) from top left to bottom left
|
||||
out.write("P6\n#rosettacode PPM\n%d %d\n255\n".fmt(w,h));
|
||||
if(raw) out.write(data);
|
||||
else [h-1..0, -1].pump(out,'wrap(h){ data.seek(3*h*w); data.read(3*w) });
|
||||
}
|
||||
fcn writeJPGFile(fname){ // Linux, using imagemagick
|
||||
System.popen(0'|convert ppm:- jpg:"%s"|.fmt(fname),"w") :
|
||||
write(_,vm.pasteArgs(1));
|
||||
}
|
||||
fcn readJPGFile(fileName){ // Linux, using imagemagick
|
||||
p:=System.popen("convert \"%s\" ppm:-".fmt(fileName),"r");
|
||||
img:=PPM.readPPM(p);
|
||||
p.close();
|
||||
img
|
||||
}
|
||||
fcn readPPMFile(fileName){
|
||||
f:=File(fileName,"rb"); ppm:=readPPM(f); f.close();
|
||||
ppm
|
||||
}
|
||||
fcn readPPM(image){ // image is a PPM byte stream
|
||||
// header is "P6\n[#comment\n]<w> <h>\nmaxPixelValue\n
|
||||
image.readln(); // "P6"
|
||||
while("#"==(text:=image.readln().strip())[0]){}
|
||||
w,h:=text.split().apply("toInt");
|
||||
image.readln(); // max pixel value
|
||||
ppm,sz,buffer:=PPM(w,h), 3*w, Data(sz);
|
||||
ppm.data.clear(); // gonna write file image data
|
||||
// image is stored upside down in my data structure
|
||||
do(h){ ppm.data.insert(0, image.read(sz,buffer)) }
|
||||
ppm
|
||||
}
|
||||
fcn circle(x0,y0,r,rgb){
|
||||
x:=r; y:=0; radiusError:=1-x;
|
||||
while(x >= y){
|
||||
__sSet(rgb, x + x0, y + y0);
|
||||
__sSet(rgb, y + x0, x + y0);
|
||||
__sSet(rgb,-x + x0, y + y0);
|
||||
__sSet(rgb,-y + x0, x + y0);
|
||||
self[-x + x0, -y + y0]=rgb; // or do it this way, __sSet gets called as above
|
||||
self[-y + x0, -x + y0]=rgb;
|
||||
self[ x + x0, -y + y0]=rgb;
|
||||
self[ y + x0, -x + y0]=rgb;
|
||||
y+=1;
|
||||
if (radiusError<0) radiusError+=2*y + 1;
|
||||
else{ x-=1; radiusError+=2*(y - x + 1); }
|
||||
}
|
||||
}
|
||||
fcn cross(x,y,rgb=0xff|00,len=10){
|
||||
a:=len/2; b:=len-a;
|
||||
line(x-a,y, x+b,y,rgb); line(x,y-a, x,y+b,rgb);
|
||||
}
|
||||
fcn line(x0,y0, x1,y1, rgb){
|
||||
dx:=(x1-x0).abs();
|
||||
dy:=(y1-y0).abs();
|
||||
if(x0 < x1) sx:=1 else sx:=-1;
|
||||
if(y0 < y1) sy:=1 else sy:=-1;
|
||||
err:=dx - dy;
|
||||
while(1){
|
||||
__sSet(rgb,x0,y0);
|
||||
if(x0==x1 and y0==y1) break;
|
||||
e2:=2*err;
|
||||
if(e2 > -dy){ err=err - dy; x0=x0 + sx; }
|
||||
if(e2 < dx) { err=err + dx; y0=y0 + sy; }
|
||||
}
|
||||
}
|
||||
fcn flood(x,y, repl){ // slow!
|
||||
targ:=self[x,y];
|
||||
(stack:=List.createLong(10000)).append(T(x,y));
|
||||
while(stack){
|
||||
x,y:=stack.pop();
|
||||
if((0<=y<h) and (0<=x<w)){
|
||||
p:=self[x,y];
|
||||
if(p==targ){
|
||||
self[x,y]=repl;
|
||||
stack.append( T(x-1,y), T(x+1,y), T(x, y-1), T(x, y+1) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue