Computing and inspheres and circumspheres#
Under different conditions, various types of spheres containing or contained within a shape can be useful. For example, for spheres contained in a shape we may be interested in the largest sphere contained by a shape, or the largest concentric sphere contained within the shape. For a polyhedron, we may instead want to find the sphere that touches all the faces, if it exists.
[1]:
import fresnel
import numpy as np
from matplotlib import pyplot as plt
import coxeter
[2]:
def plot_polyhedron_with_sphere(shape, insphere=True):
"""Image a polyhedron along with a sphere contained within it."""
device = fresnel.Device()
scene = fresnel.Scene(device)
transparent_material = fresnel.material.Material(
color=fresnel.color.linear([1, 1, 1]),
spec_trans=0.95,
roughness=0.2,
primitive_color_mix=0.0,
)
colored_material = fresnel.material.Material(
color=fresnel.color.linear([0.9, 0.714, 0.169]),
roughness=0.8,
)
# First make the shape and set up its properties.
primitive = fresnel.geometry.ConvexPolyhedron(
scene,
fresnel.util.convex_polyhedron_from_vertices(shape.vertices),
N=1,
outline_width=0.01,
material=transparent_material if insphere else colored_material,
)
primitive.color_by_face = 0.0
# Now draw the insphere within the shape.
sphere = fresnel.geometry.Sphere(
scene,
N=1,
material=colored_material if insphere else transparent_material,
)
# Make the sphere a little bit smaller than it really is,
# otherwise you get artifacts near the intersection of the
# polyhedron and the insphere.
sphere.radius[:] = [
shape.insphere.radius * 0.99 if insphere else shape.circumsphere.radius * 1.01
]
scene.camera = fresnel.camera.Orthographic.fit(scene, view="front")
tracer = fresnel.tracer.Path(device=device, w=300, h=300)
return tracer.sample(scene, samples=24, light_samples=40)
The Platonic solids are a canonical set of shapes we can use for our analysis. Conveniently, they can easily be generated using coxeter. A good example is the dodecahedron.
[3]:
dodecahedron = coxeter.families.PlatonicFamily.get_shape("Dodecahedron")
We can query different types of spheres from this shape now:
[4]:
# The sphere tangent to all the faces of the polyhedron.
print(dodecahedron.insphere)
# The largest concentric sphere contained in the shape.
print(dodecahedron.maximal_centered_bounded_sphere)
coxeter.shapes.Sphere(radius=0.5648000780281438, center=[-5.551115123125784e-17, -2.220446049250313e-16, -3.23771046624367e-16])
coxeter.shapes.Sphere(radius=0.564800078028144, center=[-1.7347234759768062e-17, -1.1564823173178707e-17, 1.619075244245019e-17])
Let’s visualize what these shapes look like:
[5]:
plot_polyhedron_with_sphere(dodecahedron)
[5]:
If we instead want to look at spheres containing a shape, we can get those as well.
[6]:
# The sphere tangent to all the faces of the polyhedron.
print(dodecahedron.circumsphere)
# The largest concentric sphere contained in the shape.
print(dodecahedron.minimal_centered_bounding_sphere)
coxeter.shapes.Sphere(radius=0.7107492598629351, center=[0.0, -2.7755575615628914e-17, -1.1102230246251565e-16])
coxeter.shapes.Sphere(radius=0.7107492598629351, center=[-1.7347234759768062e-17, -1.1564823173178707e-17, 1.619075244245019e-17])
[7]:
plot_polyhedron_with_sphere(dodecahedron, False)
[7]: