How do I color individual sections of a 3d sphere in Python

眉间皱痕 提交于 2020-01-03 03:33:06

问题


I have created a 3d plot of a sphere in python using Mathplotlib using the code below

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

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

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

x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))

ax.plot_surface(x, y, z, rstride=4, cstride=4, color='b')


plt.show()

Picture of plot:-

I would like to color each individual box a different color. I have tried to use a color map, but I was only able to change the color based on the z value with this.

Any suggestions would be greatly appreciated. I am open to using other tools or languages to accomplish this task, but I need the boxes to be the same size.


回答1:


@Armatita's solution is very elegant, especially if you have a mapping function. I upvoted it :). Another solution for arbitrary shapes can be done with Poly3DCollection. Now you could import actual data and the surfaces could be arbitray in space and wouldn't have to connect.

For comparison, however I used the same sphere. I edited the answer to assign the color as a function of the two angles based on your comments below.

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

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

r=1 # radius of sphere
phi = np.linspace(0,360, 12)/180.0*np.pi
theta = np.linspace(-90,90,7)/180.0*np.pi

# make up some function  like OP (original poster) suggested:
# numerical value in the range of 20-40.
vars=[]
for i  in range(len(phi)-1):
    for j in range(len(theta)-1):
        vars.append( (i*j* - i +j)/25+40)  # min at 20, max at 40

# set colors as function of data in vars        
# less than 25 as red, from 25-35 as yellow 
# and anything greater than 35 as green. –        
cols=[]
for var in vars:
    if var <25: 
        col='r'
    elif 25<=var<=35:
        col='y'
    else:
        col='g'
    cols.append(col)

verts2 = []
for i  in range(len(phi)-1):
    for j in range(len(theta)-1):
        cp0= r*np.cos(phi[i])
        cp1= r*np.cos(phi[i+1])
        sp0= r*np.sin(phi[i])
        sp1= r*np.sin(phi[i+1])

        ct0= np.cos(theta[j])
        ct1= np.cos(theta[j+1])

        st0= r*np.sin(theta[j])
        st1= r*np.sin(theta[j+1])

        verts=[]
        verts.append((cp0*ct0, sp0*ct0, st0))
        verts.append((cp1*ct0, sp1*ct0, st0))
        verts.append((cp1*ct1, sp1*ct1, st1))
        verts.append((cp0*ct1, sp0*ct1, st1))
        verts2.append(verts   )

poly3= Poly3DCollection(verts2 ,facecolor= cols)  

poly3.set_alpha(0.9)
ax.add_collection3d(poly3)
ax.set_xlabel('X')
ax.set_xlim3d(-1, 1)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, 1)
ax.set_zlabel('Z')
ax.set_zlim3d(-1, 1)
plt.show()




回答2:


Besides the link given in comments it's possible to directly map a variable to the colormap. Check your example adapted with a solution:

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

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

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

x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))

C = np.cos(x)

ax.plot_surface(x, y, z, facecolors = cm.jet(C), rstride=4, cstride=4) # Look how I gave a variable to the facecolors.

plt.show()

, this particularly bad example results in this:



来源:https://stackoverflow.com/questions/36614456/how-do-i-color-individual-sections-of-a-3d-sphere-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!