feifeifeiliu's picture
first version
865fd8a
raw
history blame
4.29 kB
import numpy as np
from .mesh import Mesh
from .colors import name_to_rgb
__all__ = ['Sphere']
class Sphere(object):
def __init__(self, center, radius):
if(center.flatten().shape != (3,)):
raise Exception("Center should have size(1,3) instead of %s" % center.shape)
self.center = center.flatten()
self.radius = radius
def __str__(self):
return "%s:%s" % (self.center, self.radius)
def to_mesh(self, color=name_to_rgb['red']):
v = np.array([[0.0000, -1.000, 0.0000], [0.7236, -0.447, 0.5257],
[-0.278, -0.447, 0.8506], [-0.894, -0.447, 0.0000],
[-0.278, -0.447, -0.850], [0.7236, -0.447, -0.525],
[0.2765, 0.4472, 0.8506], [-0.723, 0.4472, 0.5257],
[-0.720, 0.4472, -0.525], [0.2763, 0.4472, -0.850],
[0.8945, 0.4472, 0.0000], [0.0000, 1.0000, 0.0000],
[-0.165, -0.850, 0.4999], [0.4253, -0.850, 0.3090],
[0.2629, -0.525, 0.8090], [0.4253, -0.850, -0.309],
[0.8508, -0.525, 0.0000], [-0.525, -0.850, 0.0000],
[-0.688, -0.525, 0.4999], [-0.162, -0.850, -0.499],
[-0.688, -0.525, -0.499], [0.2628, -0.525, -0.809],
[0.9518, 0.0000, -0.309], [0.9510, 0.0000, 0.3090],
[0.5876, 0.0000, 0.8090], [0.0000, 0.0000, 1.0000],
[-0.588, 0.0000, 0.8090], [-0.951, 0.0000, 0.3090],
[-0.955, 0.0000, -0.309], [-0.587, 0.0000, -0.809],
[0.0000, 0.0000, -1.000], [0.5877, 0.0000, -0.809],
[0.6889, 0.5257, 0.4999], [-0.262, 0.5257, 0.8090],
[-0.854, 0.5257, 0.0000], [-0.262, 0.5257, -0.809],
[0.6889, 0.5257, -0.499], [0.5257, 0.8506, 0.0000],
[0.1626, 0.8506, 0.4999], [-0.425, 0.8506, 0.3090],
[-0.422, 0.8506, -0.309], [0.1624, 0.8506, -0.499]])
f = np.array([[15, 3, 13], [13, 14, 15], [2, 15, 14], [13, 1, 14], [17, 2, 14], [14, 16, 17],
[6, 17, 16], [14, 1, 16], [19, 4, 18], [18, 13, 19], [3, 19, 13], [18, 1, 13],
[21, 5, 20], [20, 18, 21], [4, 21, 18], [20, 1, 18], [22, 6, 16], [16, 20, 22],
[5, 22, 20], [16, 1, 20], [24, 2, 17], [17, 23, 24], [11, 24, 23], [23, 17, 6],
[26, 3, 15], [15, 25, 26], [7, 26, 25], [25, 15, 2], [28, 4, 19], [19, 27, 28],
[8, 28, 27], [27, 19, 3], [30, 5, 21], [21, 29, 30], [9, 30, 29], [29, 21, 4],
[32, 6, 22], [22, 31, 32], [10, 32, 31], [31, 22, 5], [33, 7, 25], [25, 24, 33],
[11, 33, 24], [24, 25, 2], [34, 8, 27], [27, 26, 34], [7, 34, 26], [26, 27, 3],
[35, 9, 29], [29, 28, 35], [8, 35, 28], [28, 29, 4], [36, 10, 31], [31, 30, 36],
[9, 36, 30], [30, 31, 5], [37, 11, 23], [23, 32, 37], [10, 37, 32], [32, 23, 6],
[39, 7, 33], [33, 38, 39], [12, 39, 38], [38, 33, 11], [40, 8, 34], [34, 39, 40],
[12, 40, 39], [39, 34, 7], [41, 9, 35], [35, 40, 41], [12, 41, 40], [40, 35, 8],
[42, 10, 36], [36, 41, 42], [12, 42, 41], [41, 36, 9], [38, 11, 37], [37, 42, 38],
[12, 38, 42], [42, 37, 10]]) - 1
return Mesh(v=v * self.radius + self.center, f=f, vc=np.tile(color, (v.shape[0], 1)))
def has_inside(self, point):
return np.linalg.norm(point - self.center) <= self.radius
def intersects(self, sphere):
return np.linalg.norm(sphere.center - self.center) < (self.radius + sphere.radius)
def intersection_vol(self, sphere):
if not self.intersects(sphere):
return 0
d = np.linalg.norm(sphere.center - self.center)
R, r = (self.radius, sphere.radius) if (self.radius > sphere.radius) else (sphere.radius, self.radius)
if R >= (d + r):
return (4 * np.pi * (r ** 3)) / 3
# http://mathworld.wolfram.com/Sphere-SphereIntersection.html
return (np.pi * (R + r - d) ** 2 * (d ** 2 + 2 * d * r - 3 * r * r + 2 * d * R + 6 * r * R - 3 * R * R)) / (12 * d)