Base classes for 3D graphics objects and plotting¶
The most important facts about these classes are
that you can simply add graphics objects
together (G1+G2
, see Graphics3d.__add__()
),
and the Graphics3d.show()
method with its options for
choosing a viewer and setting
various parameters for displaying the graphics.
Most of the other methods of these classes are technical and for special usage.
AUTHORS:
Robert Bradshaw (2007-02): initial version
Robert Bradshaw (2007-08): Cythonization, much optimization
William Stein (2008)
Paul Masson (2016): Three.js support
Joshua Campbell (2020): Three.js animation support
Günter Rote (2021): camera and light parameters for tachyon
Todo
finish integrating tachyon – good default lights
full documentation of three.js viewer parameters
zoom by changing camera parameters instead of scaling objects
- class sage.plot.plot3d.base.BoundingSphere(cen, r)[source]¶
Bases:
SageObject
A bounding sphere is like a bounding box, but is simpler to deal with and behaves better under rotations.
- transform(T)[source]¶
Return the bounding sphere of this sphere acted on by T. This always returns a new sphere, even if the resulting object is an ellipsoid.
EXAMPLES:
sage: from sage.plot.plot3d.transform import Transformation sage: from sage.plot.plot3d.base import BoundingSphere sage: BoundingSphere((0,0,0), 10).transform(Transformation(trans=(1,2,3))) Center (1.0, 2.0, 3.0) radius 10.0 sage: BoundingSphere((0,0,0), 10).transform(Transformation(scale=(1/2, 1, 2))) Center (0.0, 0.0, 0.0) radius 20.0 sage: BoundingSphere((0,0,3), 10).transform(Transformation(scale=(2, 2, 2))) Center (0.0, 0.0, 6.0) radius 20.0
>>> from sage.all import * >>> from sage.plot.plot3d.transform import Transformation >>> from sage.plot.plot3d.base import BoundingSphere >>> BoundingSphere((Integer(0),Integer(0),Integer(0)), Integer(10)).transform(Transformation(trans=(Integer(1),Integer(2),Integer(3)))) Center (1.0, 2.0, 3.0) radius 10.0 >>> BoundingSphere((Integer(0),Integer(0),Integer(0)), Integer(10)).transform(Transformation(scale=(Integer(1)/Integer(2), Integer(1), Integer(2)))) Center (0.0, 0.0, 0.0) radius 20.0 >>> BoundingSphere((Integer(0),Integer(0),Integer(3)), Integer(10)).transform(Transformation(scale=(Integer(2), Integer(2), Integer(2)))) Center (0.0, 0.0, 6.0) radius 20.0
- class sage.plot.plot3d.base.Graphics3d[source]¶
Bases:
SageObject
This is the baseclass for all 3d graphics objects.
- __add__(left, right)[source]¶
Addition of objects adds them to the same scene.
EXAMPLES:
sage: A = sphere((0,0,0), 1, color='red') sage: B = dodecahedron((2, 0, 0), color='yellow') sage: A+B Graphics3d Object
>>> from sage.all import * >>> A = sphere((Integer(0),Integer(0),Integer(0)), Integer(1), color='red') >>> B = dodecahedron((Integer(2), Integer(0), Integer(0)), color='yellow') >>> A+B Graphics3d Object
For convenience, we take 0 and
None
to be the additive identity:sage: A + 0 is A True sage: A + None is A, 0 + A is A, None + A is A (True, True, True)
>>> from sage.all import * >>> A + Integer(0) is A True >>> A + None is A, Integer(0) + A is A, None + A is A (True, True, True)
In particular, this allows us to use the sum() function without having to provide an empty starting object:
sage: sum(point3d((cos(n), sin(n), n)) for n in [0..10, step=.1]) Graphics3d Object
>>> from sage.all import * >>> sum(point3d((cos(n), sin(n), n)) for n in (ellipsis_range(Integer(0),Ellipsis,Integer(10), step=RealNumber('.1')))) Graphics3d Object
A Graphics 3d object and a 2d object can also be added:
sage: A = sphere((0, 0, 0), 1) + circle((0, 0), 1.5) sage: A.show(aspect_ratio=1)
>>> from sage.all import * >>> A = sphere((Integer(0), Integer(0), Integer(0)), Integer(1)) + circle((Integer(0), Integer(0)), RealNumber('1.5')) >>> A.show(aspect_ratio=Integer(1))
- _rich_repr_(display_manager, **kwds)[source]¶
Rich Output Magic Method.
See
sage.repl.rich_output
for details.EXAMPLES:
sage: from sage.repl.rich_output import get_display_manager sage: dm = get_display_manager() sage: g = sphere() sage: g._rich_repr_(dm) # OutputSceneThreejs container outside doctest mode OutputSceneJmol container
>>> from sage.all import * >>> from sage.repl.rich_output import get_display_manager >>> dm = get_display_manager() >>> g = sphere() >>> g._rich_repr_(dm) # OutputSceneThreejs container outside doctest mode OutputSceneJmol container
- amf_ascii_string(name='surface')[source]¶
Return an AMF (Additive Manufacturing File Format) representation of the surface.
Warning
This only works for triangulated surfaces!
INPUT:
name
– string (default:'surface'
); name of the surface
OUTPUT: string that represents the surface in the AMF format
See Wikipedia article Additive_Manufacturing_File_Format.
Todo
This should rather be saved as a ZIP archive to save space.
EXAMPLES:
sage: # needs sage.symbolic sage: x,y,z = var('x,y,z') sage: a = implicit_plot3d(x^2+y^2+z^2-9,[x,-5,5],[y,-5,5],[z,-5,5]) sage: a_amf = a.amf_ascii_string() sage: a_amf[:160] '<?xml version="1.0" encoding="utf-8"?><amf><object id="surface"><mesh><vertices><vertex><coordinates><x>2.948717948717948</x><y>-0.384615384615385</y><z>-0.3935' sage: p = polygon3d([[0,0,0], [1,2,3], [3,0,0]]) sage: print(p.amf_ascii_string(name='triangle')) <?xml version="1.0" encoding="utf-8"?><amf><object id="triangle"><mesh><vertices><vertex><coordinates><x>0.0</x><y>0.0</y><z>0.0</z></coordinates></vertex><vertex><coordinates><x>1.0</x><y>2.0</y><z>3.0</z></coordinates></vertex><vertex><coordinates><x>3.0</x><y>0.0</y><z>0.0</z></coordinates></vertex></vertices><volume><triangle><v1>0</v1><v2>1</v2><v3>2</v3></triangle></volume></mesh></object></amf>
>>> from sage.all import * >>> # needs sage.symbolic >>> x,y,z = var('x,y,z') >>> a = implicit_plot3d(x**Integer(2)+y**Integer(2)+z**Integer(2)-Integer(9),[x,-Integer(5),Integer(5)],[y,-Integer(5),Integer(5)],[z,-Integer(5),Integer(5)]) >>> a_amf = a.amf_ascii_string() >>> a_amf[:Integer(160)] '<?xml version="1.0" encoding="utf-8"?><amf><object id="surface"><mesh><vertices><vertex><coordinates><x>2.948717948717948</x><y>-0.384615384615385</y><z>-0.3935' >>> p = polygon3d([[Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(2),Integer(3)], [Integer(3),Integer(0),Integer(0)]]) >>> print(p.amf_ascii_string(name='triangle')) <?xml version="1.0" encoding="utf-8"?><amf><object id="triangle"><mesh><vertices><vertex><coordinates><x>0.0</x><y>0.0</y><z>0.0</z></coordinates></vertex><vertex><coordinates><x>1.0</x><y>2.0</y><z>3.0</z></coordinates></vertex><vertex><coordinates><x>3.0</x><y>0.0</y><z>0.0</z></coordinates></vertex></vertices><volume><triangle><v1>0</v1><v2>1</v2><v3>2</v3></triangle></volume></mesh></object></amf>
- aspect_ratio(v=None)[source]¶
Set or get the preferred aspect ratio.
INPUT:
v
– (default:None
) must be a list or tuple of length three, or the integer1
. If no arguments are provided then the default aspect ratio is returned.
EXAMPLES:
sage: D = dodecahedron() sage: D.aspect_ratio() [1.0, 1.0, 1.0] sage: D.aspect_ratio([1,2,3]) sage: D.aspect_ratio() [1.0, 2.0, 3.0] sage: D.aspect_ratio(1) sage: D.aspect_ratio() [1.0, 1.0, 1.0]
>>> from sage.all import * >>> D = dodecahedron() >>> D.aspect_ratio() [1.0, 1.0, 1.0] >>> D.aspect_ratio([Integer(1),Integer(2),Integer(3)]) >>> D.aspect_ratio() [1.0, 2.0, 3.0] >>> D.aspect_ratio(Integer(1)) >>> D.aspect_ratio() [1.0, 1.0, 1.0]
- bounding_box()[source]¶
Return the lower and upper corners of a 3d bounding box.
This is used for rendering, and the scene should fit entirely within this box.
Specifically, the first point returned has x, y, and z coordinates that are the respective minimum over all points in the graphics, and the second point is the maximum.
The default return value is simply the box containing the origin.
EXAMPLES:
sage: sphere((1,1,1), 2).bounding_box() ((-1.0, -1.0, -1.0), (3.0, 3.0, 3.0)) sage: G = line3d([(1, 2, 3), (-1,-2,-3)]) sage: G.bounding_box() ((-1.0, -2.0, -3.0), (1.0, 2.0, 3.0))
>>> from sage.all import * >>> sphere((Integer(1),Integer(1),Integer(1)), Integer(2)).bounding_box() ((-1.0, -1.0, -1.0), (3.0, 3.0, 3.0)) >>> G = line3d([(Integer(1), Integer(2), Integer(3)), (-Integer(1),-Integer(2),-Integer(3))]) >>> G.bounding_box() ((-1.0, -2.0, -3.0), (1.0, 2.0, 3.0))
- default_render_params()[source]¶
Return an instance of RenderParams suitable for plotting this object.
EXAMPLES:
sage: type(dodecahedron().default_render_params()) <class 'sage.plot.plot3d.base.RenderParams'>
>>> from sage.all import * >>> type(dodecahedron().default_render_params()) <class 'sage.plot.plot3d.base.RenderParams'>
- export_jmol(filename='jmol_shape.jmol', force_reload=False, zoom=1, spin=False, background=(1, 1, 1), stereo=False, mesh=False, dots=False, perspective_depth=True, orientation=(-764, -346, -545, 76.39), **ignored_kwds)[source]¶
A jmol scene consists of a script which refers to external files. Fortunately, we are able to put all of them in a single zip archive, which is the output of this call.
EXAMPLES:
sage: out_file = tmp_filename(ext='.jmol') sage: G = sphere((1, 2, 3), 5) + cube() + sage.plot.plot3d.shapes.Text("hi") sage: G.export_jmol(out_file) sage: import zipfile sage: z = zipfile.ZipFile(out_file) sage: z.namelist() ['obj_...pmesh', 'SCRIPT'] sage: print(z.read('SCRIPT').decode('ascii')) data "model list" 2 empty Xx 0 0 0 Xx 5.5 5.5 5.5 end "model list"; show data select * wireframe off; spacefill off set labelOffset 0 0 background [255,255,255] spin OFF moveto 0 -764 -346 -545 76.39 centerAt absolute {0 0 0} zoom 100 frank OFF set perspectivedepth ON isosurface sphere_1 center {1.0 2.0 3.0} sphere 5.0 color isosurface [102,102,255] pmesh obj_... "obj_...pmesh" color pmesh [102,102,255] select atomno = 1 color atom [102,102,255] label "hi" isosurface fullylit; pmesh o* fullylit; set antialiasdisplay on; sage: print(z.read(z.namelist()[0]).decode('ascii')) 24 0.5 0.5 0.5 -0.5 0.5 0.5 ... -0.5 -0.5 -0.5 6 5 0 1 ...
>>> from sage.all import * >>> out_file = tmp_filename(ext='.jmol') >>> G = sphere((Integer(1), Integer(2), Integer(3)), Integer(5)) + cube() + sage.plot.plot3d.shapes.Text("hi") >>> G.export_jmol(out_file) >>> import zipfile >>> z = zipfile.ZipFile(out_file) >>> z.namelist() ['obj_...pmesh', 'SCRIPT'] >>> print(z.read('SCRIPT').decode('ascii')) data "model list" 2 empty Xx 0 0 0 Xx 5.5 5.5 5.5 end "model list"; show data select * wireframe off; spacefill off set labelOffset 0 0 background [255,255,255] spin OFF moveto 0 -764 -346 -545 76.39 centerAt absolute {0 0 0} zoom 100 frank OFF set perspectivedepth ON isosurface sphere_1 center {1.0 2.0 3.0} sphere 5.0 color isosurface [102,102,255] pmesh obj_... "obj_...pmesh" color pmesh [102,102,255] select atomno = 1 color atom [102,102,255] label "hi" isosurface fullylit; pmesh o* fullylit; set antialiasdisplay on; >>> print(z.read(z.namelist()[Integer(0)]).decode('ascii')) 24 0.5 0.5 0.5 -0.5 0.5 0.5 ... -0.5 -0.5 -0.5 6 5 0 1 ...
- flatten()[source]¶
Try to reduce the depth of the scene tree by consolidating groups and transformations.
The generic Graphics3d object cannot be made flatter.
EXAMPLES:
sage: G = sage.plot.plot3d.base.Graphics3d() sage: G.flatten() is G True
>>> from sage.all import * >>> G = sage.plot.plot3d.base.Graphics3d() >>> G.flatten() is G True
- frame_aspect_ratio(v=None)[source]¶
Set or get the preferred frame aspect ratio.
INPUT:
v
– (default:None
) must be a list or tuple of length three, or the integer1
. If no arguments are provided then the default frame aspect ratio is returned.
EXAMPLES:
sage: D = dodecahedron() sage: D.frame_aspect_ratio() [1.0, 1.0, 1.0] sage: D.frame_aspect_ratio([2,2,1]) sage: D.frame_aspect_ratio() [2.0, 2.0, 1.0] sage: D.frame_aspect_ratio(1) sage: D.frame_aspect_ratio() [1.0, 1.0, 1.0]
>>> from sage.all import * >>> D = dodecahedron() >>> D.frame_aspect_ratio() [1.0, 1.0, 1.0] >>> D.frame_aspect_ratio([Integer(2),Integer(2),Integer(1)]) >>> D.frame_aspect_ratio() [2.0, 2.0, 1.0] >>> D.frame_aspect_ratio(Integer(1)) >>> D.frame_aspect_ratio() [1.0, 1.0, 1.0]
- jmol_repr(render_params)[source]¶
A (possibly nested) list of strings which will be concatenated and used by jmol to render the object.
(Nested lists of strings are used because otherwise all the intermediate concatenations can kill performance). This may refer to several remove files, which are stored in render_parames.output_archive.
EXAMPLES:
sage: G = sage.plot.plot3d.base.Graphics3d() sage: G.jmol_repr(G.default_render_params()) [] sage: G = sphere((1, 2, 3)) sage: G.jmol_repr(G.default_render_params()) [['isosurface sphere_1 center {1.0 2.0 3.0} sphere 1.0\ncolor isosurface [102,102,255]']]
>>> from sage.all import * >>> G = sage.plot.plot3d.base.Graphics3d() >>> G.jmol_repr(G.default_render_params()) [] >>> G = sphere((Integer(1), Integer(2), Integer(3))) >>> G.jmol_repr(G.default_render_params()) [['isosurface sphere_1 center {1.0 2.0 3.0} sphere 1.0\ncolor isosurface [102,102,255]']]
- json_repr(render_params)[source]¶
A (possibly nested) list of strings. Each entry is formatted as JSON, so that a JavaScript client could eval it and get an object. Each object has fields to encapsulate the faces and vertices of the object. This representation is intended to be consumed by the canvas3d viewer backend.
EXAMPLES:
sage: G = sage.plot.plot3d.base.Graphics3d() sage: G.json_repr(G.default_render_params()) []
>>> from sage.all import * >>> G = sage.plot.plot3d.base.Graphics3d() >>> G.json_repr(G.default_render_params()) []
- mtl_str()[source]¶
Return the contents of a .mtl file, to be used to provide coloring information for an .obj file.
EXAMPLES:
sage: G = tetrahedron(color='red') + tetrahedron(color='yellow', opacity=0.5) sage: print(G.mtl_str()) newmtl ... Ka 0.5 5e-06 5e-06 Kd 1.0 1e-05 1e-05 Ks 0.0 0.0 0.0 illum 1 Ns 1.0 d 1.0 newmtl ... Ka 0.5 0.5 5e-06 Kd 1.0 1.0 1e-05 Ks 0.0 0.0 0.0 illum 1 Ns 1.0 d 0.5
>>> from sage.all import * >>> G = tetrahedron(color='red') + tetrahedron(color='yellow', opacity=RealNumber('0.5')) >>> print(G.mtl_str()) newmtl ... Ka 0.5 5e-06 5e-06 Kd 1.0 1e-05 1e-05 Ks 0.0 0.0 0.0 illum 1 Ns 1.0 d 1.0 newmtl ... Ka 0.5 0.5 5e-06 Kd 1.0 1.0 1e-05 Ks 0.0 0.0 0.0 illum 1 Ns 1.0 d 0.5
- obj()[source]¶
An .obj scene file (as a string) containing the this object.
A .mtl file of the same name must also be produced for coloring.
EXAMPLES:
sage: from sage.plot.plot3d.shapes import ColorCube sage: print(ColorCube(1, ['red', 'yellow', 'blue']).obj()) g obj_1 usemtl ... v 1 1 1 v -1 1 1 v -1 -1 1 v 1 -1 1 f 1 2 3 4 ... g obj_6 usemtl ... v -1 -1 1 v -1 1 1 v -1 1 -1 v -1 -1 -1 f 21 22 23 24
>>> from sage.all import * >>> from sage.plot.plot3d.shapes import ColorCube >>> print(ColorCube(Integer(1), ['red', 'yellow', 'blue']).obj()) g obj_1 usemtl ... v 1 1 1 v -1 1 1 v -1 -1 1 v 1 -1 1 f 1 2 3 4 ... g obj_6 usemtl ... v -1 -1 1 v -1 1 1 v -1 1 -1 v -1 -1 -1 f 21 22 23 24
- obj_repr(render_params)[source]¶
A (possibly nested) list of strings which will be concatenated and used to construct an .obj file of the object.
(Nested lists of strings are used because otherwise all the intermediate concatenations can kill performance). This may include a reference to color information which is stored elsewhere.
EXAMPLES:
sage: G = sage.plot.plot3d.base.Graphics3d() sage: G.obj_repr(G.default_render_params()) [] sage: G = cube() sage: G.obj_repr(G.default_render_params()) ['g obj_1', 'usemtl ...', ['v 0.5 0.5 0.5', 'v -0.5 0.5 0.5', 'v -0.5 -0.5 0.5', 'v 0.5 -0.5 0.5', 'v 0.5 0.5 -0.5', 'v -0.5 0.5 -0.5', 'v 0.5 -0.5 -0.5', 'v -0.5 -0.5 -0.5'], ['f 1 2 3 4', 'f 1 5 6 2', 'f 1 4 7 5', 'f 6 5 7 8', 'f 7 4 3 8', 'f 3 2 6 8'], []]
>>> from sage.all import * >>> G = sage.plot.plot3d.base.Graphics3d() >>> G.obj_repr(G.default_render_params()) [] >>> G = cube() >>> G.obj_repr(G.default_render_params()) ['g obj_1', 'usemtl ...', ['v 0.5 0.5 0.5', 'v -0.5 0.5 0.5', 'v -0.5 -0.5 0.5', 'v 0.5 -0.5 0.5', 'v 0.5 0.5 -0.5', 'v -0.5 0.5 -0.5', 'v 0.5 -0.5 -0.5', 'v -0.5 -0.5 -0.5'], ['f 1 2 3 4', 'f 1 5 6 2', 'f 1 4 7 5', 'f 6 5 7 8', 'f 7 4 3 8', 'f 3 2 6 8'], []]
- plot()[source]¶
Draw a 3D plot of this graphics object, which just returns this object since this is already a 3D graphics object. Needed to support PLOT in docstrings, see Issue #17498
EXAMPLES:
sage: S = sphere((0,0,0), 2) sage: S.plot() is S True
>>> from sage.all import * >>> S = sphere((Integer(0),Integer(0),Integer(0)), Integer(2)) >>> S.plot() is S True
- ply_ascii_string(name='surface')[source]¶
Return a PLY (Polygon File Format) representation of the surface.
INPUT:
name
– string (default:'surface'
); name of the surface
OUTPUT: string that represents the surface in the PLY format
See Wikipedia article PLY_(file_format).
EXAMPLES:
sage: # needs sage.symbolic sage: x,y,z = var('x,y,z') sage: a = implicit_plot3d(x^2+y^2+z^2-9,[x,-5,5],[y,-5,5],[z,-5,5]) sage: astl = a.ply_ascii_string() sage: astl.splitlines()[:10] ['ply', 'format ascii 1.0', 'comment surface', 'element vertex 15540', 'property float x', 'property float y', 'property float z', 'element face 5180', 'property list uchar int vertex_indices', 'end_header'] sage: p = polygon3d([[0,0,0], [1,2,3], [3,0,0]]) sage: print(p.ply_ascii_string(name='triangle')) ply format ascii 1.0 comment triangle element vertex 3 property float x property float y property float z element face 1 property list uchar int vertex_indices end_header 0.0 0.0 0.0 1.0 2.0 3.0 3.0 0.0 0.0 3 0 1 2
>>> from sage.all import * >>> # needs sage.symbolic >>> x,y,z = var('x,y,z') >>> a = implicit_plot3d(x**Integer(2)+y**Integer(2)+z**Integer(2)-Integer(9),[x,-Integer(5),Integer(5)],[y,-Integer(5),Integer(5)],[z,-Integer(5),Integer(5)]) >>> astl = a.ply_ascii_string() >>> astl.splitlines()[:Integer(10)] ['ply', 'format ascii 1.0', 'comment surface', 'element vertex 15540', 'property float x', 'property float y', 'property float z', 'element face 5180', 'property list uchar int vertex_indices', 'end_header'] >>> p = polygon3d([[Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(2),Integer(3)], [Integer(3),Integer(0),Integer(0)]]) >>> print(p.ply_ascii_string(name='triangle')) ply format ascii 1.0 comment triangle element vertex 3 property float x property float y property float z element face 1 property list uchar int vertex_indices end_header 0.0 0.0 0.0 1.0 2.0 3.0 3.0 0.0 0.0 3 0 1 2
- rotate(v, theta)[source]¶
Return the object rotated about the vector \(v\) by \(\theta\) radians.
EXAMPLES:
sage: from math import pi sage: from sage.plot.plot3d.shapes import Cone sage: v = (1,2,3) sage: G = arrow3d((0, 0, 0), v) sage: G += Cone(1/5, 1).translate((0, 0, 2)) sage: C = Cone(1/5, 1, opacity=.25).translate((0, 0, 2)) sage: G += sum(C.rotate(v, pi*t/4) for t in [1..7]) sage: G.show(aspect_ratio=1) sage: from sage.plot.plot3d.shapes import Box sage: Box(1/3, 1/5, 1/7).rotate((1, 1, 1), pi/3).show(aspect_ratio=1)
>>> from sage.all import * >>> from math import pi >>> from sage.plot.plot3d.shapes import Cone >>> v = (Integer(1),Integer(2),Integer(3)) >>> G = arrow3d((Integer(0), Integer(0), Integer(0)), v) >>> G += Cone(Integer(1)/Integer(5), Integer(1)).translate((Integer(0), Integer(0), Integer(2))) >>> C = Cone(Integer(1)/Integer(5), Integer(1), opacity=RealNumber('.25')).translate((Integer(0), Integer(0), Integer(2))) >>> G += sum(C.rotate(v, pi*t/Integer(4)) for t in (ellipsis_range(Integer(1),Ellipsis,Integer(7)))) >>> G.show(aspect_ratio=Integer(1)) >>> from sage.plot.plot3d.shapes import Box >>> Box(Integer(1)/Integer(3), Integer(1)/Integer(5), Integer(1)/Integer(7)).rotate((Integer(1), Integer(1), Integer(1)), pi/Integer(3)).show(aspect_ratio=Integer(1))
- rotateX(theta)[source]¶
Return the object rotated about the \(x\)-axis by the given angle.
EXAMPLES:
sage: from math import pi sage: from sage.plot.plot3d.shapes import Cone sage: G = Cone(1/5, 1) + Cone(1/5, 1, opacity=.25).rotateX(pi/2) sage: G.show(aspect_ratio=1)
>>> from sage.all import * >>> from math import pi >>> from sage.plot.plot3d.shapes import Cone >>> G = Cone(Integer(1)/Integer(5), Integer(1)) + Cone(Integer(1)/Integer(5), Integer(1), opacity=RealNumber('.25')).rotateX(pi/Integer(2)) >>> G.show(aspect_ratio=Integer(1))
- rotateY(theta)[source]¶
Return the object rotated about the \(y\)-axis by the given angle.
EXAMPLES:
sage: from math import pi sage: from sage.plot.plot3d.shapes import Cone sage: G = Cone(1/5, 1) + Cone(1/5, 1, opacity=.25).rotateY(pi/3) sage: G.show(aspect_ratio=1)
>>> from sage.all import * >>> from math import pi >>> from sage.plot.plot3d.shapes import Cone >>> G = Cone(Integer(1)/Integer(5), Integer(1)) + Cone(Integer(1)/Integer(5), Integer(1), opacity=RealNumber('.25')).rotateY(pi/Integer(3)) >>> G.show(aspect_ratio=Integer(1))
- rotateZ(theta)[source]¶
Return the object rotated about the \(z\)-axis by the given angle.
EXAMPLES:
sage: from math import pi sage: from sage.plot.plot3d.shapes import Box sage: G = Box(1/2, 1/3, 1/5) + Box(1/2, 1/3, 1/5, opacity=.25).rotateZ(pi/5) sage: G.show(aspect_ratio=1)
>>> from sage.all import * >>> from math import pi >>> from sage.plot.plot3d.shapes import Box >>> G = Box(Integer(1)/Integer(2), Integer(1)/Integer(3), Integer(1)/Integer(5)) + Box(Integer(1)/Integer(2), Integer(1)/Integer(3), Integer(1)/Integer(5), opacity=RealNumber('.25')).rotateZ(pi/Integer(5)) >>> G.show(aspect_ratio=Integer(1))
- save(filename, **kwds)[source]¶
Save the graphic in a file.
The file type depends on the file extension you give in the filename. This can be either:
an image file (of type: PNG, BMP, GIF, PPM, or TIFF) rendered using Jmol (default) or Tachyon,
a Sage object file (of type
.sobj
) that you can load back later (a pickle),an HTML file depicting the graphic using the Three.js viewer,
a data file (of type: X3D, STL, AMF, PLY) for export and use in other software.
For data files, the support is only partial. For instance STL and AMF only works for triangulated surfaces. The prefered format is X3D.
INPUT:
filename
– string; where to save the image or object**kwds
– when specifying an image file to be rendered by Tachyon or Jmol, any of the viewing options accepted byshow()
are valid as keyword arguments to this function and they will behave in the same way. Accepted keywords include:viewer
,verbosity
,figsize
,aspect_ratio
,frame_aspect_ratio
,zoom
,frame
, andaxes
. Default values are provided.
EXAMPLES:
sage: f = tmp_filename(ext='.png') sage: G = sphere() sage: G.save(f)
>>> from sage.all import * >>> f = tmp_filename(ext='.png') >>> G = sphere() >>> G.save(f)
We demonstrate using keyword arguments to control the appearance of the output image:
sage: G.save(f, zoom=2, figsize=[5, 10])
>>> from sage.all import * >>> G.save(f, zoom=Integer(2), figsize=[Integer(5), Integer(10)])
Using Tachyon instead of the default viewer (Jmol) to create the image:
sage: G.save(f, viewer='tachyon')
>>> from sage.all import * >>> G.save(f, viewer='tachyon')
Since Tachyon only outputs PNG images, PIL will be used to convert to alternate formats:
sage: cube().save(tmp_filename(ext='.gif'), viewer='tachyon')
>>> from sage.all import * >>> cube().save(tmp_filename(ext='.gif'), viewer='tachyon')
Here is how to save in one of the data formats:
sage: f = tmp_filename(ext='.x3d') sage: cube().save(f) sage: open(f).read().splitlines()[7] "<Shape><Box size='0.5 0.5 0.5'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape>"
>>> from sage.all import * >>> f = tmp_filename(ext='.x3d') >>> cube().save(f) >>> open(f).read().splitlines()[Integer(7)] "<Shape><Box size='0.5 0.5 0.5'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape>"
Producing a Three.js-based HTML file:
sage: f = tmp_filename(ext='.html') sage: G.save(f, frame=False, online=True)
>>> from sage.all import * >>> f = tmp_filename(ext='.html') >>> G.save(f, frame=False, online=True)
- save_image(filename, **kwds)[source]¶
Save a 2-D image rendering.
The image type is determined by the extension of the filename. For example, this could be
.png
,.jpg
,.gif
,.pdf
,.svg
.INPUT:
filename
– string; the file name under which to save the image
Any further keyword arguments are passed to the renderer.
EXAMPLES:
sage: G = sphere() sage: png = tmp_filename(ext='.png') sage: G.save_image(png) sage: with open(png, 'rb') as fobj: ....: assert fobj.read().startswith(b'\x89PNG') sage: gif = tmp_filename(ext='.gif') sage: G.save_image(gif) sage: with open(gif, 'rb') as fobj: ....: assert fobj.read().startswith(b'GIF')
>>> from sage.all import * >>> G = sphere() >>> png = tmp_filename(ext='.png') >>> G.save_image(png) >>> with open(png, 'rb') as fobj: ... assert fobj.read().startswith(b'\x89PNG') >>> gif = tmp_filename(ext='.gif') >>> G.save_image(gif) >>> with open(gif, 'rb') as fobj: ... assert fobj.read().startswith(b'GIF')
- scale(*x)[source]¶
Return the object scaled in the x, y, and z directions.
EXAMPLES:
sage: G = dodecahedron() + dodecahedron(opacity=.5).scale(2) sage: G.show(aspect_ratio=1) sage: G = icosahedron() + icosahedron(opacity=.5).scale([1, 1/2, 2]) sage: G.show(aspect_ratio=1)
>>> from sage.all import * >>> G = dodecahedron() + dodecahedron(opacity=RealNumber('.5')).scale(Integer(2)) >>> G.show(aspect_ratio=Integer(1)) >>> G = icosahedron() + icosahedron(opacity=RealNumber('.5')).scale([Integer(1), Integer(1)/Integer(2), Integer(2)]) >>> G.show(aspect_ratio=Integer(1))
- show(**kwds)[source]¶
Display graphics immediately.
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.
INPUT:
viewer
– string (default:'threejs'
); how to view the plot. Admissible values are'threejs'
: interactive web-based 3D viewer using JavaScript and a WebGL renderer'jmol'
: interactive 3D viewer using Java'tachyon'
: ray tracer generating a static PNG image; can produce high-resolution graphics, but does not show any text labels'canvas3d'
: web-based 3D viewer using JavaScript and a canvas renderer (Sage notebook only)
verbosity
– display information about rendering the figurefigsize
– (default: 5) x or pair [x,y] for numbers, e.g., [5,5]; controls the size of the output figure. With ‘tachyon’, the resolution (in number of pixels) is 100 timesfigsize
. This is ignored for the jmol embedded renderer.aspect_ratio
– (default:'automatic'
) aspect ratio of the coordinate system itself; give [1,1,1] or 1 to make spheres look roundframe_aspect_ratio
– (default:'automatic'
) aspect ratio of frame that contains the 3d scenezoom
– (default: 1) how zoomed inframe
– boolean (default:True
); ifTrue
, draw a bounding frame with labelsaxes
– boolean (default:False
); ifTrue
, draw coordinate axescamera_position
– (for tachyon) (default: (2.3, 2.4, 2.0)) the viewpoint, with respect to the cube $[-1,1]\times[-1,1]\times[-1,1]$, into which the bounding box of the scene is scaled and centered. The default viewing direction is towards the origin.viewdir
– (for tachyon) (default:None
) three coordinates specifying the viewing directionupdir
– (for tachyon) (default: (0,0,1)) the “upward” direction of the cameralight_position
– (for tachyon) (default: (4,3,2)) the position of the single light source in the scene (in addition to ambient light)antialiasing
– (for tachyon) (default:False
)raydepth
– (for tachyon) (default: 8) see thesage.plot.plot3d.tachyon.Tachyon
classshade
– (for tachyon) string (default:'full'
); shading options. Admissible values are'full'
: best quality rendering (and slowest). Sets tachyon command line flag-fullshade
.'medium
: good quality rendering, but no shadows. Sets tachyon command line flag-mediumshade
.'low'
: low quality rendering, preview (and fast). Sets tachyon command line flag-lowshade
.'lowest'
: worst quality rendering, preview (and fastest). Sets tachyon command line flag-lowestshade
.
extra_opts
– (for tachyon) string (default: empty string); extra options that will be appended to the tachyon command line**kwds
– other options, which make sense for particular rendering engines
OUTPUT:
This method does not return anything. Use
save()
if you want to save the figure as an image file.Warning
By default, the jmol and tachyon viewers perform some non-uniform scaling of the axes.
If this is not desired, one can set
aspect_ratio=1
:sage: p = plot3d(lambda u,v:(cos(u)-cos(v)), (-0.2,0.2),(-0.2,0.2)) sage: p.show(viewer='threejs') sage: p.show(viewer='jmol') sage: p.show(viewer='jmol',aspect_ratio=1) sage: p.show(viewer='tachyon',camera_position=(4,0,0)) sage: p.show(viewer='tachyon',camera_position=(2,2,0.3),aspect_ratio=1)
>>> from sage.all import * >>> p = plot3d(lambda u,v:(cos(u)-cos(v)), (-RealNumber('0.2'),RealNumber('0.2')),(-RealNumber('0.2'),RealNumber('0.2'))) >>> p.show(viewer='threejs') >>> p.show(viewer='jmol') >>> p.show(viewer='jmol',aspect_ratio=Integer(1)) >>> p.show(viewer='tachyon',camera_position=(Integer(4),Integer(0),Integer(0))) >>> p.show(viewer='tachyon',camera_position=(Integer(2),Integer(2),RealNumber('0.3')),aspect_ratio=Integer(1))
CHANGING DEFAULTS: Defaults can be uniformly changed by importing a dictionary and changing it. For example, here we change the default so images display without a frame instead of with one:
sage: from sage.plot.plot3d.base import SHOW_DEFAULTS sage: SHOW_DEFAULTS['frame'] = False
>>> from sage.all import * >>> from sage.plot.plot3d.base import SHOW_DEFAULTS >>> SHOW_DEFAULTS['frame'] = False
This sphere will not have a frame around it:
sage: sphere((0,0,0)) Graphics3d Object
>>> from sage.all import * >>> sphere((Integer(0),Integer(0),Integer(0))) Graphics3d Object
We change the default back:
sage: SHOW_DEFAULTS['frame'] = True
>>> from sage.all import * >>> SHOW_DEFAULTS['frame'] = True
Now this sphere is enclosed in a frame:
sage: sphere((0,0,0)) Graphics3d Object
>>> from sage.all import * >>> sphere((Integer(0),Integer(0),Integer(0))) Graphics3d Object
EXAMPLES: We illustrate use of the
aspect_ratio
option:sage: x, y = var('x,y') # needs sage.symbolic sage: p = plot3d(2*sin(x*y), (x, -pi, pi), (y, -pi, pi)) # needs sage.symbolic sage: p.show(aspect_ratio=[1,1,1]) # needs sage.symbolic
>>> from sage.all import * >>> x, y = var('x,y') # needs sage.symbolic >>> p = plot3d(Integer(2)*sin(x*y), (x, -pi, pi), (y, -pi, pi)) # needs sage.symbolic >>> p.show(aspect_ratio=[Integer(1),Integer(1),Integer(1)]) # needs sage.symbolic
This looks flattened, but filled with the plot:
sage: p.show(frame_aspect_ratio=[1,1,1/16]) # needs sage.symbolic
>>> from sage.all import * >>> p.show(frame_aspect_ratio=[Integer(1),Integer(1),Integer(1)/Integer(16)]) # needs sage.symbolic
This looks flattened, but the plot is square and smaller:
sage: p.show(aspect_ratio=[1,1,1], frame_aspect_ratio=[1,1,1/8]) # needs sage.symbolic
>>> from sage.all import * >>> p.show(aspect_ratio=[Integer(1),Integer(1),Integer(1)], frame_aspect_ratio=[Integer(1),Integer(1),Integer(1)/Integer(8)]) # needs sage.symbolic
This example shows indirectly that the defaults from
plot()
are dealt with properly:sage: plot(vector([1,2,3])) Graphics3d Object
>>> from sage.all import * >>> plot(vector([Integer(1),Integer(2),Integer(3)])) Graphics3d Object
We use the ‘canvas3d’ backend from inside the notebook to get a view of the plot rendered inline using HTML canvas:
sage: p.show(viewer='canvas3d') # needs sage.symbolic
>>> from sage.all import * >>> p.show(viewer='canvas3d') # needs sage.symbolic
Sometimes shadows in Tachyon-produced images can lead to confusing plots. To remove them:
sage: p.show(viewer='tachyon', shade='medium') # needs sage.symbolic
>>> from sage.all import * >>> p.show(viewer='tachyon', shade='medium') # needs sage.symbolic
One can also pass Tachyon command line flags directly. For example, the following line produces the same result as the previous one:
sage: p.show(viewer='tachyon', extra_opts='-mediumshade') # needs sage.symbolic
>>> from sage.all import * >>> p.show(viewer='tachyon', extra_opts='-mediumshade') # needs sage.symbolic
- stl_ascii_string(name='surface')[source]¶
Return an STL (STereoLithography) representation of the surface.
Warning
This only works for surfaces, not for general plot objects!
INPUT:
name
– string (default:'surface'
); name of the surface
OUTPUT: string that represents the surface in the STL format
See Wikipedia article STL_(file_format)
See also
EXAMPLES:
sage: # needs sage.symbolic sage: x,y,z = var('x,y,z') sage: a = implicit_plot3d(x^2+y^2+z^2-9,[x,-5,5],[y,-5,5],[z,-5,5]) sage: astl = a.stl_ascii_string() sage: astl.splitlines()[:7] # abs tol 1e-10 ['solid surface', 'facet normal 0.9733285267845754 -0.16222142113076257 -0.16222142113076257', ' outer loop', ' vertex 2.94871794872 -0.384615384615 -0.39358974359', ' vertex 2.95021367521 -0.384615384615 -0.384615384615', ' vertex 2.94871794872 -0.39358974359 -0.384615384615', ' endloop'] sage: p = polygon3d([[0,0,0], [1,2,3], [3,0,0]]) sage: print(p.stl_ascii_string(name='triangle')) solid triangle facet normal 0.0 0.8320502943378436 -0.5547001962252291 outer loop vertex 0.0 0.0 0.0 vertex 1.0 2.0 3.0 vertex 3.0 0.0 0.0 endloop endfacet endsolid triangle
>>> from sage.all import * >>> # needs sage.symbolic >>> x,y,z = var('x,y,z') >>> a = implicit_plot3d(x**Integer(2)+y**Integer(2)+z**Integer(2)-Integer(9),[x,-Integer(5),Integer(5)],[y,-Integer(5),Integer(5)],[z,-Integer(5),Integer(5)]) >>> astl = a.stl_ascii_string() >>> astl.splitlines()[:Integer(7)] # abs tol 1e-10 ['solid surface', 'facet normal 0.9733285267845754 -0.16222142113076257 -0.16222142113076257', ' outer loop', ' vertex 2.94871794872 -0.384615384615 -0.39358974359', ' vertex 2.95021367521 -0.384615384615 -0.384615384615', ' vertex 2.94871794872 -0.39358974359 -0.384615384615', ' endloop'] >>> p = polygon3d([[Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(2),Integer(3)], [Integer(3),Integer(0),Integer(0)]]) >>> print(p.stl_ascii_string(name='triangle')) solid triangle facet normal 0.0 0.8320502943378436 -0.5547001962252291 outer loop vertex 0.0 0.0 0.0 vertex 1.0 2.0 3.0 vertex 3.0 0.0 0.0 endloop endfacet endsolid triangle
Now works when faces have more then 3 sides:
sage: # needs sage.geometry.polyhedron sage.groups sage: P = polytopes.dodecahedron() sage: Q = P.plot().all[-1] sage: print(Q.stl_ascii_string().splitlines()[:7]) ['solid surface', 'facet normal 0.0 0.5257311121191338 0.8506508083520399', ' outer loop', ' vertex -0.7639320225002102 0.7639320225002102 0.7639320225002102', ' vertex -0.4721359549995796 0.0 1.2360679774997898', ' vertex 0.4721359549995796 0.0 1.2360679774997898', ' endloop']
>>> from sage.all import * >>> # needs sage.geometry.polyhedron sage.groups >>> P = polytopes.dodecahedron() >>> Q = P.plot().all[-Integer(1)] >>> print(Q.stl_ascii_string().splitlines()[:Integer(7)]) ['solid surface', 'facet normal 0.0 0.5257311121191338 0.8506508083520399', ' outer loop', ' vertex -0.7639320225002102 0.7639320225002102 0.7639320225002102', ' vertex -0.4721359549995796 0.0 1.2360679774997898', ' vertex 0.4721359549995796 0.0 1.2360679774997898', ' endloop']
- stl_binary()[source]¶
Return an STL (STereoLithography) binary representation of the surface.
Warning
This only works for surfaces, transforms and unions of surfaces, but not for general plot objects!
OUTPUT: a binary string that represents the surface in the binary STL format
See Wikipedia article STL_(file_format)
See also
EXAMPLES:
sage: # needs sage.symbolic sage: x,y,z = var('x,y,z') sage: a = implicit_plot3d(x^2+y^2+z^2-9,[x,-5,5],[y,-5,5],[z,-5,5]) sage: astl = a.stl_binary() sage: print(astl[:40].decode('ascii')) STL binary file / made by SageMath / ### sage: p = polygon3d([[0,0,0], [1,2,3], [3,0,0]]) sage: print(p.stl_binary()[:40].decode('ascii')) STL binary file / made by SageMath / ###
>>> from sage.all import * >>> # needs sage.symbolic >>> x,y,z = var('x,y,z') >>> a = implicit_plot3d(x**Integer(2)+y**Integer(2)+z**Integer(2)-Integer(9),[x,-Integer(5),Integer(5)],[y,-Integer(5),Integer(5)],[z,-Integer(5),Integer(5)]) >>> astl = a.stl_binary() >>> print(astl[:Integer(40)].decode('ascii')) STL binary file / made by SageMath / ### >>> p = polygon3d([[Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(2),Integer(3)], [Integer(3),Integer(0),Integer(0)]]) >>> print(p.stl_binary()[:Integer(40)].decode('ascii')) STL binary file / made by SageMath / ###
This works when faces have more then 3 sides:
sage: # needs sage.geometry.polyhedron sage.groups sage: P = polytopes.dodecahedron() sage: Q = P.plot().all[-1] sage: print(Q.stl_binary()[:40].decode('ascii')) STL binary file / made by SageMath / ###
>>> from sage.all import * >>> # needs sage.geometry.polyhedron sage.groups >>> P = polytopes.dodecahedron() >>> Q = P.plot().all[-Integer(1)] >>> print(Q.stl_binary()[:Integer(40)].decode('ascii')) STL binary file / made by SageMath / ###
- tachyon(zoom=1.0, antialiasing=False, figsize=[5, 5], raydepth=8, camera_position=[2.3, 2.4, 2.0], updir=[0, 0, 1], light_position=[4.0, 3.0, 2.0], viewdir=None)[source]¶
A tachyon input file (as a string) containing the this object.
EXAMPLES:
sage: print(sphere((1, 2, 3), 5, color='yellow').tachyon()) begin_scene resolution 500 500 camera ... plane center -592.870151560437 618.647114671761 -515.539262226467 normal -2.3 2.4 -2.0 TEXTURE AMBIENT 1.0 DIFFUSE 0.0 SPECULAR 0.0 OPACITY 1.0 COLOR 1.0 1.0 1.0 TEXFUNC 0 Texdef texture... Ambient 0.3333333333333333 Diffuse 0.6666666666666666 Specular 0.0 Opacity 1.0 Color 1.0 1.0 0.0 TexFunc 0 Sphere center 1.0 -2.0 3.0 Rad 5.0 texture... end_scene sage: G = icosahedron(color='red') + sphere((1,2,3), 0.5, color='yellow') sage: G.show(viewer='tachyon', frame=false) sage: print(G.tachyon()) begin_scene ... Texdef texture... Ambient 0.3333333333333333 Diffuse 0.6666666666666666 Specular 0.0 Opacity 1.0 Color 1.0 1.0 0.0 TexFunc 0 TRI V0 ... Sphere center 1.0 -2.0 3.0 Rad 0.5 texture... end_scene
>>> from sage.all import * >>> print(sphere((Integer(1), Integer(2), Integer(3)), Integer(5), color='yellow').tachyon()) <BLANKLINE> begin_scene resolution 500 500 <BLANKLINE> camera ... plane center -592.870151560437 618.647114671761 -515.539262226467 normal -2.3 2.4 -2.0 TEXTURE AMBIENT 1.0 DIFFUSE 0.0 SPECULAR 0.0 OPACITY 1.0 COLOR 1.0 1.0 1.0 TEXFUNC 0 <BLANKLINE> Texdef texture... Ambient 0.3333333333333333 Diffuse 0.6666666666666666 Specular 0.0 Opacity 1.0 Color 1.0 1.0 0.0 TexFunc 0 <BLANKLINE> Sphere center 1.0 -2.0 3.0 Rad 5.0 texture... <BLANKLINE> end_scene >>> G = icosahedron(color='red') + sphere((Integer(1),Integer(2),Integer(3)), RealNumber('0.5'), color='yellow') >>> G.show(viewer='tachyon', frame=false) >>> print(G.tachyon()) begin_scene ... Texdef texture... Ambient 0.3333333333333333 Diffuse 0.6666666666666666 Specular 0.0 Opacity 1.0 Color 1.0 1.0 0.0 TexFunc 0 TRI V0 ... Sphere center 1.0 -2.0 3.0 Rad 0.5 texture... end_scene
- tachyon_keywords = ('antialiasing', 'zoom', 'raydepth', 'figsize', 'light_position', 'camera_position', 'updir', 'viewdir')¶
- tachyon_repr(render_params)[source]¶
A (possibly nested) list of strings which will be concatenated and used by tachyon to render the object.
(Nested lists of strings are used because otherwise all the intermediate concatenations can kill performance). This may include a reference to color information which is stored elsewhere.
EXAMPLES:
sage: G = sage.plot.plot3d.base.Graphics3d() sage: G.tachyon_repr(G.default_render_params()) [] sage: G = sphere((1, 2, 3)) sage: G.tachyon_repr(G.default_render_params()) ['Sphere center 1.0 2.0 3.0 Rad 1.0 texture...']
>>> from sage.all import * >>> G = sage.plot.plot3d.base.Graphics3d() >>> G.tachyon_repr(G.default_render_params()) [] >>> G = sphere((Integer(1), Integer(2), Integer(3))) >>> G.tachyon_repr(G.default_render_params()) ['Sphere center 1.0 2.0 3.0 Rad 1.0 texture...']
- testing_render_params()[source]¶
Return an instance of RenderParams suitable for testing this object.
In particular, it opens up a temporary file as an auxiliary zip file for jmol.
EXAMPLES:
sage: type(dodecahedron().testing_render_params()) <class 'sage.plot.plot3d.base.RenderParams'>
>>> from sage.all import * >>> type(dodecahedron().testing_render_params()) <class 'sage.plot.plot3d.base.RenderParams'>
- texture_set()[source]¶
Often the textures of a 3d file format are kept separate from the objects themselves. This function returns the set of textures used, so they can be defined in a preamble or separate file.
EXAMPLES:
sage: sage.plot.plot3d.base.Graphics3d().texture_set() set() sage: G = tetrahedron(color='red') + tetrahedron(color='yellow') + tetrahedron(color='red', opacity=0.5) sage: [t for t in G.texture_set() if t.color == colors.red] # we should have two red textures [Texture(texture..., red, ff0000), Texture(texture..., red, ff0000)] sage: [t for t in G.texture_set() if t.color == colors.yellow] # ...and one yellow [Texture(texture..., yellow, ffff00)]
>>> from sage.all import * >>> sage.plot.plot3d.base.Graphics3d().texture_set() set() >>> G = tetrahedron(color='red') + tetrahedron(color='yellow') + tetrahedron(color='red', opacity=RealNumber('0.5')) >>> [t for t in G.texture_set() if t.color == colors.red] # we should have two red textures [Texture(texture..., red, ff0000), Texture(texture..., red, ff0000)] >>> [t for t in G.texture_set() if t.color == colors.yellow] # ...and one yellow [Texture(texture..., yellow, ffff00)]
- threejs_repr(render_params)[source]¶
A flat list of
(kind, desc)
tuples wherekind
is one of: ‘point’, ‘line’, ‘text’, or ‘surface’; and wheredesc
is a dictionary describing a point, line, text, or surface.EXAMPLES:
sage: G = sage.plot.plot3d.base.Graphics3d() sage: G.threejs_repr(G.default_render_params()) []
>>> from sage.all import * >>> G = sage.plot.plot3d.base.Graphics3d() >>> G.threejs_repr(G.default_render_params()) []
- transform(**kwds)[source]¶
Apply a transformation, where the inputs are passed onto a TransformGroup object.
Mostly for internal use; see the translate, scale, and rotate methods for more details.
EXAMPLES:
sage: sphere((0,0,0), 1).transform(trans=(1, 0, 0), scale=(2,3,4)).bounding_box() ((-1.0, -3.0, -4.0), (3.0, 3.0, 4.0))
>>> from sage.all import * >>> sphere((Integer(0),Integer(0),Integer(0)), Integer(1)).transform(trans=(Integer(1), Integer(0), Integer(0)), scale=(Integer(2),Integer(3),Integer(4))).bounding_box() ((-1.0, -3.0, -4.0), (3.0, 3.0, 4.0))
- translate(*x)[source]¶
Return the object translated by the given vector (which can be given either as a 3-iterable or via positional arguments).
EXAMPLES:
sage: icosahedron() + sum(icosahedron(opacity=0.25).translate(2*n, 0, 0) for n in [1..4]) Graphics3d Object sage: icosahedron() + sum(icosahedron(opacity=0.25).translate([-2*n, n, n^2]) for n in [1..4]) Graphics3d Object
>>> from sage.all import * >>> icosahedron() + sum(icosahedron(opacity=RealNumber('0.25')).translate(Integer(2)*n, Integer(0), Integer(0)) for n in (ellipsis_range(Integer(1),Ellipsis,Integer(4)))) Graphics3d Object >>> icosahedron() + sum(icosahedron(opacity=RealNumber('0.25')).translate([-Integer(2)*n, n, n**Integer(2)]) for n in (ellipsis_range(Integer(1),Ellipsis,Integer(4)))) Graphics3d Object
- viewpoint()[source]¶
Return the viewpoint of this plot.
Currently only a stub for x3d.
EXAMPLES:
sage: type(dodecahedron().viewpoint()) <class 'sage.plot.plot3d.base.Viewpoint'>
>>> from sage.all import * >>> type(dodecahedron().viewpoint()) <class 'sage.plot.plot3d.base.Viewpoint'>
- x3d()[source]¶
An x3d scene file (as a string) containing the this object.
EXAMPLES:
sage: print(sphere((1, 2, 3), 5).x3d()) <X3D version='3.0' profile='Immersive' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation=' http://www.web3d.org/specifications/x3d-3.0.xsd '> <head> <meta name='title' content='sage3d'/> </head> <Scene> <Viewpoint position='0 0 6'/> <Transform translation='1 2 3'> <Shape><Sphere radius='5.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform> </Scene> </X3D> sage: G = icosahedron() + sphere((0,0,0), 0.5, color='red') sage: print(G.x3d()) <X3D version='3.0' profile='Immersive' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation=' http://www.web3d.org/specifications/x3d-3.0.xsd '> <head> <meta name='title' content='sage3d'/> </head> <Scene> <Viewpoint position='0 0 6'/> <Shape> <IndexedFaceSet coordIndex='...'> <Coordinate point='...'/> </IndexedFaceSet> <Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> <Transform translation='0 0 0'> <Shape><Sphere radius='0.5'/><Appearance><Material diffuseColor='1.0 0.0 0.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform> </Scene> </X3D>
>>> from sage.all import * >>> print(sphere((Integer(1), Integer(2), Integer(3)), Integer(5)).x3d()) <X3D version='3.0' profile='Immersive' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation=' http://www.web3d.org/specifications/x3d-3.0.xsd '> <head> <meta name='title' content='sage3d'/> </head> <Scene> <Viewpoint position='0 0 6'/> <Transform translation='1 2 3'> <Shape><Sphere radius='5.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform> </Scene> </X3D> >>> G = icosahedron() + sphere((Integer(0),Integer(0),Integer(0)), RealNumber('0.5'), color='red') >>> print(G.x3d()) <X3D version='3.0' profile='Immersive' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation=' http://www.web3d.org/specifications/x3d-3.0.xsd '> <head> <meta name='title' content='sage3d'/> </head> <Scene> <Viewpoint position='0 0 6'/> <Shape> <IndexedFaceSet coordIndex='...'> <Coordinate point='...'/> </IndexedFaceSet> <Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> <Transform translation='0 0 0'> <Shape><Sphere radius='0.5'/><Appearance><Material diffuseColor='1.0 0.0 0.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform> </Scene> </X3D>
- class sage.plot.plot3d.base.Graphics3dGroup(all=(), rot=None, trans=None, scale=None, T=None)[source]¶
Bases:
Graphics3d
This class represents a collection of 3d objects. Usually they are formed implicitly by summing.
- bounding_box()[source]¶
Box that contains the bounding boxes of the objects.
EXAMPLES:
sage: A = sphere((0,0,0), 5) sage: B = sphere((1, 5, 10), 1) sage: A.bounding_box() ((-5.0, -5.0, -5.0), (5.0, 5.0, 5.0)) sage: B.bounding_box() ((0.0, 4.0, 9.0), (2.0, 6.0, 11.0)) sage: (A+B).bounding_box() ((-5.0, -5.0, -5.0), (5.0, 6.0, 11.0)) sage: (A+B).show(aspect_ratio=1, frame=True) sage: sage.plot.plot3d.base.Graphics3dGroup([]).bounding_box() ((0.0, 0.0, 0.0), (0.0, 0.0, 0.0))
>>> from sage.all import * >>> A = sphere((Integer(0),Integer(0),Integer(0)), Integer(5)) >>> B = sphere((Integer(1), Integer(5), Integer(10)), Integer(1)) >>> A.bounding_box() ((-5.0, -5.0, -5.0), (5.0, 5.0, 5.0)) >>> B.bounding_box() ((0.0, 4.0, 9.0), (2.0, 6.0, 11.0)) >>> (A+B).bounding_box() ((-5.0, -5.0, -5.0), (5.0, 6.0, 11.0)) >>> (A+B).show(aspect_ratio=Integer(1), frame=True) >>> sage.plot.plot3d.base.Graphics3dGroup([]).bounding_box() ((0.0, 0.0, 0.0), (0.0, 0.0, 0.0))
- flatten()[source]¶
Try to reduce the depth of the scene tree by consolidating groups and transformations.
EXAMPLES:
sage: G = sum([circle((0, 0), t) for t in [1..10]], sphere()); G Graphics3d Object sage: G.flatten() Graphics3d Object sage: len(G.all) 2 sage: len(G.flatten().all) 11
>>> from sage.all import * >>> G = sum([circle((Integer(0), Integer(0)), t) for t in (ellipsis_range(Integer(1),Ellipsis,Integer(10)))], sphere()); G Graphics3d Object >>> G.flatten() Graphics3d Object >>> len(G.all) 2 >>> len(G.flatten().all) 11
- jmol_repr(render_params)[source]¶
The jmol representation of a group is simply the concatenation of the representation of its objects.
EXAMPLES:
sage: G = sphere() + sphere((1,2,3)) sage: G.jmol_repr(G.default_render_params()) [[['isosurface sphere_1 center {0.0 0.0 0.0} sphere 1.0\ncolor isosurface [102,102,255]']], [['isosurface sphere_2 center {1.0 2.0 3.0} sphere 1.0\ncolor isosurface [102,102,255]']]]
>>> from sage.all import * >>> G = sphere() + sphere((Integer(1),Integer(2),Integer(3))) >>> G.jmol_repr(G.default_render_params()) [[['isosurface sphere_1 center {0.0 0.0 0.0} sphere 1.0\ncolor isosurface [102,102,255]']], [['isosurface sphere_2 center {1.0 2.0 3.0} sphere 1.0\ncolor isosurface [102,102,255]']]]
- json_repr(render_params)[source]¶
The JSON representation of a group is simply the concatenation of the representations of its objects.
EXAMPLES:
sage: G = sphere() + sphere((1, 2, 3)) sage: G.json_repr(G.default_render_params()) [[['{"vertices":...']], [['{"vertices":...']]]
>>> from sage.all import * >>> G = sphere() + sphere((Integer(1), Integer(2), Integer(3))) >>> G.json_repr(G.default_render_params()) [[['{"vertices":...']], [['{"vertices":...']]]
- obj_repr(render_params)[source]¶
The obj representation of a group is simply the concatenation of the representation of its objects.
EXAMPLES:
sage: G = tetrahedron() + tetrahedron().translate(10, 10, 10) sage: G.obj_repr(G.default_render_params()) [['g obj_1', 'usemtl ...', ['v 0 0 1', 'v 0.942809 0 -0.333333', 'v -0.471405 0.816497 -0.333333', 'v -0.471405 -0.816497 -0.333333'], ['f 1 2 3', 'f 2 4 3', 'f 1 3 4', 'f 1 4 2'], []], [['g obj_2', 'usemtl ...', ['v 10 10 11', 'v 10.9428 10 9.66667', 'v 9.5286 10.8165 9.66667', 'v 9.5286 9.1835 9.66667'], ['f 5 6 7', 'f 6 8 7', 'f 5 7 8', 'f 5 8 6'], []]]]
>>> from sage.all import * >>> G = tetrahedron() + tetrahedron().translate(Integer(10), Integer(10), Integer(10)) >>> G.obj_repr(G.default_render_params()) [['g obj_1', 'usemtl ...', ['v 0 0 1', 'v 0.942809 0 -0.333333', 'v -0.471405 0.816497 -0.333333', 'v -0.471405 -0.816497 -0.333333'], ['f 1 2 3', 'f 2 4 3', 'f 1 3 4', 'f 1 4 2'], []], [['g obj_2', 'usemtl ...', ['v 10 10 11', 'v 10.9428 10 9.66667', 'v 9.5286 10.8165 9.66667', 'v 9.5286 9.1835 9.66667'], ['f 5 6 7', 'f 6 8 7', 'f 5 7 8', 'f 5 8 6'], []]]]
- set_texture(**kwds)[source]¶
EXAMPLES:
sage: G = dodecahedron(color='red', opacity=.5) + icosahedron((3, 0, 0), color='blue') sage: G Graphics3d Object sage: G.set_texture(color='yellow') sage: G Graphics3d Object
>>> from sage.all import * >>> G = dodecahedron(color='red', opacity=RealNumber('.5')) + icosahedron((Integer(3), Integer(0), Integer(0)), color='blue') >>> G Graphics3d Object >>> G.set_texture(color='yellow') >>> G Graphics3d Object
- stl_binary_repr(render_params)[source]¶
The stl binary representation of a group is simply the concatenation of the representation of its objects.
The STL binary representation is a list of binary strings, one for each triangle.
EXAMPLES:
sage: G = sphere() + sphere((1,2,3)) sage: len(G.stl_binary_repr(G.default_render_params())) 2736
>>> from sage.all import * >>> G = sphere() + sphere((Integer(1),Integer(2),Integer(3))) >>> len(G.stl_binary_repr(G.default_render_params())) 2736
- tachyon_repr(render_params)[source]¶
The tachyon representation of a group is simply the concatenation of the representations of its objects.
EXAMPLES:
sage: G = sphere() + sphere((1,2,3)) sage: G.tachyon_repr(G.default_render_params()) [['Sphere center 0.0 0.0 0.0 Rad 1.0 texture...'], ['Sphere center 1.0 2.0 3.0 Rad 1.0 texture...']]
>>> from sage.all import * >>> G = sphere() + sphere((Integer(1),Integer(2),Integer(3))) >>> G.tachyon_repr(G.default_render_params()) [['Sphere center 0.0 0.0 0.0 Rad 1.0 texture...'], ['Sphere center 1.0 2.0 3.0 Rad 1.0 texture...']]
- texture_set()[source]¶
The texture set of a group is simply the union of the textures of all its objects.
EXAMPLES:
sage: G = sphere(color='red') + sphere(color='yellow') sage: [t for t in G.texture_set() if t.color == colors.red] # one red texture [Texture(texture..., red, ff0000)] sage: [t for t in G.texture_set() if t.color == colors.yellow] # one yellow texture [Texture(texture..., yellow, ffff00)] sage: T = sage.plot.plot3d.texture.Texture('blue'); T Texture(texture..., blue, 0000ff) sage: G = sphere(texture=T) + sphere((1, 1, 1), texture=T) sage: len(G.texture_set()) 1
>>> from sage.all import * >>> G = sphere(color='red') + sphere(color='yellow') >>> [t for t in G.texture_set() if t.color == colors.red] # one red texture [Texture(texture..., red, ff0000)] >>> [t for t in G.texture_set() if t.color == colors.yellow] # one yellow texture [Texture(texture..., yellow, ffff00)] >>> T = sage.plot.plot3d.texture.Texture('blue'); T Texture(texture..., blue, 0000ff) >>> G = sphere(texture=T) + sphere((Integer(1), Integer(1), Integer(1)), texture=T) >>> len(G.texture_set()) 1
- threejs_repr(render_params)[source]¶
The three.js representation of a group is the concatenation of the representations of its objects.
EXAMPLES:
sage: G = point3d((1,2,3)) + point3d((4,5,6)) + line3d([(1,2,3), (4,5,6)]) sage: G.threejs_repr(G.default_render_params()) [('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (1.0, 2.0, 3.0), 'size': 5.0}), ('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (4.0, 5.0, 6.0), 'size': 5.0}), ('line', {'color': '#6666ff', 'linewidth': 1.0, 'opacity': 1.0, 'points': [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)]})]
>>> from sage.all import * >>> G = point3d((Integer(1),Integer(2),Integer(3))) + point3d((Integer(4),Integer(5),Integer(6))) + line3d([(Integer(1),Integer(2),Integer(3)), (Integer(4),Integer(5),Integer(6))]) >>> G.threejs_repr(G.default_render_params()) [('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (1.0, 2.0, 3.0), 'size': 5.0}), ('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (4.0, 5.0, 6.0), 'size': 5.0}), ('line', {'color': '#6666ff', 'linewidth': 1.0, 'opacity': 1.0, 'points': [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)]})]
- transform(**kwds)[source]¶
Transforming this entire group simply makes a transform group with the same contents.
EXAMPLES:
sage: G = dodecahedron(color='red', opacity=.5) + icosahedron(color='blue') sage: G Graphics3d Object sage: G.transform(scale=(2,1/2,1)) Graphics3d Object sage: G.transform(trans=(1,1,3)) Graphics3d Object
>>> from sage.all import * >>> G = dodecahedron(color='red', opacity=RealNumber('.5')) + icosahedron(color='blue') >>> G Graphics3d Object >>> G.transform(scale=(Integer(2),Integer(1)/Integer(2),Integer(1))) Graphics3d Object >>> G.transform(trans=(Integer(1),Integer(1),Integer(3))) Graphics3d Object
- x3d_str()[source]¶
The x3d representation of a group is simply the concatenation of the representation of its objects.
EXAMPLES:
sage: G = sphere() + sphere((1,2,3)) sage: print(G.x3d_str()) <Transform translation='0 0 0'> <Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform> <Transform translation='1 2 3'> <Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform>
>>> from sage.all import * >>> G = sphere() + sphere((Integer(1),Integer(2),Integer(3))) >>> print(G.x3d_str()) <Transform translation='0 0 0'> <Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform> <Transform translation='1 2 3'> <Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape> </Transform>
- class sage.plot.plot3d.base.KeyframeAnimationGroup(all=(), **kwds)[source]¶
Bases:
Graphics3dGroup
A group of objects, each depicting a single frame of animation
- threejs_repr(render_params)[source]¶
Add keyframe information to the representations of the group’s contents.
EXAMPLES:
sage: a = point3d((0, 0, 1)) sage: b = point3d((0, 1, 0)) sage: c = point3d((1, 0, 0)) sage: g = sage.plot.plot3d.base.KeyframeAnimationGroup([a, b, c]) sage: g.threejs_repr(g.default_render_params()) [('point', {..., 'keyframe': 0, ..., 'point': (0.0, 0.0, 1.0), ...}), ('point', {..., 'keyframe': 1, ..., 'point': (0.0, 1.0, 0.0), ...}), ('point', {..., 'keyframe': 2, ..., 'point': (1.0, 0.0, 0.0), ...})]
>>> from sage.all import * >>> a = point3d((Integer(0), Integer(0), Integer(1))) >>> b = point3d((Integer(0), Integer(1), Integer(0))) >>> c = point3d((Integer(1), Integer(0), Integer(0))) >>> g = sage.plot.plot3d.base.KeyframeAnimationGroup([a, b, c]) >>> g.threejs_repr(g.default_render_params()) [('point', {..., 'keyframe': 0, ..., 'point': (0.0, 0.0, 1.0), ...}), ('point', {..., 'keyframe': 1, ..., 'point': (0.0, 1.0, 0.0), ...}), ('point', {..., 'keyframe': 2, ..., 'point': (1.0, 0.0, 0.0), ...})]
Only top-level objects get a unique keyframe. Nested objects share the same keyframe:
sage: g = sage.plot.plot3d.base.KeyframeAnimationGroup([a + b, c]) sage: g.threejs_repr(g.default_render_params()) [('point', {..., 'keyframe': 0, ..., 'point': (0.0, 0.0, 1.0), ...}), ('point', {..., 'keyframe': 0, ..., 'point': (0.0, 1.0, 0.0), ...}), ('point', {..., 'keyframe': 1, ..., 'point': (1.0, 0.0, 0.0), ...})]
>>> from sage.all import * >>> g = sage.plot.plot3d.base.KeyframeAnimationGroup([a + b, c]) >>> g.threejs_repr(g.default_render_params()) [('point', {..., 'keyframe': 0, ..., 'point': (0.0, 0.0, 1.0), ...}), ('point', {..., 'keyframe': 0, ..., 'point': (0.0, 1.0, 0.0), ...}), ('point', {..., 'keyframe': 1, ..., 'point': (1.0, 0.0, 0.0), ...})]
- class sage.plot.plot3d.base.PrimitiveObject[source]¶
Bases:
Graphics3d
This is the base class for the non-container 3d objects.
- get_texture()[source]¶
EXAMPLES:
sage: G = dodecahedron(color='red') sage: G.get_texture() Texture(texture..., red, ff0000)
>>> from sage.all import * >>> G = dodecahedron(color='red') >>> G.get_texture() Texture(texture..., red, ff0000)
- jmol_repr(render_params)[source]¶
Default behavior is to render the triangulation. The actual polygon data is stored in a separate file.
EXAMPLES:
sage: from sage.plot.plot3d.shapes import Torus sage: G = Torus(1, .5) sage: G.jmol_repr(G.testing_render_params()) ['pmesh obj_1 "obj_1.pmesh"\ncolor pmesh [102,102,255]']
>>> from sage.all import * >>> from sage.plot.plot3d.shapes import Torus >>> G = Torus(Integer(1), RealNumber('.5')) >>> G.jmol_repr(G.testing_render_params()) ['pmesh obj_1 "obj_1.pmesh"\ncolor pmesh [102,102,255]']
- obj_repr(render_params)[source]¶
Default behavior is to render the triangulation.
EXAMPLES:
sage: from sage.plot.plot3d.shapes import Torus sage: G = Torus(1, .5) sage: G.obj_repr(G.default_render_params()) ['g obj_1', 'usemtl ...', ['v 0 1 0.5', ... 'f ...'], []]
>>> from sage.all import * >>> from sage.plot.plot3d.shapes import Torus >>> G = Torus(Integer(1), RealNumber('.5')) >>> G.obj_repr(G.default_render_params()) ['g obj_1', 'usemtl ...', ['v 0 1 0.5', ... 'f ...'], []]
- set_texture(texture=None, **kwds)[source]¶
EXAMPLES:
sage: G = dodecahedron(color='red'); G Graphics3d Object sage: G.set_texture(color='yellow'); G Graphics3d Object
>>> from sage.all import * >>> G = dodecahedron(color='red'); G Graphics3d Object >>> G.set_texture(color='yellow'); G Graphics3d Object
- tachyon_repr(render_params)[source]¶
Default behavior is to render the triangulation.
EXAMPLES:
sage: from sage.plot.plot3d.shapes import Torus sage: G = Torus(1, .5) sage: G.tachyon_repr(G.default_render_params()) ['TRI V0 0 1 0.5 ... 'texture...']
>>> from sage.all import * >>> from sage.plot.plot3d.shapes import Torus >>> G = Torus(Integer(1), RealNumber('.5')) >>> G.tachyon_repr(G.default_render_params()) ['TRI V0 0 1 0.5 ... 'texture...']
- texture_set()[source]¶
EXAMPLES:
sage: G = dodecahedron(color='red') sage: G.texture_set() {Texture(texture..., red, ff0000)}
>>> from sage.all import * >>> G = dodecahedron(color='red') >>> G.texture_set() {Texture(texture..., red, ff0000)}
- threejs_repr(render_params)[source]¶
Default behavior is to render the triangulation.
EXAMPLES:
sage: from sage.plot.plot3d.base import PrimitiveObject sage: class SimpleTriangle(PrimitiveObject): ....: def triangulation(self): ....: return polygon3d([(0,0,0), (1,0,0), (0,1,0)]) sage: G = SimpleTriangle() sage: G.threejs_repr(G.default_render_params()) [('surface', {'color': '#0000ff', 'faces': [[0, 1, 2]], 'opacity': 1.0, 'vertices': [{'x': 0.0, 'y': 0.0, 'z': 0.0}, {'x': 1.0, 'y': 0.0, 'z': 0.0}, {'x': 0.0, 'y': 1.0, 'z': 0.0}]})]
>>> from sage.all import * >>> from sage.plot.plot3d.base import PrimitiveObject >>> class SimpleTriangle(PrimitiveObject): ... def triangulation(self): ... return polygon3d([(Integer(0),Integer(0),Integer(0)), (Integer(1),Integer(0),Integer(0)), (Integer(0),Integer(1),Integer(0))]) >>> G = SimpleTriangle() >>> G.threejs_repr(G.default_render_params()) [('surface', {'color': '#0000ff', 'faces': [[0, 1, 2]], 'opacity': 1.0, 'vertices': [{'x': 0.0, 'y': 0.0, 'z': 0.0}, {'x': 1.0, 'y': 0.0, 'z': 0.0}, {'x': 0.0, 'y': 1.0, 'z': 0.0}]})]
- x3d_str()[source]¶
EXAMPLES:
sage: sphere().flatten().x3d_str() "<Transform>\n<Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape>\n\n</Transform>"
>>> from sage.all import * >>> sphere().flatten().x3d_str() "<Transform>\n<Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape>\n\n</Transform>"
- class sage.plot.plot3d.base.RenderParams(**kwds)[source]¶
Bases:
SageObject
This class is a container for all parameters that may be needed to render triangulate/render an object to a certain format. It can contain both cumulative and global parameters.
Of particular note is the transformation object, which holds the cumulative transformation from the root of the scene graph to this node in the tree.
- antialiasing = 8¶
- dots = False¶
- force_reload = False¶
- mesh = False¶
- pop_transform()[source]¶
Remove the last transformation off the stack, resetting self.transform to the previous value.
EXAMPLES:
sage: from sage.plot.plot3d.transform import Transformation sage: params = sage.plot.plot3d.base.RenderParams() sage: T = Transformation(trans=(100, 500, 0)) sage: params.push_transform(T) sage: params.transform.get_matrix() [ 1.0 0.0 0.0 100.0] [ 0.0 1.0 0.0 500.0] [ 0.0 0.0 1.0 0.0] [ 0.0 0.0 0.0 1.0] sage: params.push_transform(Transformation(trans=(-100, 500, 200))) sage: params.transform.get_matrix() [ 1.0 0.0 0.0 0.0] [ 0.0 1.0 0.0 1000.0] [ 0.0 0.0 1.0 200.0] [ 0.0 0.0 0.0 1.0] sage: params.pop_transform() sage: params.transform.get_matrix() [ 1.0 0.0 0.0 100.0] [ 0.0 1.0 0.0 500.0] [ 0.0 0.0 1.0 0.0] [ 0.0 0.0 0.0 1.0]
>>> from sage.all import * >>> from sage.plot.plot3d.transform import Transformation >>> params = sage.plot.plot3d.base.RenderParams() >>> T = Transformation(trans=(Integer(100), Integer(500), Integer(0))) >>> params.push_transform(T) >>> params.transform.get_matrix() [ 1.0 0.0 0.0 100.0] [ 0.0 1.0 0.0 500.0] [ 0.0 0.0 1.0 0.0] [ 0.0 0.0 0.0 1.0] >>> params.push_transform(Transformation(trans=(-Integer(100), Integer(500), Integer(200)))) >>> params.transform.get_matrix() [ 1.0 0.0 0.0 0.0] [ 0.0 1.0 0.0 1000.0] [ 0.0 0.0 1.0 200.0] [ 0.0 0.0 0.0 1.0] >>> params.pop_transform() >>> params.transform.get_matrix() [ 1.0 0.0 0.0 100.0] [ 0.0 1.0 0.0 500.0] [ 0.0 0.0 1.0 0.0] [ 0.0 0.0 0.0 1.0]
- push_transform(T)[source]¶
Push a transformation onto the stack, updating self.transform.
EXAMPLES:
sage: from sage.plot.plot3d.transform import Transformation sage: params = sage.plot.plot3d.base.RenderParams() sage: params.transform is None True sage: T = Transformation(scale=(10,20,30)) sage: params.push_transform(T) sage: params.transform.get_matrix() [10.0 0.0 0.0 0.0] [ 0.0 20.0 0.0 0.0] [ 0.0 0.0 30.0 0.0] [ 0.0 0.0 0.0 1.0] sage: params.push_transform(T) # scale again sage: params.transform.get_matrix() [100.0 0.0 0.0 0.0] [ 0.0 400.0 0.0 0.0] [ 0.0 0.0 900.0 0.0] [ 0.0 0.0 0.0 1.0]
>>> from sage.all import * >>> from sage.plot.plot3d.transform import Transformation >>> params = sage.plot.plot3d.base.RenderParams() >>> params.transform is None True >>> T = Transformation(scale=(Integer(10),Integer(20),Integer(30))) >>> params.push_transform(T) >>> params.transform.get_matrix() [10.0 0.0 0.0 0.0] [ 0.0 20.0 0.0 0.0] [ 0.0 0.0 30.0 0.0] [ 0.0 0.0 0.0 1.0] >>> params.push_transform(T) # scale again >>> params.transform.get_matrix() [100.0 0.0 0.0 0.0] [ 0.0 400.0 0.0 0.0] [ 0.0 0.0 900.0 0.0] [ 0.0 0.0 0.0 1.0]
- randomize_counter = 0¶
- unique_name(desc='name')[source]¶
Return a unique identifier starting with
desc
.INPUT:
desc
– string (default:'name'
); the prefix of the names
EXAMPLES:
sage: params = sage.plot.plot3d.base.RenderParams() sage: params.unique_name() 'name_1' sage: params.unique_name() 'name_2' sage: params.unique_name('texture') 'texture_3'
>>> from sage.all import * >>> params = sage.plot.plot3d.base.RenderParams() >>> params.unique_name() 'name_1' >>> params.unique_name() 'name_2' >>> params.unique_name('texture') 'texture_3'
- class sage.plot.plot3d.base.TransformGroup(all=[], rot=None, trans=None, scale=None, T=None)[source]¶
Bases:
Graphics3dGroup
This class is a container for a group of objects with a common transformation.
- bounding_box()[source]¶
Return the bounding box, i.e., the box containing the contents of the object after applying the transformation.
EXAMPLES:
sage: from math import pi sage: G = cube() sage: G.bounding_box() ((-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)) sage: G.scale(4).bounding_box() ((-2.0, -2.0, -2.0), (2.0, 2.0, 2.0)) sage: G.rotateZ(pi/4).bounding_box() ((-0.7071067811865475, -0.7071067811865475, -0.5), (0.7071067811865475, 0.7071067811865475, 0.5))
>>> from sage.all import * >>> from math import pi >>> G = cube() >>> G.bounding_box() ((-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)) >>> G.scale(Integer(4)).bounding_box() ((-2.0, -2.0, -2.0), (2.0, 2.0, 2.0)) >>> G.rotateZ(pi/Integer(4)).bounding_box() ((-0.7071067811865475, -0.7071067811865475, -0.5), (0.7071067811865475, 0.7071067811865475, 0.5))
- flatten()[source]¶
Try to reduce the depth of the scene tree by consolidating groups and transformations.
EXAMPLES:
sage: G = sphere((1,2,3)).scale(100) sage: T = G.get_transformation() sage: T.get_matrix() [100.0 0.0 0.0 0.0] [ 0.0 100.0 0.0 0.0] [ 0.0 0.0 100.0 0.0] [ 0.0 0.0 0.0 1.0] sage: G.flatten().get_transformation().get_matrix() [100.0 0.0 0.0 100.0] [ 0.0 100.0 0.0 200.0] [ 0.0 0.0 100.0 300.0] [ 0.0 0.0 0.0 1.0]
>>> from sage.all import * >>> G = sphere((Integer(1),Integer(2),Integer(3))).scale(Integer(100)) >>> T = G.get_transformation() >>> T.get_matrix() [100.0 0.0 0.0 0.0] [ 0.0 100.0 0.0 0.0] [ 0.0 0.0 100.0 0.0] [ 0.0 0.0 0.0 1.0] >>> G.flatten().get_transformation().get_matrix() [100.0 0.0 0.0 100.0] [ 0.0 100.0 0.0 200.0] [ 0.0 0.0 100.0 300.0] [ 0.0 0.0 0.0 1.0]
- get_transformation()[source]¶
Return the current transformation object.
EXAMPLES:
sage: G = sphere().scale(100) sage: T = G.get_transformation() sage: T.get_matrix() [100.0 0.0 0.0 0.0] [ 0.0 100.0 0.0 0.0] [ 0.0 0.0 100.0 0.0] [ 0.0 0.0 0.0 1.0]
>>> from sage.all import * >>> G = sphere().scale(Integer(100)) >>> T = G.get_transformation() >>> T.get_matrix() [100.0 0.0 0.0 0.0] [ 0.0 100.0 0.0 0.0] [ 0.0 0.0 100.0 0.0] [ 0.0 0.0 0.0 1.0]
- jmol_repr(render_params)[source]¶
Transformations for jmol are applied at the leaf nodes.
EXAMPLES:
sage: G = sphere((1,2,3)).scale(2) sage: G.jmol_repr(G.default_render_params()) [[['isosurface sphere_1 center {2.0 4.0 6.0} sphere 2.0\ncolor isosurface [102,102,255]']]]
>>> from sage.all import * >>> G = sphere((Integer(1),Integer(2),Integer(3))).scale(Integer(2)) >>> G.jmol_repr(G.default_render_params()) [[['isosurface sphere_1 center {2.0 4.0 6.0} sphere 2.0\ncolor isosurface [102,102,255]']]]
- json_repr(render_params)[source]¶
Transformations are applied at the leaf nodes.
EXAMPLES:
sage: G = cube().rotateX(0.2) sage: G.json_repr(G.default_render_params()) [['{"vertices":[{"x":0.5,"y":0.589368,"z":0.390699},...']]
>>> from sage.all import * >>> G = cube().rotateX(RealNumber('0.2')) >>> G.json_repr(G.default_render_params()) [['{"vertices":[{"x":0.5,"y":0.589368,"z":0.390699},...']]
- obj_repr(render_params)[source]¶
Transformations for .obj files are applied at the leaf nodes.
EXAMPLES:
sage: G = cube().scale(4).translate(1, 2, 3) sage: G.obj_repr(G.default_render_params()) [[['g obj_1', 'usemtl ...', ['v 3 4 5', 'v -1 4 5', 'v -1 0 5', 'v 3 0 5', 'v 3 4 1', 'v -1 4 1', 'v 3 0 1', 'v -1 0 1'], ['f 1 2 3 4', 'f 1 5 6 2', 'f 1 4 7 5', 'f 6 5 7 8', 'f 7 4 3 8', 'f 3 2 6 8'], []]]]
>>> from sage.all import * >>> G = cube().scale(Integer(4)).translate(Integer(1), Integer(2), Integer(3)) >>> G.obj_repr(G.default_render_params()) [[['g obj_1', 'usemtl ...', ['v 3 4 5', 'v -1 4 5', 'v -1 0 5', 'v 3 0 5', 'v 3 4 1', 'v -1 4 1', 'v 3 0 1', 'v -1 0 1'], ['f 1 2 3 4', 'f 1 5 6 2', 'f 1 4 7 5', 'f 6 5 7 8', 'f 7 4 3 8', 'f 3 2 6 8'], []]]]
- stl_binary_repr(render_params)[source]¶
Transformations are applied at the leaf nodes.
The STL binary representation is a list of binary strings, one for each triangle.
EXAMPLES:
sage: G = sphere().translate((1,2,0)) sage: len(G.stl_binary_repr(G.default_render_params())) 1368
>>> from sage.all import * >>> G = sphere().translate((Integer(1),Integer(2),Integer(0))) >>> len(G.stl_binary_repr(G.default_render_params())) 1368
- tachyon_repr(render_params)[source]¶
Transformations for Tachyon are applied at the leaf nodes.
EXAMPLES:
sage: G = sphere((1,2,3)).scale(2) sage: G.tachyon_repr(G.default_render_params()) [['Sphere center 2.0 4.0 6.0 Rad 2.0 texture...']]
>>> from sage.all import * >>> G = sphere((Integer(1),Integer(2),Integer(3))).scale(Integer(2)) >>> G.tachyon_repr(G.default_render_params()) [['Sphere center 2.0 4.0 6.0 Rad 2.0 texture...']]
- threejs_repr(render_params)[source]¶
Transformations for three.js are applied at the leaf nodes.
EXAMPLES:
sage: G = point3d((1,2,3)) + point3d((4,5,6)) sage: G = G.translate(-1, -2, -3).scale(10) sage: G.threejs_repr(G.default_render_params()) [('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (0.0, 0.0, 0.0), 'size': 5.0}), ('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (30.0, 30.0, 30.0), 'size': 5.0})]
>>> from sage.all import * >>> G = point3d((Integer(1),Integer(2),Integer(3))) + point3d((Integer(4),Integer(5),Integer(6))) >>> G = G.translate(-Integer(1), -Integer(2), -Integer(3)).scale(Integer(10)) >>> G.threejs_repr(G.default_render_params()) [('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (0.0, 0.0, 0.0), 'size': 5.0}), ('point', {'color': '#6666ff', 'opacity': 1.0, 'point': (30.0, 30.0, 30.0), 'size': 5.0})]
- transform(**kwds)[source]¶
Transforming this entire group can be done by composing transformations.
EXAMPLES:
sage: G = dodecahedron(color='red', opacity=.5) + icosahedron(color='blue') sage: G Graphics3d Object sage: G.transform(scale=(2,1/2,1)) Graphics3d Object sage: G.transform(trans=(1,1,3)) Graphics3d Object
>>> from sage.all import * >>> G = dodecahedron(color='red', opacity=RealNumber('.5')) + icosahedron(color='blue') >>> G Graphics3d Object >>> G.transform(scale=(Integer(2),Integer(1)/Integer(2),Integer(1))) Graphics3d Object >>> G.transform(trans=(Integer(1),Integer(1),Integer(3))) Graphics3d Object
- x3d_str()[source]¶
To apply a transformation to a set of objects in x3d, simply make them all children of an x3d Transform node.
EXAMPLES:
sage: sphere((1,2,3)).x3d_str() "<Transform translation='1 2 3'>\n<Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape>\n\n</Transform>"
>>> from sage.all import * >>> sphere((Integer(1),Integer(2),Integer(3))).x3d_str() "<Transform translation='1 2 3'>\n<Shape><Sphere radius='1.0'/><Appearance><Material diffuseColor='0.4 0.4 1.0' shininess='1.0' specularColor='0.0 0.0 0.0'/></Appearance></Shape>\n\n</Transform>"
- class sage.plot.plot3d.base.Viewpoint(*x)[source]¶
Bases:
Graphics3d
This class represents a viewpoint, necessary for x3d.
In the future, there could be multiple viewpoints, and they could have more properties. (Currently they only hold a position).
- sage.plot.plot3d.base.flatten_list(L)[source]¶
This is an optimized routine to turn a list of lists (of lists …) into a single list. We generate data in a non-flat format to avoid multiple data copying, and then concatenate it all at the end.
This is NOT recursive, otherwise there would be a lot of redundant copying (which we are trying to avoid in the first place, though at least it would be just the pointers).
EXAMPLES:
sage: from sage.plot.plot3d.base import flatten_list sage: flatten_list([]) [] sage: flatten_list([[[[]]]]) [] sage: flatten_list([['a', 'b'], 'c']) ['a', 'b', 'c'] sage: flatten_list([['a'], [[['b'], 'c'], ['d'], [[['e', 'f', 'g']]]]]) ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> from sage.all import * >>> from sage.plot.plot3d.base import flatten_list >>> flatten_list([]) [] >>> flatten_list([[[[]]]]) [] >>> flatten_list([['a', 'b'], 'c']) ['a', 'b', 'c'] >>> flatten_list([['a'], [[['b'], 'c'], ['d'], [[['e', 'f', 'g']]]]]) ['a', 'b', 'c', 'd', 'e', 'f', 'g']
- sage.plot.plot3d.base.max3(v)[source]¶
Return the componentwise maximum of a list of 3-tuples.
EXAMPLES:
sage: from sage.plot.plot3d.base import min3, max3 sage: max3([(-1,2,5), (-3, 4, 2)]) (-1, 4, 5)
>>> from sage.all import * >>> from sage.plot.plot3d.base import min3, max3 >>> max3([(-Integer(1),Integer(2),Integer(5)), (-Integer(3), Integer(4), Integer(2))]) (-1, 4, 5)
- sage.plot.plot3d.base.min3(v)[source]¶
Return the componentwise minimum of a list of 3-tuples.
EXAMPLES:
sage: from sage.plot.plot3d.base import min3, max3 sage: min3([(-1,2,5), (-3, 4, 2)]) (-3, 2, 2)
>>> from sage.all import * >>> from sage.plot.plot3d.base import min3, max3 >>> min3([(-Integer(1),Integer(2),Integer(5)), (-Integer(3), Integer(4), Integer(2))]) (-3, 2, 2)
- sage.plot.plot3d.base.optimal_aspect_ratios(ratios)[source]¶
Average the aspect ratios. compute the elementwise maximum of triples.
- sage.plot.plot3d.base.optimal_extra_kwds(v)[source]¶
Merge a list v of dictionaries such that later dictionaries have precedence.
- sage.plot.plot3d.base.point_list_bounding_box(v)[source]¶
Return the bounding box of a list of points.
EXAMPLES:
sage: from sage.plot.plot3d.base import point_list_bounding_box sage: point_list_bounding_box([(1,2,3),(4,5,6),(-10,0,10)]) ((-10.0, 0.0, 3.0), (4.0, 5.0, 10.0)) sage: point_list_bounding_box([(float('nan'), float('inf'), float('-inf')), (10,0,10)]) ((10.0, 0.0, 10.0), (10.0, 0.0, 10.0))
>>> from sage.all import * >>> from sage.plot.plot3d.base import point_list_bounding_box >>> point_list_bounding_box([(Integer(1),Integer(2),Integer(3)),(Integer(4),Integer(5),Integer(6)),(-Integer(10),Integer(0),Integer(10))]) ((-10.0, 0.0, 3.0), (4.0, 5.0, 10.0)) >>> point_list_bounding_box([(float('nan'), float('inf'), float('-inf')), (Integer(10),Integer(0),Integer(10))]) ((10.0, 0.0, 10.0), (10.0, 0.0, 10.0))