feat: idx
This commit is contained in:
parent
25b851a1bf
commit
902550225e
64
fvi.py
64
fvi.py
|
@ -1,7 +1,7 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
def fast_voxel_intersect(start, end, origin, step) -> tuple[list, list]:
|
def fast_voxel_intersect(start, end, origin, step, shape) -> tuple[list, list, list]:
|
||||||
"""Compute the voxels intersected by a line segment.
|
"""Compute the voxels intersected by a line segment.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -13,6 +13,7 @@ def fast_voxel_intersect(start, end, origin, step) -> tuple[list, list]:
|
||||||
Returns:
|
Returns:
|
||||||
list: list of intersection points
|
list: list of intersection points
|
||||||
list: list of intersected voxels
|
list: list of intersected voxels
|
||||||
|
list: list of voxels idx
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Convert to numpy arrays
|
# Convert to numpy arrays
|
||||||
|
@ -28,17 +29,18 @@ def fast_voxel_intersect(start, end, origin, step) -> tuple[list, list]:
|
||||||
# Initialize list of intersected voxels
|
# Initialize list of intersected voxels
|
||||||
intersections = []
|
intersections = []
|
||||||
voxels = []
|
voxels = []
|
||||||
|
voxels_idx = []
|
||||||
|
|
||||||
# Compute direction of line segment
|
# Compute direction of line segment
|
||||||
direction = end - start
|
direction = end - start
|
||||||
global_distance = np.linalg.norm(direction, axis=0)
|
global_distance = np.linalg.norm(direction, axis=0)
|
||||||
if global_distance == 0:
|
if global_distance == 0:
|
||||||
return intersections
|
return intersections, voxels, voxels_idx
|
||||||
direction = direction / global_distance
|
direction = direction / global_distance
|
||||||
|
non_zero_direction = (direction != 0).argmax()
|
||||||
|
|
||||||
# Compute the sign of the direction
|
# Compute the sign of the direction
|
||||||
direction_signs = np.sign(direction)
|
direction_signs = np.sign(direction)
|
||||||
is_positive = direction_signs > 0
|
|
||||||
is_negative = direction_signs < 0
|
is_negative = direction_signs < 0
|
||||||
|
|
||||||
# Initialize current position to start
|
# Initialize current position to start
|
||||||
|
@ -48,7 +50,7 @@ def fast_voxel_intersect(start, end, origin, step) -> tuple[list, list]:
|
||||||
while True:
|
while True:
|
||||||
# Compute the distance to the next boundaries
|
# Compute the distance to the next boundaries
|
||||||
next_boundaries = np.divide(position + step * direction_signs, step)
|
next_boundaries = np.divide(position + step * direction_signs, step)
|
||||||
distances = (is_positive * np.floor(next_boundaries) +
|
distances = ((1 - is_negative) * np.floor(next_boundaries) +
|
||||||
is_negative * np.ceil(next_boundaries)) * step - position
|
is_negative * np.ceil(next_boundaries)) * step - position
|
||||||
|
|
||||||
# Determine the nearest boundary to be reached
|
# Determine the nearest boundary to be reached
|
||||||
|
@ -57,7 +59,7 @@ def fast_voxel_intersect(start, end, origin, step) -> tuple[list, list]:
|
||||||
clothest_boundary_distance = boundary_distances[clothest_boundary]
|
clothest_boundary_distance = boundary_distances[clothest_boundary]
|
||||||
|
|
||||||
# Check if we are done
|
# Check if we are done
|
||||||
distance_to_end = abs((end[0] - position[0]) / direction[0])
|
distance_to_end = abs((end[non_zero_direction] - position[non_zero_direction]) / direction[non_zero_direction])
|
||||||
if clothest_boundary_distance > distance_to_end:
|
if clothest_boundary_distance > distance_to_end:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -69,22 +71,25 @@ def fast_voxel_intersect(start, end, origin, step) -> tuple[list, list]:
|
||||||
position[clothest_boundary] / step[clothest_boundary]) * step[clothest_boundary]
|
position[clothest_boundary] / step[clothest_boundary]) * step[clothest_boundary]
|
||||||
|
|
||||||
# Get corresponding voxel
|
# Get corresponding voxel
|
||||||
boundary_reached_negativly = np.zeros(start.shape, dtype=bool)
|
on_boundary = np.mod(position, step) == 0
|
||||||
boundary_reached_negativly[clothest_boundary] = is_negative[clothest_boundary]
|
voxel = np.floor(position) - is_negative * on_boundary * step
|
||||||
voxel = np.floor(position) - boundary_reached_negativly * step
|
|
||||||
|
|
||||||
# Add voxel to list
|
# Add voxel to list
|
||||||
|
idx = np.floor_divide(voxel, step).astype(int)
|
||||||
|
if np.any(idx < 0) or np.any(idx >= shape):
|
||||||
|
continue
|
||||||
intersections.append(position + origin)
|
intersections.append(position + origin)
|
||||||
voxels.append(voxel + origin)
|
voxels.append(voxel + origin)
|
||||||
|
voxels_idx.append(idx)
|
||||||
|
|
||||||
return intersections, voxels
|
return intersections, voxels, voxels_idx
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
def update_figure():
|
def update_figure():
|
||||||
positions, voxels = fast_voxel_intersect(start, end, origin, step)
|
positions, voxels, voxels_idx = fast_voxel_intersect(start, end, origin, step, shape)
|
||||||
|
|
||||||
plt.clf()
|
plt.clf()
|
||||||
|
|
||||||
|
@ -94,6 +99,15 @@ if __name__ == '__main__':
|
||||||
[voxel[1], voxel[1], voxel[1] + step[1], voxel[1] + step[1]],
|
[voxel[1], voxel[1], voxel[1] + step[1], voxel[1] + step[1]],
|
||||||
color='#e25', alpha=0.5)
|
color='#e25', alpha=0.5)
|
||||||
|
|
||||||
|
for voxel_id in voxels_idx:
|
||||||
|
plt.fill([
|
||||||
|
origin[0] + voxel_id[0] * step[0], origin[0] + (voxel_id[0] + 1) * step[0],
|
||||||
|
origin[0] + (voxel_id[0] + 1) * step[0], origin[0] + voxel_id[0] * step[0]
|
||||||
|
], [
|
||||||
|
origin[1] + voxel_id[1] * step[1], origin[1] + voxel_id[1] * step[1],
|
||||||
|
origin[1] + (voxel_id[1] + 1) * step[1], origin[1] + (voxel_id[1] + 1) * step[1]
|
||||||
|
], color='#2e3', alpha=0.5)
|
||||||
|
|
||||||
# Plot line segment
|
# Plot line segment
|
||||||
plt.plot([start[0], end[0]], [start[1], end[1]], 'k-')
|
plt.plot([start[0], end[0]], [start[1], end[1]], 'k-')
|
||||||
plt.plot(start[0], start[1], 'go')
|
plt.plot(start[0], start[1], 'go')
|
||||||
|
@ -107,35 +121,31 @@ if __name__ == '__main__':
|
||||||
plt.axis('equal')
|
plt.axis('equal')
|
||||||
plt.xlim((-10, 10))
|
plt.xlim((-10, 10))
|
||||||
plt.ylim((-10, 10))
|
plt.ylim((-10, 10))
|
||||||
xmin, xmax = plt.xlim()
|
plt.xticks(origin[0] + step[0] * np.arange(shape[0] + 1))
|
||||||
ymin, ymax = plt.ylim()
|
plt.yticks(origin[1] + step[1] * np.arange(shape[1] + 1))
|
||||||
plt.xticks(np.arange(xmin + origin[0],
|
|
||||||
xmax + origin[0] + step[0], step[0]))
|
|
||||||
plt.yticks(np.arange(ymin + origin[1],
|
|
||||||
ymax + origin[1] + step[1], step[1]))
|
|
||||||
plt.grid()
|
plt.grid()
|
||||||
plt.draw()
|
plt.draw()
|
||||||
|
|
||||||
def onclick(event):
|
def onkey(event):
|
||||||
global start, end
|
global start, end
|
||||||
# if event.button == 1:
|
if event.key == ' ':
|
||||||
# start = np.array([event.xdata, event.ydata])
|
start = np.random.rand(2) * 20 - 10
|
||||||
# elif event.button == 3:
|
end = np.random.rand(2) * 20 - 10
|
||||||
# end = np.array([event.xdata, event.ydata])
|
|
||||||
start = np.random.rand(2) * 10 - 5
|
|
||||||
end = np.random.rand(2) * 10 - 5
|
|
||||||
update_figure()
|
update_figure()
|
||||||
|
|
||||||
# Define voxel grid
|
# Define voxel grid
|
||||||
origin = np.array([.1, -.3])
|
origin = np.array([-5., -5.])
|
||||||
step = np.array([1.0, 1.0])
|
step = np.array([1.0, 1.0])
|
||||||
|
shape = (10, 10)
|
||||||
|
|
||||||
# Define segment
|
# Define segment
|
||||||
start = np.random.rand(2) * 10 - 5
|
# start = np.random.rand(2) * 20 - 10
|
||||||
end = np.random.rand(2) * 10 - 5
|
# end = np.random.rand(2) * 20 - 10
|
||||||
|
start = np.array([0., 0.])
|
||||||
|
end = np.array([4., -4.])
|
||||||
|
|
||||||
# Plot
|
# Plot
|
||||||
fig = plt.figure()
|
fig = plt.figure()
|
||||||
fig.canvas.mpl_connect('button_press_event', onclick)
|
fig.canvas.mpl_connect('key_press_event', onkey)
|
||||||
update_figure()
|
update_figure()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
Loading…
Reference in a new issue