Source code for irfpy.util.icosahedron

''' Module for regular icosahedron.

.. codeauthor:: Yoshifumi Futaana

Regular icosahedron is is a regular polyhedron with 20
idenical equilateral triangle.
Thre are 30 edges with 12 vertices.
'''

import math
import numpy as np
from irfpy.util import triangle



[docs]class RegularIcosahedron(): ''' Class of regular icosahedron. ''' def __init__(self, radius=None, edgeLength=None): ''' Instance the regular icosahedron. Instances the regular icosahedron. Parameter radius specifies the raidus of a circumsribed sphere. >>> ic = RegularIcosahedron() >>> print(ic.radius) 1.0 >>> print('%.5f' % ic.edgeLength) 1.05146 >>> ic = RegularIcosahedron(radius = 3.5) >>> edgeLen = ic.edgeLength >>> ic = RegularIcosahedron(edgeLength = edgeLen) >>> print('%.1f' % ic.radius) 3.5 ''' if edgeLength is None: if radius is None: radius = 1.0 self.radius = radius self.edgeLength = self.radius * 4 / math.sqrt( 10 + 2 * math.sqrt(5)) else: if radius is None: self.radius = edgeLength * math.sqrt( 10 + 2 * math.sqrt(5)) / 4. self.edgeLength = edgeLength else: raise RuntimeError("RegularIcosahedron::__init__() can have " + "only one keyword either radius or edgeLength.")
[docs] def numberEdges(self): ''' Get the number of edges, i.e. 30. >>> ico = RegularIcosahedron() >>> print(ico.numberEdges()) 30 ''' return 30
[docs] def numberVertices(self): ''' Return the number of vertices, i.e. 12. >>> ico = RegularIcosahedron() >>> print(ico.numberVertices()) 12 ''' return 12
[docs] def getArea(self): r''' Get the surface area (in total of 20 faces). The surface area is calculated as 5\sqrt(3)a^2 where a is the edge length. >>> ico = RegularIcosahedron(radius=5) >>> print('%.2f' % ico.getArea()) 239.36 >>> print('%.3f' % (ico.getArea() / ( 4. * math.pi * 5 * 5))) 0.762 ''' return 5 * math.sqrt(3) * (self.edgeLength ** 2)
[docs] def getVolume(self): r''' Get the volume. The volume is calculated as (3+\sqrt(5)) * 5/12 * a^3 where a is the edge length. >>> ico = RegularIcosahedron(radius=3) >>> print('%.2f' % ico.getVolume()) 68.48 >>> sphere = 4. / 3. * math.pi * 3 * 3 * 3 >>> print('%.3f' % (ico.getVolume() / sphere)) 0.605 ''' return (3 + math.sqrt(5)) * 5. / 12. * (self.edgeLength ** 3)
[docs] def getVertices(self): ''' Returns the 12 coordinates for vertices and the indexes to connect. Vertices have 12 elements. Connection has 20 elements. >>> ic = RegularIcosahedron() >>> v, p = ic.getVertices() >>> len(v) 12 >>> len(p) 20 ''' from math import cos, sin r = 2 / math.sqrt(5) h = 1 / math.sqrt(5) rad36 = 36. * math.pi / 180. v = [] v.append(np.array([0, 0, 1]) * self.radius) for ang in range(5): v.append(np.array([r * cos(rad36 * 2 * ang), r * sin(rad36 * 2 * ang), h]) * self.radius) for ang in range(5): v.append(np.array([r * cos(rad36 * (1 + 2 * ang)), r * sin(rad36 * (1 + 2 * ang)), -h]) * self.radius) v.append(np.array([0, 0, -1]) * self.radius) ### Connection is the pair of indexes to be connected. pair = ( (0, 1, 2), (0, 2, 3), (0, 3, 4), (0, 4, 5), (0, 5, 1), (1, 6, 2), (2, 6, 7), (2, 7, 3), (3, 7, 8), (3, 8, 4), (4, 8, 9), (4, 9, 5), (5, 9, 10), (5, 10, 1), (1, 10, 6), (6, 11, 7), (7, 11, 8), (8, 11, 9), (9, 11, 10), (10, 11, 6), ) return v, pair
[docs] def getTriangles(self): ''' Returns the instance of :class:`irfpy.util.triangle.Triangle`. All the triangles will have normal vectors pointing outward. ''' vert, pair = self.getVertices() tris = [] for v0, v1, v2 in pair: tris.append(triangle.Triangle(vert[v0], vert[v1], vert[v2])) return tuple(tris)
[docs] def getNpTriangles(self): ''' Returns the instance of :class:`irfpy.util.triangle.NpTriangle`. All the triangles will have normal vectors pointing outward. ''' vert, pair = self.getVertices() tris = [] for v0, v1, v2 in pair: tris.append(triangle.NpTriangle(vert[v0], vert[v1], vert[v2])) return tuple(tris)
import unittest import doctest
[docs]def doctests(): return unittest.TestSuite(( doctest.DocTestSuite(), ))
if __name__ == '__main__': unittest.main(defaultTest='doctests')