diff --git a/src/sage/plot/plot3d/base.pyx b/src/sage/plot/plot3d/base.pyx
index 693c4e27d31..e17c8a95fed 100644
--- a/src/sage/plot/plot3d/base.pyx
+++ b/src/sage/plot/plot3d/base.pyx
@@ -52,7 +52,14 @@ include "point_c.pxi"
from sage.interfaces.tachyon import tachyon_rt
-from renderers.jmol import JMOLRenderer
+
+import renderers.jmol
+import renderers.json
+import renderers.canvas3d
+import renderers.x3d
+import renderers.obj
+import renderers.tachyon
+import renderers.wavefront
# import the double infinity constant
cdef extern from "math.h":
@@ -69,6 +76,7 @@ cdef class Graphics3d(SageObject):
.. automethod:: __add__
.. automethod:: _rich_repr_
"""
+ render_method = "render_graphics3d"
def __cinit__(self):
"""
The Cython constructor
@@ -135,7 +143,7 @@ cdef class Graphics3d(SageObject):
if viewer == 'jmol' and not can_view_jmol: viewer = 'tachyon'
### Second, return the corresponding graphics file
if viewer == 'jmol':
- rrr = JMOLRenderer()
+ rrr = renderers.jmol.JMOLRenderer()
return rrr.rich_repr_graphics3d(self, **opts)
elif viewer == 'tachyon':
preferred = (
@@ -1346,7 +1354,7 @@ end_scene""" % (render_params.antialiasing,
render = self._rich_repr_tachyon(OutputImagePng, **opts)
render.png.save_as(filename)
elif viewer == 'jmol':
- rrr = JMOLRenderer()
+ rrr = renderers.jmol.JMOLRenderer()
scene = rrr.rich_repr_graphics3d(self, **opts)
scene.preview_png.save_as(filename)
else:
@@ -1457,6 +1465,7 @@ class Graphics3dGroup(Graphics3d):
This class represents a collection of 3d objects. Usually they are formed
implicitly by summing.
"""
+ render_method = "render_graphics3d_group"
def __init__(self, all=(), rot=None, trans=None, scale=None, T=None):
"""
EXAMPLES::
@@ -1570,7 +1579,8 @@ class Graphics3dGroup(Graphics3d):
sage: G.json_repr(G.default_render_params())
[[["{vertices:..."]], [["{vertices:..."]]]
"""
- return [g.json_repr(render_params) for g in self.all]
+ rrr = renderers.json.JsonRenderer()
+ return rrr.render_graphics3d_group(self, render_params)
def tachyon_repr(self, render_params):
"""
@@ -1584,25 +1594,13 @@ class Graphics3dGroup(Graphics3d):
[['Sphere center 0.0 0.0 0.0 Rad 1.0 texture...'],
['Sphere center 1.0 2.0 3.0 Rad 1.0 texture...']]
"""
- return [g.tachyon_repr(render_params) for g in self.all]
+ rrr = renderers.tachyon.TachyonRenderer()
+ return rrr.render_graphics3d_group(self, render_params)
def x3d_str(self):
- """
- The x3d representation of a group is simply the concatenation of
- the representation of its objects.
+ rrr = renderers.x3d.X3dRenderer()
+ return rrr.render_graphics3d_group(self, render_params=None)
- EXAMPLES::
-
- sage: G = sphere() + sphere((1,2,3))
- sage: print G.x3d_str()
-
-
-
-
-
-
- """
- return "\n".join([g.x3d_str() for g in self.all])
def obj_repr(self, render_params):
"""
@@ -1630,7 +1628,8 @@ class Graphics3dGroup(Graphics3d):
['f 5 6 7', 'f 6 8 7', 'f 5 7 8', 'f 5 8 6'],
[]]]]
"""
- return [g.obj_repr(render_params) for g in self.all]
+ rrr = renderers.obj.ObjRenderer()
+ return rrr.render_graphics3d_group(self, render_params)
def jmol_repr(self, render_params):
r"""
@@ -1644,7 +1643,8 @@ class Graphics3dGroup(Graphics3d):
[[['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]']]]
"""
- return [g.jmol_repr(render_params) for g in self.all]
+ rrr = renderers.jmol.JMOLRenderer()
+ return rrr.render_graphics3d_group(self, render_params)
def texture_set(self):
"""
@@ -1701,6 +1701,7 @@ class TransformGroup(Graphics3dGroup):
This class is a container for a group of objects with a common
transformation.
"""
+ render_method = "render_transform_group"
def __init__(self, all=[], rot=None, trans=None, scale=None, T=None):
"""
EXAMPLES::
@@ -1952,6 +1953,7 @@ cdef class PrimitiveObject(Graphics3d):
"""
This is the base class for the non-container 3d objects.
"""
+ render_method = "render_primitive_object"
def __init__(self, **kwds):
if 'texture' in kwds:
self.texture = kwds['texture']
diff --git a/src/sage/plot/plot3d/implicit_surface.pyx b/src/sage/plot/plot3d/implicit_surface.pyx
index be288cde294..d3026d58021 100644
--- a/src/sage/plot/plot3d/implicit_surface.pyx
+++ b/src/sage/plot/plot3d/implicit_surface.pyx
@@ -1132,7 +1132,7 @@ cdef class ImplicitSurface(IndexFaceSet):
sage: show(G, viewer='jmol') # indirect doctest
"""
rrr = renderers.jmol.JMOLRenderer()
- return rrr.render_implicit_surface(self, render_params)
+ return [rrr.render_implicit_surface(self, render_params)]
def json_repr(self, render_params):
"""
diff --git a/src/sage/plot/plot3d/index_face_set.pyx b/src/sage/plot/plot3d/index_face_set.pyx
index 42210344a64..9fad161e5c0 100644
--- a/src/sage/plot/plot3d/index_face_set.pyx
+++ b/src/sage/plot/plot3d/index_face_set.pyx
@@ -68,7 +68,14 @@ from sage.plot.plot3d.base import Graphics3dGroup
from transform cimport Transformation
-import renderers
+import renderers.jmol
+import renderers.json
+import renderers.canvas3d
+import renderers.x3d
+import renderers.obj
+import renderers.tachyon
+import renderers.wavefront
+
@@ -76,64 +83,6 @@ import renderers
# Fast routines for generating string representations of the polygons.
# --------------------------------------------------------------------
-cdef inline format_tachyon_texture(color_c rgb):
- cdef char rs[200]
- cdef Py_ssize_t cr = sprintf_3d(rs,
- "TEXTURE\n AMBIENT 0.3 DIFFUSE 0.7 SPECULAR 0 OPACITY 1.0\n COLOR %g %g %g \n TEXFUNC 0",
- rgb.r, rgb.g, rgb.b)
- return PyString_FromStringAndSize(rs, cr)
-
-
-cdef inline format_tachyon_triangle(point_c P, point_c Q, point_c R):
- cdef char ss[250]
- # PyString_FromFormat doesn't do floats?
- cdef Py_ssize_t r = sprintf_9d(ss,
- "TRI V0 %g %g %g V1 %g %g %g V2 %g %g %g",
- P.x, P.y, P.z,
- Q.x, Q.y, Q.z,
- R.x, R.y, R.z )
- return PyString_FromStringAndSize(ss, r)
-
-
-cdef inline format_json_vertex(point_c P):
- cdef char ss[100]
- cdef Py_ssize_t r = sprintf_3d(ss, "{x:%g,y:%g,z:%g}", P.x, P.y, P.z)
- return PyString_FromStringAndSize(ss, r)
-
-cdef inline format_json_face(face_c face):
- return "[{}]".format(",".join([str(face.vertices[i])
- for i from 0 <= i < face.n]))
-
-cdef inline format_obj_vertex(point_c P):
- cdef char ss[100]
- # PyString_FromFormat doesn't do floats?
- cdef Py_ssize_t r = sprintf_3d(ss, "v %g %g %g", P.x, P.y, P.z)
- return PyString_FromStringAndSize(ss, r)
-
-cdef inline format_obj_face(face_c face, int off):
- cdef char ss[100]
- cdef Py_ssize_t r, i
- if face.n == 3:
- r = sprintf_3i(ss, "f %d %d %d", face.vertices[0] + off, face.vertices[1] + off, face.vertices[2] + off)
- elif face.n == 4:
- r = sprintf_4i(ss, "f %d %d %d %d", face.vertices[0] + off, face.vertices[1] + off, face.vertices[2] + off, face.vertices[3] + off)
- else:
- return "f " + " ".join([str(face.vertices[i] + off) for i from 0 <= i < face.n])
- # PyString_FromFormat is almost twice as slow
- return PyString_FromStringAndSize(ss, r)
-
-cdef inline format_obj_face_back(face_c face, int off):
- cdef char ss[100]
- cdef Py_ssize_t r, i
- if face.n == 3:
- r = sprintf_3i(ss, "f %d %d %d", face.vertices[2] + off, face.vertices[1] + off, face.vertices[0] + off)
- elif face.n == 4:
- r = sprintf_4i(ss, "f %d %d %d %d", face.vertices[3] + off, face.vertices[2] + off, face.vertices[1] + off, face.vertices[0] + off)
- else:
- return "f " + " ".join([str(face.vertices[i] + off) for i from face.n > i >= 0])
- return PyString_FromStringAndSize(ss, r)
-
-
cdef class IndexFaceSet(PrimitiveObject):
"""
@@ -699,160 +648,16 @@ cdef class IndexFaceSet(PrimitiveObject):
return all
def tachyon_repr(self, render_params):
- """
- Return a tachyon object for ``self``.
-
- EXAMPLES:
-
- A basic test with a triangle::
-
- sage: G = polygon([(0,0,1), (1,1,1), (2,0,1)])
- sage: s = G.tachyon_repr(G.default_render_params()); s
- ['TRI V0 0 0 1 V1 1 1 1 V2 2 0 1', ...]
-
- A simple colored one::
-
- sage: from sage.plot.plot3d.index_face_set import IndexFaceSet
- sage: from sage.plot.plot3d.texture import Texture
- sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)]
- sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]]
- sage: col = rainbow(10, 'rgbtuple')
- sage: t_list=[Texture(col[i]) for i in range(10)]
- sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list)
- sage: S.tachyon_repr(S.default_render_params())
- ['TRI V0 2 0 0 V1 1 0 1 V2 1 1 0',
- 'TEXTURE... AMBIENT 0.3 DIFFUSE 0.7 SPECULAR 0 OPACITY 1.0... COLOR 1 0 0 ... TEXFUNC 0',...]
- """
- cdef Transformation transform = render_params.transform
- lines = []
- cdef point_c P, Q, R
- cdef face_c face
- cdef Py_ssize_t i, k
- sig_on()
- for i from 0 <= i < self.fcount:
- face = self._faces[i]
- if transform is not None:
- transform.transform_point_c(&P, self.vs[face.vertices[0]])
- transform.transform_point_c(&Q, self.vs[face.vertices[1]])
- transform.transform_point_c(&R, self.vs[face.vertices[2]])
- else:
- P = self.vs[face.vertices[0]]
- Q = self.vs[face.vertices[1]]
- R = self.vs[face.vertices[2]]
- PyList_Append(lines, format_tachyon_triangle(P, Q, R))
- if self.global_texture:
- PyList_Append(lines, self.texture.id)
- else:
- PyList_Append(lines, format_tachyon_texture(face.color))
- if face.n > 3:
- for k from 3 <= k < face.n:
- Q = R
- if transform is not None:
- transform.transform_point_c(&R, self.vs[face.vertices[k]])
- else:
- R = self.vs[face.vertices[k]]
- PyList_Append(lines, format_tachyon_triangle(P, Q, R))
- if self.global_texture:
- PyList_Append(lines, self.texture.id)
- else:
- PyList_Append(lines, format_tachyon_texture(face.color))
- sig_off()
-
- return lines
+ rrr = renderers.tachyon.TachyonRenderer()
+ return rrr.render_index_face_set(self, render_params)
def json_repr(self, render_params):
- """
- Return a json representation for ``self``.
-
- TESTS:
-
- A basic test with a triangle::
-
- sage: G = polygon([(0,0,1), (1,1,1), (2,0,1)])
- sage: G.json_repr(G.default_render_params())
- ["{vertices:[{x:0,y:0,z:1},{x:1,y:1,z:1},{x:2,y:0,z:1}],faces:[[0,1,2]],color:'#0000ff'}"]
-
- A simple colored one::
-
- sage: from sage.plot.plot3d.index_face_set import IndexFaceSet
- sage: from sage.plot.plot3d.texture import Texture
- sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)]
- sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]]
- sage: col = rainbow(10, 'rgbtuple')
- sage: t_list=[Texture(col[i]) for i in range(10)]
- sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list)
- sage: S.json_repr(S.default_render_params())
- ["{vertices:[{x:2,y:0,z:0},{x:0,y:2,z:0},{x:0,y:0,z:2},{x:0,y:1,z:1},{x:1,y:0,z:1},{x:1,y:1,z:0}],faces:[[0,4,5],[3,4,5],[2,3,4],[1,3,5]],face_colors:['#ff0000','#ff9900','#cbff00','#33ff00']}"]
- """
- cdef Transformation transform = render_params.transform
- cdef point_c res
-
- if transform is None:
- vertices_str = "[{}]".format(
- ",".join([format_json_vertex(self.vs[i])
- for i from 0 <= i < self.vcount]))
- else:
- vertices_str = "["
- for i from 0 <= i < self.vcount:
- transform.transform_point_c(&res, self.vs[i])
- if i > 0:
- vertices_str += ","
- vertices_str += format_json_vertex(res)
- vertices_str += "]"
-
- faces_str = "[{}]".format(",".join([format_json_face(self._faces[i])
- for i from 0 <= i < self.fcount]))
- if self.global_texture:
- color_str = "'#{}'".format(self.texture.hex_rgb())
- return ["{vertices:%s,faces:%s,color:%s}" %
- (vertices_str, faces_str, color_str)]
- else:
- color_str = "[{}]".format(",".join(["'{}'".format(
- Color(self._faces[i].color.r,
- self._faces[i].color.g,
- self._faces[i].color.b).html_color())
- for i from 0 <= i < self.fcount]))
- return ["{vertices:%s,faces:%s,face_colors:%s}" %
- (vertices_str, faces_str, color_str)]
+ rrr = renderers.json.JsonRenderer()
+ return [rrr.render_index_face_set(self, render_params)]
def obj_repr(self, render_params):
- """
- Return an obj representation for ``self``.
-
- TESTS::
-
- sage: from sage.plot.plot3d.shapes import *
- sage: S = Cylinder(1,1)
- sage: s = S.obj_repr(S.default_render_params())
- """
- cdef Transformation transform = render_params.transform
- cdef int off = render_params.obj_vertex_offset
- cdef Py_ssize_t i
- cdef point_c res
-
- sig_on()
- if transform is None:
- points = [format_obj_vertex(self.vs[i]) for i from 0 <= i < self.vcount]
- else:
- points = []
- for i from 0 <= i < self.vcount:
- transform.transform_point_c(&res, self.vs[i])
- PyList_Append(points, format_obj_vertex(res))
-
- faces = [format_obj_face(self._faces[i], off) for i from 0 <= i < self.fcount]
- if not self.enclosed:
- back_faces = [format_obj_face_back(self._faces[i], off) for i from 0 <= i < self.fcount]
- else:
- back_faces = []
-
- render_params.obj_vertex_offset += self.vcount
- sig_off()
-
- return ["g " + render_params.unique_name('obj'),
- "usemtl " + self.texture.id,
- points,
- faces,
- back_faces]
+ rrr = renderers.obj.ObjRenderer()
+ return rrr.render_index_face_set(self, render_params)
def jmol_repr(self, render_params):
rrr = renderers.jmol.JMOLRenderer()
diff --git a/src/sage/plot/plot3d/parametric_surface.pyx b/src/sage/plot/plot3d/parametric_surface.pyx
index e0d803741c2..689c4e88747 100644
--- a/src/sage/plot/plot3d/parametric_surface.pyx
+++ b/src/sage/plot/plot3d/parametric_surface.pyx
@@ -272,7 +272,7 @@ cdef class ParametricSurface(IndexFaceSet):
['pmesh obj_1 "obj_1.pmesh"\ncolor pmesh [102,102,255]']
"""
rrr = renderers.jmol.JMOLRenderer()
- return rrr.render_implicit_surface(self, render_params)
+ return [rrr.render_implicit_surface(self, render_params)]
def json_repr(self, render_params):
"""
diff --git a/src/sage/plot/plot3d/renderers/api.py b/src/sage/plot/plot3d/renderers/api.py
index 589f3fe511b..6a0ae02c691 100644
--- a/src/sage/plot/plot3d/renderers/api.py
+++ b/src/sage/plot/plot3d/renderers/api.py
@@ -16,7 +16,7 @@ def render_graphics3d(self, obj, render_params):
return ''
def render_graphics3d_group(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
+ return [g.render(render_params, renderer=self) for g in obj.all]
def render_transform_group(self, obj, render_params):
return self.render_graphics3d_group(obj, render_params)
diff --git a/src/sage/plot/plot3d/renderers/canvas3d.py b/src/sage/plot/plot3d/renderers/canvas3d.py
index c1e400cede2..176ba16c106 100644
--- a/src/sage/plot/plot3d/renderers/canvas3d.py
+++ b/src/sage/plot/plot3d/renderers/canvas3d.py
@@ -4,7 +4,7 @@
from . import register, Graphics3dRenderer
-class Canvas3dRenderer(object):
+class Canvas3dRenderer(Graphics3dRenderer):
def render_graphics3d(self, obj, render_params):
"""
@@ -13,8 +13,8 @@ def render_graphics3d(self, obj, render_params):
"""
return ''
- def render_graphics3d_group(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
+ # def render_graphics3d_group(self, obj, render_params):
+ # return self.render_graphics3d(obj, render_params)
def render_transform_group(self, obj, render_params):
return self.render_graphics3d_group(obj, render_params)
diff --git a/src/sage/plot/plot3d/renderers/jmol.py b/src/sage/plot/plot3d/renderers/jmol.py
index ac98d5dd1f7..82d11d82939 100644
--- a/src/sage/plot/plot3d/renderers/jmol.py
+++ b/src/sage/plot/plot3d/renderers/jmol.py
@@ -62,6 +62,21 @@ def render_graphics3d_image(self,obj):
scene = obj._rich_repr_jmol(**opts)
scene.preview_png.save_as(filename)
+ def render_graphics3d(self, obj, render_params):
+ return ''
+
+ def render_graphics3d_group(self, obj, render_params):
+ return [g.render(render_params, renderer=self) for g in obj.all]
+ def render_transform_group(self, obj, render_params):
+ return self.render_graphics3d_group(obj, render_params)
+
+ def render_primitive_object(self, obj, render_params):
+ return self.render_graphics3d(obj, render_params)
+ def render_line(self, obj, render_params):
+ return self.render_primitive_objectd(obj, render_params)
+ def render_point(self, obj, render_params):
+ return self.render_primitive_object(obj, render_params)
+
def render_index_face_set(self, obj, render_params):
"""
Return a jmol representation for ``obj``.
@@ -79,7 +94,7 @@ def render_index_face_set(self, obj, render_params):
obj._seperate_creases(render_params.crease_threshold)
if transform is None:
- points = ["%g %g %g"%v for v in vertices]
+ points = ["%g %g %g"%tuple(v) for v in vertices]
else:
points = ["%g %g %g"%transform.transform_point(v) for v in vertices]
@@ -142,25 +157,6 @@ def render_index_face_set(self, obj, render_params):
s += '\npmesh %s dots\n' % name
return s
-
-
- def render_graphics3d(self, obj, render_params):
- return ''
-
- def render_graphics3d_group(self, obj, render_params):
- return [g.render(render_params, renderer=self) for g in obj.all]
- def render_transform_group(self, obj, render_params):
- return self.render_graphics3d_group(obj, render_params)
-
- def render_primitive_object(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
- def render_line(self, obj, render_params):
- return self.render_primitive_objectd(obj, render_params)
- def render_point(self, obj, render_params):
- return self.render_primitive_object(obj, render_params)
-
- def render_index_face_set(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
def render_box(self, obj, render_params):
return self.render_index_face_set(obj, render_params)
@@ -208,7 +204,7 @@ def render_sphere(self, obj, render_params):
res = "resolution %s" % min(int(7/rad), 100)
else:
res = ""
- return ["isosurface %s %s center {%s %s %s} sphere %s\n%s" % (name, res, cen[0], cen[1], cen[2], rad, obj.texture.jmol_str("isosurface"))]
+ return "isosurface %s %s center {%s %s %s} sphere %s\n%s" % (name, res, cen[0], cen[1], cen[2], rad, obj.texture.jmol_str("isosurface"))
def render_cylinder(self, obj, render_params):
diff --git a/src/sage/plot/plot3d/renderers/json.py b/src/sage/plot/plot3d/renderers/json.py
index af298ef6fae..0d3b7fab2f6 100644
--- a/src/sage/plot/plot3d/renderers/json.py
+++ b/src/sage/plot/plot3d/renderers/json.py
@@ -4,7 +4,7 @@
from . import register, Graphics3dRenderer
-class JsonRenderer(object):
+class JsonRenderer(Graphics3dRenderer):
def render_graphics3d(self, obj, render_params):
"""
@@ -13,8 +13,8 @@ def render_graphics3d(self, obj, render_params):
"""
return ''
- def render_graphics3d_group(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
+ # def render_graphics3d_group(self, obj, render_params):
+ # return self.render_graphics3d(obj, render_params)
def render_transform_group(self, obj, render_params):
return self.render_graphics3d_group(obj, render_params)
@@ -26,7 +26,58 @@ def render_point(self, obj, render_params):
return self.render_primitive_object(obj, render_params)
def render_index_face_set(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
+ """
+ Return a json representation for ``self``.
+
+ TESTS:
+
+ A basic test with a triangle::
+
+ sage: G = polygon([(0,0,1), (1,1,1), (2,0,1)])
+ sage: G.json_repr(G.default_render_params())
+ ["{vertices:[{x:0,y:0,z:1},{x:1,y:1,z:1},{x:2,y:0,z:1}],faces:[[0,1,2]],color:'#0000ff'}"]
+
+ A simple colored one::
+
+ sage: from sage.plot.plot3d.index_face_set import IndexFaceSet
+ sage: from sage.plot.plot3d.texture import Texture
+ sage: point_list = [(2,0,0),(0,2,0),(0,0,2),(0,1,1),(1,0,1),(1,1,0)]
+ sage: face_list = [[0,4,5],[3,4,5],[2,3,4],[1,3,5]]
+ sage: col = rainbow(10, 'rgbtuple')
+ sage: t_list=[Texture(col[i]) for i in range(10)]
+ sage: S = IndexFaceSet(face_list, point_list, texture_list=t_list)
+ sage: S.json_repr(S.default_render_params())
+ ["{vertices:[{x:2,y:0,z:0},{x:0,y:2,z:0},{x:0,y:0,z:2},{x:0,y:1,z:1},{x:1,y:0,z:1},{x:1,y:1,z:0}],faces:[[0,4,5],[3,4,5],[2,3,4],[1,3,5]],face_colors:['#ff0000','#ff9900','#cbff00','#33ff00']}"]
+ """
+ transform = render_params.transform
+ vertices = obj.vertices()
+ faces = obj.faces()
+
+ if transform is None:
+ vertices_str = "[{}]".format(",".join(["{x:%g,y:%g,z:%g}"%tuple(v) for v in vertices]))
+ else:
+ vertices_str = "[{}]".format(",".join(
+ ["{x:%g,y:%g,z:%g}"%transform.transform_point(v) for v in vertices]
+ ))
+
+ faces_str = "[{}]".format(",".join(
+ ["[{}]".format(",".join(
+ [str(v) for v in face.iter_index()]
+ )) for face in faces]
+ ))
+
+ if True:#obj.global_texture:
+ color_str = "'#{}'".format(obj.texture.hex_rgb())
+ return "{vertices:%s,faces:%s,color:%s}"%(vertices_str, faces_str, color_str)
+ # else:
+ # color_str = "[{}]".format(",".join(["'{}'".format(
+ # Color(obj._faces[i].color.r,
+ # obj._faces[i].color.g,
+ # obj._faces[i].color.b).html_color())
+ # for i from 0 <= i < obj.fcount]))
+ # return "{vertices:%s,faces:%s,face_colors:%s}"%(vertices_str, faces_str, color_str)
+
+
def render_box(self, obj, render_params):
return self.render_index_face_set(obj, render_params)
@@ -50,3 +101,13 @@ def render_implicit_surface(self, obj, render_params):
register(JsonRenderer)
+
+# cdef inline format_json_vertex(point_c P):
+# cdef char ss[100]
+# cdef Py_ssize_t r = sprintf_3d(ss, "{x:%g,y:%g,z:%g}", P.x, P.y, P.z)
+# return PyString_FromStringAndSize(ss, r)
+
+# cdef inline format_json_face(face_c face):
+# return "[{}]".format(",".join([str(face.vertices[i])
+# for i from 0 <= i < face.n]))
+
diff --git a/src/sage/plot/plot3d/renderers/obj.py b/src/sage/plot/plot3d/renderers/obj.py
index e2bc82765d6..b7979cb5fd3 100644
--- a/src/sage/plot/plot3d/renderers/obj.py
+++ b/src/sage/plot/plot3d/renderers/obj.py
@@ -4,49 +4,87 @@
from . import register, Graphics3dRenderer
-class ObjRenderer(object):
+class ObjRenderer(Graphics3dRenderer):
- def render_graphics3d(self, obj, render_params):
+ # grob = (gr)aphics (ob)ject
+ def render_graphics3d(self, grob, render_params):
"""
Unless otherwise changed, all rendering methods fall back to this
one.
"""
return ''
- def render_graphics3d_group(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
- def render_transform_group(self, obj, render_params):
- return self.render_graphics3d_group(obj, render_params)
-
- def render_primitive_object(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
- def render_line(self, obj, render_params):
- return self.render_primitive_objectd(obj, render_params)
- def render_point(self, obj, render_params):
- return self.render_primitive_object(obj, render_params)
-
- def render_index_face_set(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
- def render_box(self, obj, render_params):
- return self.render_index_face_set(obj, render_params)
-
- def render_parametric_surface(self, obj, render_params):
- obj.triangulate()
- return self.render_index_face_set(obj, render_params)
- def render_sphere(self, obj, render_params):
- return self.render_parametric_surface(obj, render_params)
- def render_cylinder(self, obj, render_params):
- return self.render_parametric_surface(obj, render_params)
- def render_torus(self, obj, render_params):
- return self.render_parametric_surface(obj, render_params)
- def render_cone(self, obj, render_params):
- return self.render_parametric_surface(obj, render_params)
- def render_mobius_strip(self, obj, render_params):
- return self.render_parametric_surface(obj, render_params)
-
- def render_implicit_surface(self, obj, render_params):
- obj.triangulate()
- return self.render_index_face_set(obj, render_params)
+ # def render_graphics3d_group(self, grob, render_params):
+ # return self.render_graphics3d(grob, render_params)
+ def render_transform_group(self, grob, render_params):
+ return self.render_graphics3d_group(grob, render_params)
+
+ def render_primitive_grobect(self, grob, render_params):
+ return self.render_graphics3d(grob, render_params)
+ def render_line(self, grob, render_params):
+ return self.render_primitive_grobectd(grob, render_params)
+ def render_point(self, grob, render_params):
+ return self.render_primitive_grobect(grob, render_params)
+
+ def render_index_face_set(self, grob, render_params):
+ """
+ Return an obj representation for ``grob``.
+
+ TESTS::
+
+ sage: from sage.plot.plot3d.shapes import *
+ sage: S = Cylinder(1,1)
+ sage: s = S.obj_repr(S.default_render_params())
+ """
+ transform = render_params.transform
+ if transform is None:
+ transform_point = tuple
+ else:
+ transform_point = transform.transform_point
+
+ off = render_params.obj_vertex_offset
+
+ grob_faces = grob.faces()
+
+ points = ["v %g %g %g"%(transform_point(v)) for v in grob.vertices()]
+
+ faces = [format_obj_face(indexed_face, off) for indexed_face in grob.index_faces()]
+ if not grob.is_enclosed():
+ back_faces = [format_obj_face(indexed_face, off, order=-1) for indexed_face in grob.index_faces()]
+ else:
+ back_faces = []
+
+ render_params.obj_vertex_offset += len(grob.vertices())
+
+
+ return ["g " + render_params.unique_name('obj'),
+ "usemtl " + grob.texture.id,
+ points,
+ faces,
+ back_faces]
+
+ def render_box(self, grob, render_params):
+ return self.render_index_face_set(grob, render_params)
+
+ def render_parametric_surface(self, grob, render_params):
+ grob.triangulate()
+ return self.render_index_face_set(grob, render_params)
+ def render_sphere(self, grob, render_params):
+ return self.render_parametric_surface(grob, render_params)
+ def render_cylinder(self, grob, render_params):
+ return self.render_parametric_surface(grob, render_params)
+ def render_torus(self, grob, render_params):
+ return self.render_parametric_surface(grob, render_params)
+ def render_cone(self, grob, render_params):
+ return self.render_parametric_surface(grob, render_params)
+ def render_mobius_strip(self, grob, render_params):
+ return self.render_parametric_surface(grob, render_params)
+
+ def render_implicit_surface(self, grob, render_params):
+ grob.triangulate()
+ return self.render_index_face_set(grob, render_params)
register(ObjRenderer)
+def format_obj_face(indexed_face, off, order=1):
+ return "f "+" ".join("%d"%(j+off) for j in indexed_face[::order])
diff --git a/src/sage/plot/plot3d/renderers/wavefront.py b/src/sage/plot/plot3d/renderers/wavefront.py
index d954bc6e3f8..650cdc8a663 100644
--- a/src/sage/plot/plot3d/renderers/wavefront.py
+++ b/src/sage/plot/plot3d/renderers/wavefront.py
@@ -4,7 +4,7 @@
from . import register, Graphics3dRenderer
-class WavefrontRenderer(object):
+class WavefrontRenderer(Graphics3dRenderer):
def render_graphics3d(self, obj, render_params):
"""
@@ -13,8 +13,8 @@ def render_graphics3d(self, obj, render_params):
"""
return ''
- def render_graphics3d_group(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
+ # def render_graphics3d_group(self, obj, render_params):
+ # return self.render_graphics3d(obj, render_params)
def render_transform_group(self, obj, render_params):
return self.render_graphics3d_group(obj, render_params)
diff --git a/src/sage/plot/plot3d/renderers/x3d.py b/src/sage/plot/plot3d/renderers/x3d.py
index 936be026a55..4efcc60f546 100644
--- a/src/sage/plot/plot3d/renderers/x3d.py
+++ b/src/sage/plot/plot3d/renderers/x3d.py
@@ -4,7 +4,7 @@
from . import register, Graphics3dRenderer
-class X3dRenderer(object):
+class X3dRenderer(Graphics3dRenderer):
def render_graphics3d(self, obj, render_params):
"""
@@ -14,7 +14,23 @@ def render_graphics3d(self, obj, render_params):
return ''
def render_graphics3d_group(self, obj, render_params):
- return self.render_graphics3d(obj, render_params)
+ """
+ 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()
+
+
+
+
+
+
+ """
+ return "\n".join([g.x3d_str() for g in obj.all])
+
def render_transform_group(self, obj, render_params):
return self.render_graphics3d_group(obj, render_params)
diff --git a/src/sage/plot/plot3d/shapes.pyx b/src/sage/plot/plot3d/shapes.pyx
index 48b25d76d5e..bd7952e6c6a 100644
--- a/src/sage/plot/plot3d/shapes.pyx
+++ b/src/sage/plot/plot3d/shapes.pyx
@@ -740,7 +740,7 @@ cdef class Sphere(ParametricSurface):
def jmol_repr(self, render_params):
rrr = renderers.jmol.JMOLRenderer()
- return rrr.render_sphere(self, render_params)
+ return [rrr.render_sphere(self, render_params)]
def get_grid(self, double ds):
"""
Return the range of variables to be evaluated on to render as a