synopsis (of previous events)
If you want to draw a soccer ball elegantly, then you first need to draw the ortho icosahedron:Drawing ortho icosahedra with Python
Its core code is
import numpy as np from itertools import product G = ((5)-1)/2 def getVertex(): pt2 = [(a,b) for a,b in product([1,-1], [G, -G])] pts = [(a,b,0) for a,b in pt2] pts += [(0,a,b) for a,b in pt2] pts += [(b,0,a) for a,b in pt2] return (pts) def getDisMat(pts): N = len(pts) dMat = ([N,N])* for i in range(N): for j in range(i): dMat[i,j] = ([pts[i]-pts[j]]) return dMat pts = getVertex() dMat = getDisMat(pts) # The values of the edges obtained may not be unique due to rounding errors ix, jx = (((dMat))<0.01) # Get the edges of an icosahedron edges = [pts[[i,j]] for i,j in zip(ix, jx)] def isFace(e1, e2, e3): pts = ([e1, e2, e3]) pts = (pts, axis=0) return len(pts)==3 from itertools import combinations # Get the faces of an icosahedron faces = [es for es in combinations(edges, 3) if isFace(*es)]
To overcome the plot_trisurf bug in the xy coordinate system, it is necessary to do a little rotation of the soccer ball, so the rotation matrix is written below.
# Turn the angle in radians and then find the cosine # cos = lambda th : (np.deg2rad(th)) sin = lambda th : (np.deg2rad(th)) # i.e. Rx(th) => Matrix Rx = lambda th : ([ [1, 0, 0], [0, cos(th), -sin(th)], [0, sin(th), cos(th)]]) Ry = lambda th : ([ [cos(th), 0, sin(th)], [0 , 1, 0], [-sin(th), 0, cos(th)] ]) Rz = lambda th : ([ [cos(th) , sin(th), 0], [-sin(th), cos(th), 0], [0 , 0, 1]])
The final ortho icosahedron obtained is
Draw the hexagon first
A soccer ball is actually an icosahedron with its vertices cut off. An icosahedron has 20 faces and 12 vertices, each of which is a triangle. Cutting off the vertices means cutting off three corners for a triangle, and if you choose to cut the corners at exactly 1/3 of the way down, the triangle becomes an orthohexagon; whereas there are exactly 5 prongs at each vertex, and the vertices become ortho-pentagons when they are cut off.
And it just so happens that the hexagonal and pentagonal sides of a soccer ball have different colors, so you can draw them in steps and take care of the hexagonal side first.
Since all the faces of the ortho icosahedron have been previously obtained, along with all the corresponding sides of this face, it is only necessary to truncate at 1/3 and 2/3 of each side to obtain the ortho hexagon of the soccer ball.
def getHexEdges(face): pts = [] for st,ed in face: ((2*st+ed)/3) ((st+2*ed)/3) return (pts) ax = (projection='3d') for f in faces: pt = getHexEdges(f) pt = Rx(1)@Ry(1)@ ax.plot_trisurf(*pt, color="white")
So a soccer ball with holes in it was easily drawn
Draw the pentagon again.
The next thing to do is to fill in the holes in the pentagon, which, as stated at the beginning, can be understood as obtained by chipping away at the vertices, so the first thing to do is to find all the edges around a vertex. This is done by iterating over all the edges for each vertex, and if this vertex is present in a particular edge, then include that edge in the connecting edge of that vertex.
def getPtEdges(pts, edges): N = len(pts) pEdge = [[] for pt in pts] for i,e in product(range(N),edges): if (pts[i] == e[0]).all(): pt = (2*pts[i]+e[1])/3 elif (pts[i] == e[1]).all(): pt = (2*pts[i]+e[0])/3 else: continue pEdge[i].append(pt) return (pEdge) pEdge = getPtEdges(pts, edges)
Next, it's time to draw the soccer ball
ax = (projection='3d') for f in faces: pt = getHexEdges(f) pt = Rx(1)@Ry(1)@ ax.plot_trisurf(*pt, color="white") for pt in pEdge: pt = Rx(1)@Ry(1)@ ax.plot_trisurf(*pt, color="black") ()
have the effect of
The above is based on Python implementation of drawing a soccer ball in detail, more information about Python soccer ball please pay attention to my other related articles!