import numpy as np
from itertools import product
import k3d
class PlatonicSolid(object):
"""Base class for platonic solids."""
@property
def mesh(self):
"""Return k3d.mesh object of the solid."""
return k3d.mesh(self.vertices, self.indices, side='double')
@property
def points(self):
"""Return k3d.points object of solid vertices."""
return k3d.points(self.vertices, point_size=np.sqrt(np.sum((self.vertices[0] - self.vertices[1]) ** 2)) / 20)
[docs]class Dodecahedron(PlatonicSolid):
"""Create a dodecahedron solid.
"""
def __init__(self, origin=[0, 0, 0], size=1):
"""Inits Dodecahedron with an origin and a size.
Args:
origin (list, optional): The position of centroid of the solid. Defaults to [0, 0, 0].
size (int, optional): The size*sqrt(3) is the distance of each vertex of the solid. Defaults to 1.
Raises:
TypeError: Origin should have 3 coordinates.
"""
origin = np.array(origin, dtype=np.float32)
if origin.shape == (3,):
fi = (1 + np.sqrt(5)) / 2
dodecahedron_vertices = list(
product([-1, 1], [-1, 1], [-1, 1]))
dodecahedron_vertices += [(0, fi, 1 / fi), (0, -fi, 1 / fi), (0, -fi, -1 / fi), (0, fi, -1 / fi),
(1 / fi, 0, fi), (-1 / fi, 0,
fi), (-1 / fi, 0, -fi), (1 / fi, 0, -fi),
(fi, 1 / fi, 0), (-fi, 1 / fi, 0), (-fi, -1 / fi, 0), (fi, -1 / fi, 0)]
dodecahedron_vertices = np.float32(
size * np.array(dodecahedron_vertices) + origin)
self.vertices = dodecahedron_vertices
self.indices = [0, 1, 18, 0, 1, 10, 1, 9, 10, 0, 10, 14, 10, 14, 15, 4, 10, 15, 4, 9, 10, 4, 5, 9, 4, 5, 19,
4, 15, 19, 6, 15, 19, 6, 16, 19,
6, 7, 16, 6, 7, 8, 6, 8, 11, 2, 3, 17, 2, 3, 8, 2, 8, 11, 1, 3, 13, 1, 3, 18, 3, 17, 18, 1,
9, 13, 9, 12, 13, 5, 9, 12,
5, 12, 19, 12, 16, 19, 7, 12, 16, 3, 7, 8, 3, 7, 12, 3, 12, 13, 14, 6, 15, 14, 6, 11, 2, 11,
14, 0, 17, 18, 0, 2, 17, 0, 2, 14]
else:
raise TypeError('Origin should have 3 coordinates.')
[docs]class Cube(PlatonicSolid):
"""Create a cube.
"""
def __init__(self, origin=[0, 0, 0], size=1):
"""Inits Cube with an origin and a size.
Args:
origin (list, optional): The position of centroid of the solid. Defaults to [0, 0, 0].
size (int, optional): The size*sqrt(3) is the distance of each vertex from centroid of the solid. Defaults to 1.
Raises:
TypeError: Origin attribute should have 3 coordinates.
"""
origin = np.array(origin, dtype=np.float32)
if origin.shape == (3,):
cube_vertices = np.array(
list(product([1, -1], [1, -1], [1, -1])), np.float32)
cube_vertices = np.float32(size * cube_vertices + origin)
self.vertices = cube_vertices
self.indices = [0, 1, 2, 1, 2, 3, 0, 1, 4, 1, 4, 5, 1, 3, 5, 3, 5, 7, 0, 2, 4, 2, 4, 6, 2, 3, 7, 2, 6, 7, 4,
5, 6, 5, 6, 7]
else:
raise TypeError('Origin attribute should have 3 coordinates.')
[docs]class Icosahedron(PlatonicSolid):
"""Create a icosahedron solid.
"""
def __init__(self, origin=[0, 0, 0], size=1):
"""Inits Icosahedron with an origne and a size.
Args:
origin (list, optional): The position of centroid of the solid. Defaults to [0, 0, 0].
size (int, optional): The size of the solid. Defaults to 1.
Raises:
TypeError: Origin attribute should have 3 coordinates.
"""
origin = np.array(origin, dtype=np.float32)
if origin.shape == (3,):
fi = (1 + np.sqrt(5)) / 2
icosahedron_vertices = [(1, fi, 0), (1, -fi, 0), (-1, fi, 0), (-1, -fi, 0),
(fi, 0, 1), (fi, 0, -
1), (-fi, 0, 1), (-fi, 0, -1),
(0, 1, fi), (0, 1, -fi), (0, -1, fi), (0, -1, -fi)]
icosahedron_vertices = np.float32(
size * np.array(icosahedron_vertices) + origin)
self.vertices = icosahedron_vertices
self.indices = [0, 2, 8, 0, 4, 8, 0, 2, 9, 0, 5, 9, 2, 6, 8, 2, 7, 9, 2, 6, 7, 0, 4, 5, 1, 4, 5, 1, 5, 11,
7, 9, 11, 3, 7, 11, 3, 6, 7, 3, 6, 10, 4, 8, 10, 6, 8, 10, 1, 4, 10, 1, 3, 11, 1, 3, 10, 5,
9, 11]
else:
raise TypeError('Origin attribute should have 3 coordinates.')
[docs]class Octahedron(PlatonicSolid):
"""Create a octahedron solid.
"""
def __init__(self, origin=[0, 0, 0], size=1):
"""Inits Octahedron with an origin and a size
Args:
origin (list, optional): The position of centroid of the solid. Defaults to [0, 0, 0].
size (int, optional): The distance of each vertex from centroid of the solid. Defaults to 1.
Raises:
TypeError: Origin attribute should have 3 coordinates.
"""
origin = np.array(origin, dtype=np.float32)
if origin.shape == (3,):
octahedron_vertices = [
(1, 0, 0), (0, 1, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0), (0, 0, -1)]
octahedron_vertices = np.float32(
size * np.array(octahedron_vertices) + origin)
self.vertices = octahedron_vertices
self.indices = [0, 1, 2, 0, 1, 5, 1, 2, 3, 1,
3, 5, 0, 4, 5, 0, 2, 4, 2, 3, 4, 3, 4, 5]
else:
raise TypeError('Origin attribute should have 3 coordinates.')
[docs]class Tetrahedron(PlatonicSolid):
"""Create a tetrahedron solid.
"""
def __init__(self, origin=[0, 0, 0], size=1):
"""Inits Tetrahedron with an origin and a size.
Args:
origin (list, optional): The position of centroid of the solid. Defaults to [0, 0, 0].
size (int, optional): The size*sqrt(3) is the distance of each vertex from centroid of the solid. Defaults to 1.
Raises:
TypeError: Origin attribute should have 3 coordinates.
"""
origin = np.array(origin, dtype=np.float32)
if origin.shape == (3,):
tetrahedron_vertices = [
(1, 1, 1), (1, -1, -1), (-1, 1, -1), (-1, -1, 1)]
tetrahedron_vertices = np.float32(
size * np.array(tetrahedron_vertices) + origin)
self.vertices = tetrahedron_vertices
self.indices = [0, 1, 2, 0, 1, 3, 1, 2, 3, 0, 2, 3]
else:
raise TypeError('Origin attribute should have 3 coordinates.')