Search code examples
pythonmatplotlibraytracingmatplotlib-3d

How to plot multiple lines from a loop on one 3d plot


Basically, I am looping generation of rays in Python and I'm trying to plot them all on the same graph. They should all be on a circle of radius 0.1. Each ray should be at a position on the circle that is varied by the arg which is in this case the theta. Also, just to mention (although I don't think it's that relevant) I am doing OOP here.

I get correct rays but I can't get them on the same 3d graph and I'm not sure how I'm supposed to do it. I thought using plt.show() would give me a graph with all 24 rays but it just plots 24 graphs. Here is the relevant bit of code for reference:

r = 0.1
arg = 0
for i in range (0,24):
    arg += np.pi/12
    x = r*np.sin(arg)
    y = r*np.cos(arg)
    l = ray.Ray(r=np.array([x,y,0]),v=np.array([0.5,0,5]))
    c = ray.SphericalRefraction(z0 = 100, curv = 0.0009, n1 = 1.0, n2 = 1.5, ar = 5)
    c.propagate_ray(l)
    o = ray.OutputPlane(250)
    o.outputintercept(l)
    points = np.array(l.vertices())
    fig = plt.figure()
    ax = plt.axes(projection='3d')
    #ax = fig.add_subplot(1,2,1,projection='3d')
    #plt.plot(points[:,2],points[:,0])
    ax.plot3D(points[:,0],points[:,1],points[:,2])
plt.show()

Solution

  • Expanding on the comment by Mercury, the figure and also axes object must be created outside the loop.

    import matplotlib.pyplot as plt
    import numpy as np
    
    r = 0.1
    arg = 0
    
    fig = plt.figure()
    ax = plt.axes(projection='3d')
    for i in range(0,24):
        arg += np.pi/12 * i
        v1 = r*np.sin(arg)
        v2 = r*np.cos(arg)
        # ...
        # using sample data
        x = []
        y = []
        z = []
        for j in range(2):
            x.append(j*v1)
            y.append(j*v2)
            z.append(j)
        # add vertex to the axes object
        ax.plot3D(x, y, z)
    plt.show()
    

    sample 3d plot