How can I connect scatter points in a 3D space?

I want to connect the starting point and ending point of all arcs together in matplotlib. Red arc is the centre of all four surrounding green arcs. Below you'll find a code to draw parallel arcs.

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import interactive
interactive(True)


def cart2sphere(x, y, z):
    r = np.sqrt(x**2 + y**2 + z**2)
    theta = np.arccos(z, r)
    phi = np.arctan2(y, x)
    return(r, theta, phi)

def sphere2cart(r, theta, phi):
    theta = theta - np.pi/2
    x = r * np.sin(theta)* np.cos(phi)
    y = r * np.sin(theta)* np.sin(phi)
    z = r * np.cos(theta)
    return(x, y, z)

def pol2cart(rho, phi):
    x = rho * np.cos(phi)
    y = rho * np.sin(phi)
    return(x, y)

# define values 
theta = np.pi/2 # arclength in radians
radius = 10 # raduis of circle
k = 1/radius # if you want to use k instead of radius
phi = np.pi/6 # angle of circle in xy plane

radius1 = 7.5
radius2 = 12.5

# discretize for plotting
arcIndex = np.linspace(0, theta, num = 100)


X, Y, Z, = sphere2cart(radius, arcIndex, phi)

X1, Y1, Z1, = sphere2cart(radius2, arcIndex, phi)
X2, Y2, Z2, = sphere2cart(radius1, arcIndex, phi)
X3, Y3, Z3, = sphere2cart(radius1, arcIndex, phi)
X4, Y4, Z4, = sphere2cart(radius2, arcIndex, phi)


# move center or arc to xy plane
# =============================================================================
x1, y1 = pol2cart(radius, phi) #arc
X += x1
Y += y1
x2, y2 = pol2cart(radius, phi) #L1 
X1 += x2
Y1 += 1.5+y2
x3, y3 = pol2cart(radius, phi) #L2 
X2 += x3
Y2 += y3-1.5
x4, y4 = pol2cart(radius, phi) #L3 
X3 += x4
Y3 += 1.5+y4
x5, y5 = pol2cart(radius, phi) #L4 
X4 += x5
Y4 += y5-1.5
# =============================================================================

fig = plt.figure()
ax = fig.gca(projection='3d')

# plot arc
ax.plot(X, Y, Z, c= "red", label='arc')
ax.plot(X1, Y1, Z1, c= "Green", label='L1')
ax.plot(X2, Y2, Z2, c= "Green", label='L2')
ax.plot(X3, Y3, Z3, c= "Green", label='L3')
ax.plot(X4, Y4, Z4, c= "Green", label='L4')


# plot axes
ax.plot(np.zeros(100), np.zeros(100), np.linspace(-np.max(np.abs(Z)), np.max(np.abs(Z)), 100), c= "black", alpha = 0.15)
ax.plot(np.zeros(100), np.linspace(-np.max(np.abs(Z)), np.max(np.abs(Z)), 100), np.zeros(100),  c= "black", alpha = 0.15)
ax.plot(np.linspace(-np.max(np.abs(Z)), np.max(np.abs(Z)), 100), np.zeros(100), np.zeros(100),  c= "black", alpha = 0.15)

# plot center of circle
ax.scatter(np.array([x1]), np.array([y1]), np.array([0]), c = 'Green', label = "center of circle", s=10)

# plot endpoint
# =============================================================================
ax.scatter(X[0], Y[0], Z[0], color="red", label= "origin", s=30)
ax.scatter(X[-1], Y[-1], Z[-1], color= 'red', label = "endpoint", s=30)
ax.scatter(X1[-1], Y1[-1], Z1[-1], color= 'red', s=30)
ax.scatter(X2[-1], Y2[-1], Z2[-1], color= 'red', s=30)
ax.scatter(X3[-1], Y3[-1], Z3[-1], color= 'red', s=30)
ax.scatter(X4[-1], Y4[-1], Z4[-1], color= 'red', s=30)
ax.scatter(X1[1], Y1[1], Z1[1], color= 'red', s=30)
ax.scatter(X2[1], Y2[1], Z2[1], color= 'red', s=30)
ax.scatter(X3[1], Y3[1], Z3[1], color= 'red', s=30)
ax.scatter(X4[1], Y4[1], Z4[1], color= 'red', s=30)
# =============================================================================

# plot projection on each axis
ax.plot(X, np.zeros(len(X)), np.zeros(len(X)), color = "blue", label = "X projection")
ax.plot(np.zeros(len(X)), Y, np.zeros(len(X)), color = "green", label = "Y projection")
ax.plot(np.zeros(len(X)), np.zeros(len(X)), Z, color = "brown", label = "Z projection")

ax.legend()

Result that I got from this code shown below, enter image description here

I'm trying to connect all these red scatter points together such that they can make a square at the starting and ending of the arc. What I want is something just like the figure shown below, enter image description here

How do I connect each point in the space with the next one to make it a smooth line graph?


Solution 1:

I recommend to not use Matplotlib for 3d plotting at all. You will hit a wall sooner or later. Even though there are cool looking plots around, it does not work well especially if you want to visualize scatter plots with many data points. And it will fail for sure if you want to plot colorized triangular meshes or complex surfaces.

Instead use one of the following toolkits:

  • https://docs.enthought.com/mayavi/mayavi/ (3d, fast, nice)
  • http://www.pyqtgraph.org/ (2d/3d, very fast)

    A very good example showing different approaches for multiple real time plots can be found here

  • https://plot.ly/python/3d-surface-plots/ (2d/3d, nice)

  • http://vispy.org/documentation.html (2d/3d, very fast, nice, requires OpenGL)

    Might be the future, check the high-level functions vispy.plot() and vispy.scene(), I guess they made some progress)

    For examples see here, look for the ones with "scene". There also seems to be some interface to use Vispy to render Matplotlib plots.