import k3d
import numpy as np
from math import sqrt, sin, cos
from skimage.measure import label
width = height = length = 100
def r(x, y, z):
r = sqrt((x - width / 2) * (x - width / 2) + (y - height / 2) * (y - height / 2) + (z - length / 2) * (z - length / 2))
r += sin(x / 2) * 3
r += cos(y / 10) * 5
return r
def f(x, y, z):
return 0 if r(x, y, z) > width / 2 else (1 if y + sin(x / 20) * 10 > height / 2 else 2)
def on_click(x, y, z):
coords = [x, y, z]
missing = None
missing_count = 0
for idx, v in enumerate([np.array([0,0,1]), np.array([0,1,0]), np.array([1,0,0])]):
axis = coords[idx]
if axis == 0 or (obj.voxels[tuple(np.array([z, y, x]) - v)] == 0):
missing = -v
missing_count += 1
if axis == obj.voxels.shape[2 - idx] - 1 or obj.voxels[tuple(np.array([z, y, x]) + v)] == 0:
missing = v
missing_count += 1
if missing_count == 1:
if missing[0] != 0:
slice = obj.voxels[z, :, :]
mask = label(slice, connectivity = 2)
slice[mask == mask[y, x]] = plot.voxel_paint_color
if missing[1] != 0:
slice = obj.voxels[:, y, :]
mask = label(slice, connectivity = 2)
slice[mask == mask[z, x]] = plot.voxel_paint_color
if missing[2] != 0:
slice = obj.voxels[:, :, x]
mask = label(slice, connectivity = 2)
slice[mask == mask[z, y]] = plot.voxel_paint_color
obj.push_data('voxels')
color_map = (0xffff00, 0xff0000, 0x00ff00)
voxels = np.array([[[f(x, y, z) for x in range(width)] for y in range(height)] for z in range(length)])
obj = k3d.voxels(voxels.astype(np.uint8), color_map)
plot = k3d.plot()
plot += obj
obj.click_callback = on_click
plot.voxel_paint_color = 3