1

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).

enter image description here

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. – Steven B. Segletes Apr 17 at 14:48
  • 1
    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. – Phelype Oleinik Apr 17 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 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 at 14:55
  • 1
    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 at 14:58
1

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*}
\readmesh{nodedata.dat}{elementdata.dat}

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}
\readmesh{}{}

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}
\usepackage{tikz,listofitems,readarray,filecontents}
\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
      \xaddtomacro\tmp{(\noddat[\zzzcnt,2]#1,\noddat[\zzzcnt,3]#1)}\fi
  }%
}

\makeatletter\let\addtomacro\g@addto@macro\makeatother
\newcommand\xaddtomacro[2]{%
  \edef\xtmp{#2}%
  \expandafter\addtomacro\expandafter#1\expandafter{\xtmp}%
}

\newcommand\drawmesh[1][\draw]{%
  \def\tmp{}%
  \foreachitem\z\in\eledat[]{%
    \addtomacro\tmp{#1}%
    \foreachitem\zz\in\eledat[\zcnt]{%
      \ifnum\zzcnt=1\relax\else
        \ifnum\zzcnt<\listlen\eledat[\zcnt]\relax
          \ifnum\zzcnt=2\relax\coord{\zz}\fi
          \addtomacro\tmp{--}%
          \coord{\eledat[\zcnt,\the\numexpr\zzcnt+1\relax]}%
        \else
          \addtomacro\tmp{--}%
          \coord{\eledat[\zcnt,2]}%
        \fi
      \fi
    }%
    \addtomacro\tmp{;}%
  }%
  \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
  }%
}

\newcommand\readmesh[2]{%
  \ignoreemptyitems%
  \readarraysepchar{,}%
  \ifx\relax#1\relax\else\readdef{#1}\nodedata\fi
  \ifx\relax#2\relax\else\readdef{#2}\elementdata\fi
  \setsepchar{,/ }%
  \readlist*\noddat{\nodedata}%
  \readlist*\eledat{\elementdata}%
}
\begin{document}
%% FILE INPUT
\readmesh{nodedata.dat}{elementdata.dat}

%% 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}
%\readmesh{}{}

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}

enter image description here

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}
\usepackage{tikz,listofitems,readarray}
\usetikzlibrary{calc}
\newcommand\coord[2][]{%
  \edef\comparenode{#2}%
  \foreachitem\zzz\in\noddat[]{%
    \edef\testnode{\noddat[\zzzcnt,1]}%
    \ifx\testnode\comparenode
      \xaddtomacro\tmp{(\noddat[\zzzcnt,2]#1,\noddat[\zzzcnt,3]#1)}\fi
  }%
}
\makeatletter\let\addtomacro\g@addto@macro\makeatother
\newcommand\xaddtomacro[2]{%
  \edef\xtmp{#2}%
  \expandafter\addtomacro\expandafter#1\expandafter{\xtmp}%
}
\newcommand\drawmesh[1][\draw]{%
  \def\tmp{}%
  \foreachitem\z\in\eledat[]{%
    \addtomacro\tmp{#1}%
    \foreachitem\zz\in\eledat[\zcnt]{%
      \ifnum\zzcnt=1\relax\else
        \ifnum\zzcnt<\listlen\eledat[\zcnt]\relax
          \ifnum\zzcnt=2\relax\coord{\zz}\fi
          \addtomacro\tmp{--}%
          \coord{\eledat[\zcnt,\the\numexpr\zzcnt+1\relax]}%
        \else
          \addtomacro\tmp{--}%
          \coord{\eledat[\zcnt,2]}%
        \fi
      \fi
    }%
    \addtomacro\tmp{;}%
  }%
  \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
  }%
}
\newcommand\readmesh[2]{%
  \ignoreemptyitems%
  \readarraysepchar{,}%
  \ifx\relax#1\relax\else\readdef{#1}\nodedata\fi
  \ifx\relax#2\relax\else\readdef{#2}\elementdata\fi
  \setsepchar{,/ }%
  \readlist*\noddat{\nodedata}%
  \readlist*\eledat{\elementdata}%
}
\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}
\readmesh{}{}
\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 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! :^) – Steven B. Segletes Apr 17 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 at 18:23
  • 1
    @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. – Steven B. Segletes Apr 17 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. – Steven B. Segletes Apr 17 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.