Search code examples
python-3.xmatplotlib3dtriangulation

How to plot a double cone with dashed outline and no surface color?


I tried the following script, but I do not know how to plot only an outline.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib.tri import Triangulation

theta = np.linspace(0, 2*np.pi, 20)
rho = np.linspace(-2, 2, 20)
theta, rho = np.meshgrid(theta, rho)

x = np.ravel(rho*np.cos(theta))
y = np.ravel(rho*np.sin(theta))
z = np.ravel(rho)

fig, ax = plt.subplots()
plt.rcParams["figure.figsize"] = [10, 3]
ax = plt.axes(projection='3d')

tri = Triangulation(np.ravel(theta), np.ravel(rho))

ax.plot_trisurf(x, y, z, triangles=tri.triangles, antialiased=True) 

plt.show()

The desired result is a simple double cone with an outline. Something like this but only with black lines. enter image description here


Solution

  • To plot the geometries you specified:- 2 circles, and 3 lines, you just plot each of them. There are some tricks involved that I commmented in the code given below.

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits import mplot3d
    
    nn = 400  #number of points along circle's perimeter
    theta = np.linspace(0, 2*np.pi, nn)
    rho = np.ones(nn)
    
    # (x,y) represents points on circle's perimeter
    x = np.ravel(rho*np.cos(theta))
    y = np.ravel(rho*np.sin(theta))
    
    fig, ax = plt.subplots()
    plt.rcParams["figure.figsize"] = [10, 6]
    ax = plt.axes(projection='3d')  #set the axes for 3D plot
    
    # low, high values of z for plotting 2 circles at different elev.
    loz, hiz = -5, 5
    
    ax.plot(x, y, hiz, color='red')   #plot red circle
    ax.plot(x, y, loz, color='blue')  #plot blue circle
    
    # set some indices to get proper (x,y) for line plotting
    lo1,hi1 = 15, 15+nn//2
    lo2,hi2 = lo1+nn//2-27, hi1-nn//2-27
    
    # plot 3d lines using coordinates of selected points
    ax.plot([x[lo1], x[hi1]], [y[lo1], y[hi1]], [loz, hiz], color='black') #black line
    ax.plot([x[lo2], x[hi2]], [y[lo2], y[hi2]], [loz, hiz], color='green') #green line
    
    m = nn//4
    ax.plot([0, x[m]], [0, y[m]], [hiz, hiz], color='brown')  #brown line
    
    # must set proper viewing angles to get the plot as needed
    ax.azim = 270.5   # y rotation (default=270)
    ax.elev = 20      # x rotation (default=0)
    ax.dist = 10      # zoom perspective
    
    ax.axis("off")  # hide frame
    plt.show()
    

    The output plot:

    enter image description here