Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
more progress
Browse files Browse the repository at this point in the history
  • Loading branch information
nilesjohnson committed May 26, 2015
1 parent 8305657 commit 1f756f1
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 304 deletions.
46 changes: 24 additions & 22 deletions src/sage/plot/plot3d/base.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand All @@ -69,6 +76,7 @@ cdef class Graphics3d(SageObject):
.. automethod:: __add__
.. automethod:: _rich_repr_
"""
render_method = "render_graphics3d"
def __cinit__(self):
"""
The Cython constructor
Expand Down Expand Up @@ -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 = (
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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::
Expand Down Expand Up @@ -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):
"""
Expand All @@ -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()
<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>
"""
return "\n".join([g.x3d_str() for g in self.all])

def obj_repr(self, render_params):
"""
Expand Down Expand Up @@ -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"""
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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::
Expand Down Expand Up @@ -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']
Expand Down
2 changes: 1 addition & 1 deletion src/sage/plot/plot3d/implicit_surface.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
223 changes: 14 additions & 209 deletions src/sage/plot/plot3d/index_face_set.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -68,72 +68,21 @@ 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




# --------------------------------------------------------------------
# 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):
"""
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/sage/plot/plot3d/parametric_surface.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
Loading

0 comments on commit 1f756f1

Please sign in to comment.