-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbresenham_line_algorithm.py
168 lines (133 loc) · 4.66 KB
/
bresenham_line_algorithm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
'''
This program implements Bresenham's Line Drawing algorithm.
This program uses the Python Imaging Library in order to
assist with line drawing.
'''
# Standard Libraries
import time
from decimal import Decimal, getcontext
from random import randint
# Image module from the Python Imaging Library
from PIL import Image
# Creates an empty black image
image = Image.new(mode = "RGB", size = (500, 500), color = (0,0,0))
def bresenham_alg(x0, y0, x1, y1):
'''
This function uses Bresenham's Line Drawing Algorithm
to draw a line from coordinates (x0, y0) to (x1, y1).
Meanwhile, this function also keeps track of the total
time it takes for all lines to be drawn.
Returns
-------
draw_time
total time it takes to draw one line
'''
# Used for calculating total time to draw all the given lines
draw_time = 0
# Used to round the timer to 5 significant figures
getcontext().prec = 5
# Assigns random RGB values to differenciate between different drawn lines.
r = randint(0,255)
g = randint(0,255)
b = randint(0,255)
# If x0 == x1 : the line is vertical
if x0 == x1:
y_min = min(y0, y1)
# Starts the timer for the critical loop
start_time = Decimal(time.perf_counter())
# Critical loop
for y_coord in range(abs(y1 - y0)):
image.putpixel((x0, y_min + y_coord), (r, g, b))
# Stops timer
end_time = Decimal(time.perf_counter())
# Calculates total time
draw_time += (end_time - start_time)
# Else, the line is not vertical
else:
# Check if |x1 - x0| >= |y1 - y0|
if abs(x1 - x0) >= abs(y1 - y0):
# If x0 > x1, switch values of each coordinate pair
if x0 > x1:
(x0, x1) = (x1, x0)
(y0, y1) = (y1, y0)
# Calculates slope, delta x, and delta y, and E
slope = (y1 - y0) / (x1 - x0)
dx = abs(x1 - x0)
dy = abs(y1 - y0)
big_e = 2 * dy - dx
# Calculates each increment value and x, y, and x_max values for loop
inc1 = 2 * dy
inc2 = 2 * (dy - dx)
x = x0
y = y0
x_max = max(x0, x1)
# Starts timer for loop
start_time = Decimal(time.perf_counter())
# Critical loop
while True:
image.putpixel((x, y), (r, g, b))
if big_e < 0:
big_e += inc1
else:
# if slope >= 0, y += 1; otherwise y -= 1
if slope >= 0:
y += 1
else:
y -= 1
big_e += inc2
x += 1
if x >= x_max:
break
# Stops timer once loop breaks
end_time = Decimal(time.perf_counter())
# Calculates total time
draw_time += (end_time - start_time)
# else if |y1 - y0| > |x1 - x0|
elif abs(y1 - y0) > abs(x1 - x0):
# If y0 > y1, switch values of each coordinate pair
if y0 > y1:
(x0, x1) = (x1, x0)
(y0, y1) = (y1, y0)
# Calculates slope, delta x, and delta y, and E
slope = (y1 - y0) / (x1 - x0)
dx = abs(x1 - x0)
dy = abs(y1 - y0)
big_e = 2 * dx - dy
# Calculates each increment value and x, y, and y_max values for loop
inc1 = 2 * dx
inc2 = 2 * (dx - dy)
x = x0
y = y0
y_max = max(y0, y1)
# Starts timer for loop
start_time = Decimal(time.perf_counter())
# Critical loop
while True:
image.putpixel((x, y), (r, g, b))
if big_e < 0:
big_e += inc1
else:
# if slope >= 0, x += 1; otherwise x -= 1
if slope >= 0:
x += 1
else:
x -= 1
big_e += inc2
y += 1
if y >= y_max:
break
# Stops timer once loop breaks
end_time = Decimal(time.perf_counter())
# Calculates total time
draw_time += (end_time - start_time)
return draw_time
'''
# Debug
total = 0
total += bresenham_alg(50, 100, 50, 200)
total += bresenham_alg(75, 75, 237, 100)
total += bresenham_alg(85, 45, 337, 20)
total += bresenham_alg(30, 30, 80, 30)
print(f'Loop took {total} seconds long.')
image.show()
'''