5

I have 6 points which all lie on the surface of a sphere and are the vertices of an octohedron. How can I plot the surface of this octohedron within the sphere on a 3d axes?

I have the following code but it does not do what I was hoping:

from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt

Points=[[ 0.17770898,  0.72315927,  0.66742804],
       [-0.65327074, -0.4196453 ,  0.63018661],
       [ 0.65382635,  0.42081934, -0.62882604],
       [-0.17907021, -0.72084723, -0.66956189],
       [-0.73452809,  0.5495376 , -0.39809158],
       [ 0.73451554, -0.55094017,  0.39617148]]

fig=plt.figure()
ax =fig.add_subplot(1, 1, 1, projection='3d', aspect='auto')

ax.add_collection3d(Poly3DCollection([Points]))

u = np.linspace(0, np.pi, 30)
v = np.linspace(0, 2 * np.pi, 30)

x = np.outer(np.sin(u), np.sin(v))
y = np.outer(np.sin(u), np.cos(v))
z = np.outer(np.cos(u), np.ones_like(v))

ax.plot_wireframe(x, y, z, alpha=0.3)

plt.show()

This is the current plot. There's no error, but the octohedron surface is not correct.

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Thomas Hopkins
  • 671
  • 2
  • 10
  • 20

2 Answers2

4

To add upon HYRY's answer; a volume is built from a list of several polygonal faces, and each face is in turn built by a list of points. (Each point is thus present several times in the list of lists, if the faces are adjacent). Consider the following snippet, where the points have been labeled.

Tested in python 3.11.2, matplotlib 3.7.1, numpy 1.24.3

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

fig = plt.figure ()
ax = fig.add_subplot (1, 1, 1, projection = '3d', aspect = 'auto')

# octahedron
A = [ 0.17770898,  0.72315927,  0.66742804]
B = [-0.65327074, -0.4196453 ,  0.63018661]
C = [ 0.65382635,  0.42081934, -0.62882604]
D = [-0.17907021, -0.72084723, -0.66956189]
E = [-0.73452809,  0.5495376 , -0.39809158]
F = [ 0.73451554, -0.55094017,  0.39617148]
OCTO = [[E, A, B],
        [E, B, D],
        [E, D, C],
        [E, C, A],
        [F, A, B],
        [F, B, D],
        [F, D, C],
        [F, C, A],
]
ax.add_collection3d (Poly3DCollection (OCTO))

# sphere
u = np.linspace (0, np.pi, 30)
v = np.linspace (0, 2 * np.pi, 30)
x = np.outer (np.sin (u), np.sin (v))
y = np.outer (np.sin (u), np.cos (v))
z = np.outer (np.cos (u), np.ones_like (v))
ax.plot_wireframe (x, y, z, alpha = 0.3)

plt.show ()

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
RolKau
  • 1,737
  • 1
  • 19
  • 18
2

A Poly3DCollection is a list of Polygons, and a Polygon is a list of points, a point is a list that contains three values. So you should pass a list of list of list of values to Poly3DCollection. Change the following code:

ax.add_collection3d(Poly3DCollection([Points]))
HYRY
  • 94,853
  • 25
  • 187
  • 187