2
N-D Bresenham line algo
5
def _bresenhamline_nslope(slope):
7
Normalize slope for Bresenham's line algorithm.
9
>>> s = np.array([[-2, -2, -2, 0]])
10
>>> _bresenhamline_nslope(s)
11
array([[-1., -1., -1., 0.]])
13
>>> s = np.array([[0, 0, 0, 0]])
14
>>> _bresenhamline_nslope(s)
15
array([[ 0., 0., 0., 0.]])
17
>>> s = np.array([[0, 0, 9, 0]])
18
>>> _bresenhamline_nslope(s)
19
array([[ 0., 0., 1., 0.]])
21
scale = np.amax(np.abs(slope), axis=1).reshape(-1, 1)
22
zeroslope = (scale == 0).all(1)
23
scale[zeroslope] = np.ones(1)
24
normalizedslope = slope.astype(np.double) / scale
25
normalizedslope[zeroslope] = np.zeros(slope[0].shape)
26
return normalizedslope
28
def _bresenhamlines(start, end, max_iter):
30
Returns npts lines of length max_iter each. (npts x max_iter x dimension)
32
>>> s = np.array([[3, 1, 9, 0],[0, 0, 3, 0]])
33
>>> _bresenhamlines(s, np.zeros(s.shape[1]), max_iter=-1)
34
array([[[ 3, 1, 8, 0],
55
max_iter = np.amax(np.amax(np.abs(end - start), axis=1))
56
npts, dim = start.shape
57
nslope = _bresenhamline_nslope(end - start)
60
stepseq = np.arange(1, max_iter + 1)
61
stepmat = np.tile(stepseq, (dim, 1)).T
63
# some hacks for broadcasting properly
64
bline = start[:, np.newaxis, :] + nslope[:, np.newaxis, :] * stepmat
66
# Approximate to nearest int
67
return np.rint(bline).astype(start.dtype)
69
def bresenhamline(start, end, max_iter=5):
71
Returns a list of points from (start, end] by ray tracing a line b/w the
74
start: An array of start points (number of points x dimension)
75
end: An end points (1 x dimension)
76
or An array of end point corresponding to each start point
77
(number of points x dimension)
78
max_iter: Max points to traverse. if -1, maximum number of required
82
linevox (n x dimension) A cumulative array of all points traversed by
85
>>> s = np.array([[3, 1, 9, 0],[0, 0, 3, 0]])
86
>>> bresenhamline(s, np.zeros(s.shape[1]), max_iter=-1)
106
# Return the points as a single array
107
return _bresenhamlines(start, end, max_iter).reshape(-1, start.shape[-1])
110
if __name__ == "__main__":