# Generating Tikz codes from Sage for drawing scattering points in 3D

I am a beginner in Sage and Tikz, and have written the following snippet of Sage code:

P = Polyhedron(ieqs=[(30, -2, -2, -1), (25, -1.5, -2, -3),(20,-2,-1,-1), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)])
pts = P.integral_points()
point3d(pts,rgbcolor=(1,0, 0), size=10) + P.plot(rgbcolor = 'yellow', opacity = 0.5)


The purpose of the codes is to generate the integral points interior to the polytopes bound by 6 inequalities as given in the codes. The output is in the following link:

http://www.cse.cuhk.edu.hk/~jlee/dots.png (www.cse.cuhk.edu.hk/~jlee/dots.png)

I tried to follow the following reference:

doc.sagemath.org/html/en/thematic_tutorials/polytope_tikz.html

to generate Tikz codes for LaTeX and failed. Unlike Polyhedron which is a kind of object that can respond to "projection", point3d generates only a Graphics3D object which doesn't understand "projection".

Is there any way to output these points to Tikz?

Also, is it possible to ask Sage to color each of the facets of the polytope in different colors (just like Tikz can)?

edit retag close merge delete

Sort by » oldest newest most voted

The following is a possibility to get a picture:

import re
P = Polyhedron( ieqs=[ (30, -2  , -2, -1),
(25, -1.5, -2, -3),
(20, -2  , -1, -1),
( 0,  1  ,  0,  0),
( 0,  0  ,  1,  0),
( 0,  0  ,  0,  1), ] )
tex = P.projection().tikz( view=[775,386,500], angle=105, scale=0.7, opacity=0.1 )
tex = re.sub( r'\\end\{tikzpicture\}'
, '% \end{tikzpicture} % manually commented, we still have to work'
, tex )

for v in P.integral_points():
tex += ( '\n\\node[inner sep=1pt,circle,draw=red!25!black,fill=red!75!black,thick,anchor=base] at (%s, %s, %s) {};'
% tuple(v) )

tex += '\n\n\\end{tikzpicture}'
print tex


The view point, and maybe all optional parameters declared above should be change to follow the given needs.

The string tex contains the tikz code to be inserted in a valid $\LaTeX$ document, with correct imports for tikz, e.g.

\usepackage{tikz}


should be enough. Here, as a matter of taste, manual adjustments of the code are still needed. For instance:

The faces are colored w.r.t. the specifications in the lines starting with \fill[facet], and the facet style is declared in

\begin{tikzpicture}%
[x={(0.497546cm, 0.859773cm)},
y={(-0.106336cm, -0.071189cm)},
z={(0.860895cm, -0.505690cm)},
scale=0.700000,
back/.style={loosely dotted, thin},
edge/.style={color=blue!95!black, thick},
facet/.style={fill=blue!95!black,fill opacity=0.100000},
vertex/.style={inner sep=1pt,circle,draw=green!25!black,fill=green!75!black,thick,anchor=base}]


If you need special colors for each face, than define them either inside the \begin{tikzpicture}[ ... ] as facet1/.style={...} or directly at the right place. The back style should also be adjusted. Herein is also a good place to insert for instance something like

latticepoint/.style={inner sep=1pt,circle,draw=red!25!black,fill=red!75!black,thick,anchor=base}


and to use this style in the changed line of code

tex += ( '\n\\node[latticepoint] at (%s, %s, %s) {};' % tuple(v) )


to have a more compact $\LaTeX$ code. This should be a good start, good luck!

more

You can change the vertex, edge and facet color directly in the tikz method using the parameters "vertex_color", "edge_color" and "facet_color". They can take any string argument which tikz can interpret as a color. One slight issue with the above loop on integral points is that it may not iterate the interior lattice points according to the projection, i.e. from the furthest to closest to the screen, and maybe some point nodes intersect in a weird way. You could sort them as follows:

proj_vector = vector([775,386,500])
linear_proj = [(proj_vector*p,p) for p in P.integral_points()]
linear_proj.sort()
for v in linear_proj:
tex += ( '\n\\node[inner sep=1pt,circle,draw=red!25!black,fill=red!75!black,thick,anchor=base] at (%s, %s, %s) {};' %tuple(v)