Graphics 3D object for representing and triangulating isosurfaces

AUTHORS:

  • Robert Hanson (2007): initial Java version, in Jmol.

  • Carl Witty (2009-01): first Cython version.

  • Bill Cauchois (2009): improvements for inclusion into Sage.

class sage.plot.plot3d.implicit_surface.ImplicitSurface[source]

Bases: IndexFaceSet

bounding_box()[source]

Return a bounding box for the ImplicitSurface, as a tuple of two 3-dimensional points.

EXAMPLES:

Note that the bounding box corresponds exactly to the x-, y-, and z- range:

sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
sage: G = ImplicitSurface(0, (0, 1), (0, 1), (0, 1))
sage: G.bounding_box()
((0.0, 0.0, 0.0), (1.0, 1.0, 1.0))
>>> from sage.all import *
>>> from sage.plot.plot3d.implicit_surface import ImplicitSurface
>>> G = ImplicitSurface(Integer(0), (Integer(0), Integer(1)), (Integer(0), Integer(1)), (Integer(0), Integer(1)))
>>> G.bounding_box()
((0.0, 0.0, 0.0), (1.0, 1.0, 1.0))
color_function[source]
colormap[source]
contours[source]
f[source]
gradient[source]
jmol_repr(render_params)[source]

Return a representation of this object suitable for use with the Jmol renderer.

json_repr(render_params)[source]

Return a representation of this object in JavaScript Object Notation (JSON).

obj_repr(render_params)[source]

Return a representation of this object in the .obj format.

plot_points[source]
region[source]
smooth[source]
tachyon_repr(render_params)[source]

Return a representation of this object suitable for use with the Tachyon renderer.

threejs_repr(render_params)[source]

Return a representation of the surface suitable for plotting with three.js.

EXAMPLES:

sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
sage: _ = var('x,y,z')
sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
sage: G.threejs_repr(G.default_render_params())
[('surface',
  {'color': '#6666ff',
   'faces': [[0, 1, 2],
    ...
   'opacity': 1.0,
   'vertices': [{'x': ...,
     'y': -0.9743589743589...,
     'z': -0.02564102564102...},
    ...
    {'x': -1.0, 'y': 0.9487179487179..., 'z': 0.05128205128205...}]})]
>>> from sage.all import *
>>> from sage.plot.plot3d.implicit_surface import ImplicitSurface
>>> _ = var('x,y,z')
>>> G = ImplicitSurface(x + y + z, (x,-Integer(1), Integer(1)), (y,-Integer(1), Integer(1)), (z,-Integer(1), Integer(1)))
>>> G.threejs_repr(G.default_render_params())
[('surface',
  {'color': '#6666ff',
   'faces': [[0, 1, 2],
    ...
   'opacity': 1.0,
   'vertices': [{'x': ...,
     'y': -0.9743589743589...,
     'z': -0.02564102564102...},
    ...
    {'x': -1.0, 'y': 0.9487179487179..., 'z': 0.05128205128205...}]})]
triangulate(force=False)[source]

The IndexFaceSet will be empty until you call this method, which generates the faces and vertices according to the parameters specified in the constructor for ImplicitSurface.

Note that if you call this method more than once, subsequent invocations will have no effect (this is an optimization to avoid repeated work) unless you specify force=True in the keywords.

EXAMPLES:

sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
sage: var('x,y,z')
(x, y, z)
sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
sage: len(G.vertex_list()), len(G.face_list())
(0, 0)
sage: G.triangulate()
sage: len(G.vertex_list()) > 0, len(G.face_list()) > 0
(True, True)
sage: G.show() # This should be fast, since the mesh is already triangulated.
>>> from sage.all import *
>>> from sage.plot.plot3d.implicit_surface import ImplicitSurface
>>> var('x,y,z')
(x, y, z)
>>> G = ImplicitSurface(x + y + z, (x,-Integer(1), Integer(1)), (y,-Integer(1), Integer(1)), (z,-Integer(1), Integer(1)))
>>> len(G.vertex_list()), len(G.face_list())
(0, 0)
>>> G.triangulate()
>>> len(G.vertex_list()) > Integer(0), len(G.face_list()) > Integer(0)
(True, True)
>>> G.show() # This should be fast, since the mesh is already triangulated.
vars[source]
xrange[source]
yrange[source]
zrange[source]
class sage.plot.plot3d.implicit_surface.MarchingCubes[source]

Bases: object

Handles marching cube rendering.

Protocol:

  1. Create the class.

  2. Call process_slice once for each X slice, from self.nx > x >= 0.

  3. Call finish(), which returns a list of strings.

Note

Actually, only 4 slices ever exist; the caller will re-use old storage.

color_function[source]
colormap[source]
contour[source]
finish()[source]

Return the results of the marching cubes algorithm as a list.

The format is specific to the subclass implementing this method.

gradient[source]
nx[source]
ny[source]
nz[source]
region[source]
results[source]
smooth[source]
transform[source]
xrange[source]
yrange[source]
zrange[source]
class sage.plot.plot3d.implicit_surface.MarchingCubesTriangles[source]

Bases: MarchingCubes

A subclass of MarchingCubes that returns its results as a list of triangles, including their vertices and normals (if smooth=True).

And also their vertex colors if a vertex coloring function is given.

add_triangle(v1, v2, v3)[source]

Called when a new triangle is generated by the marching cubes algorithm to update the results array.

process_cubes(_left, _right)[source]
process_slice(x, slice)[source]

Process a single slice of function evaluations at the specified \(x\) coordinate.

EXAMPLES:

sage: from sage.plot.plot3d.implicit_surface import MarchingCubesTriangles
sage: import numpy as np
sage: cube_marcher = MarchingCubesTriangles((-2, 2), (-2, 2), (-2, 2), 4, (10,)*3, smooth=False)
sage: f = lambda x, y, z: x^2 + y^2 + z^2
sage: slices = np.zeros((10, 10, 10), dtype=np.double)
sage: for x in reversed(range(0, 10)):
....:     for y in range(0, 10):
....:         for z in range(0, 10):
....:             slices[x, y, z] = f(*[a * (4 / 9) -2 for a in (x, y, z)])
....:     cube_marcher.process_slice(x, slices[x, :, :])
sage: faces = cube_marcher.finish()
sage: faces[0][0]
{'x': 1.555555555555..., 'y': -1.111111111111..., 'z': -0.555555555555...}
>>> from sage.all import *
>>> from sage.plot.plot3d.implicit_surface import MarchingCubesTriangles
>>> import numpy as np
>>> cube_marcher = MarchingCubesTriangles((-Integer(2), Integer(2)), (-Integer(2), Integer(2)), (-Integer(2), Integer(2)), Integer(4), (Integer(10),)*Integer(3), smooth=False)
>>> f = lambda x, y, z: x**Integer(2) + y**Integer(2) + z**Integer(2)
>>> slices = np.zeros((Integer(10), Integer(10), Integer(10)), dtype=np.double)
>>> for x in reversed(range(Integer(0), Integer(10))):
...     for y in range(Integer(0), Integer(10)):
...         for z in range(Integer(0), Integer(10)):
...             slices[x, y, z] = f(*[a * (Integer(4) / Integer(9)) -Integer(2) for a in (x, y, z)])
...     cube_marcher.process_slice(x, slices[x, :, :])
>>> faces = cube_marcher.finish()
>>> faces[Integer(0)][Integer(0)]
{'x': 1.555555555555..., 'y': -1.111111111111..., 'z': -0.555555555555...}

We render the isosurface using IndexFaceSet:

sage: from sage.plot.plot3d.index_face_set import IndexFaceSet
sage: IndexFaceSet([tuple((p['x'], p['y'], p['z']) for p in face) for face in faces])
Graphics3d Object
>>> from sage.all import *
>>> from sage.plot.plot3d.index_face_set import IndexFaceSet
>>> IndexFaceSet([tuple((p['x'], p['y'], p['z']) for p in face) for face in faces])
Graphics3d Object
slices[source]
x_vertices[source]
y_vertices[source]
y_vertices_swapped[source]
z_vertices[source]
z_vertices_swapped[source]
class sage.plot.plot3d.implicit_surface.VertexInfo

Bases: object

sage.plot.plot3d.implicit_surface.render_implicit(f, xrange, yrange, zrange, plot_points, cube_marchers)[source]

INPUT:

  • f – a (fast!) callable function

  • xrange – a 2-tuple (x_min, x_max)

  • yrange – a 2-tuple (y_min, y_may)

  • zrange – a 2-tuple (z_min, z_maz)

  • plot_points – a triple of integers indicating the number of function evaluations in each direction

  • cube_marchers – list of cube marchers, one for each contour

OUTPUT:

A representation of the isosurface, in the format specified by the individual cube marchers.