# Drawing polyhedra using TikZ with semi-transparent and shading effect

I would like to draw an Octahedron using TikZ, I found nowhere to start, I tried drawing 6 points and then connecting them properly, but this method gives no 3D feel at all, this is my drawing:

\begin{tikzpicture}[scale=3]
\coordinate (A1) at (0,0);
\coordinate (A2) at (0.6,0.2);
\coordinate (A3) at (1,0);
\coordinate (A4) at (0.4,-0.2);
\coordinate (B1) at (0.5,0.5);
\coordinate (B2) at (0.5,-0.5);

\draw[dashed] (A1) -- (A2) -- (A3);
\draw (A1) -- (A4) -- (A3);
\draw[dashed] (B1) -- (A2) -- (B2);
\draw (B1) -- (A4) -- (B2);
\draw (B1) -- (A1) -- (B2) -- (A3) --cycle;
\end{tikzpicture}


I wonder how can I add shading to each surface, and make each surface semi-transparent, also adjust the invisible edges' color lighter from the observer perspective, like the one on the wikipedia page:

So my question is: How to polish my TikZ drawing to make a polyhedron look like a 3D object? or is there a package other than TikZ could do that? Thanks

You can use the fill and opacity constructs:

\documentclass{article}
\usepackage{tikz}

\definecolor{cof}{RGB}{219,144,71}
\definecolor{pur}{RGB}{186,146,162}
\definecolor{greeo}{RGB}{91,173,69}
\definecolor{greet}{RGB}{52,111,72}

\begin{document}

\begin{tikzpicture}[thick,scale=5]
\coordinate (A1) at (0,0);
\coordinate (A2) at (0.6,0.2);
\coordinate (A3) at (1,0);
\coordinate (A4) at (0.4,-0.2);
\coordinate (B1) at (0.5,0.5);
\coordinate (B2) at (0.5,-0.5);

\begin{scope}[thick,dashed,,opacity=0.6]
\draw (A1) -- (A2) -- (A3);
\draw (B1) -- (A2) -- (B2);
\end{scope}
\draw[fill=cof,opacity=0.6] (A1) -- (A4) -- (B1);
\draw[fill=pur,opacity=0.6] (A1) -- (A4) -- (B2);
\draw[fill=greeo,opacity=0.6] (A3) -- (A4) -- (B1);
\draw[fill=greet,opacity=0.6] (A3) -- (A4) -- (B2);
\draw (B1) -- (A1) -- (B2) -- (A3) --cycle;
\end{tikzpicture}

\end{document}


TikZ also has an xyz-coordinate system that is quite useful here. There's a nice answer making use of this feature: Table, i.e. the piece of furniture on which one eats, in Tikz

Here's a way of drawing your octahedron. To rotate it, play around with the x, y and z options of the tikzpicture:

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[line join=bevel,z=-5.5]
\coordinate (A1) at (0,0,-1);
\coordinate (A2) at (-1,0,0);
\coordinate (A3) at (0,0,1);
\coordinate (A4) at (1,0,0);
\coordinate (B1) at (0,1,0);
\coordinate (C1) at (0,-1,0);

\draw (A1) -- (A2) -- (B1) -- cycle;
\draw (A4) -- (A1) -- (B1) -- cycle;
\draw (A1) -- (A2) -- (C1) -- cycle;
\draw (A4) -- (A1) -- (C1) -- cycle;
\draw [fill opacity=0.7,fill=green!80!blue] (A2) -- (A3) -- (B1) -- cycle;
\draw [fill opacity=0.7,fill=orange!80!black] (A3) -- (A4) -- (B1) -- cycle;
\draw [fill opacity=0.7,fill=green!30!black] (A2) -- (A3) -- (C1) -- cycle;
\draw [fill opacity=0.7,fill=purple!70!black] (A3) -- (A4) -- (C1) -- cycle;
\end{tikzpicture}

\end{document}


PSTricks can handle this one. Run it with xelatex or latex->dvips->ps2pdf

\documentclass{article}
\usepackage[dvipsnames]{pstricks}
\usepackage{pst-solides3d}
\begin{document}

\begin{pspicture}(-2.5,-2)(2.5,2.5)
\psset{lightsrc=10 20 30,viewpoint=40 10 30 rtp2xyz,Decran=40}
\psSolid[object=octahedron,a=3,linecolor=blue,
opacity=0.6,hollow,hue=0 1,
action=draw**]
% \axesIIID(3,3,3)(4,4,4)
\end{pspicture}

\end{document}


• I'm trying to make 3D polyhedra and this is nicer than tikz-* for me because you don't need to manually specify the face order! (You specify the vertices, and for each face, its vertices in anticlockwise order relative to the exterior.) – daveagp Jun 3 '12 at 0:23

It think a solution with tikz-3dplot should not be missing here.

\documentclass{minimal}
\usepackage{tikz,tikz-3dplot}

\definecolor{cof}{RGB}{219,144,71}
\definecolor{pur}{RGB}{186,146,162}
\definecolor{greeo}{RGB}{91,173,69}
\definecolor{greet}{RGB}{52,111,72}

\tdplotsetmaincoords{70}{165}

\begin{document}
\begin{tikzpicture}[scale=3,tdplot_main_coords]
\coordinate (O) at (0,0,0);

%    \draw[thick,->] (0,0,0) -- (1,0,0) node[anchor=north east]{$x$};
%    \draw[thick,->] (0,0,0) -- (0,1,0) node[anchor=north west]{$y$};
%    \draw[thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$};

\tdplotsetcoord{A}{1}{90}{0}    % cartesian (1,0,0)
\tdplotsetcoord{B}{1}{90}{90}   % cartesian (0,1,0)
\tdplotsetcoord{C}{1}{90}{180}  % cartesian (-1,0,0)
\tdplotsetcoord{D}{1}{90}{270}  % cartesian (0,-1,0)
\tdplotsetcoord{E}{1}{0}{0}     % cartesian (0,0,1)
\tdplotsetcoord{F}{1}{180}{0}   % cartesian (0,0,-1)

\draw (A) -- (B) -- (C);
\draw (E) -- (A) -- (F);
\draw (E) -- (B) -- (F);
\draw (E) -- (C) -- (F);
\draw[dashed] (C) -- (D) -- (A);
\draw[dashed](E) -- (D) -- (F);
\fill[cof,opacity=0.6](A) -- (B) -- (E) -- cycle;
\fill[pur,opacity=0.6](A) -- (B) -- (F) -- cycle;
\fill[greeo,opacity=0.6](B) -- (C) -- (E) -- cycle;
\fill[greet,opacity=0.6](B) -- (C) -- (F) -- cycle;
\end{tikzpicture}
\end{document}


• \tdplotsetcoord{A}{1}{90}{0} % cartesian (1,0,0) is better spelt \coordinate (A) at (1, 0, 0) – Eric Nov 1 '19 at 13:25

To add another approach to the collection: The development version of pgfplots supports "patch plots", where the user supplies a collection of polygons to be plotted:

\documentclass{minimal}

\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}[axis equal]
patch table={
0 1 4\\
1 2 4\\
2 3 4\\
3 0 4\\
0 1 5\\
1 2 5\\
2 3 5\\
3 0 5\\
}]
table
{
-1 0 0\\
0 -1 0\\
1 0 0\\
0 1 0\\
0 0 1\\
0 0 -1\\
};
\end{axis}
\end{tikzpicture}
\end{document}


With tkz-berge and some macros of TikZ but tkz-berge is not a perfect tool for this kind of picture. This is only to give some ideas.

%  based on the work of Andreas Menge with my package
\documentclass{scrartcl}
\usepackage[usenames,dvipsnames,pdftex]{xcolor}
\usepackage{tkz-berge}
\newcommand{\GlobalTransformation}[2]{%
\pgftransformcm{1}{0}{0.6}{0.2}{\pgfpoint{#1cm}{#2cm}}
}
% some colors from  Gonzalo Medina' answer
\definecolor{cof}{RGB}{219,144,71}
\definecolor{pur}{RGB}{186,146,162}
\definecolor{greeo}{RGB}{91,173,69}
\definecolor{greet}{RGB}{52,111,72}

\begin{document}
\pagestyle{empty}

\begin{tikzpicture}
\GraphInit[vstyle=Art]
\begin{scope}
\GlobalTransformation{0}{0}
\grEmptyCycle[prefix=a,RA=4]{4}
\end{scope}
\begin{scope}
\GlobalTransformation{0}{-4}
\Vertex{x}
\end{scope}
\begin{scope}
\GlobalTransformation{0}{4}
\Vertex{y}
\end{scope}
% add color to the faces
\fill[color=cof,opacity=0.6] (a2.center)--(y.center)--(a3.center)--cycle;
\fill[color=pur,opacity=0.6] (y.center)--(a3.center)--(a0.center)--cycle;
\fill[color=greeo,opacity=0.6] (x.center)--(a2.center)--(a3.center)--cycle;
\fill[color=greet,opacity=0.6] (x.center)--(a3.center)--(a0.center)--cycle;
\Edges(a0,y,a2,a3,a0,x,a2)  \Edges(y,a3,x,a2)
% dashed edges
\tikzset{EdgeStyle/.append style={dashed}}
\Edges(y,a1,x)  \Edges(a0,a1,a2)
% redraw some vertices
\foreach \n in {a0,a2,a3,x,y} {\Vertex[Node]{\n}}
\end{tikzpicture}

\end{document}


I suggest you to give a look at Sketch program here:

http://www.frontiernet.net/~eugene.ressler/

It is a language based on C that permits you to create a simple 3D scene.

After the compilation it gives you a tex file where TikZ code is written.

The useful thing about it is that if you want to change the view point, it needs only to change the eye position and another compilation.

FYI: It is possible to use Sage to produce TikZ pictures of any 3-D polytope. See this ticket followed by this ticket. For documentations and examples, see the official reference of sage and the page of the author.

Here is an example code (from the author's webpage) generated by Sage. As you can see, the code can be customized as you want (semi-transparent, shading effect, etc.).

\begin{tikzpicture}%
[x={(0.249656cm, -0.577639cm)},
y={(0.777700cm, -0.358578cm)},
z={(-0.576936cm, -0.733318cm)},
scale=3.000000,
back/.style={loosely dashed,line width=2pt},
edge/.style={color=yellow, line width=2pt},
facet/.style={fill=cyan,fill opacity=0.400000},
vertex/.style={inner sep=4pt,star,star points=7,draw=blue!75!white,fill=blue!85!white,thick,anchor=base}]
%
%
%% Coordinate of the vertices:
%%
\coordinate (-0.500, -0.500, -0.500) at (-0.500, -0.500, -0.500);
\coordinate (-1.00, 0.000, 0.000) at (-1.00, 0.000, 0.000);
\coordinate (-1.00, 0.000, 1.00) at (-1.00, 0.000, 1.00);
\coordinate (-1.00, 1.00, 0.000) at (-1.00, 1.00, 0.000);
\coordinate (-1.00, 1.00, 1.00) at (-1.00, 1.00, 1.00);
\coordinate (0.000, -1.00, 0.000) at (0.000, -1.00, 0.000);
\coordinate (0.000, -1.00, 1.00) at (0.000, -1.00, 1.00);
\coordinate (0.000, 0.000, -1.00) at (0.000, 0.000, -1.00);
\coordinate (0.000, 1.00, -1.00) at (0.000, 1.00, -1.00);
\coordinate (1.00, -1.00, 0.000) at (1.00, -1.00, 0.000);
\coordinate (1.00, -1.00, 1.00) at (1.00, -1.00, 1.00);
\coordinate (1.00, 0.000, -1.00) at (1.00, 0.000, -1.00);
\coordinate (1.00, 1.00, -1.00) at (1.00, 1.00, -1.00);
\coordinate (1.00, 1.00, 1.00) at (1.00, 1.00, 1.00);
%%
%%
%% Drawing edges in the back
%%
\draw[edge,back] (0.000, -1.00, 0.000) -- (1.00, -1.00, 0.000);
\draw[edge,back] (0.000, 0.000, -1.00) -- (1.00, 0.000, -1.00);
\draw[edge,back] (1.00, -1.00, 0.000) -- (1.00, -1.00, 1.00);
\draw[edge,back] (1.00, -1.00, 0.000) -- (1.00, 0.000, -1.00);
\draw[edge,back] (1.00, 0.000, -1.00) -- (1.00, 1.00, -1.00);
%%
%%
%% Drawing vertices in the back
%%
\node[vertex] at (1.00, -1.00, 0.000)     {};
\node[vertex] at (1.00, 0.000, -1.00)     {};
%%
%%
%% Drawing the facets
%%
\fill[facet] (1.00, 1.00, 1.00) -- (-1.00, 1.00, 1.00) -- (-1.00, 1.00, 0.000) -- (0.000, 1.00, -1.00) -- (1.00, 1.00, -1.00) -- cycle {};
\fill[facet] (1.00, 1.00, 1.00) -- (-1.00, 1.00, 1.00) -- (-1.00, 0.000, 1.00) -- (0.000, -1.00, 1.00) -- (1.00, -1.00, 1.00) -- cycle {};
\fill[facet] (0.000, -1.00, 1.00) -- (-1.00, 0.000, 1.00) -- (-1.00, 0.000, 0.000) -- (-0.500, -0.500, -0.500) -- (0.000, -1.00, 0.000) -- cycle {};
\fill[facet] (0.000, 1.00, -1.00) -- (-1.00, 1.00, 0.000) -- (-1.00, 0.000, 0.000) -- (-0.500, -0.500, -0.500) -- (0.000, 0.000, -1.00) -- cycle {};
\fill[facet] (-1.00, 1.00, 1.00) -- (-1.00, 0.000, 1.00) -- (-1.00, 0.000, 0.000) -- (-1.00, 1.00, 0.000) -- cycle {};
%%
%%
%% Drawing edges in the front
%%
\draw[edge] (-0.500, -0.500, -0.500) -- (-1.00, 0.000, 0.000);
\draw[edge] (-0.500, -0.500, -0.500) -- (0.000, -1.00, 0.000);
\draw[edge] (-0.500, -0.500, -0.500) -- (0.000, 0.000, -1.00);
\draw[edge] (-1.00, 0.000, 0.000) -- (-1.00, 0.000, 1.00);
\draw[edge] (-1.00, 0.000, 0.000) -- (-1.00, 1.00, 0.000);
\draw[edge,->,orange] (-1.00, 0.000, 1.00) -- node[below left] {\color{white}FLOW} (-1.00, 1.00, 1.00);
\draw[edge] (-1.00, 0.000, 1.00) -- (0.000, -1.00, 1.00);
\draw[edge,->,orange] (-1.00, 1.00, 0.000) -- node[below right] {\color{white}TO THE} (-1.00, 1.00, 1.00);
\draw[edge] (-1.00, 1.00, 0.000) -- (0.000, 1.00, -1.00);
\draw[edge,<-,orange] (-1.00, 1.00, 1.00) -- node[above left] {\color{white}VERTEX}(1.00, 1.00, 1.00);
\draw[edge] (0.000, -1.00, 0.000) -- (0.000, -1.00, 1.00);
\draw[edge] (0.000, -1.00, 1.00) -- (1.00, -1.00, 1.00);
\draw[edge] (0.000, 0.000, -1.00) -- (0.000, 1.00, -1.00);
\draw[edge] (0.000, 1.00, -1.00) -- (1.00, 1.00, -1.00);
\draw[edge] (1.00, -1.00, 1.00) -- (1.00, 1.00, 1.00);
\draw[edge] (1.00, 1.00, -1.00) -- (1.00, 1.00, 1.00);
%%
%%
%% Drawing the vertices in the front
%%
\node[vertex] at (-0.500, -0.500, -0.500)     {$\alpha$};
\node[vertex] at (-1.00, 0.000, 0.000)     {};
\node[vertex] at (-1.00, 0.000, 1.00)     {};
\node[vertex] at (-1.00, 1.00, 0.000)     {};
\node at (-1.00, 1.00, 1.00)     {};
\node[vertex] at (0.000, -1.00, 0.000)     {};
\node[vertex] at (0.000, -1.00, 1.00)     {};
\node[vertex] at (0.000, 0.000, -1.00)     {};
\node[vertex] at (0.000, 1.00, -1.00)     {};
\node[vertex] at (1.00, -1.00, 1.00)     {};
\node[vertex,label=right:{$\Sigma\times\Omega$}] at (1.00, 1.00, -1.00)     {};
\node[vertex] at (1.00, 1.00, 1.00)     {\color{white}$\lim_{n\rightarrow \infty}$};
%%
%%
\end{tikzpicture}


And below is an example picture from the author's webpage:

This should work.

\begin{tikzpicture}[scale=3]
\coordinate (A1) at (0,0);
\coordinate (A2) at (0.6,0.2);
\coordinate (A3) at (1,0);
\coordinate (A4) at (0.4,-0.2);
\coordinate (B1) at (0.5,0.5);
\coordinate (B2) at (0.5,-0.5);

\draw[dashed] (A1) -- (A2) -- (A3);
\draw[dashed] (B1) -- (A2) -- (B2);

\filldraw[fill=red,fill opacity=0.7] (B1)--(A4)--(A3)--cycle;
\filldraw[fill=green,fill opacity=0.7] (B1)--(A4)--(A1)--cycle;
\filldraw[fill=green!60!black,fill opacity=0.7] (B2)--(A4)--(A1)--cycle;
\filldraw[fill=purple,fill opacity=0.7] (B2)--(A4)--(A3)--cycle;
\end{tikzpicture}


You probably have to correct the colours.

\documentclass[oneside,tikz]{book}
\usepackage{tikz}
\usepackage{caption}
\usepackage{float}
\usepackage{graphicx}
\usetikzlibrary{calc}

\begin{document}
\begin{figure}[H]
\begin{center}
\begin{tikzpicture}[line join=bevel,z=-5.5,scale=3]
\coordinate (A1) at (0,0,-1);
%\path(A1) node {A1};
\coordinate (A2) at (-1,0,0);
%\path(A2) node {A2};
\coordinate (A3) at (0,0,1);
%\path(A3) node {A3};
\coordinate (A4) at (1,0,0);
%\path(A4) node {A4};
\coordinate (B1) at (0,1,0);
%\path(B1) node {B1};
\coordinate (C1) at (0,-1,0);
%\path(C1) node {C1};
\coordinate (X) at (0,0,0);
%\path(X) node {X};
\draw (A1) -- (A2) -- (B1) -- cycle;
\draw (A4) -- (A1) -- (B1) -- cycle;
\draw (A1) -- (A2) -- (C1) -- cycle;
\draw (A4) -- (A1) -- (C1) -- cycle;
\draw(A1) -- (A3);
\draw(A2) -- (A4);
\draw(B1) -- (C1);
\draw [fill opacity=0.7,fill=green!80!blue] (A2) -- (A3) -- (B1) -- cycle;
\draw [fill opacity=0.7,fill=green!70!black] (A2) -- (A3) -- (X) -- cycle;
\draw [fill opacity=0.7,fill=orange!80!black] (A3) -- (A4) -- (B1) -- cycle;
\draw [fill opacity=0.7,fill=orange!80!black] (X) -- (A4) -- (B1) -- cycle;
\draw [fill opacity=0.7,fill=green!30!black] (A2) -- (A3) -- (C1) -- cycle;
\draw [fill opacity=0.7,fill=purple!70!black] (A3) -- (A4) -- (C1) -- cycle;
\draw [fill opacity=0.7,fill=purple!80!black] (A3) -- (X) -- (C1) -- cycle;
\draw [fill opacity=0.9,fill=orange!60!black] (A3) -- (A4) -- (X) -- cycle;
\end{tikzpicture}