B
This commit is contained in:
parent
e5e8880e41
commit
518da4a923
1019 changed files with 15877 additions and 0 deletions
1
Task/Bitmap-Bresenhams-line-algorithm/0DESCRIPTION
Normal file
1
Task/Bitmap-Bresenhams-line-algorithm/0DESCRIPTION
Normal file
|
|
@ -0,0 +1 @@
|
|||
Using the data storage type defined [[Basic_bitmap_storage|on this page]] for raster graphics images, draw a line given 2 points with the [[wp:Bresenham's_line_algorithm|Bresenham's algorithm]].
|
||||
4
Task/Bitmap-Bresenhams-line-algorithm/1META.yaml
Normal file
4
Task/Bitmap-Bresenhams-line-algorithm/1META.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Graphics algorithms
|
||||
note: Raster graphics operations
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
PRAGMAT READ "Basic_bitmap_storage.a68" PRAGMAT;
|
||||
|
||||
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 #;
|
||||
|
||||
###
|
||||
The test program:
|
||||
###
|
||||
IF test THEN
|
||||
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)
|
||||
FI
|
||||
|
|
@ -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,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,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,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 (abs (- x1 x2))
|
||||
dist-y (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 (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 (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,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,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,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,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,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,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,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,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,64 @@
|
|||
/*REXX program plots/draws a line using the Bresenham's line algorithm. */
|
||||
|
||||
EoE = 1000 /*EOE = End Of Earth, er, plot. */
|
||||
image. = 'fa'x /*fill the array with middle-dots*/
|
||||
plotC = 'fe'x /*character used for plotting pts*/
|
||||
do j=-EoE to +EoE /*draw grid from lowest──>highest*/
|
||||
image.j.0 = '─' /*draw the horizontal axis. */
|
||||
image.0.j = '│' /* " " verical " */
|
||||
end /*j*/
|
||||
image.0.0='┼' /*"draw" the axis origin. */
|
||||
parse arg xi yi xf yf . /*allow specifying line-end pts. */
|
||||
if xi=='' | xi==',' then xi = -1 /*if not specified, use default. */
|
||||
if yi=='' | yi==',' then yi = -3 /* " " " " " */
|
||||
if xf=='' | xf==',' then xf = 6 /* " " " " " */
|
||||
if yf=='' | yf==',' then yf = 10 /* " " " " " */
|
||||
call draw_line xi, yi, xf, yf /*call subroutine and draw line. */
|
||||
call findMaxXY
|
||||
do y=maxY by -1 to minY; aRow=
|
||||
do x=minX to maxX
|
||||
aRow=aRow || image.x.y
|
||||
end /*x*/
|
||||
say aRow
|
||||
end /*y*/
|
||||
exit
|
||||
/*────────────────────────────────DRAW_LINE subroutine──────────────────*/
|
||||
draw_line: procedure expose image. plotC; error=0
|
||||
parse arg xi 1 x0, yi 1 y0 1 y, xf 1 x1, yf 1 y1
|
||||
steep= abs(y1-y0) > abs(x1-x0)
|
||||
if steep then parse value x0 y0 x1 y1 with y0 x0 y1 x1
|
||||
if x0>x1 then parse value x0 x1 y0 y1 with x1 x0 y1 y0
|
||||
|
||||
if y0<y1 then yInc = 1
|
||||
else yInc = -1
|
||||
deltaE=abs(y1-y0) / (x1-x0)
|
||||
|
||||
do x=x0 to x1
|
||||
if steep then image.y.x=plotC
|
||||
else image.x.y=plotC
|
||||
error=error+deltaE
|
||||
if error>=.5 then do; y=y+yInc; error=error-1; end
|
||||
end
|
||||
return
|
||||
/*────────────────────────────────FINDMAXXY subroutine──────────────────*/
|
||||
findMaxXY: extra=3 /*don't just show cropped plot. */
|
||||
do minX=-EoE to +EoE /*find min X in the plot field. */
|
||||
do y=-EoE to +EoE; if .isP(image.minX.y) then leave minX; end /*y*/
|
||||
end /*minX*/
|
||||
|
||||
do maxX=+EoE to -EoE by -1 /*find max X in the plot field. */
|
||||
do y=-EoE to +EoE; if .isP(image.maxX.y) then leave maxX; end /*y*/
|
||||
end /*maxX*/
|
||||
|
||||
do minY=-EoE to +EoE /*find min Y in the plot field. */
|
||||
do x=-EoE to +EoE; if .isP(image.x.minY) then leave minY; end /*x*/
|
||||
end /*minY*/
|
||||
|
||||
do maxY=+EoE to -EoE by -1 /*find max Y in the plot field. */
|
||||
do x=-EoE to +EoE; if .isP(image.X.maxy) then leave maxY; end /*x*/
|
||||
end /*maxY*/
|
||||
|
||||
minX=minX-extra*2; minY=minY-extra /*like showbiz, show a little more*/
|
||||
maxX=maxX+extra*2; maxY=maxY+extra /* " " " " " " */
|
||||
return /*go ye forth and show ye plot. */
|
||||
.isP: return pos(arg(1),plotC)\==0
|
||||
|
|
@ -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,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=(x<=x1 && y<=y1)
|
||||
}
|
||||
|
||||
for((x,y) <- it)
|
||||
bm.setPixel(x, y, c)
|
||||
}
|
||||
}
|
||||
|
|
@ -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}
|
||||
Loading…
Add table
Add a link
Reference in a new issue