0

I was looking for a way to build cubes of the same size, then draw a line through this space and output the result in the form of coordinates of cubes that this line intersects and paint these cubes with a different color. The line can be either straight or curved.

I used matplotlib to plot cubes and lines. From these sources:

https://www.geeksforgeeks.org/how-to-draw-3d-cube-using-matplotlib-in-python/

Representing voxels with matplotlib

Example code:

from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

axes = [5, 5, 5]

# Create Data
data = np.ones(axes, dtype=np.bool)

# Controll Tranperency
alpha = 0.3

# Control colour
colors = np.empty(axes + [4], dtype=np.float32)

colors[0] = [1, 0, 0, alpha]  # red
colors[1] = [0, 1, 0, alpha]  # green
colors[2] = [0, 0, 1, alpha]  # blue
colors[3] = [1, 1, 0, alpha]  # yellow
colors[4] = [1, 1, 1, alpha]  # grey

# Plot figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x1 = [1, 4]
y1 = [0, 5]
z1 = [0, 5]

ax.plot3D(x1, y1, z1, 'black', linewidth = 5)

# Voxels is used to customizations of
# the sizes, positions and colors.
ax.voxels(data, facecolors=colors, edgecolors='grey')

result

In short: I need to plot a grid of cubes and draw a line through it. After determine which cubes this line intersects.

Is it possible to do this in Matplotlib or do I need to use another library to solve my question?

Егор
  • 3
  • 1

1 Answers1

1

God, why do I put myself though this.
Anyways, here is an iterative solution because I do not feel like doing linear algebra. I tried and I failed.

# Here be dragons
def linelamb(x,y,z):
    return lambda s: [int(i) for i in [x[0]+s*(x[1]-x[0]), y[0]+s*(y[1]-y[0]), z[0]+s*(z[1]-z[0])]]

line = linelamb(x1,y1,z1)

hitboxes = np.zeros(axes)

x,y,z = 0,0,0

for r in [i for i in np.arange(0,1,0.001)]:
    xnew,ynew,znew = line(r)
    if not (x == xnew and y == ynew and z == znew):
        hitboxes[xnew,ynew,znew] = 1
    x,y,z = xnew,ynew,znew

ax.voxels(hitboxes, facecolors=[0,0,0,0.5], edgecolors='black');

Pain

I spent some extra time to make this more adaptable but my brain stopped working. You might want to adaptively change the step size of the range but good luck.

Tempman383838
  • 544
  • 1
  • 10
  • Thank you, everything works correctly. How to do this in case with the curved line? for example: x1 = [1,1, 4] y1 = [0, 1, 5] z1 = [0,1, 5] – Егор Feb 12 '22 at 14:04
  • If you have a parameterized line equation, you just step though it line by line and check for "box updates" every time you enter a new section. Keep in mind that this is an iterative method, which means if your step size is too large, you might skip near misses. – Tempman383838 Feb 14 '22 at 07:49