# Ticket #12083: trac12083_tikz_polytope_review.patch

File trac12083_tikz_polytope_review.patch, 22.4 KB (added by jipilab, 10 years ago)

Apply over the precedent patch

• ## sage/geometry/polyhedra.py

# HG changeset patch
# User Jean-Philippe Labbé <labbe at math.fu-berlin.de>
# Date 1338471031 -7200
# Node ID 0bfb394ac7bd32f7896c4607da026b4f717b01c0
# Parent  65c1e557ebb3ce13d509a0eecabb8605598b920d
trac #12083: first review version

diff --git a/sage/geometry/polyhedra.py b/sage/geometry/polyhedra.py
 a from subprocess import Popen, PIPE from sage.misc.all import tmp_filename from sage.misc.functional import norm, n from sage.misc.functional import norm from sage.misc.package import is_package_installed from sage.misc.latex import LatexExpr from sage.rings.all import Integer, QQ, ZZ, primes_first_n from sage.rings.real_double import RDF from sage.modules.free_module_element import vector from sage.modules.free_module import VectorSpace from sage.matrix.constructor import matrix, identity_matrix from sage.functions.other import sqrt, floor, ceil from sage.functions.trig import sin, cos self._restricted_automorphism_group = group return group def tikz(self, view=[0,0,1], rot_angle=0, scale=2, def tikz(self, view=[0,0,1], angle=0, scale=2, edge_color='blue!95!black', facet_color='blue!95!black', opacity=0.8, vertex_color='green', axis=False): """ Return a string tikz_pic consisting of a tikz picture of self according to a projection view and an angle rot_angle according to a projection view and an angle angle obtained via Jmol through the current state property. INPUT: - view -- a list of length 3 representing a vector; - rot_angle -- an angle in degree from 0 to 360; - scale -- an integer specifying the scaling of the tikz picture; - edge_color, facet_color, vertex_color -- string representing colors which tikz recognize; - opacity -- a real number between 0 and 1 giving the opacity of the front facets; - axis -- a Boolean, to draw the axes at the origin. - view - list (default: [0,0,1]) representing the rotation axis (see note below). - angle - integer (default: 0) angle of rotation in degree from 0 to 360 (see note below). - scale - integer (default: 2) specifying the scaling of the tikz picture. - edge_color - string (default: 'blue!95!black') representing colors which tikz recognize. - facet_color - string (default: 'blue!95!black') representing colors which tikz recognize. - vertex_color - string (default: 'green') representing colors which tikz recognize. - opacity - real number (default: 0.8) between 0 and 1 giving the opacity of the front facets. - axis - Boolean (default: False) draw the axes at the origin or not. OUTPUT: - tikz_pic -- a string containing the raw text of a TikZ picture. - LatexExpr -- containing the TikZ picture. .. NOTE:: The inputs view and rot_angle can be obtained from the viewer The inputs view and angle can be obtained from the viewer Jmol: 1) Right click on the image; 2) Select Console; 3) Select the tab State; 2) Select Console; 3) Select the tab State; 4) Scroll to the line moveto It read something like: It read something like:: moveto 0.0 {x y z angle} Scale The view is then [x,y,z] and rot_angle is angle. The view is then [x,y,z] and angle is angle. The following number is the scale. Jmol performs a rotation of angle degrees along the vector [x,y,z] and show the result from the z-axis. EXAMPLES:: sage: P1 = polytopes.small_rhombicuboctahedron() sage: Image1 = P1.tikz([1,3,5], 175, scale=4) sage: open('polytope-tikz.tex', 'w').write(Image1) sage: type(Image1) sage: print '\n'.join(Image1.splitlines()[:4]) \begin{tikzpicture}% [x={(-0.939161cm, 0.244762cm)}, y={(0.097442cm, -0.482887cm)}, z={(0.329367cm, 0.840780cm)}, sage: open('polytope-tikz1.tex', 'w').write(Image1)    # not tested sage: P2 = Polyhedron(vertices=[[1, 1],[1, 2],[2, 1]]) sage: Image2 = P2.tikz(scale=3, edge_color='blue!95!black', facet_color='orange!95!black', opacity=0.4, vertex_color='yellow', axis=True) sage: open('polytope-tikz2.tex', 'w').write(Image2) sage: type(Image1) sage: print '\n'.join(Image2.splitlines()[:4]) \begin{tikzpicture}% [scale=3.000000, back/.style={loosely dotted, thin}, edge/.style={color=blue!95!black, thick}, sage: open('polytope-tikz2.tex', 'w').write(Image2)    # not tested sage: P3 = Polyhedron(vertices=[[-1, -1, 2],[-1, 2, -1],[2, -1, -1]]) sage: P3 A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices. sage: Image3 = P3.tikz([0.5,-1,-0.1], 55, scale=3, edge_color='blue!95!black', facet_color='orange!95!black', opacity=0.7, vertex_color='yellow', axis=True) sage: open('polytope-tikz3.tex', 'w').write(Image3) sage: Image3 = P3.tikz([0.5,-1,-0.1], 55, scale=3, edge_color='blue!95!black',facet_color='orange!95!black', opacity=0.7, vertex_color='yellow', axis=True) sage: print '\n'.join(Image3.splitlines()[:4]) \begin{tikzpicture}% [x={(0.658184cm, -0.242192cm)}, y={(-0.096240cm, 0.912008cm)}, z={(-0.746680cm, -0.331036cm)}, sage: open('polytope-tikz3.tex', 'w').write(Image3)    # not tested sage: P=Polyhedron(vertices=[[1,1,0,0],[1,2,0,0],[2,1,0,0],[0,0,1,0],[0,0,0,1]]) sage: P ... NotImplementedError: The polytope has to live in 2 or 3 dimensions. .. TO DO:: Make it possible to draw Schlegel diagram for 4-polytope. return self._tikz_2d(scale, edge_color, facet_color, opacity, vertex_color, axis) elif self.dim() == 2: return self._tikz_2d_in_3d(view, rot_angle, scale, edge_color, return self._tikz_2d_in_3d(view, angle, scale, edge_color, facet_color, opacity, vertex_color, axis) else: return self._tikz_3d_in_3d(view, rot_angle, scale, edge_color, return self._tikz_3d_in_3d(view, angle, scale, edge_color, facet_color, opacity, vertex_color, axis) def _tikz_2d(self, scale, edge_color, facet_color, opacity, vertex_color, axis): INPUT: - scale -- an integer specifying the scaling of the tikz picture; - edge_color, facet_color, vertex_color -- string representing colors which tikz recognize; - opacity -- a real number between 0 and 1 giving the opacity of the front facets; - axis -- a Boolean, to draw the axes at the origin. - scale - integer specifying the scaling of the tikz picture. - edge_color - string representing colors which tikz recognize. - facet_color - string representing colors which tikz recognize. - vertex_color - string representing colors which tikz recognize. - opacity - real number between 0 and 1 giving the opacity of the front facets. - axis - Boolean (default: False) draw the axes at the origin or not. OUTPUT: - LatexExpr -- containing the TikZ picture. EXAMPLES:: sage: P = Polyhedron(vertices=[[1, 1],[1, 2],[2, 1]]) sage: Image = P._tikz_2d(scale=3, edge_color='black', facet_color='orange', opacity=0.75, vertex_color='yellow', axis=True) sage: type(Image) sage: print '\n'.join(Image.splitlines()[:4]) \begin{tikzpicture}% [scale=3.000000, back/.style={loosely dotted, thin}, edge/.style={color=black, thick}, sage: open('polytope-tikz2.tex', 'w').write(Image2)    # not tested .. NOTE:: tikz_pic += '\tedge/.style={color=%s, thick},\n' %edge_color tikz_pic += '\tfacet/.style={fill=%s,fill opacity=%f},\n' %(facet_color,opacity) tikz_pic += '\tvertex/.style={inner sep=1pt,circle,draw=%s!25!black,' %vertex_color tikz_pic += 'fill=%s!75!black,thick,anchor=base}]\n\n\n' %vertex_color tikz_pic += 'fill=%s!75!black,thick,anchor=base}]\n%%\n%%\n' %vertex_color # Draws the axes if True if axis: tikz_pic += '\\draw[color=black,thick,->] (0,0,0) -- (0,1,0) node[anchor=north west]{$y$};\n' # Create the coordinate of the vertices: tikz_pic += '%% Coordinate of the vertices:\n\n' tikz_pic += '%% Coordinate of the vertices:\n%%\n' for v in self.Vrep_generator(): tikz_pic += dict_drawing[v][1] # Draw the interior by going in a cycle tikz_pic += '\n\n%% Drawing the interior\n\n' tikz_pic += '%%\n%%\n%% Drawing the interior\n%%\n' cyclic_vert = cyclic_sort_vertices_2d(list(self.Vrep_generator())) tikz_pic += '\\fill[facet] ' for v in cyclic_vert: tikz_pic += 'cycle {};\n' # Draw the edges in the front tikz_pic += '\n\n%% Drawing edges in the front\n\n' tikz_pic += '%%\n%%\n%% Drawing edges in the front\n%%\n' tikz_pic += edges # Finally, the vertices in front are drawn on top of everything. tikz_pic += '\n\n%% Drawing the vertices in the front\n\n' tikz_pic += '%%\n%%\n%% Drawing the vertices in the front\n%%\n' for v in self.Vrep_generator(): tikz_pic += dict_drawing[v][0] tikz_pic += '\n\n\\end{tikzpicture}' return tikz_pic def _tikz_2d_in_3d(self, view, rot_angle, scale, edge_color, facet_color, tikz_pic += '%%\n%%\n\\end{tikzpicture}' return LatexExpr(tikz_pic) def _tikz_2d_in_3d(self, view, angle, scale, edge_color, facet_color, opacity, vertex_color, axis): """ Return a string tikz_pic consisting of a tikz picture of self according to a projection view and an angle rot_angle according to a projection view and an angle angle obtained via Jmol through the current state property. INPUT: - view -- a list of length 3 representing a vector; - rot_angle -- an angle in degree from 0 to 360 (rotation along the view); - scale -- an integer specifying the scaling of the tikz picture; - edge_color, facet_color, vertex_color -- string representing colors which tikz recognize; - opacity -- a real number between 0 and 1 giving the opacity of the front facets; - axis -- a Boolean, to draw the axes at the origin. - view - list (default: [0,0,1]) representing the rotation axis. - angle - integer angle of rotation in degree from 0 to 360. - scale - integer specifying the scaling of the tikz picture. - edge_color - string representing colors which tikz recognize. - facet_color - string representing colors which tikz recognize. - vertex_color - string representing colors which tikz recognize. - opacity - real number between 0 and 1 giving the opacity of the front facets. - axis - Boolean draw the axes at the origin or not. OUTPUT: - LatexExpr -- containing the TikZ picture. EXAMPLE:: sage: P = Polyhedron(vertices=[[-1, -1, 2],[-1, 2, -1],[2, -1, -1]]) sage: P A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices. sage: Image = P._tikz_2d_in_3d(view=[0.5,-1,-0.5], angle=55, scale=3, edge_color='blue!95!black', facet_color='orange', opacity=0.5, vertex_color='yellow', axis=True) sage: print '\n'.join(Image.splitlines()[:4]) \begin{tikzpicture}% [x={(0.644647cm, -0.476559cm)}, y={(0.192276cm, 0.857859cm)}, z={(-0.739905cm, -0.192276cm)}, sage: open('polytope-tikz3.tex', 'w').write(Image3)    # not tested .. NOTE:: """ V = VectorSpace(RDF,3) view_vector = V(view) rot = rotate_arbitrary(view_vector,-(rot_angle/360)*2*pi) view_vector = vector(RDF, view) rot = rotate_arbitrary(view_vector,-(angle/360)*2*pi) rotation_matrix = rot[:2].transpose() # Creates the nodes, coordinate and tag for every vertex of the polytope. # Start to write the output tikz_pic = '' tikz_pic += '\\begin{tikzpicture}%\n' tikz_pic += '\t[x={(%fcm, %fcm)},\n' %(n(rotation_matrix[0][0]),n(rotation_matrix[0][1])) tikz_pic += '\ty={(%fcm, %fcm)},\n' %(n(rotation_matrix[1][0]),n(rotation_matrix[1][1])) tikz_pic += '\tz={(%fcm, %fcm)},\n' %(n(rotation_matrix[2][0]),n(rotation_matrix[2][1])) tikz_pic += '\t[x={(%fcm, %fcm)},\n' %(RDF(rotation_matrix[0][0]),RDF(rotation_matrix[0][1])) tikz_pic += '\ty={(%fcm, %fcm)},\n' %(RDF(rotation_matrix[1][0]),RDF(rotation_matrix[1][1])) tikz_pic += '\tz={(%fcm, %fcm)},\n' %(RDF(rotation_matrix[2][0]),RDF(rotation_matrix[2][1])) tikz_pic += '\tscale=%f,\n' %scale tikz_pic += '\tback/.style={loosely dotted, thin},\n' tikz_pic += '\tedge/.style={color=%s, thick},\n' %edge_color tikz_pic += '\tfacet/.style={fill=%s,fill opacity=%f},\n' %(facet_color,opacity) tikz_pic += '\tvertex/.style={inner sep=1pt,circle,draw=%s!25!black,' %vertex_color tikz_pic += 'fill=%s!75!black,thick,anchor=base}]\n\n\n' %vertex_color tikz_pic += 'fill=%s!75!black,thick,anchor=base}]\n%%\n%%\n' %vertex_color # Draws the axes if True if axis: tikz_pic += '\\draw[color=black,thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$};\n' # Create the coordinate of the vertices: tikz_pic += '%% Coordinate of the vertices:\n\n' tikz_pic += '%% Coordinate of the vertices:\n%%\n' for v in self.Vrep_generator(): tikz_pic += dict_drawing[v][1] # Draw the interior by going in a cycle tikz_pic += '\n\n%% Drawing the interior\n\n' tikz_pic += '%%\n%%\n%% Drawing the interior\n%%\n' cyclic_vert = cyclic_sort_vertices_2d(list(self.Vrep_generator())) tikz_pic += '\\fill[facet] ' for v in cyclic_vert: tikz_pic += 'cycle {};\n' # Draw the edges in the front tikz_pic += '\n\n%% Drawing edges in the front\n\n' tikz_pic += '%%\n%%\n%% Drawing edges in the front\n%%\n' tikz_pic += edges # Finally, the vertices in front are drawn on top of everything. tikz_pic += '\n\n%% Drawing the vertices in the front\n\n' tikz_pic += '%%\n%%\n%% Drawing the vertices in the front\n%%\n' for v in self.Vrep_generator(): tikz_pic += dict_drawing[v][0] tikz_pic += '\n\n\\end{tikzpicture}' return tikz_pic def _tikz_3d_in_3d(self, view, rot_angle, scale, edge_color, tikz_pic += '%%\n%%\n\\end{tikzpicture}' return LatexExpr(tikz_pic) def _tikz_3d_in_3d(self, view, angle, scale, edge_color, facet_color, opacity, vertex_color, axis): """ Return a string tikz_pic consisting of a tikz picture of self according to a projection view and an angle rot_angle according to a projection view and an angle angle obtained via Jmol through the current state property. INPUT: - view -- a list of length 3 representing a vector; - rot_angle -- an angle in degree from 0 to 360; - scale -- an integer specifying the scaling of the tikz picture; - edge_color, facet_color, vertex_color -- string representing colors which tikz recognize; - opacity -- a real number between 0 and 1 giving the opacity of the front facets; - axis -- a Boolean, to draw the axes at the origin. """ V = VectorSpace(RDF,3) view_vector = V(view) rot = rotate_arbitrary(view_vector,-(rot_angle/360)*2*pi) - view - list (default: [0,0,1]) representing the rotation axis. - angle - integer angle of rotation in degree from 0 to 360. - scale - integer specifying the scaling of the tikz picture. - edge_color - string representing colors which tikz recognize. - facet_color - string representing colors which tikz recognize. - vertex_color - string representing colors which tikz recognize. - opacity - real number between 0 and 1 giving the opacity of the front facets. - axis - Boolean draw the axes at the origin or not. OUTPUT: - LatexExpr -- containing the TikZ picture. EXAMPLES:: sage: P = polytopes.small_rhombicuboctahedron() sage: Image = P._tikz_3d_in_3d([3,7,5], 100, scale=3, edge_color='blue', facet_color='orange', opacity=0.5, vertex_color='green', axis=True) sage: type(Image) sage: print '\n'.join(Image.splitlines()[:4]) \begin{tikzpicture}% [x={(-0.046385cm, 0.837431cm)}, y={(-0.243536cm, 0.519228cm)}, z={(0.968782cm, 0.170622cm)}, sage: open('polytope-tikz1.tex', 'w').write(Image1)    # not tested """ view_vector = vector(RDF, view) rot = rotate_arbitrary(view_vector,-(angle/360)*2*pi) rotation_matrix = rot[:2].transpose() proj_vector = (rot**(-1))*V([0,0,1]) proj_vector = (rot**(-1))*vector(RDF, [0,0,1]) # First compute the back and front vertices and facets front_facets = [] # Start to write the output tikz_pic = '' tikz_pic += '\\begin{tikzpicture}%\n' tikz_pic += '\t[x={(%fcm, %fcm)},\n' %(n(rotation_matrix[0][0]),n(rotation_matrix[0][1])) tikz_pic += '\ty={(%fcm, %fcm)},\n' %(n(rotation_matrix[1][0]),n(rotation_matrix[1][1])) tikz_pic += '\tz={(%fcm, %fcm)},\n' %(n(rotation_matrix[2][0]),n(rotation_matrix[2][1])) tikz_pic += '\t[x={(%fcm, %fcm)},\n' %(RDF(rotation_matrix[0][0]),RDF(rotation_matrix[0][1])) tikz_pic += '\ty={(%fcm, %fcm)},\n' %(RDF(rotation_matrix[1][0]),RDF(rotation_matrix[1][1])) tikz_pic += '\tz={(%fcm, %fcm)},\n' %(RDF(rotation_matrix[2][0]),RDF(rotation_matrix[2][1])) tikz_pic += '\tscale=%f,\n' %scale tikz_pic += '\tback/.style={loosely dotted, thin},\n' tikz_pic += '\tedge/.style={color=%s, thick},\n' %edge_color tikz_pic += '\tfacet/.style={fill=%s,fill opacity=%f},\n' %(facet_color,opacity) tikz_pic += '\tvertex/.style={inner sep=1pt,circle,draw=%s!25!black,' %vertex_color tikz_pic += 'fill=%s!75!black,thick,anchor=base}]\n\n\n' %vertex_color tikz_pic += 'fill=%s!75!black,thick,anchor=base}]\n%%\n%%\n' %vertex_color # Draws the axes if True if axis: tikz_pic += '\\draw[color=black,thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$};\n' # Create the coordinate of the vertices tikz_pic += '%% Coordinate of the vertices:\n\n' tikz_pic += '%% Coordinate of the vertices:\n%%\n' for v in self.Vrep_generator(): tikz_pic += dict_drawing[v][1] # Draw the edges in the back tikz_pic += '\n\n%% Drawing edges in the back\n\n' tikz_pic += '%%\n%%\n%% Drawing edges in the back\n%%\n' tikz_pic += first_part # Draw the vertices on top of the back-edges tikz_pic += '\n\n%% Drawing vertices in the back\n\n' tikz_pic += '%%\n%%\n%% Drawing vertices in the back\n%%\n' for v in self.Vrep_generator(): if v in back_vertices and v not in front_vertices: tikz_pic += dict_drawing[v][0] # Draw the facets in the front by going in cycles for every facet. tikz_pic += '\n\n%% Drawing the facets\n\n' tikz_pic += '%%\n%%\n%% Drawing the facets\n%%\n' for facet in front_facets: cyclic_vert = cyclic_sort_vertices_2d(list(facet.incident())) tikz_pic += '\\fill[facet] ' tikz_pic += 'cycle {};\n' # Draw the edges in the front tikz_pic += '\n\n%% Drawing edges in the front\n\n' tikz_pic += '%%\n%%\n%% Drawing edges in the front\n%%\n' tikz_pic += second_part # Finally, the vertices in front are drawn on top of everything. tikz_pic += '\n\n%% Drawing the vertices in the front\n\n' tikz_pic += '%%\n%%\n%% Drawing the vertices in the front\n%%\n' for v in self.Vrep_generator(): if v in front_vertices: tikz_pic += dict_drawing[v][0] tikz_pic += '\n\n\\end{tikzpicture}' return tikz_pic tikz_pic += '%%\n%%\n\\end{tikzpicture}' return LatexExpr(tikz_pic) ############################################################# def cyclic_sort_vertices_2d(Vlist):