# How to draw small a triangle mesh using tikz?

My question is simple but I haven't been able to find any answers.

How can I draw a small a small triangle mesh (4-5) triangles using tikz and label each node and triangle face?

This is a diagram that I would like to recreate (but fewer triangles and labels for each node and triangle face).

Let me be clear I am not trying to generate a mesh or read from a mesh file. I Just want to make a simple diagram with 4-5 triangles with labels.

• Since LaTeX is not a mesh generator, it would probably work best to read in the node/connectivity data from an external file and then use something like tikz to take that data and plot it. Apr 17 '19 at 14:48
• There was an answer (now deleted, unfortunately) which had an example on how to use the luamesh package to generate meshes in LuaTeX. Your TeX distribution should already have that. Apr 17 '19 at 14:49
• If you have a prescription for the mesh nodes, you can most likely draw it. However, expecting us to infer the prescription from the screen shot may be too optimistic.
– user121799
Apr 17 '19 at 14:51
• @Marmot Let me clarify I don't want to actually recreate a mesh in latex. I just want to make a diagram with a few triangles. I have other ways of displaying meshes in latex. I just want to make a simplified diagram that explains what I am doing but instead of 100+ triangles it only has 4-5. I don't care what the triangles are.
– AzJ
Apr 17 '19 at 14:55
• You can draw a triangle with e.g. \draw (-1.5,-1) coordinate [label=left:$A$] (A) -- (1.5,1) coordinate [label=above:$B$] (B) -- (1.5,-1)coordinate [label=below right:$C$] (C) -- cycle; but most likely this is not what you are after, right?
– user121799
Apr 17 '19 at 14:58

I'm a beginner at tikz and I just developed this on the fly, so it is not pretty. I also included a lot of diagnostic text so as to help you follow my logic.

It takes a node file that provides node numbers and their coordinates.

And an element file that gives an element number and the nodes that make up the connectivity of the element. Doesn't matter if they are triangles or quads, or something else.

The macro \drawmesh, used inside a tikzpicture creates the string of \draws to formulate the mesh. Note numbers, coordinates, element connectivity are all stored in accessible, expandable arrays \noddat[row,col] and \eledat[row,col].

EDITED to add the macro \labelnodes.

EDITED to add the macro \labelelements.

EDITED to allow for either file input or manual input of node and element data. The file input approach would look like this:

\begin{filecontents*}{nodedata.dat}
1  0.000  0.000
2  1.000  0.000
3  2.000  0.500
4  0.000  1.000
5  1.000  1.000
6  1.750  1.300
7  2.700  0.800
8  2.300  1.700
\end{filecontents*}
\begin{filecontents*}{elementdata.dat}
1  1  2  5
2  5  4  1
3  2  3  6
4  6  5  2
5  3  7  8  6
\end{filecontents*}


The manual input approach like this:

\def\nodedata{1 0.000 0.000,2 1.000 0.000,3 2.000 0.500,
4 0.000 1.000,5 1.000 1.000,6 1.750 1.300,7 2.700 0.800,8 2.300 1.700}
\def\elementdata{1 1 2 5,2 5 4 1,3 2 3 6,4 6 5 2,5 3 7 8 6}


EDITED to allow several alternatives for \labelnode appearance

EDITED to allow LaTeX style labels for nodes and elements, rather than just numbers.

The MWE:

\documentclass{article}
\usetikzlibrary{calc}
\begin{filecontents*}{nodedata.dat}
1  0.000  0.000
2  1.000  0.000
3  2.000  0.500
4  0.000  1.000
5  1.000  1.000
6  1.750  1.300
7  2.700  0.800
n_8  2.300  1.700
\end{filecontents*}
\begin{filecontents*}{elementdata.dat}
E_1  1  2  5
2  5  4  1
3  2  3  6
4  6  5  2
5  3  7  n_8  6
\end{filecontents*}

\newcommand\coord[2][]{%
\edef\comparenode{#2}%
\foreachitem\zzz\in\noddat[]{%
\edef\testnode{\noddat[\zzzcnt,1]}%
\ifx\testnode\comparenode
}%
}

\edef\xtmp{#2}%
}

\newcommand\drawmesh[1][\draw]{%
\def\tmp{}%
\foreachitem\z\in\eledat[]{%
\foreachitem\zz\in\eledat[\zcnt]{%
\ifnum\zzcnt=1\relax\else
\ifnum\zzcnt<\listlen\eledat[\zcnt]\relax
\ifnum\zzcnt=2\relax\coord{\zz}\fi
\coord{\eledat[\zcnt,\the\numexpr\zzcnt+1\relax]}%
\else
\coord{\eledat[\zcnt,2]}%
\fi
\fi
}%
}%
\tmp%
}

\newcommand\labelnodes[1][\node at]{%
\foreachitem\z\in\noddat[]{%
#1 (\noddat[\zcnt,2],\noddat[\zcnt,3]){%
%% ALTERNATIVE 1
%      \textcolor{red}{$\noddat[\zcnt,1]$}};
%% ALTERNATIVE 2
\fboxsep=0pt\relax
\colorbox{white}{\color{red}$\noddat[\zcnt,1]$}};
%%
}%
}

\newcommand\labelelements[1][\node at]{%
\foreachitem\z\in\eledat[]{%
\def\tmp{#1 }%
\addtomacro\tmp{($} \foreachitem\zz\in\eledat[\zcnt]{% \ifnum\zzcnt=1\relax\else \ifnum\zzcnt=2\relax\else\addtomacro\tmp{ + }\fi% \coord[{/\the\numexpr\listlen\eledat[\zcnt]-1\relax}]{% \eledat[\zcnt,\zzcnt]}% \fi }% \addtomacro\tmp{$)}%
\xaddtomacro\tmp{{\noexpand\textcolor{blue!70!green}{$\eledat[\zcnt,1]$}};}%
\tmp
}%
}

\ignoreemptyitems%
\setsepchar{,/ }%
}
\begin{document}
%% FILE INPUT

%% OR MANUAL INPUT
%\def\nodedata{1 0.000 0.000,2 1.000 0.000,3 2.000 0.500,
%4 0.000 1.000,5 1.000 1.000,6 1.750 1.300,7 2.700 0.800,n_8 2.300 1.700}
%\def\elementdata{E_1 1 2 5,2 5 4 1,3 2 3 6,4 6 5 2,5 3 7 n_8 6}

Selected data extracts: \eledat[3,3], \noddat[3,3]

Segment list in terms of node numbers:\\
\foreachitem\z\in\eledat[]{%
Element $\eledat[\zcnt,1]$:
\foreachitem\zz\in\eledat[\zcnt]{%
\ifnum\zzcnt=1\relax\else
\ifnum\zzcnt<\listlen\eledat[\zcnt]\relax
$\zz$--$\eledat[\zcnt,\the\numexpr\zzcnt+1\relax]$,
\else
$\zz$--$\eledat[\zcnt,2]$
\fi
\fi
}%
\\
}

Segment list in terms of node coordinates:\\
\drawmesh[draw]

\begin{figure}[ht]
\centering
\begin{tikzpicture}[scale=1.5]
\drawmesh
\labelnodes
\labelelements
\end{tikzpicture}
\caption{A finite element mesh}
\end{figure}
\end{document}


Without all the diagnostic stuff included, and choosing manual over file input as the mode of input, the code is a bit more streamlined

\documentclass{article}
\usetikzlibrary{calc}
\newcommand\coord[2][]{%
\edef\comparenode{#2}%
\foreachitem\zzz\in\noddat[]{%
\edef\testnode{\noddat[\zzzcnt,1]}%
\ifx\testnode\comparenode
}%
}
\edef\xtmp{#2}%
}
\newcommand\drawmesh[1][\draw]{%
\def\tmp{}%
\foreachitem\z\in\eledat[]{%
\foreachitem\zz\in\eledat[\zcnt]{%
\ifnum\zzcnt=1\relax\else
\ifnum\zzcnt<\listlen\eledat[\zcnt]\relax
\ifnum\zzcnt=2\relax\coord{\zz}\fi
\coord{\eledat[\zcnt,\the\numexpr\zzcnt+1\relax]}%
\else
\coord{\eledat[\zcnt,2]}%
\fi
\fi
}%
}%
\tmp%
}
\newcommand\labelnodes[1][\node at]{%
\foreachitem\z\in\noddat[]{%
#1 (\noddat[\zcnt,2],\noddat[\zcnt,3]){%
\fboxsep=0pt\relax
\colorbox{white}{\color{red}$\noddat[\zcnt,1]$}};
}%
}
\newcommand\labelelements[1][\node at]{%
\foreachitem\z\in\eledat[]{%
\def\tmp{#1 }%
\addtomacro\tmp{($} \foreachitem\zz\in\eledat[\zcnt]{% \ifnum\zzcnt=1\relax\else \ifnum\zzcnt=2\relax\else\addtomacro\tmp{ + }\fi% \coord[{/\the\numexpr\listlen\eledat[\zcnt]-1\relax}]{% \eledat[\zcnt,\zzcnt]}% \fi }% \addtomacro\tmp{$)}%
\xaddtomacro\tmp{{\noexpand\textcolor{blue!70!green}{$\eledat[\zcnt,1]$}};}%
\tmp
}%
}
\ignoreemptyitems%
\setsepchar{,/ }%
}
\begin{document}
\def\nodedata{1 0.000 0.000,2 1.000 0.000,3 2.000 0.500,
4 0.000 1.000,5 1.000 1.000,6 1.750 1.300,7 2.700 0.800,n_8 2.300 1.700}
\def\elementdata{E_1 1 2 5,2 5 4 1,3 2 3 6,4 6 5 2,5 3 7 n_8 6}
\begin{figure}[ht]
\centering
\begin{tikzpicture}[scale=1.5]
\drawmesh
\labelnodes
\labelelements
\end{tikzpicture}
\caption{A finite element mesh}
\end{figure}
\end{document}

• May I recommend section 4.6.13 Patch Plots of the pgfplots manual?
– user121799
Apr 17 '19 at 18:19
• @marmot May I recommend looking at the last line of my profile (tex.stackexchange.com/users/25858/steven-b-segletes?tab=profile)? I enjoy reinventing the wheel! :^) Apr 17 '19 at 18:20
• I did not mean to be nasty, and apologize if I was. It is just that the patch plots work very similarly to what you are doing, define a set of vertices and then just provide the data how one is to connect them.
– user121799
Apr 17 '19 at 18:23
• @marmot No apologies are necessary. My answer was merely be snide on my part. I am sure software already exists, but this looked like a good learning exercise to reinvent the wheel. Apr 17 '19 at 18:28
• @marmot In particular, I wanted to see how the listofitems package could streamline this process. So I am very sorry for being sarcastic towards you. Apr 17 '19 at 18:51