-
Notifications
You must be signed in to change notification settings - Fork 2
/
murphy_line_draw.m
151 lines (124 loc) · 4.4 KB
/
murphy_line_draw.m
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
function bitmap = murphy_line_draw(bitmap, pt0, pt1, thickness)
% A modified version of Bresenham's line algorithm for drawing lines of
% arbitrary thickness.
%
%
% Documentation
% -------------
% The function implements Murphy's line algorithm [1] to draw lines of
% arbitrary thickness. It is a modified version of Bresenham's line
% algorithm [2].
% This implementation works in all octants of the Cartesian coordinate
% system.
%
% Inputs:
% bitmap NxM matrix
% pt0 startpoint of line (struct with fields x,y)
% pt1 endpoint of line (struct with fields x,y)
% thickness thickness of line
%
% Output:
% bitmap NxM matrix with drawn line
%
%
% References
% ----------
% [1] Line Thickening by Modification To Bresenham's Algorithm,
% A.S. Murphy,
% IBM Technical Disclosure Bulletin, Vol. 20, No. 12, May 1978.
%
% [2] Algorithm for computer control of a digital plotter,
% J.E. Bresenham,
% IBM Systems Journal, 4, 1, 1965, S. 25–30
%
%
% Copyright (C) 2015 Daniel Bartel
% Distributed under the GNU GPL v2. For full terms see the file LICENSE.
%
% Distinction of octants
% ----------------------
dx = pt1.x - pt0.x;
dy = pt1.y - pt0.y;
inc_x = sign(sign(dx) + 0.5); % signum function
inc_y = sign(sign(dy) + 0.5);
if dx < 0; dx = -dx; end
if dy < 0; dy = -dy; end
if dx > dy
len = dx;
sd0x = 0; sd0y = inc_y;
dd0x = -inc_x; dd0y = inc_y;
sd1x = inc_x; sd1y = 0;
dd1x = inc_x; dd1y = inc_y;
ku = 2*dx; % 2*dx
kv = 2*dy; % 2*dy
kd = kv - ku; % 2*dy - 2*dx
kt = dx - kv; % threshold for error term
else
len = dy;
sd0x = inc_x; sd0y = 0;
dd0x = inc_x; dd0y = -inc_y;
sd1x = 0; sd1y = inc_y;
dd1x = inc_x; dd1y = inc_y;
ku = 2*dy; % 2*dy
kv = 2*dx; % 2*dx
kd = kv - ku; % 2*dx - 2*dy
kt = dy - kv; % threshold for error term
end
% Initialization % Figure 5A in [1]
% --------------
tk = 2*thickness*sqrt(dx*dx + dy*dy); % threshold for thickness
d0 = 0; % outer loop error term
d1 = 0; % inner loop error term
dd = 0; % thickness error term
% Murphy line draw
% ----------------
while dd < tk % outer loop (perpendicular to line)
bitmap = bresenham_line_draw(bitmap, pt0, d1);
if d0 < kt % square move (d0 -> M0, dd -> M0)
pt0.x = pt0.x + sd0x;
pt0.y = pt0.y + sd0y;
else % diagonal move (d0 -> M1, dd -> M1)
dd = dd + kv;
d0 = d0 - ku;
if d1 < kt % diagonal move (d1 needs extra M0)
pt0.x = pt0.x + dd0x;
pt0.y = pt0.y + dd0y;
d1 = d1 - kv;
else % (double) square move (d1 needs extra M1)
if dx > dy
pt0.x = pt0.x + dd0x;
else
pt0.y = pt0.y + dd0y;
end
d1 = d1 - kd;
if dd > tk
return % breakout on the extra line
end
bitmap = bresenham_line_draw(bitmap, pt0, d1);
if dx > dy
pt0.y = pt0.y + dd0y;
else
pt0.x = pt0.x + dd0x;
end
end
end
dd = dd + ku;
d0 = d0 + kv;
end
% Bresenham line draw
% -------------------
function bitmap = bresenham_line_draw(bitmap, pt, d1) % Figure 5B in [1]
for p = 0:len % inner loop (parallel to line)
bitmap(pt.x, pt.y) = bitmap(pt.x, pt.y) + 1;
if d1 <= kt % square move (d1 -> M0)
pt.x = pt.x + sd1x;
pt.y = pt.y + sd1y;
d1 = d1 + kv;
else % diagonal move (d1 -> M1)
pt.x = pt.x + dd1x;
pt.y = pt.y + dd1y;
d1 = d1 + kd;
end
end
end
end