The Tachyon 3D Ray Tracer - 3D Graphics

Skip to content
Back to top
View this page
Edit this page

# The Tachyon 3D Ray Tracer

Given any 3D graphics object `M` one can compute a raytraced representation by typing `M.show(viewer='tachyon')`. For example, we draw two translucent spheres that contain a red tube, and render the result using Tachyon.

Sage

    sage: S = sphere(opacity=0.8, aspect_ratio=[1,1,1])
    sage: L = line3d([(0,0,0),(2,0,0)], thickness=10, color='red')
    sage: M = S + S.translate((2,0,0)) + L
    sage: M.show(viewer='tachyon')

Python

    >>> from sage.all import *
    >>> S = sphere(opacity=RealNumber('0.8'), aspect_ratio=[Integer(1),Integer(1),Integer(1)])
    >>> L = line3d([(Integer(0),Integer(0),Integer(0)),(Integer(2),Integer(0),Integer(0))], thickness=Integer(10), color='red')
    >>> M = S + S.translate((Integer(2),Integer(0),Integer(0))) + L
    >>> M.show(viewer='tachyon')

A number of options can be given to the `show()` method and correspondingly to the `save()` method for saving the generated image to a file:

Sage

    sage: M.show(viewer='tachyon',
    ....:    antialiasing=True, raydepth=3,
    ....:    figsize=[12,8], # the image resolution is 100*figsize
    ....:    camera_position=[4, 4.4, 1], # a distant camera position combined with
    ....:    zoom=3, # a large zoom factor will decrease perspective distortion.
    ....:    updir=(0, -0.1, 1), # the camera is slightly tilted
    ....:    viewdir=(-2.,-2.,-0.5), # slightly off-center
    ....:    light_position=(4.0, -3.0, 2.0),
    ....:   )

[Python]

    >>> from sage.all import *
    >>> M.show(viewer='tachyon',
    ...    antialiasing=True, raydepth=Integer(3),
    ...    figsize=[Integer(12),Integer(8)], # the image resolution is 100*figsize
    ...    camera_position=[Integer(4), RealNumber('4.4'), Integer(1)], # a distant camera position combined with
    ...    zoom=Integer(3), # a large zoom factor will decrease perspective distortion.
    ...    updir=(Integer(0), -RealNumber('0.1'), Integer(1)), # the camera is slightly tilted
    ...    viewdir=(-RealNumber('2.'),-RealNumber('2.'),-RealNumber('0.5')), # slightly off-center
    ...    light_position=(RealNumber('4.0'), -RealNumber('3.0'), RealNumber('2.0')),
    ...   )

One can also directly control Tachyon by creating a `Tachyon` object and adding elements of the scene one by one, which gives a huge amount of flexibility. For example, here we directly use Tachyon to draw 3 spheres on the coordinate axes:

Sage

    sage: t = Tachyon(xres=500, yres=500, camera_position=(2,0,0))
    sage: t.light((4,3,2), 0.2, (1,1,1))
    sage: t.texture('t2', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(1,0,0))
    sage: t.texture('t3', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(0,1,0))
    sage: t.texture('t4', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(0,0,1))
    sage: t.sphere((0,0.5,0), 0.2, 't2')
    sage: t.sphere((0.5,0,0), 0.2, 't3')
    sage: t.sphere((0,0,0.5), 0.2, 't4')
    sage: t.show()

Python

    >>> from sage.all import *
    >>> t = Tachyon(xres=Integer(500), yres=Integer(500), camera_position=(Integer(2),Integer(0),Integer(0)))
    >>> t.light((Integer(4),Integer(3),Integer(2)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
    >>> t.texture('t2', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(1),Integer(0),Integer(0)))
    >>> t.texture('t3', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(0),Integer(1),Integer(0)))
    >>> t.texture('t4', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(0),Integer(0),Integer(1)))
    >>> t.sphere((Integer(0),RealNumber('0.5'),Integer(0)), RealNumber('0.2'), 't2')
    >>> t.sphere((RealNumber('0.5'),Integer(0),Integer(0)), RealNumber('0.2'), 't3')
    >>> t.sphere((Integer(0),Integer(0),RealNumber('0.5')), RealNumber('0.2'), 't4')
    >>> t.show()

For scenes with many reflections it is helpful to increase the raydepth option, and turn on antialiasing. The following scene is an extreme case with many reflections between four cotangent spheres:

Sage

    sage: t = Tachyon(camera_position=(0,-4,1), xres=800, yres=600, raydepth=12,
    ....:             aspectratio=.75, antialiasing=4)
    sage: t.light((0.02,0.012,0.001), 0.01, (1,0,0))
    sage: t.light((0,0,10), 0.01, (0,0,1))
    sage: t.texture('s', color=(.8,1,1), opacity=.9, specular=.95, diffuse=.3, ambient=0.05)
    sage: t.texture('p', color=(0,0,1), opacity=1, specular=.2)
    sage: t.sphere((-1,-.57735,-0.7071),1,'s')
    sage: t.sphere((1,-.57735,-0.7071),1,'s')
    sage: t.sphere((0,1.15465,-0.7071),1,'s')
    sage: t.sphere((0,0,0.9259),1,'s')
    sage: t.plane((0,0,-1.9259),(0,0,1),'p')
    sage: t.show() # long time

[Python]

    >>> from sage.all import *
    >>> t = Tachyon(camera_position=(Integer(0),-Integer(4),Integer(1)), xres=Integer(800), yres=Integer(600), raydepth=Integer(12),
    ...             aspectratio=RealNumber('.75'), antialiasing=Integer(4))
    >>> t.light((RealNumber('0.02'),RealNumber('0.012'),RealNumber('0.001')), RealNumber('0.01'), (Integer(1),Integer(0),Integer(0)))
    >>> t.light((Integer(0),Integer(0),Integer(10)), RealNumber('0.01'), (Integer(0),Integer(0),Integer(1)))
    >>> t.texture('s', color=(RealNumber('.8'),Integer(1),Integer(1)), opacity=RealNumber('.9'), specular=RealNumber('.95'), diffuse=RealNumber('.3'), ambient=RealNumber('0.05'))
    >>> t.texture('p', color=(Integer(0),Integer(0),Integer(1)), opacity=Integer(1), specular=RealNumber('.2'))
    >>> t.sphere((-Integer(1),-RealNumber('.57735'),-RealNumber('0.7071')),Integer(1),'s')
    >>> t.sphere((Integer(1),-RealNumber('.57735'),-RealNumber('0.7071')),Integer(1),'s')
    >>> t.sphere((Integer(0),RealNumber('1.15465'),-RealNumber('0.7071')),Integer(1),'s')
    >>> t.sphere((Integer(0),Integer(0),RealNumber('0.9259')),Integer(1),'s')
    >>> t.plane((Integer(0),Integer(0),-RealNumber('1.9259')),(Integer(0),Integer(0),Integer(1)),'p')
    >>> t.show() # long time

Different projection options are available. The following examples all use a sphere and cube:

Sage

    sage: cedges = [[[1, 1, 1], [-1, 1, 1]], [[1, 1, 1], [1, -1, 1]],
    ....: [[1, 1, 1], [1, 1, -1]], [[-1, 1, 1], [-1, -1, 1]], [[-1, 1, 1],
    ....: [-1, 1, -1]], [[1, -1, 1], [-1, -1, 1]], [[1, -1, 1], [1, -1, -1]],
    ....: [[-1, -1, 1], [-1, -1, -1]], [[1, 1, -1], [-1, 1, -1]],
    ....: [[1, 1, -1], [1, -1, -1]], [[-1, 1, -1], [-1, -1, -1]],
    ....: [[1, -1, -1], [-1, -1, -1]]]

Python

    >>> from sage.all import *
    >>> cedges = [[[Integer(1), Integer(1), Integer(1)], [-Integer(1), Integer(1), Integer(1)]], [[Integer(1), Integer(1), Integer(1)], [Integer(1), -Integer(1), Integer(1)]],
    ... [[Integer(1), Integer(1), Integer(1)], [Integer(1), Integer(1), -Integer(1)]], [[-Integer(1), Integer(1), Integer(1)], [-Integer(1), -Integer(1), Integer(1)]], [[-Integer(1), Integer(1), Integer(1)],
    ... [-Integer(1), Integer(1), -Integer(1)]], [[Integer(1), -Integer(1), Integer(1)], [-Integer(1), -Integer(1), Integer(1)]], [[Integer(1), -Integer(1), Integer(1)], [Integer(1), -Integer(1), -Integer(1)]],
    ... [[-Integer(1), -Integer(1), Integer(1)], [-Integer(1), -Integer(1), -Integer(1)]], [[Integer(1), Integer(1), -Integer(1)], [-Integer(1), Integer(1), -Integer(1)]],
    ... [[Integer(1), Integer(1), -Integer(1)], [Integer(1), -Integer(1), -Integer(1)]], [[-Integer(1), Integer(1), -Integer(1)], [-Integer(1), -Integer(1), -Integer(1)]],
    ... [[Integer(1), -Integer(1), -Integer(1)], [-Integer(1), -Integer(1), -Integer(1)]]]

The default projection is `'perspective'`:

Sage

    sage: t = Tachyon(xres=800, yres=600, camera_position=(-1.5,0.0,0.0), zoom=.2)
    sage: t.texture('t1', color=(0,0,1))
    sage: for ed in cedges:
    ....:     t.fcylinder(ed[0], ed[1], .05, 't1')
    sage: t.light((-4,-4,4), .1, (1,1,1))
    sage: t.show()

[Python]

    >>> from sage.all import *
    >>> t = Tachyon(xres=Integer(800), yres=Integer(600), camera_position=(-RealNumber('1.5'),RealNumber('0.0'),RealNumber('0.0')), zoom=RealNumber('.2'))
    >>> t.texture('t1', color=(Integer(0),Integer(0),Integer(1)))
    >>> for ed in cedges:
    ...     t.fcylinder(ed[Integer(0)], ed[Integer(1)], RealNumber('.05'), 't1')
    >>> t.light((-Integer(4),-Integer(4),Integer(4)), RealNumber('.1'), (Integer(1),Integer(1),Integer(1)))
    >>> t.show()

Another option is `projection='fisheye'`, which requires frustum information. The frustum data is (bottom angle, top angle, left angle, right angle):

Sage

    sage: t = Tachyon(xres=800, yres=600, camera_position=(-1.5,0.0,0.0),
    ....: projection='fisheye', frustum=(-1.2, 1.2, -1.2, 1.2))
    sage: t.texture('t1', color=(0,0,1))
    sage: for ed in cedges:
    ....:     t.fcylinder(ed[0], ed[1], .05, 't1')
    sage: t.light((-4,-4,4), .1, (1,1,1))
    sage: t.show()

Python

    >>> from sage.all import *
    >>> t = Tachyon(xres=Integer(800), yres=Integer(600), camera_position=(-RealNumber('1.5'),RealNumber('0.0'),RealNumber('0.0')),
    ... projection='fisheye', frustum=(-RealNumber('1.2'), RealNumber('1.2'), -RealNumber('1.2'), RealNumber('1.2')))
    >>> t.texture('t1', color=(Integer(0),Integer(0),Integer(1)))
    >>> for ed in cedges:
    ...     t.fcylinder(ed[Integer(0)], ed[Integer(1)], RealNumber('.05'), 't1')
    >>> t.light((-Integer(4),-Integer(4),Integer(4)), RealNumber('.1'), (Integer(1),Integer(1),Integer(1)))
    >>> t.show()

Finally there is the `projection='perspective_dof'` option.

Sage

    sage: T = Tachyon(xres=800, antialiasing=4, raydepth=10,
    ....:             projection='perspective_dof', focallength='1.0', aperture='.0025')
    sage: T.light((0,5,7), 1.0, (1,1,1))
    sage: T.texture('t1', opacity=1, specular=.3)
    sage: T.texture('t2', opacity=1, specular=.3, color=(0,0,1))
    sage: T.texture('t3', opacity=1, specular=1, color=(1,.8,1), diffuse=0.2)
    sage: T.plane((0,0,-1), (0,0,1), 't3')
    sage: ttlist = ['t1', 't2']
    sage: tt = 't1'
    sage: T.cylinder((0,0,.1), (1,1/3,0), .05, 't3')
    sage: for q in srange(-3, 100, .15):
    ....:     if tt == 't1':
    ....:         tt = 't2'
    ....:     else:
    ....:         tt = 't1'
    ....:     T.sphere((q, q/3+.3*sin(3*q), .1+.3*cos(3*q)), .1, tt)
    sage: T.show()

[Python]

    >>> from sage.all import *
    >>> T = Tachyon(xres=Integer(800), antialiasing=Integer(4), raydepth=Integer(10),
    ...             projection='perspective_dof', focallength='1.0', aperture='.0025')
    >>> T.light((Integer(0),Integer(5),Integer(7)), RealNumber('1.0'), (Integer(1),Integer(1),Integer(1)))
    >>> T.texture('t1', opacity=Integer(1), specular=RealNumber('.3'))
    >>> T.texture('t2', opacity=Integer(1), specular=RealNumber('.3'), color=(Integer(0),Integer(0),Integer(1)))
    >>> T.texture('t3', opacity=Integer(1), specular=Integer(1), color=(Integer(1),RealNumber('.8'),Integer(1)), diffuse=RealNumber('0.2'))
    >>> T.plane((Integer(0),Integer(0),-Integer(1)), (Integer(0),Integer(0),Integer(1)), 't3')
    >>> ttlist = ['t1', 't2']
    >>> tt = 't1'
    >>> T.cylinder((Integer(0),Integer(0),RealNumber('.1')), (Integer(1),Integer(1)/Integer(3),Integer(0)), RealNumber('.05'), 't3')
    >>> for q in srange(-Integer(3), Integer(100), RealNumber('.15')):
    ...     if tt == 't1':
    ...         tt = 't2'
    ...     else:
    ...         tt = 't1'
    ...     T.sphere((q, q/Integer(3)+RealNumber('.3')*sin(Integer(3)*q), RealNumber('.1')+RealNumber('.3')*cos(Integer(3)*q)), RealNumber('.1'), tt)
    >>> T.show()

Image files in the `ppm` format can be used to tile planes or cover cylinders or spheres. In this example an image is created and then used to tile the plane:

Sage

    sage: T = Tachyon(xres=800, yres=600, camera_position=(-2.0,-.1,.3),
    ....:             projection='fisheye', frustum=(-1.0, 1.0, -1.0, 1.0))
    sage: T.texture('t1',color=(0,0,1))
    sage: for ed in cedges:
    ....:     T.fcylinder(ed[0], ed[1], .05, 't1')
    sage: T.light((-4,-4,4),.1,(1,1,1))
    sage: fname_png = tmp_filename(ext='.png')
    sage: fname_ppm = tmp_filename(ext='.ppm')
    sage: T.save(fname_png)
    sage: from sage.features.imagemagick import Magick
    sage: r2 = os.system(Magick().executable+' '+fname_png+' '+fname_ppm)    # optional -- ImageMagick
    sage: # optional - imagemagick
    sage: T = Tachyon(xres=800, yres=600,
    ....:             camera_position=(-2.0,-.1,.3),
    ....:             projection='fisheye',
    ....:             frustum=(-1.0, 1.0, -1.0, 1.0))
    sage: T.texture('t1', color=(1,0,0), specular=.9)
    sage: T.texture('p1', color=(1,1,1), opacity=.1,
    ....:           imagefile=fname_ppm, texfunc=9)
    sage: T.sphere((0,0,0), .5, 't1')
    sage: T.plane((0,0,-1), (0,0,1), 'p1')
    sage: T.light((-4,-4,4), .1, (1,1,1))
    sage: T.show()

Python

    >>> from sage.all import *
    >>> T = Tachyon(xres=Integer(800), yres=Integer(600), camera_position=(-RealNumber('2.0'),-RealNumber('.1'),RealNumber('.3')),
    ...             projection='fisheye', frustum=(-RealNumber('1.0'), RealNumber('1.0'), -RealNumber('1.0'), RealNumber('1.0')))
    >>> T.texture('t1',color=(Integer(0),Integer(0),Integer(1)))
    >>> for ed in cedges:
    ...     T.fcylinder(ed[Integer(0)], ed[Integer(1)], RealNumber('.05'), 't1')
    >>> T.light((-Integer(4),-Integer(4),Integer(4)),RealNumber('.1'),(Integer(1),Integer(1),Integer(1)))
    >>> fname_png = tmp_filename(ext='.png')
    >>> fname_ppm = tmp_filename(ext='.ppm')
    >>> T.save(fname_png)
    >>> from sage.features.imagemagick import Magick
    >>> r2 = os.system(Magick().executable+' '+fname_png+' '+fname_ppm)    # optional -- ImageMagick
    >>> # optional - imagemagick
    >>> T = Tachyon(xres=Integer(800), yres=Integer(600),
    ...             camera_position=(-RealNumber('2.0'),-RealNumber('.1'),RealNumber('.3')),
    ...             projection='fisheye',
    ...             frustum=(-RealNumber('1.0'), RealNumber('1.0'), -RealNumber('1.0'), RealNumber('1.0')))
    >>> T.texture('t1', color=(Integer(1),Integer(0),Integer(0)), specular=RealNumber('.9'))
    >>> T.texture('p1', color=(Integer(1),Integer(1),Integer(1)), opacity=RealNumber('.1'),
    ...           imagefile=fname_ppm, texfunc=Integer(9))
    >>> T.sphere((Integer(0),Integer(0),Integer(0)), RealNumber('.5'), 't1')
    >>> T.plane((Integer(0),Integer(0),-Integer(1)), (Integer(0),Integer(0),Integer(1)), 'p1')
    >>> T.light((-Integer(4),-Integer(4),Integer(4)), RealNumber('.1'), (Integer(1),Integer(1),Integer(1)))
    >>> T.show()

AUTHOR:

- John E. Stone (johns@megapixel.com): wrote tachyon ray tracer

- William Stein: sage-tachyon interface

- Joshua Kantor: 3d function plotting

- Tom Boothby: 3d function plotting n’stuff

- Leif Hille: key idea for bugfix for texfunc issue (Issue #799)

- Marshall Hampton: improved doctests, rings, axis-aligned boxes.

- Paul Graham: Respect global verbosity settings (Issue #16228)

Todo

- clean up trianglefactory stuff

class sage.plot.plot3d.tachyon.Axis_aligned_box(min_p, max_p, texture)

  Bases: `object`

  Box with axis-aligned edges with the given min and max coordinates.

  str()

    Return the scene string of the axis-aligned box.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Axis_aligned_box
        sage: aab = Axis_aligned_box((0,0,0),(1,1,1),'s')
        sage: aab.str()
        '\n        box min  0.0 0.0 0.0  max  1.0 1.0 1.0  s\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Axis_aligned_box
        >>> aab = Axis_aligned_box((Integer(0),Integer(0),Integer(0)),(Integer(1),Integer(1),Integer(1)),'s')
        >>> aab.str()
        '\n        box min  0.0 0.0 0.0  max  1.0 1.0 1.0  s\n        '

class sage.plot.plot3d.tachyon.Cylinder(center, axis, radius, texture)

  Bases: `object`

  An infinite cylinder.

  str()

    Return the scene string of the cylinder.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: from sage.plot.plot3d.tachyon import Cylinder
        sage: c = Cylinder((0,0,0),(1,1,1),.1,'s')
        sage: c.str()
        '\n        cylinder center  0.0 0.0 0.0  axis  1.0 1.0 1.0  rad 0.1 s\n        '

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> from sage.plot.plot3d.tachyon import Cylinder
        >>> c = Cylinder((Integer(0),Integer(0),Integer(0)),(Integer(1),Integer(1),Integer(1)),RealNumber('.1'),'s')
        >>> c.str()
        '\n        cylinder center  0.0 0.0 0.0  axis  1.0 1.0 1.0  rad 0.1 s\n        '

class sage.plot.plot3d.tachyon.FCylinder(base, apex, radius, texture)

  Bases: `object`

  A finite cylinder.

  str()

    Return the scene string of the finite cylinder.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import FCylinder
        sage: fc = FCylinder((0,0,0),(1,1,1),.1,'s')
        sage: fc.str()
        '\n        fcylinder base  0.0 0.0 0.0  apex  1.0 1.0 1.0  rad 0.1 s\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import FCylinder
        >>> fc = FCylinder((Integer(0),Integer(0),Integer(0)),(Integer(1),Integer(1),Integer(1)),RealNumber('.1'),'s')
        >>> fc.str()
        '\n        fcylinder base  0.0 0.0 0.0  apex  1.0 1.0 1.0  rad 0.1 s\n        '

class sage.plot.plot3d.tachyon.FractalLandscape(res, scale, center, texture)

  Bases: `object`

  Axis-aligned fractal landscape.

  Does not seem very useful at the moment, but perhaps will be improved in the future.

  str()

    Return the scene string of the fractal landscape.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import FractalLandscape
        sage: fl = FractalLandscape([20,20],[30,30],[1,2,3],'s')
        sage: fl.str()
        '\n        scape res  20 20  scale  30 30  center  1.0 2.0 3.0  s\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import FractalLandscape
        >>> fl = FractalLandscape([Integer(20),Integer(20)],[Integer(30),Integer(30)],[Integer(1),Integer(2),Integer(3)],'s')
        >>> fl.str()
        '\n        scape res  20 20  scale  30 30  center  1.0 2.0 3.0  s\n        '

class sage.plot.plot3d.tachyon.Light(center, radius, color)

  Bases: `object`

  Represent lighting objects.

  EXAMPLES:

  Sage

      sage: from sage.plot.plot3d.tachyon import Light
      sage: q = Light((1,1,1), 1, (1,1,1))
      sage: q._center
      (1.0, 1.0, 1.0)

  Python

      >>> from sage.all import *
      >>> from sage.plot.plot3d.tachyon import Light
      >>> q = Light((Integer(1),Integer(1),Integer(1)), Integer(1), (Integer(1),Integer(1),Integer(1)))
      >>> q._center
      (1.0, 1.0, 1.0)

  str()

    Return the tachyon string defining the light source.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Light
        sage: q = Light((1,1,1), 1, (1,1,1))
        sage: print(q.str())
                light center  1.0 1.0 1.0
                      rad 1.0
                      color  1.0 1.0 1.0

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Light
        >>> q = Light((Integer(1),Integer(1),Integer(1)), Integer(1), (Integer(1),Integer(1),Integer(1)))
        >>> print(q.str())
                light center  1.0 1.0 1.0
                      rad 1.0
                      color  1.0 1.0 1.0

class sage.plot.plot3d.tachyon.ParametricPlot(f, t_0, t_f, tex, r=0.1, cylinders=True, min_depth=4, max_depth=8, e_rel=0.01, e_abs=0.01)

  Bases: `object`

  Parametric plotting routines.

  str()

    Return the tachyon string representation of the parameterized curve.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import ParametricPlot
        sage: f = lambda t: (t,t^2,t^3)
        sage: q = ParametricPlot(f,0,1,'s')
        sage: q.str()[9:69]
        'sphere center  0.0 0.0 0.0  rad 0.1 s\n        \n        fcyli'

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import ParametricPlot
        >>> f = lambda t: (t,t**Integer(2),t**Integer(3))
        >>> q = ParametricPlot(f,Integer(0),Integer(1),'s')
        >>> q.str()[Integer(9):Integer(69)]
        'sphere center  0.0 0.0 0.0  rad 0.1 s\n        \n        fcyli'

  tol(est, val)

    Check relative, then absolute tolerance.

    If both fail, return `False`.

    This is a zero-safe error checker.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import ParametricPlot
        sage: f = lambda t: (t,t^2,t^3)
        sage: q = ParametricPlot(f,0,1,'s')
        sage: q.tol([0,0,0],[1,0,0])
        False
        sage: q.tol([0,0,0],[.0001,0,0])
        True

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import ParametricPlot
        >>> f = lambda t: (t,t**Integer(2),t**Integer(3))
        >>> q = ParametricPlot(f,Integer(0),Integer(1),'s')
        >>> q.tol([Integer(0),Integer(0),Integer(0)],[Integer(1),Integer(0),Integer(0)])
        False
        >>> q.tol([Integer(0),Integer(0),Integer(0)],[RealNumber('.0001'),Integer(0),Integer(0)])
        True

class sage.plot.plot3d.tachyon.Plane(center, normal, texture)

  Bases: `object`

  An infinite plane.

  str()

    Return the scene string of the plane.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Plane
        sage: p = Plane((1,2,3),(1,2,4),'s')
        sage: p.str()
        '\n        plane center  1.0 2.0 3.0  normal  1.0 2.0 4.0  s\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Plane
        >>> p = Plane((Integer(1),Integer(2),Integer(3)),(Integer(1),Integer(2),Integer(4)),'s')
        >>> p.str()
        '\n        plane center  1.0 2.0 3.0  normal  1.0 2.0 4.0  s\n        '

class sage.plot.plot3d.tachyon.Ring(center, normal, inner, outer, texture)

  Bases: `object`

  An annulus of zero thickness.

  str()

    Return the scene string of the ring.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Ring
        sage: r = Ring((0,0,0), (1,1,0), 1.0, 2.0, 's')
        sage: r.str()
        '\n        ring center  0.0 0.0 0.0  normal  1.0 1.0 0.0  inner 1.0 outer 2.0 s\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Ring
        >>> r = Ring((Integer(0),Integer(0),Integer(0)), (Integer(1),Integer(1),Integer(0)), RealNumber('1.0'), RealNumber('2.0'), 's')
        >>> r.str()
        '\n        ring center  0.0 0.0 0.0  normal  1.0 1.0 0.0  inner 1.0 outer 2.0 s\n        '

class sage.plot.plot3d.tachyon.Sphere(center, radius, texture)

  Bases: `object`

  A class for creating spheres in tachyon.

  str()

    Return the scene string for the sphere.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: from sage.plot.plot3d.tachyon import Sphere
        sage: t.texture('r', color=(.8,0,0), ambient = .1)
        sage: s = Sphere((1,1,1), 1, 'r')
        sage: s.str()
        '\n        sphere center  1.0 1.0 1.0  rad 1.0 r\n        '

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> from sage.plot.plot3d.tachyon import Sphere
        >>> t.texture('r', color=(RealNumber('.8'),Integer(0),Integer(0)), ambient = RealNumber('.1'))
        >>> s = Sphere((Integer(1),Integer(1),Integer(1)), Integer(1), 'r')
        >>> s.str()
        '\n        sphere center  1.0 1.0 1.0  rad 1.0 r\n        '

class sage.plot.plot3d.tachyon.Tachyon(xres=350, yres=350, zoom=1.0, antialiasing=False, aspectratio=1.0, raydepth=8, camera_position=None, camera_center=None, updir=[0, 0, 1], look_at=[0, 0, 0], viewdir=None, projection='PERSPECTIVE', focallength='', aperture='', frustum='')

  Bases: `WithEqualityById`, `SageObject`

  Create a scene the can be rendered using the Tachyon ray tracer.

  INPUT:

  - `xres` – (default: 350)

  - `yres` – (default: 350)

  - `zoom` – (default: 1.0)

  - `antialiasing` – (default: `False`)

  - `aspectratio` – (default: 1.0)

  - `raydepth` – (default: 8)

  - `camera_position` – (default: (-3, 0, 0))

  - `updir` – (default: (0, 0, 1))

  - `look_at` – (default: (0,0,0))

  - `viewdir` – (default: `None`) otherwise list of three numbers

  - `projection` – `'PERSPECTIVE'` (default) `'perspective_dof'` or `'fisheye'`

  - `frustum` – (default: `''`) otherwise list of four numbers. Only used with `projection='fisheye'`.

  - `focallength` – (default: `''`) otherwise a number. Only used with `projection='perspective_dof'`.

  - `aperture` – (default: `''`) otherwise a number. Only used with `projection='perspective_dof'`.

  OUTPUT: a Tachyon 3d scene

  Note that the coordinates are by default such that \(z\) is up, positive \(y\) is to the {left} and \(x\) is toward you. This is not oriented according to the right hand rule.

  EXAMPLES: Spheres along the twisted cubic.

  Sage

      sage: t = Tachyon(xres=512,yres=512, camera_position=(3,0.3,0))
      sage: t.light((4,3,2), 0.2, (1,1,1))
      sage: t.texture('t0', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(1.0,0,0))
      sage: t.texture('t1', ambient=0.1, diffuse=0.9, specular=0.3, opacity=1.0, color=(0,1.0,0))
      sage: t.texture('t2', ambient=0.2, diffuse=0.7, specular=0.5, opacity=0.7, color=(0,0,1.0))
      sage: k=0
      sage: for i in srange(-1,1,0.05):
      ....:    k += 1
      ....:    t.sphere((i,i^2-0.5,i^3), 0.1, 't%s'%(k%3))
      sage: t.show()

  Python

      >>> from sage.all import *
      >>> t = Tachyon(xres=Integer(512),yres=Integer(512), camera_position=(Integer(3),RealNumber('0.3'),Integer(0)))
      >>> t.light((Integer(4),Integer(3),Integer(2)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
      >>> t.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
      >>> t.texture('t1', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.3'), opacity=RealNumber('1.0'), color=(Integer(0),RealNumber('1.0'),Integer(0)))
      >>> t.texture('t2', ambient=RealNumber('0.2'), diffuse=RealNumber('0.7'), specular=RealNumber('0.5'), opacity=RealNumber('0.7'), color=(Integer(0),Integer(0),RealNumber('1.0')))
      >>> k=Integer(0)
      >>> for i in srange(-Integer(1),Integer(1),RealNumber('0.05')):
      ...    k += Integer(1)
      ...    t.sphere((i,i**Integer(2)-RealNumber('0.5'),i**Integer(3)), RealNumber('0.1'), 't%s'%(k%Integer(3)))
      >>> t.show()

  Another twisted cubic, but with a white background, got by putting infinite planes around the scene.

  Sage

      sage: t = Tachyon(xres=512,yres=512, camera_position=(3,0.3,0), raydepth=8)
      sage: t.light((4,3,2), 0.2, (1,1,1))
      sage: t.texture('t0', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(1.0,0,0))
      sage: t.texture('t1', ambient=0.1, diffuse=0.9, specular=0.3, opacity=1.0, color=(0,1.0,0))
      sage: t.texture('t2', ambient=0.2,diffuse=0.7, specular=0.5, opacity=0.7, color=(0,0,1.0))
      sage: t.texture('white', color=(1,1,1))
      sage: t.plane((0,0,-1), (0,0,1), 'white')
      sage: t.plane((0,-20,0), (0,1,0), 'white')
      sage: t.plane((-20,0,0), (1,0,0), 'white')

  [Python]

      >>> from sage.all import *
      >>> t = Tachyon(xres=Integer(512),yres=Integer(512), camera_position=(Integer(3),RealNumber('0.3'),Integer(0)), raydepth=Integer(8))
      >>> t.light((Integer(4),Integer(3),Integer(2)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
      >>> t.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
      >>> t.texture('t1', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.3'), opacity=RealNumber('1.0'), color=(Integer(0),RealNumber('1.0'),Integer(0)))
      >>> t.texture('t2', ambient=RealNumber('0.2'),diffuse=RealNumber('0.7'), specular=RealNumber('0.5'), opacity=RealNumber('0.7'), color=(Integer(0),Integer(0),RealNumber('1.0')))
      >>> t.texture('white', color=(Integer(1),Integer(1),Integer(1)))
      >>> t.plane((Integer(0),Integer(0),-Integer(1)), (Integer(0),Integer(0),Integer(1)), 'white')
      >>> t.plane((Integer(0),-Integer(20),Integer(0)), (Integer(0),Integer(1),Integer(0)), 'white')
      >>> t.plane((-Integer(20),Integer(0),Integer(0)), (Integer(1),Integer(0),Integer(0)), 'white')

  Sage

      sage: k=0
      sage: for i in srange(-1,1,0.05):
      ....:    k += 1
      ....:    t.sphere((i,i^2 - 0.5,i^3), 0.1, 't%s'%(k%3))
      ....:    t.cylinder((0,0,0), (0,0,1), 0.05,'t1')
      sage: t.show()

  Python

      >>> from sage.all import *
      >>> k=Integer(0)
      >>> for i in srange(-Integer(1),Integer(1),RealNumber('0.05')):
      ...    k += Integer(1)
      ...    t.sphere((i,i**Integer(2) - RealNumber('0.5'),i**Integer(3)), RealNumber('0.1'), 't%s'%(k%Integer(3)))
      ...    t.cylinder((Integer(0),Integer(0),Integer(0)), (Integer(0),Integer(0),Integer(1)), RealNumber('0.05'),'t1')
      >>> t.show()

  Many random spheres:

  Sage

      sage: t = Tachyon(xres=512,yres=512, camera_position=(2,0.5,0.5), look_at=(0.5,0.5,0.5), raydepth=4)
      sage: t.light((4,3,2), 0.2, (1,1,1))
      sage: t.texture('t0', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(1.0,0,0))
      sage: t.texture('t1', ambient=0.1, diffuse=0.9, specular=0.3, opacity=1.0, color=(0,1.0,0))
      sage: t.texture('t2', ambient=0.2, diffuse=0.7, specular=0.5, opacity=0.7, color=(0,0,1.0))
      sage: k=0
      sage: for i in range(100):
      ....:    k += 1
      ....:    t.sphere((random(),random(), random()), random()/10, 't%s'%(k%3))
      sage: t.show()

  [Python]

      >>> from sage.all import *
      >>> t = Tachyon(xres=Integer(512),yres=Integer(512), camera_position=(Integer(2),RealNumber('0.5'),RealNumber('0.5')), look_at=(RealNumber('0.5'),RealNumber('0.5'),RealNumber('0.5')), raydepth=Integer(4))
      >>> t.light((Integer(4),Integer(3),Integer(2)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
      >>> t.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
      >>> t.texture('t1', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.3'), opacity=RealNumber('1.0'), color=(Integer(0),RealNumber('1.0'),Integer(0)))
      >>> t.texture('t2', ambient=RealNumber('0.2'), diffuse=RealNumber('0.7'), specular=RealNumber('0.5'), opacity=RealNumber('0.7'), color=(Integer(0),Integer(0),RealNumber('1.0')))
      >>> k=Integer(0)
      >>> for i in range(Integer(100)):
      ...    k += Integer(1)
      ...    t.sphere((random(),random(), random()), random()/Integer(10), 't%s'%(k%Integer(3)))
      >>> t.show()

  Points on an elliptic curve, their height indicated by their height above the axis:

  Sage

      sage: # needs sage.schemes
      sage: t = Tachyon(camera_position=(5,2,2), look_at=(0,1,0))
      sage: t.light((10,3,2), 0.2, (1,1,1))
      sage: t.texture('t0', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(1,0,0))
      sage: t.texture('t1', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(0,1,0))
      sage: t.texture('t2', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(0,0,1))
      sage: E = EllipticCurve('37a')                                                  # needs sage.schemes
      sage: P = E([0,0])                                                              # needs sage.schemes
      sage: Q = P                                                                     # needs sage.schemes
      sage: n = 100
      sage: for i in range(n):   # increase 20 for a better plot                      # needs sage.schemes
      ....:    Q = Q + P
      ....:    t.sphere((Q[1], Q[0], ZZ(i)/n), 0.1, 't%s'%(i%3))
      sage: t.show()                                                                  # needs sage.schemes

  Python

      >>> from sage.all import *
      >>> # needs sage.schemes
      >>> t = Tachyon(camera_position=(Integer(5),Integer(2),Integer(2)), look_at=(Integer(0),Integer(1),Integer(0)))
      >>> t.light((Integer(10),Integer(3),Integer(2)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
      >>> t.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(1),Integer(0),Integer(0)))
      >>> t.texture('t1', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(0),Integer(1),Integer(0)))
      >>> t.texture('t2', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(0),Integer(0),Integer(1)))
      >>> E = EllipticCurve('37a')                                                  # needs sage.schemes
      >>> P = E([Integer(0),Integer(0)])                                                              # needs sage.schemes
      >>> Q = P                                                                     # needs sage.schemes
      >>> n = Integer(100)
      >>> for i in range(n):   # increase 20 for a better plot                      # needs sage.schemes
      ...    Q = Q + P
      ...    t.sphere((Q[Integer(1)], Q[Integer(0)], ZZ(i)/n), RealNumber('0.1'), 't%s'%(i%Integer(3)))
      >>> t.show()                                                                  # needs sage.schemes

  A beautiful picture of rational points on a rank 1 elliptic curve.

  Sage

      sage: # needs sage.schemes
      sage: t = Tachyon(xres=1000, yres=800, camera_position=(2,7,4),
      ....:             look_at=(2,0,0), raydepth=4)
      sage: t.light((10,3,2), 1, (1,1,1))
      sage: t.light((10,-3,2), 1, (1,1,1))
      sage: t.texture('black', color=(0,0,0))
      sage: t.texture('red', color=(1,0,0))
      sage: t.texture('grey', color=(.9,.9,.9))
      sage: t.plane((0,0,0),(0,0,1),'grey')
      sage: t.cylinder((0,0,0),(1,0,0),.01,'black')
      sage: t.cylinder((0,0,0),(0,1,0),.01,'black')
      sage: E = EllipticCurve('37a')                                                  # needs sage.schemes
      sage: P = E([0,0])                                                              # needs sage.schemes
      sage: Q = P                                                                     # needs sage.schemes
      sage: n = 100
      sage: for i in range(n):                                                        # needs sage.schemes
      ....:    Q = Q + P
      ....:    c = i/n + .1
      ....:    t.texture('r%s'%i,color=(float(i/n),0,0))
      ....:    t.sphere((Q[0], -Q[1], .01), .04, 'r%s'%i)
      sage: t.show()                          # long time                             # needs sage.schemes

  [Python]

      >>> from sage.all import *
      >>> # needs sage.schemes
      >>> t = Tachyon(xres=Integer(1000), yres=Integer(800), camera_position=(Integer(2),Integer(7),Integer(4)),
      ...             look_at=(Integer(2),Integer(0),Integer(0)), raydepth=Integer(4))
      >>> t.light((Integer(10),Integer(3),Integer(2)), Integer(1), (Integer(1),Integer(1),Integer(1)))
      >>> t.light((Integer(10),-Integer(3),Integer(2)), Integer(1), (Integer(1),Integer(1),Integer(1)))
      >>> t.texture('black', color=(Integer(0),Integer(0),Integer(0)))
      >>> t.texture('red', color=(Integer(1),Integer(0),Integer(0)))
      >>> t.texture('grey', color=(RealNumber('.9'),RealNumber('.9'),RealNumber('.9')))
      >>> t.plane((Integer(0),Integer(0),Integer(0)),(Integer(0),Integer(0),Integer(1)),'grey')
      >>> t.cylinder((Integer(0),Integer(0),Integer(0)),(Integer(1),Integer(0),Integer(0)),RealNumber('.01'),'black')
      >>> t.cylinder((Integer(0),Integer(0),Integer(0)),(Integer(0),Integer(1),Integer(0)),RealNumber('.01'),'black')
      >>> E = EllipticCurve('37a')                                                  # needs sage.schemes
      >>> P = E([Integer(0),Integer(0)])                                                              # needs sage.schemes
      >>> Q = P                                                                     # needs sage.schemes
      >>> n = Integer(100)
      >>> for i in range(n):                                                        # needs sage.schemes
      ...    Q = Q + P
      ...    c = i/n + RealNumber('.1')
      ...    t.texture('r%s'%i,color=(float(i/n),Integer(0),Integer(0)))
      ...    t.sphere((Q[Integer(0)], -Q[Integer(1)], RealNumber('.01')), RealNumber('.04'), 'r%s'%i)
      >>> t.show()                          # long time                             # needs sage.schemes

  A beautiful spiral.

  Sage

      sage: t = Tachyon(xres=800, yres=800, camera_position=(2,5,2), look_at=(2.5,0,0))
      sage: t.light((0,0,100), 1, (1,1,1))
      sage: t.texture('r', ambient=0.1, diffuse=0.9, specular=0.5,
      ....:           opacity=1.0, color=(1,0,0))
      sage: for i in srange(0,50,0.1):
      ....:    t.sphere((i/10.0,sin(i),cos(i)), 0.05, 'r')
      sage: t.texture('white', color=(1,1,1), opacity=1, specular=1, diffuse=1)
      sage: t.plane((0,0,-100), (0,0,-100), 'white')
      sage: t.show()

  Python

      >>> from sage.all import *
      >>> t = Tachyon(xres=Integer(800), yres=Integer(800), camera_position=(Integer(2),Integer(5),Integer(2)), look_at=(RealNumber('2.5'),Integer(0),Integer(0)))
      >>> t.light((Integer(0),Integer(0),Integer(100)), Integer(1), (Integer(1),Integer(1),Integer(1)))
      >>> t.texture('r', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'),
      ...           opacity=RealNumber('1.0'), color=(Integer(1),Integer(0),Integer(0)))
      >>> for i in srange(Integer(0),Integer(50),RealNumber('0.1')):
      ...    t.sphere((i/RealNumber('10.0'),sin(i),cos(i)), RealNumber('0.05'), 'r')
      >>> t.texture('white', color=(Integer(1),Integer(1),Integer(1)), opacity=Integer(1), specular=Integer(1), diffuse=Integer(1))
      >>> t.plane((Integer(0),Integer(0),-Integer(100)), (Integer(0),Integer(0),-Integer(100)), 'white')
      >>> t.show()

  If the optional parameter `viewdir` is not set, the camera center should not coincide with the point which is looked at (see Issue #7232):

  Sage

      sage: t = Tachyon(xres=80,yres=80, camera_position=(2,5,2), look_at=(2,5,2))
      Traceback (most recent call last):
      ...
      ValueError: camera_position and look_at coincide

  [Python]

      >>> from sage.all import *
      >>> t = Tachyon(xres=Integer(80),yres=Integer(80), camera_position=(Integer(2),Integer(5),Integer(2)), look_at=(Integer(2),Integer(5),Integer(2)))
      Traceback (most recent call last):
      ...
      ValueError: camera_position and look_at coincide

  Use of a fisheye lens perspective.

  Sage

      sage: T = Tachyon(xres=800, yres=600, camera_position=(-1.5,-1.5,.3),
      ....:             projection='fisheye', frustum=(-1.0, 1.0, -1.0, 1.0))
      sage: T.texture('t1', color=(0,0,1))
      sage: cedges = [[[1, 1, 1], [-1, 1, 1]], [[1, 1, 1], [1, -1, 1]],
      ....:           [[1, 1, 1], [1, 1, -1]], [[-1, 1, 1], [-1, -1, 1]],
      ....:           [[-1, 1, 1], [-1, 1, -1]], [[1, -1, 1], [-1, -1, 1]],
      ....:           [[1, -1, 1], [1, -1, -1]], [[-1, -1, 1], [-1, -1, -1]],
      ....:           [[1, 1, -1], [-1, 1, -1]], [[1, 1, -1], [1, -1, -1]],
      ....:           [[-1, 1, -1], [-1, -1, -1]], [[1, -1, -1], [-1, -1, -1]]]
      sage: for ed in cedges:
      ....:     T.fcylinder(ed[0], ed[1], .05, 't1')
      sage: T.light((-4,-4,4), .1, (1,1,1))
      sage: T.show()

  Python

      >>> from sage.all import *
      >>> T = Tachyon(xres=Integer(800), yres=Integer(600), camera_position=(-RealNumber('1.5'),-RealNumber('1.5'),RealNumber('.3')),
      ...             projection='fisheye', frustum=(-RealNumber('1.0'), RealNumber('1.0'), -RealNumber('1.0'), RealNumber('1.0')))
      >>> T.texture('t1', color=(Integer(0),Integer(0),Integer(1)))
      >>> cedges = [[[Integer(1), Integer(1), Integer(1)], [-Integer(1), Integer(1), Integer(1)]], [[Integer(1), Integer(1), Integer(1)], [Integer(1), -Integer(1), Integer(1)]],
      ...           [[Integer(1), Integer(1), Integer(1)], [Integer(1), Integer(1), -Integer(1)]], [[-Integer(1), Integer(1), Integer(1)], [-Integer(1), -Integer(1), Integer(1)]],
      ...           [[-Integer(1), Integer(1), Integer(1)], [-Integer(1), Integer(1), -Integer(1)]], [[Integer(1), -Integer(1), Integer(1)], [-Integer(1), -Integer(1), Integer(1)]],
      ...           [[Integer(1), -Integer(1), Integer(1)], [Integer(1), -Integer(1), -Integer(1)]], [[-Integer(1), -Integer(1), Integer(1)], [-Integer(1), -Integer(1), -Integer(1)]],
      ...           [[Integer(1), Integer(1), -Integer(1)], [-Integer(1), Integer(1), -Integer(1)]], [[Integer(1), Integer(1), -Integer(1)], [Integer(1), -Integer(1), -Integer(1)]],
      ...           [[-Integer(1), Integer(1), -Integer(1)], [-Integer(1), -Integer(1), -Integer(1)]], [[Integer(1), -Integer(1), -Integer(1)], [-Integer(1), -Integer(1), -Integer(1)]]]
      >>> for ed in cedges:
      ...     T.fcylinder(ed[Integer(0)], ed[Integer(1)], RealNumber('.05'), 't1')
      >>> T.light((-Integer(4),-Integer(4),Integer(4)), RealNumber('.1'), (Integer(1),Integer(1),Integer(1)))
      >>> T.show()

  Use of the `projection='perspective_dof'` option. This may not be implemented correctly.

  Sage

      sage: T = Tachyon(xres=800, antialiasing=4, raydepth=10,
      ....:             projection='perspective_dof', focallength='1.0', aperture='.0025')
      sage: T.light((0,5,7), 1.0, (1,1,1))
      sage: T.texture('t1', opacity=1, specular=.3)
      sage: T.texture('t2', opacity=1, specular=.3, color=(0,0,1))
      sage: T.texture('t3', opacity=1, specular=1, color=(1,.8,1), diffuse=0.2)
      sage: T.plane((0,0,-1), (0,0,1), 't3')
      sage: ttlist = ['t1', 't2']
      sage: tt = 't1'
      sage: T.cylinder((0,0,.1), (1,1/3,0), .05, 't3')
      sage: for q in srange(-3, 100, .15):
      ....:     if tt == 't1':
      ....:         tt = 't2'
      ....:     else:
      ....:         tt = 't1'
      ....:     T.sphere((q, q/3+.3*sin(3*q), .1+.3*cos(3*q)), .1, tt)
      sage: T.show()

  [Python]

      >>> from sage.all import *
      >>> T = Tachyon(xres=Integer(800), antialiasing=Integer(4), raydepth=Integer(10),
      ...             projection='perspective_dof', focallength='1.0', aperture='.0025')
      >>> T.light((Integer(0),Integer(5),Integer(7)), RealNumber('1.0'), (Integer(1),Integer(1),Integer(1)))
      >>> T.texture('t1', opacity=Integer(1), specular=RealNumber('.3'))
      >>> T.texture('t2', opacity=Integer(1), specular=RealNumber('.3'), color=(Integer(0),Integer(0),Integer(1)))
      >>> T.texture('t3', opacity=Integer(1), specular=Integer(1), color=(Integer(1),RealNumber('.8'),Integer(1)), diffuse=RealNumber('0.2'))
      >>> T.plane((Integer(0),Integer(0),-Integer(1)), (Integer(0),Integer(0),Integer(1)), 't3')
      >>> ttlist = ['t1', 't2']
      >>> tt = 't1'
      >>> T.cylinder((Integer(0),Integer(0),RealNumber('.1')), (Integer(1),Integer(1)/Integer(3),Integer(0)), RealNumber('.05'), 't3')
      >>> for q in srange(-Integer(3), Integer(100), RealNumber('.15')):
      ...     if tt == 't1':
      ...         tt = 't2'
      ...     else:
      ...         tt = 't1'
      ...     T.sphere((q, q/Integer(3)+RealNumber('.3')*sin(Integer(3)*q), RealNumber('.1')+RealNumber('.3')*cos(Integer(3)*q)), RealNumber('.1'), tt)
      >>> T.show()

  axis_aligned_box(min_p, max_p, texture)

    Create an axis-aligned box with minimal point `min_p` and maximum point `max_p`.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.axis_aligned_box((0,0,0),(2,2,2),'s')

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.axis_aligned_box((Integer(0),Integer(0),Integer(0)),(Integer(2),Integer(2),Integer(2)),'s')

  cylinder(center, axis, radius, texture)

    Create the scene information for a infinite cylinder with the given center, axis direction, radius, and texture.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.texture('c')
        sage: t.cylinder((0,0,0),(-1,-1,-1),.1,'c')

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.texture('c')
        >>> t.cylinder((Integer(0),Integer(0),Integer(0)),(-Integer(1),-Integer(1),-Integer(1)),RealNumber('.1'),'c')

  fcylinder(base, apex, radius, texture)

    Finite cylinders are almost the same as infinite ones, but the center and length of the axis determine the extents of the cylinder.

    The finite cylinder is also really a shell, it does not have any caps. If you need to close off the ends of the cylinder, use two ring objects, with the inner radius set to 0.0 and the normal set to be the axis of the cylinder. Finite cylinders are built this way to enhance speed.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.fcylinder((1,1,1),(1,2,3),.01,'s')
        sage: len(t.str())
        451

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.fcylinder((Integer(1),Integer(1),Integer(1)),(Integer(1),Integer(2),Integer(3)),RealNumber('.01'),'s')
        >>> len(t.str())
        451

  fractal_landscape(res, scale, center, texture)

    Axis-aligned fractal landscape.

    Not very useful at the moment.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.texture('s')
        sage: t.fractal_landscape([30,30],[80,80],[0,0,0],'s')
        sage: len(t._objects)
        2

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.texture('s')
        >>> t.fractal_landscape([Integer(30),Integer(30)],[Integer(80),Integer(80)],[Integer(0),Integer(0),Integer(0)],'s')
        >>> len(t._objects)
        2

  light(center, radius, color)

    Create a light source of the given center, radius, and color.

    EXAMPLES:

    Sage

        sage: q = Tachyon()
        sage: q.light((1,1,1),1.0,(.2,0,.8))
        sage: q.str().split('\n')[17]
        '        light center  1.0 1.0 1.0 '

    Python

        >>> from sage.all import *
        >>> q = Tachyon()
        >>> q.light((Integer(1),Integer(1),Integer(1)),RealNumber('1.0'),(RealNumber('.2'),Integer(0),RealNumber('.8')))
        >>> q.str().split('\n')[Integer(17)]
        '        light center  1.0 1.0 1.0 '

  parametric_plot(f, t_0, t_f, tex, r=0.1, cylinders=True, min_depth=4, max_depth=8, e_rel=0.01, e_abs=0.01)

    Plot a space curve as a series of spheres and finite cylinders.

    Example (twisted cubic)

    Sage

        sage: f = lambda t: (t,t^2,t^3)
        sage: t = Tachyon(camera_position=(5,0,4))
        sage: t.texture('t')
        sage: t.light((-20,-20,40), 0.2, (1,1,1))
        sage: t.parametric_plot(f,-5,5,'t',min_depth=6)
        sage: t.show(verbose=1)
        tachyon ...
        Scene contains 482 objects.
        ...

    Python

        >>> from sage.all import *
        >>> f = lambda t: (t,t**Integer(2),t**Integer(3))
        >>> t = Tachyon(camera_position=(Integer(5),Integer(0),Integer(4)))
        >>> t.texture('t')
        >>> t.light((-Integer(20),-Integer(20),Integer(40)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> t.parametric_plot(f,-Integer(5),Integer(5),'t',min_depth=Integer(6))
        >>> t.show(verbose=Integer(1))
        tachyon ...
        Scene contains 482 objects.
        ...

  plane(center, normal, texture)

    Create an infinite plane with the given center and normal.

  plot(f, xmin_xmax, ymin_ymax, texture, grad_f=None, max_bend=0.7, max_depth=5, initial_depth=3, num_colors=None)

    INPUT:

    - `f` – function of two variables, which returns a float (or coercible to a float) (xmin,xmax)

    - `(ymin,ymax)` – defines the rectangle to plot over texture: Name of texture to be used Optional arguments:

    - `grad_f` – gradient function. If specified, smooth triangles will be used

    - `max_bend` – cosine of the threshold angle between triangles used to determine whether or not to recurse after the minimum depth

    - `max_depth` – maximum recursion depth. Maximum triangles plotted = \(2^{2*max_depth}\)

    - `initial_depth` – minimum recursion depth. No error-tolerance checking is performed below this depth. Minimum triangles plotted: \(2^{2*min_depth}\)

    - `num_colors` – number of rainbow bands to color the plot with. Texture supplied will be cloned (with different colors) using the texture_recolor method of the Tachyon object.

    Plots a function by constructing a mesh with nonstandard sampling density without gaps. At very high resolutions (depths 10) it becomes very slow. Cython may help. Complexity is approx. \(O(2^{2*maxdepth})\). This algorithm has been optimized for speed, not memory - values from f(x,y) are recycled rather than calling the function multiple times. At high recursion depth, this may cause problems for some machines.

    Flat Triangles:

    Sage

        sage: t = Tachyon(xres=512, yres=512, camera_position=(4,-4,3),
        ....:             viewdir=(-4,4,-3), raydepth=4)
        sage: t.light((4.4,-4.4,4.4), 0.2, (1,1,1))
        sage: def f(x, y): return float(sin(x*y))
        sage: t.texture('t0', ambient=0.1, diffuse=0.9, specular=0.1,
        ....:           opacity=1.0, color=(1.0,0,0))
        sage: t.plot(f, (-4,4), (-4,4), "t0", max_depth=5, initial_depth=3,         # needs sage.symbolic
        ....:        num_colors=60)  # increase min_depth for better picture
        sage: t.show(verbose=1)                                                     # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...

    Python

        >>> from sage.all import *
        >>> t = Tachyon(xres=Integer(512), yres=Integer(512), camera_position=(Integer(4),-Integer(4),Integer(3)),
        ...             viewdir=(-Integer(4),Integer(4),-Integer(3)), raydepth=Integer(4))
        >>> t.light((RealNumber('4.4'),-RealNumber('4.4'),RealNumber('4.4')), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> def f(x, y): return float(sin(x*y))
        >>> t.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.1'),
        ...           opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
        >>> t.plot(f, (-Integer(4),Integer(4)), (-Integer(4),Integer(4)), "t0", max_depth=Integer(5), initial_depth=Integer(3),         # needs sage.symbolic
        ...        num_colors=Integer(60))  # increase min_depth for better picture
        >>> t.show(verbose=Integer(1))                                                     # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...

    Plotting with Smooth Triangles (requires explicit gradient function):

    Sage

        sage: t = Tachyon(xres=512, yres=512, camera_position=(4,-4,3),
        ....:             viewdir=(-4,4,-3), raydepth=4)
        sage: t.light((4.4,-4.4,4.4), 0.2, (1,1,1))
        sage: def f(x, y): return float(sin(x*y))
        sage: def g(x, y): return (float(y*cos(x*y)), float(x*cos(x*y)), 1)
        sage: t.texture('t0', ambient=0.1, diffuse=0.9, specular=0.1,
        ....:           opacity=1.0, color=(1.0,0,0))
        sage: t.plot(f, (-4,4), (-4,4), "t0", max_depth=5, initial_depth=3,         # needs sage.symbolic
        ....:        grad_f=g)  # increase min_depth for better picture
        sage: t.show(verbose=1)                                                     # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...

    [Python]

        >>> from sage.all import *
        >>> t = Tachyon(xres=Integer(512), yres=Integer(512), camera_position=(Integer(4),-Integer(4),Integer(3)),
        ...             viewdir=(-Integer(4),Integer(4),-Integer(3)), raydepth=Integer(4))
        >>> t.light((RealNumber('4.4'),-RealNumber('4.4'),RealNumber('4.4')), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> def f(x, y): return float(sin(x*y))
        >>> def g(x, y): return (float(y*cos(x*y)), float(x*cos(x*y)), Integer(1))
        >>> t.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.1'),
        ...           opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
        >>> t.plot(f, (-Integer(4),Integer(4)), (-Integer(4),Integer(4)), "t0", max_depth=Integer(5), initial_depth=Integer(3),         # needs sage.symbolic
        ...        grad_f=g)  # increase min_depth for better picture
        >>> t.show(verbose=Integer(1))                                                     # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...

    Preconditions: f is a scalar function of two variables, grad_f is None or a triple-valued function of two variables, min_x != max_x, min_y != max_y

    Sage

        sage: f = lambda x,y: x*y
        sage: t = Tachyon()
        sage: t.plot(f,(2.,2.),(-2.,2.),'')
        Traceback (most recent call last):
        ...
        ValueError: plot rectangle is really a line; make sure min_x != max_x and min_y != max_y

    Python

        >>> from sage.all import *
        >>> f = lambda x,y: x*y
        >>> t = Tachyon()
        >>> t.plot(f,(RealNumber('2.'),RealNumber('2.')),(-RealNumber('2.'),RealNumber('2.')),'')
        Traceback (most recent call last):
        ...
        ValueError: plot rectangle is really a line; make sure min_x != max_x and min_y != max_y

  ring(center, normal, inner, outer, texture)

    Create the scene information for a ring with the given parameters.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.ring([0,0,0], [0,0,1], 1.0, 2.0, 's')
        sage: t._objects[0]._center
        (0.0, 0.0, 0.0)

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.ring([Integer(0),Integer(0),Integer(0)], [Integer(0),Integer(0),Integer(1)], RealNumber('1.0'), RealNumber('2.0'), 's')
        >>> t._objects[Integer(0)]._center
        (0.0, 0.0, 0.0)

  save(filename='sage.png', verbose=None, extra_opts='')

    Save rendering of the tachyon scene.

    INPUT:

    - `filename` – (default: `'sage.png'`) output filename; the extension of the filename determines the type. Supported types include:

    - `tga` – 24-bit (uncompressed)

    - `bmp` – 24-bit Windows BMP (uncompressed)

    - `ppm` – 24-bit PPM (uncompressed)

    - `rgb` – 24-bit SGI RGB (uncompressed)

    - `png` – 24-bit PNG (compressed, lossless)

    - `verbose` – integer (default: `None`); if no verbosity setting is supplied, the verbosity level set by `sage.misc.verbose.set_verbose` is used.

    - `0` – silent

    - `1` – some output

    - `2` – very verbose output

    - `extra_opts` – passed directly to tachyon command line. Use `tachyon_rt.usage()` to see some of the possibilities.

    EXAMPLES:

    Sage

        sage: q = Tachyon()
        sage: q.light((1,1,11), 1,(1,1,1))
        sage: q.texture('s')
        sage: q.sphere((0,0,0),1,'s')
        sage: tempname = tmp_filename()
        sage: q.save(tempname)

    Python

        >>> from sage.all import *
        >>> q = Tachyon()
        >>> q.light((Integer(1),Integer(1),Integer(11)), Integer(1),(Integer(1),Integer(1),Integer(1)))
        >>> q.texture('s')
        >>> q.sphere((Integer(0),Integer(0),Integer(0)),Integer(1),'s')
        >>> tempname = tmp_filename()
        >>> q.save(tempname)

  save_image(filename=None, *args, **kwds)

    Save an image representation of `self`.

    The image type is determined by the extension of the filename. For example, this could be `.png`, `.jpg`, `.gif`, `.pdf`, `.svg`. Currently this is implemented by calling the `save()` method of self, passing along all arguments and keywords.

    Note

    Not all image types are necessarily implemented for all graphics types. See `save()` for more details.

    EXAMPLES:

    Sage

        sage: q = Tachyon()
        sage: q.light((1,1,11), 1,(1,1,1))
        sage: q.texture('s')
        sage: q.sphere((0,-1,1),1,'s')
        sage: tempname = tmp_filename()
        sage: q.save_image(tempname)

    Python

        >>> from sage.all import *
        >>> q = Tachyon()
        >>> q.light((Integer(1),Integer(1),Integer(11)), Integer(1),(Integer(1),Integer(1),Integer(1)))
        >>> q.texture('s')
        >>> q.sphere((Integer(0),-Integer(1),Integer(1)),Integer(1),'s')
        >>> tempname = tmp_filename()
        >>> q.save_image(tempname)

  show(**kwds)

    Create a PNG file of the scene.

    This method attempts to display the graphics immediately, without waiting for the currently running code (if any) to return to the command line. Be careful, calling it from within a loop will potentially launch a large number of external viewer programs.

    OUTPUT:

    This method does not return anything. Use `save()` if you want to save the figure as an image.

    EXAMPLES:

    This example demonstrates how the global Sage verbosity setting is used if none is supplied. Firstly, using a global verbosity setting of 0 means no extra technical information is displayed, and we are simply shown the plot.

    Sage

        sage: h = Tachyon(xres=512, yres=512, camera_position=(4,-4,3),
        ....:             viewdir=(-4,4,-3), raydepth=4)
        sage: h.light((4.4,-4.4,4.4), 0.2, (1,1,1))
        sage: def f(x, y): return float(sin(x*y))
        sage: h.texture('t0', ambient=0.1, diffuse=0.9, specular=0.1,
        ....:           opacity=1.0, color=(1.0,0,0))
        sage: h.plot(f, (-4,4), (-4,4), "t0", max_depth=5, initial_depth=3,         # needs sage.symbolic
        ....:        num_colors=60)  # increase min_depth for better picture
        sage: from sage.misc.verbose import set_verbose, get_verbose
        sage: set_verbose(0)
        sage: h.show()                                                              # needs sage.symbolic

    Python

        >>> from sage.all import *
        >>> h = Tachyon(xres=Integer(512), yres=Integer(512), camera_position=(Integer(4),-Integer(4),Integer(3)),
        ...             viewdir=(-Integer(4),Integer(4),-Integer(3)), raydepth=Integer(4))
        >>> h.light((RealNumber('4.4'),-RealNumber('4.4'),RealNumber('4.4')), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> def f(x, y): return float(sin(x*y))
        >>> h.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.1'),
        ...           opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
        >>> h.plot(f, (-Integer(4),Integer(4)), (-Integer(4),Integer(4)), "t0", max_depth=Integer(5), initial_depth=Integer(3),         # needs sage.symbolic
        ...        num_colors=Integer(60))  # increase min_depth for better picture
        >>> from sage.misc.verbose import set_verbose, get_verbose
        >>> set_verbose(Integer(0))
        >>> h.show()                                                              # needs sage.symbolic

    This second example, using a “medium” global verbosity setting of 1, displays some extra technical information then displays our graph.

    Sage

        sage: s = Tachyon(xres=512, yres=512, camera_position=(4,-4,3),
        ....:             viewdir=(-4,4,-3), raydepth=4)
        sage: s.light((4.4,-4.4,4.4), 0.2, (1,1,1))
        sage: def f(x, y): return float(sin(x*y))
        sage: s.texture('t0', ambient=0.1, diffuse=0.9, specular=0.1,
        ....:           opacity=1.0, color=(1.0,0,0))
        sage: s.plot(f, (-4,4), (-4,4), "t0", max_depth=5, initial_depth=3,         # needs sage.symbolic
        ....:        num_colors=60)  # increase min_depth for better picture
        sage: set_verbose(1)
        sage: s.show()                                                              # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...

    [Python]

        >>> from sage.all import *
        >>> s = Tachyon(xres=Integer(512), yres=Integer(512), camera_position=(Integer(4),-Integer(4),Integer(3)),
        ...             viewdir=(-Integer(4),Integer(4),-Integer(3)), raydepth=Integer(4))
        >>> s.light((RealNumber('4.4'),-RealNumber('4.4'),RealNumber('4.4')), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> def f(x, y): return float(sin(x*y))
        >>> s.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.1'),
        ...           opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
        >>> s.plot(f, (-Integer(4),Integer(4)), (-Integer(4),Integer(4)), "t0", max_depth=Integer(5), initial_depth=Integer(3),         # needs sage.symbolic
        ...        num_colors=Integer(60))  # increase min_depth for better picture
        >>> set_verbose(Integer(1))
        >>> s.show()                                                              # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...

    The last example shows how you can override the global Sage verbosity setting, my supplying a setting level as an argument. In this case we chose the highest verbosity setting level, 2, so much more extra technical information is shown, along with the plot.

    Sage

        sage: set_verbose(0)
        sage: d = Tachyon(xres=512, yres=512, camera_position=(4,-4,3),
        ....:             viewdir=(-4,4,-3), raydepth=4)
        sage: d.light((4.4,-4.4,4.4), 0.2, (1,1,1))
        sage: def f(x, y): return float(sin(x*y))
        sage: d.texture('t0', ambient=0.1, diffuse=0.9, specular=0.1,
        ....:           opacity=1.0, color=(1.0,0,0))
        sage: d.plot(f,(-4,4),(-4,4),"t0",max_depth=5,initial_depth=3,              # needs sage.symbolic
        ....:        num_colors=60)  # increase min_depth for better picture
        sage: get_verbose()
        0
        sage: d.show(verbose=2)                                                     # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...
        Scene contains 1 non-gridded objects
        ...

    Python

        >>> from sage.all import *
        >>> set_verbose(Integer(0))
        >>> d = Tachyon(xres=Integer(512), yres=Integer(512), camera_position=(Integer(4),-Integer(4),Integer(3)),
        ...             viewdir=(-Integer(4),Integer(4),-Integer(3)), raydepth=Integer(4))
        >>> d.light((RealNumber('4.4'),-RealNumber('4.4'),RealNumber('4.4')), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> def f(x, y): return float(sin(x*y))
        >>> d.texture('t0', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.1'),
        ...           opacity=RealNumber('1.0'), color=(RealNumber('1.0'),Integer(0),Integer(0)))
        >>> d.plot(f,(-Integer(4),Integer(4)),(-Integer(4),Integer(4)),"t0",max_depth=Integer(5),initial_depth=Integer(3),              # needs sage.symbolic
        ...        num_colors=Integer(60))  # increase min_depth for better picture
        >>> get_verbose()
        0
        >>> d.show(verbose=Integer(2))                                                     # needs sage.symbolic
        tachyon ...
        Scene contains 2713 objects.
        ...
        Scene contains 1 non-gridded objects
        ...

  smooth_triangle(vertex_1, vertex_2, vertex_3, normal_1, normal_2, normal_3, texture)

    Create a triangle along with a normal vector for smoothing.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.light((1,1,1),.1,(1,1,1))
        sage: t.texture('s')
        sage: t.smooth_triangle([0,0,0],[0,0,1],[0,1,0],[0,1,1],[-1,1,2],[3,0,0],'s')
        sage: t._objects[2].get_vertices()
        ([0, 0, 0], [0, 0, 1], [0, 1, 0])
        sage: t._objects[2].get_normals()
        ([0, 1, 1], [-1, 1, 2], [3, 0, 0])

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.light((Integer(1),Integer(1),Integer(1)),RealNumber('.1'),(Integer(1),Integer(1),Integer(1)))
        >>> t.texture('s')
        >>> t.smooth_triangle([Integer(0),Integer(0),Integer(0)],[Integer(0),Integer(0),Integer(1)],[Integer(0),Integer(1),Integer(0)],[Integer(0),Integer(1),Integer(1)],[-Integer(1),Integer(1),Integer(2)],[Integer(3),Integer(0),Integer(0)],'s')
        >>> t._objects[Integer(2)].get_vertices()
        ([0, 0, 0], [0, 0, 1], [0, 1, 0])
        >>> t._objects[Integer(2)].get_normals()
        ([0, 1, 1], [-1, 1, 2], [3, 0, 0])

  sphere(center, radius, texture)

    Create the scene information for a sphere with the given center, radius, and texture.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.texture('sphere_texture')
        sage: t.sphere((1,2,3), .1, 'sphere_texture')
        sage: t._objects[1].str()
        '\n        sphere center  1.0 2.0 3.0  rad 0.1 sphere_texture\n        '

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.texture('sphere_texture')
        >>> t.sphere((Integer(1),Integer(2),Integer(3)), RealNumber('.1'), 'sphere_texture')
        >>> t._objects[Integer(1)].str()
        '\n        sphere center  1.0 2.0 3.0  rad 0.1 sphere_texture\n        '

  str()

    Return the complete tachyon scene file as a string.

    EXAMPLES:

    Sage

        sage: t = Tachyon(xres=500,yres=500, camera_position=(2,0,0))
        sage: t.light((4,3,2), 0.2, (1,1,1))
        sage: t.texture('t2', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(1,0,0))
        sage: t.texture('t3', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(0,1,0))
        sage: t.texture('t4', ambient=0.1, diffuse=0.9, specular=0.5, opacity=1.0, color=(0,0,1))
        sage: t.sphere((0,0.5,0), 0.2, 't2')
        sage: t.sphere((0.5,0,0), 0.2, 't3')
        sage: t.sphere((0,0,0.5), 0.2, 't4')
        sage: 'PLASTIC' in t.str()
        True

    Python

        >>> from sage.all import *
        >>> t = Tachyon(xres=Integer(500),yres=Integer(500), camera_position=(Integer(2),Integer(0),Integer(0)))
        >>> t.light((Integer(4),Integer(3),Integer(2)), RealNumber('0.2'), (Integer(1),Integer(1),Integer(1)))
        >>> t.texture('t2', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(1),Integer(0),Integer(0)))
        >>> t.texture('t3', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(0),Integer(1),Integer(0)))
        >>> t.texture('t4', ambient=RealNumber('0.1'), diffuse=RealNumber('0.9'), specular=RealNumber('0.5'), opacity=RealNumber('1.0'), color=(Integer(0),Integer(0),Integer(1)))
        >>> t.sphere((Integer(0),RealNumber('0.5'),Integer(0)), RealNumber('0.2'), 't2')
        >>> t.sphere((RealNumber('0.5'),Integer(0),Integer(0)), RealNumber('0.2'), 't3')
        >>> t.sphere((Integer(0),Integer(0),RealNumber('0.5')), RealNumber('0.2'), 't4')
        >>> 'PLASTIC' in t.str()
        True

  texfunc(type=0, center=(0, 0, 0), rotate=(0, 0, 0), scale=(1, 1, 1), imagefile='')

    INPUT:

    - `type` – (default: 0)

      > 0. No special texture, plain shading

      > 1. 3D checkerboard function, like a rubik’s cube

      > 2. Grit Texture, randomized surface color

      > 3. 3D marble texture, uses object’s base color

      > 4. 3D wood texture, light and dark brown, not very good yet

      > 5. 3D gradient noise function (can’t remember what it looks like)

      > 6. Don’t remember

      > 7. Cylindrical Image Map, requires ppm filename (with path)

      > 8. Spherical Image Map, requires ppm filename (with path)

      > 9. Planar Image Map, requires ppm filename (with path)

    - `center` – (default: (0,0,0))

    - `rotate` – (default: (0,0,0))

    - `scale` – (default: (1,1,1))

    EXAMPLES: We draw an infinite checkerboard:

    Sage

        sage: t = Tachyon(camera_position=(2,7,4), look_at=(2,0,0))
        sage: t.texture('black', color=(0,0,0), texfunc=1)
        sage: t.plane((0,0,0),(0,0,1),'black')
        sage: t.show()

    Python

        >>> from sage.all import *
        >>> t = Tachyon(camera_position=(Integer(2),Integer(7),Integer(4)), look_at=(Integer(2),Integer(0),Integer(0)))
        >>> t.texture('black', color=(Integer(0),Integer(0),Integer(0)), texfunc=Integer(1))
        >>> t.plane((Integer(0),Integer(0),Integer(0)),(Integer(0),Integer(0),Integer(1)),'black')
        >>> t.show()

  texture(name, ambient=0.2, diffuse=0.8, specular=0.0, opacity=1.0, color=(1.0, 0.0, 0.5), texfunc=0, phong=0, phongsize=0.5, phongtype='PLASTIC', imagefile='')

    INPUT:

    - `name` – string; the name of the texture (to be used later)

    - `ambient` – (default: 0.2)

    - `diffuse` – (default: 0.8)

    - `specular` – (default: 0.0)

    - `opacity` – (default: 1.0)

    - `color` – (default: (1.0,0.0,0.5))

    - `texfunc` – (default: 0) a texture function; this is either the output of self.texfunc, or a number between 0 and 9, inclusive. See the docs for self.texfunc.

    - `phong` – (default: 0)

    - `phongsize` – (default: 0.5)

    - `phongtype` – (default: `'PLASTIC'`)

    EXAMPLES:

    We draw a scene with 4 spheres that illustrates various uses of the texture command:

    Sage

        sage: t = Tachyon(camera_position=(2,5,4), look_at=(2,0,0), raydepth=6)
        sage: t.light((10,3,4), 1, (1,1,1))
        sage: t.texture('mirror', ambient=0.05, diffuse=0.05, specular=.9,
        ....:           opacity=0.9, color=(.8,.8,.8))
        sage: t.texture('grey', color=(.8,.8,.8), texfunc=3)
        sage: t.plane((0,0,0),(0,0,1),'grey')
        sage: t.sphere((4,-1,1), 1, 'mirror')
        sage: t.sphere((0,-1,1), 1, 'mirror')
        sage: t.sphere((2,-1,1), 0.5, 'mirror')
        sage: t.sphere((2,1,1), 0.5, 'mirror')
        sage: show(t)  # known bug (trac #7232)

    Python

        >>> from sage.all import *
        >>> t = Tachyon(camera_position=(Integer(2),Integer(5),Integer(4)), look_at=(Integer(2),Integer(0),Integer(0)), raydepth=Integer(6))
        >>> t.light((Integer(10),Integer(3),Integer(4)), Integer(1), (Integer(1),Integer(1),Integer(1)))
        >>> t.texture('mirror', ambient=RealNumber('0.05'), diffuse=RealNumber('0.05'), specular=RealNumber('.9'),
        ...           opacity=RealNumber('0.9'), color=(RealNumber('.8'),RealNumber('.8'),RealNumber('.8')))
        >>> t.texture('grey', color=(RealNumber('.8'),RealNumber('.8'),RealNumber('.8')), texfunc=Integer(3))
        >>> t.plane((Integer(0),Integer(0),Integer(0)),(Integer(0),Integer(0),Integer(1)),'grey')
        >>> t.sphere((Integer(4),-Integer(1),Integer(1)), Integer(1), 'mirror')
        >>> t.sphere((Integer(0),-Integer(1),Integer(1)), Integer(1), 'mirror')
        >>> t.sphere((Integer(2),-Integer(1),Integer(1)), RealNumber('0.5'), 'mirror')
        >>> t.sphere((Integer(2),Integer(1),Integer(1)), RealNumber('0.5'), 'mirror')
        >>> show(t)  # known bug (trac #7232)

  texture_recolor(name, colors)

    Recolor default textures.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.texture('s')
        sage: q = t.texture_recolor('s',[(0,0,1)])
        sage: t._objects[1]._color
        (0.0, 0.0, 1.0)

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.texture('s')
        >>> q = t.texture_recolor('s',[(Integer(0),Integer(0),Integer(1))])
        >>> t._objects[Integer(1)]._color
        (0.0, 0.0, 1.0)

  triangle(vertex_1, vertex_2, vertex_3, texture)

    Create a triangle with the given vertices and texture.

    EXAMPLES:

    Sage

        sage: t = Tachyon()
        sage: t.texture('s')
        sage: t.triangle([1,2,3],[4,5,6],[7,8,10],'s')
        sage: t._objects[1].get_vertices()
        ([1, 2, 3], [4, 5, 6], [7, 8, 10])

    Python

        >>> from sage.all import *
        >>> t = Tachyon()
        >>> t.texture('s')
        >>> t.triangle([Integer(1),Integer(2),Integer(3)],[Integer(4),Integer(5),Integer(6)],[Integer(7),Integer(8),Integer(10)],'s')
        >>> t._objects[Integer(1)].get_vertices()
        ([1, 2, 3], [4, 5, 6], [7, 8, 10])

class sage.plot.plot3d.tachyon.TachyonSmoothTriangle(a, b, c, da, db, dc, color=0)

  Bases: `SmoothTriangle`

  A triangle along with a normal vector, which is used for smoothing.

  str()

    Return the scene string for a smoothed triangle.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import TachyonSmoothTriangle
        sage: t = TachyonSmoothTriangle([-1,-1,-1],[0,0,0],[1,2,3],[1,0,0],[0,1,0],[0,0,1])
        sage: t.str()
        '\n        STRI V0  ...  1.0 0.0 0.0  N1  0.0 1.0 0.0   N2  0.0 0.0 1.0 \n             0\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import TachyonSmoothTriangle
        >>> t = TachyonSmoothTriangle([-Integer(1),-Integer(1),-Integer(1)],[Integer(0),Integer(0),Integer(0)],[Integer(1),Integer(2),Integer(3)],[Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(0)],[Integer(0),Integer(0),Integer(1)])
        >>> t.str()
        '\n        STRI V0  ...  1.0 0.0 0.0  N1  0.0 1.0 0.0   N2  0.0 0.0 1.0 \n             0\n        '

class sage.plot.plot3d.tachyon.TachyonTriangle(a, b, c, color=0)

  Bases: `Triangle`

  Basic triangle class.

  str()

    Return the scene string for a triangle.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import TachyonTriangle
        sage: t = TachyonTriangle([-1,-1,-1],[0,0,0],[1,2,3])
        sage: t.str()
        '\n        TRI V0  -1.0 -1.0 -1.0   V1  0.0 0.0 0.0    V2  1.0 2.0 3.0 \n            0\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import TachyonTriangle
        >>> t = TachyonTriangle([-Integer(1),-Integer(1),-Integer(1)],[Integer(0),Integer(0),Integer(0)],[Integer(1),Integer(2),Integer(3)])
        >>> t.str()
        '\n        TRI V0  -1.0 -1.0 -1.0   V1  0.0 0.0 0.0    V2  1.0 2.0 3.0 \n            0\n        '

class sage.plot.plot3d.tachyon.TachyonTriangleFactory(tach, tex)

  Bases: `TriangleFactory`

  A class to produce triangles of various rendering types.

  get_colors(list)

    Return a list of color labels.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import TachyonTriangleFactory
        sage: t = Tachyon()
        sage: t.texture('s')
        sage: ttf = TachyonTriangleFactory(t, 's')
        sage: ttf.get_colors([(1,1,1)])
        ['SAGETEX1_0']

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import TachyonTriangleFactory
        >>> t = Tachyon()
        >>> t.texture('s')
        >>> ttf = TachyonTriangleFactory(t, 's')
        >>> ttf.get_colors([(Integer(1),Integer(1),Integer(1))])
        ['SAGETEX1_0']

  smooth_triangle(a, b, c, da, db, dc, color=None)

    Create a TachyonSmoothTriangle.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import TachyonTriangleFactory
        sage: t = Tachyon()
        sage: t.texture('s')
        sage: ttf = TachyonTriangleFactory(t, 's')
        sage: ttfst = ttf.smooth_triangle([0,0,0],[1,0,0],[0,0,1],[1,1,1],[1,2,3],[-1,-1,2])
        sage: ttfst.str()
        '\n        STRI V0  0.0 0.0 0.0  ...'

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import TachyonTriangleFactory
        >>> t = Tachyon()
        >>> t.texture('s')
        >>> ttf = TachyonTriangleFactory(t, 's')
        >>> ttfst = ttf.smooth_triangle([Integer(0),Integer(0),Integer(0)],[Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(0),Integer(1)],[Integer(1),Integer(1),Integer(1)],[Integer(1),Integer(2),Integer(3)],[-Integer(1),-Integer(1),Integer(2)])
        >>> ttfst.str()
        '\n        STRI V0  0.0 0.0 0.0  ...'

  triangle(a, b, c, color=None)

    Create a TachyonTriangle with vertices a, b, and c.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import TachyonTriangleFactory
        sage: t = Tachyon()
        sage: t.texture('s')
        sage: ttf = TachyonTriangleFactory(t, 's')
        sage: ttft = ttf.triangle([1,2,3],[3,2,1],[0,2,1])
        sage: ttft.str()
        '\n        TRI V0  1.0 2.0 3.0   V1  3.0 2.0 1.0    V2  0.0 2.0 1.0 \n            s\n        '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import TachyonTriangleFactory
        >>> t = Tachyon()
        >>> t.texture('s')
        >>> ttf = TachyonTriangleFactory(t, 's')
        >>> ttft = ttf.triangle([Integer(1),Integer(2),Integer(3)],[Integer(3),Integer(2),Integer(1)],[Integer(0),Integer(2),Integer(1)])
        >>> ttft.str()
        '\n        TRI V0  1.0 2.0 3.0   V1  3.0 2.0 1.0    V2  0.0 2.0 1.0 \n            s\n        '

class sage.plot.plot3d.tachyon.Texfunc(ttype=0, center=(0, 0, 0), rotate=(0, 0, 0), scale=(1, 1, 1), imagefile='')

  Bases: `object`

  Create a texture function.

  EXAMPLES:

  Sage

      sage: from sage.plot.plot3d.tachyon import Texfunc
      sage: t = Texfunc()
      sage: t._ttype
      0

  Python

      >>> from sage.all import *
      >>> from sage.plot.plot3d.tachyon import Texfunc
      >>> t = Texfunc()
      >>> t._ttype
      0

  str()

    Return the scene string for this texture function.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Texfunc
        sage: t = Texfunc()
        sage: t.str()
        '0'

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Texfunc
        >>> t = Texfunc()
        >>> t.str()
        '0'

class sage.plot.plot3d.tachyon.Texture(name, ambient=0.2, diffuse=0.8, specular=0.0, opacity=1.0, color=(1.0, 0.0, 0.5), texfunc=0, phong=0, phongsize=0, phongtype='PLASTIC', imagefile='')

  Bases: `object`

  Store texture information.

  EXAMPLES:

  Sage

      sage: from sage.plot.plot3d.tachyon import Texture
      sage: t = Texture('w')
      sage: t.str().split()[2:6]
      ['ambient', '0.2', 'diffuse', '0.8']

  Python

      >>> from sage.all import *
      >>> from sage.plot.plot3d.tachyon import Texture
      >>> t = Texture('w')
      >>> t.str().split()[Integer(2):Integer(6)]
      ['ambient', '0.2', 'diffuse', '0.8']

  recolor(name, color)

    Return a texture with the new given color.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Texture
        sage: t2 = Texture('w')
        sage: t2w = t2.recolor('w2', (.1,.2,.3))
        sage: t2ws = t2w.str()
        sage: color_index = t2ws.find('color')
        sage: t2ws[color_index:color_index+20]
        'color  0.1 0.2 0.3  '

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Texture
        >>> t2 = Texture('w')
        >>> t2w = t2.recolor('w2', (RealNumber('.1'),RealNumber('.2'),RealNumber('.3')))
        >>> t2ws = t2w.str()
        >>> color_index = t2ws.find('color')
        >>> t2ws[color_index:color_index+Integer(20)]
        'color  0.1 0.2 0.3  '

  str()

    Return the scene string for this texture.

    EXAMPLES:

    Sage

        sage: from sage.plot.plot3d.tachyon import Texture
        sage: t = Texture('w')
        sage: t.str().split()[2:6]
        ['ambient', '0.2', 'diffuse', '0.8']

    Python

        >>> from sage.all import *
        >>> from sage.plot.plot3d.tachyon import Texture
        >>> t = Texture('w')
        >>> t.str().split()[Integer(2):Integer(6)]
        ['ambient', '0.2', 'diffuse', '0.8']

sage.plot.plot3d.tachyon.tostr(s, length=3, out_type=<class 'float'>)

  Convert vector information to a space-separated string.

  EXAMPLES:

  Sage

      sage: from sage.plot.plot3d.tachyon import tostr
      sage: tostr((1,1,1))
      ' 1.0 1.0 1.0 '
      sage: tostr('2 3 2')
      '2 3 2'

  Python

      >>> from sage.all import *
      >>> from sage.plot.plot3d.tachyon import tostr
      >>> tostr((Integer(1),Integer(1),Integer(1)))
      ' 1.0 1.0 1.0 '
      >>> tostr('2 3 2')
      '2 3 2'