When i was a chemist, i wrote my internship report in LaTeX.
It was at first a pain in the ass, all thses weird synthaxes, no aparently coherence...
Especialy for drawing objects, graphs, shapes... (cf: PgfPlot, TikZ)
Then i moved on, never return to LaTeX because i did not need it.
But i remember the painfull hours spent trying to render a good TikZ graphic, and i do not want thoses hours to be wasted.
So 4 years later i returned to LaTeX to learn it, for real.
To make it a realy coherent mental model, learning all its invariants.
And i can say it has been a wide success, i even achieved to make a mini Doom in LaTeX.
This is not only an article, but a personal revenge.
In this deep dive into LaTeX, you will learn the basics, text formating, math formating, graphs rendering, how it can be used as a dataframe (masks filtering, transformations), shapes rendering, 3D onto 2D projections, shades... and so much more.
But also most impoortantly a deep understanding that LaTeX is not just a static markup language.
The macros are hyper powerfull.
You can even traverse a tree just by using it.
TeX is a Turing complete language.
First, all the code i will reference comes from my repo here:
The prerequisites & Basic mental model
The engine
I used lualatex as the engine that compiles LaTeX code into pdf.
On debian / ubuntu linux versions install it as:
sudo apt-get install lualatex
This is a very fast and modern engine.
I started writing my tutorial using pdflatex engine which is fine, but this newer engine bringssome features we'll discuss later.
Also, because the compile system is absolute GARBAGE, in the sense that when you modify something that impacts your TOC, or structure in general(\listoffigures, \maketitle, \label / \ref, \hyperlink, \hyperlink...), then you must compile twice (explained more later on the architectural discussion).
So to handle this i always compile with latexmk that is the "LaTeX make system".
lualatex -pdflatex="lualatex" -shell-escape file.tex
Understanding structure of LaTeX code
It is simple, you got, in order:
- document type definition (article, ...) which tels the dimensions of the pdf outputed (A3, A4...) in the tutorial we'll focus on
article-> A4 - the preambule, it is where you import packages, import packages of packages and so on, you can also define macro here, is is a good convention
- the documnent content, this is located between
\begin{document}and\end{document}, it is where the content (as you preshot) is located, what will be displayed on the pdf
It is:
\documentclass{article}
\usepackage{X} %imports
\usepackage{Y}
\usepackage{Z}
...
% macro definition
\newcommand{\link}[2]{\href{#1}{#2}}
\newcommand{\mybloglink}{https://julienlargetpiet.tech}
\definecolor{linkcolor1}{HTML}{4F9AD6} % special macro for defining color
...
\begin{document}
...
\end[document]
The imports
So in the preambule i got:
\usepackage{lipsum} % add tests \lipsum
\usepackage{tikz}
\usepackage{amsmath} % math
\usepackage{amsfonts} % more math symbols
\usepackage{graphics} % images
\usepackage{hyperref} % links
\usepackage[
top=2cm,
bottom=2cm,
left=3cm,
right=3cm
]{geometry} % margins
\usepackage{pgfplots} % simplify graphs
\usepackage{float} % add directive on figures
\usepackage{placeins} % Add \FloatBarrier for figures
%\usepackage[section]{placeins} % or here, automatically insert a \FloatBarrier at the end of every sections
\usepackage{setspace} % better lines spacing (inside paragraphs) (more breathing space), triggered with \onehalfspacing...
\usepackage{parskip} % removes paragraph indentation + add clean separation between paragrapgh, but we can
% still control vertical space manually withh \setlength{\parskip}{1em}...
\usepackage[T1]{fontenc} % use T1 font encoding -> accented character...
\usepackage{lmodern} % Latin Modern font, supports well T1 encoding
\usepackage{microtype} % better micro spacing (letters/words)
\usepackage{fancyhdr} % page headers
\usepackage{titlesec} % used for sections style here, \titleformat
\usepackage[table]{xcolor} % colors text with \textcolor - [table] means extra load of function like \rowcolor...
\usepackage{tcolorbox} % used to highlight text, literaly a colored box
\usepackage{listings} % used for code-blocks
\usepackage{minted} % used for code-blocks (alterntive) - more powerfull but rely on python - require `pdflatex -shell-escape file.tex`
\usepackage{multicol} % handle multicolumns cleanly
\usepackage{pgf-pie} % pie-chart
\usepackage{xstring} % beter for string programming
\usepackage{chemfig} % for drawing molecules
\usepackage{pgfplotstable} %read csv
\usepackage{booktabs} % nicer tabs
\usepackage{soul}
% for \path[name intersections={of=f and g}];
\usetikzlibrary{intersections}
\usetikzlibrary{trees} % you know its use just by its name lol
\usetikzlibrary{3d} % enables 3d coordinates system
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{graphs}
\usetikzlibrary{graphdrawing}
\usegdlibrary{trees} % from graphdrawning
\usegdlibrary{force}
\usepgfplotslibrary{ternary} % ternary diagramm
Wow, that is so much packages, do not worry i annotated why they are used, and later in the explanations i will describe which macro comes from which packages, so you got a good understanding of what fo what.
Note, you see thet LaTeX comments are declared with the % character. And there is no multiline comments sadly, so % everywhere :-(
And the premabule is not done yet, now let's see the real configurations setup:
But let's discuss already the importance of thse packages and what tey do already quickly
lipsum
This just brings some random latin text you can use tio test your formating, to use it in you interest sections, use:
\lipsum-> big text
Or just sequence as:
-
\lipsum[1]-> smaller text piece -
\lipsum[1-2]-> medium text piece (first piece + second)
and so on...
TikZ
hoo boy !!
That's for rendering all kind of shapes, 2D, 3D projections onto 2D plan, shaders...
And that is the fundation of PgfPlot that is used to display graphs
amsmath & amsmfonts
Used to vastly enhance the math formating (especialy for equation solving), brings some usefull features and amsmfonts brings more math symbols.
graphics
Is used to display images (JPG, PNG, JPEG...)
Example:
\includegraphics[width=0.35\textwidth]{lynxcute.jpg}

Recall include keyword, because this is key for later.
We can also tweak dimensiosn of course:
\includegraphics[height=4cm,
width=4cm]{lynxcute.jpg}

hyperref
Bring the ability to display clickable link in pdf viewer, with \href
Geometry
Look this is essential:
\usepackage[
top=2cm,
bottom=2cm,
left=3cm,
right=3cm
]{geometry} % margins
Just loading the package with options between [...] defines the margins for the entire document.
PgfPlot
This will bring all the PgfPlot macros, that are super usefull to dislay pretty much al kind of graphs.
It is dependant on TikZ, that is also a god convetion to import it after TikZ
float & placeins for figures
Here, it is a bit subtle.
In fact when you decide to draw a figure, basically a div in HTML, according to its dimension and its neighboors dimensions, LaTeX engine can optimize its placement, like on the next page, or even stack multiple figures.
But this package, you can make use of this keyword: H -> here, no exception !
Good for predictable layouts:
...
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{lynxcute.jpg}
\caption{Example Image}
\end{figure}
...
That puts the figure exactly HERE, where it is defined.
instead of:
...
\begin{figure}[htbp]
\centering
\includegraphics[width=0.5\textwidth]{lynxcute.jpg}
\caption{Example Image}
\end{figure}
...
\FloatBarrier
Where [htbp] -> here, top, bottom, placement of figures (stack of figurs with others)
So [htpb] are set of allowed placement the engine will pioche at and decide where to put this figure.
Note also that placeins provides \FloatBarrier that tells the figures defined before can not be placed after this barrier.
In fact figure is essential block for wrapping reference content.
You have to put \caption{...} inside figure for them to be referenced by the \listoffigures that is like the automatic TOC trigger (we'll discuss later) but for figures.
We will come back on that later.
Whe you add, remove a figure, you have to compile your document twice to \listoffigure take in count the changes.
latexmk -pdflatex="lualatex" -shell-escape main.tex
latexmk -pdflatex="lualatex" -shell-escape main.tex
Like TOC trigger \tableofcontents -> TOC trigger does.
setspace
Brings \onehalfspacing, \singlespacing, \doublespacing
Affectng spacing between lines of text.
Spacing inside paragraphs.
Example:
Normal text
\onehalfspacing
This paragraph has more breathing space.
\doublespacing
This one is even more spaced.
Or scoped
\begin{spacing}{1.5}
This part only is spaced.
\end{spacing}
technically it works by modifying the simple Tex primitive \baselineskip
parskip
Just by including this package, it removes indentation for each paragraph
From:
This paragraph starts with an indent.
To:
This paragraph starts with an indent.
Adds vertical spaces between paragraphs:
Paragraph 1.
Paragraph 2.
fontenc
Defines the encoding of the document character.
So here w euse T1 encoding, the default being O1
\usepackage[T1]{fontenc}
Allowing accented characetr, vry common in french for example, like "é" etcetera
But here,because we are using lualatex as the engine, T1 is not exlicitely needed.
Indeed, this engine uses direclty unicode encoding.
So it is necessary with pdflatex engine.
But with lualatex, we can remove it and instead replace it with:
\usepackage{fontspec} % use system fonct directly
\setmainfont{Latin Modern Roman} % set the font used, must be instaled on your system
instead of providing font accpete by teh engine internally like after we did:
\usepackage{lmodern} % Latin Modern font, supports well T1 encoding
microtype
Including this package automatically do the following.
It improves typographic quality automatically by adjusting:
spacing at a very fine (micro) level
The 3 main features
- Character protrusion (margin kerning)
Letters slightly “hang” into the margin:
"Hello"
-> Quotes or punctuation stick out a bit.
Why? makes text edges visually aligned avoids “ragged” margins
- Font expansion
LaTeX can slightly stretch or shrink characters:
-> like ±1–2%
This helps:
reduce bad line breaks avoid big spaces between words
- Better spacing (kerning + tracking)
It improves:
spacing between letters spacing between words
-> makes text more even and readable
Without:
- uneven spacing
- ugly justification
- large gaps between words
With:
- smooth text flow
- tighter, more consistent lines
- professional look
fancyhdr
Allow to set a common meta-style for all pages, discussed later.
titlesec
Allow to set a common style for sections text, discused later.
xcolor
Allow to color text
Example:
\textcolor{blue}{Important}
We can define our own color like so, in the HTML coordinate system:
\definecolor{mycolor1}{HTML}{1E90FF}
and then use it:
\textcolor{mycolor1}{Important} % call to mycolor1 defined in preamble with \definecolor
or use it direclty:
\textcolor[HTML]{FF5733}{Important} % inline call of HTML colors (hexadecimal)
You can also quickly define color doing so with \colorlet:
\colorlet{primary}{blue!60!black}
\colorlet{secondary}{orange!30}
\colorlet{accent}{green!40!black}
Note that it is color1!percentage_of_color1!color2
And when we do orange!30 it means orange!30!white
Here we imported as:
\usepackage[table]{xcolor}
to load exra xcolor function such as \rowcolor which is super usefull for the table, we will discuss it later.
soul
Obviously, we're not talking about music, but a simple manner to highlight text.
Just:
Hoo! \hl{highlighted} !!

And you can change defulat highlight color doing so with \sethlcolor{COLOR}:
\sethlcolor{cyan}
Hoo! \hl{highlighted} !!
Note, this affects next color of all the next occurence of \hl{TEXT}, so reset it to yellow if you want ;)

tcolorbox
Used to create a colored box wrapping text inside, like:
\begin{tcolorbox}
This is a highlighted block
\end{tcolorbox}
Customoized tcolorbox
\begin{tcolorbox}[
colback=blue!10,
colframe=blue!5!green
]
This is a second highlighted block
\end{tcolorbox}

Customoized 2 tcolorbox
\begin{tcolorbox}[
colback=blue!10,
colframe=mycolor1
]
This is a second highlighted block
\end{tcolorbox}

As you see you can customize background and border color of the boxes.
But look, you can also give them a title (title) and customize its title color (coltitle) and title color background (colbacktitle).
Inside the options [...] of this environment tcolorbox.
You can round the corner arc.
And center title -> expands to halign title=center under the hood.
Customoized 3 tcolorbox
\begin{tcolorbox}[
colback=gray!10,
colframe=gray!50,
coltitle=blue,
colbacktitle=orange!5,
arc=6pt,
boxrule=0.5pt,
title=Hell Yeah Title,
center title
]
Clean modern box
\end{tcolorbox}

And tweak border width (boxrule).
\begin{tcolorbox}[
colback=gray!10,
colframe=gray!50,
coltitle=blue,
colbacktitle=orange!5,
arc=6pt,
boxrule=2.5pt,
title=Hell Yeah Title,
]
Clean modern box2
\end{tcolorbox}

Listings For Code-Blocks
It is used for code-block
Basicaly it is a library that comes with this super powerfull configuration setup that we can call in the preambule:
First we connect tcolorbox and listings
\tcbuselibrary{listings}
Then, look !
\newtcblisting{codebox1}{
listing only,
colback=gray!5,
colframe=gray!30,
arc=4pt,
boxrule=0.5pt,
listing options={
language=C++,
basicstyle=\ttfamily\small,
keywordstyle=\color{blue},
commentstyle=\color{gray},
stringstyle=\color{green!50!black},
breaklines=true,
keepspaces=true,
columns=fullflexible,
showstringspaces=false
}
}
We are defining an environment called codebox1 (exactly what you think).
So we will able to call it like:
\begin{codebox1}
...
\end{codebox1}
Create a tcolorbox-based code environment using listings
listing only
Means:
the box contains only code no extra text content
If you removed it, you could mix text + code inside the box.
Box appearance
colback=gray!5,
colframe=gray!30,
arc=4pt,
boxrule=0.5pt,
These are pure tcolorbox options:
-
colback=gray!5-> background color -
colframe=gray!30-> border color -
arc=4pt-> rounded corners -
boxrule=0.5pt-> border thickness
The core: listing options={...}
This is where listings comes in
Language -> language=C++
Enables syntax highlighting for C++
Font
basicstyle=\ttfamily\small
-
\ttfamily-> monospace font -
\small→ smaller size
Syntax highlighting
keywordstyle=\color{blue},
commentstyle=\color{gray},
stringstyle=\color{green!50!black},
Defines colors:
keywords-> blue (int, return, etc.)comments-> graystrings-> green-ish
Layout behavior
-
breaklines=true-> Long lines wrap automatically -
keepspaces=true-> Preserves indentation (VERY important for code) -
columns=fullflexible-> Better alignment of characters (prevents weird spacing issues in monospace) -
showstringspaces=false-> Removes ugly markers for spaces inside strings
Mental model
Your environment is basically:
“A styled box + syntax-highlighted code renderer”
Instead of repeating this everywhere:
\begin{tcolorbox}
\begin{lstlisting}[... tons of options ...]
...
\end{lstlisting}
\end{tcolorbox}
You just write:
\begin{codebox1}
...
\end{codebox1}
Clean :)

Much better than nativ code-blocks with:
\begin{verbatim}
int main() {
return 0;
}
\end{verbatim}

Minted
But wait, there's more !
Yess, more beautifull code-block
In the preambule we define the style / colorsheme to be used for the code-blocks with:
\usemintedstyle{friendly}
Associated with tcolorbox box:
\begin{tcolorbox}[colback=gray!5,
colframe=gray!30,
arc=4pt]
\begin{minted}{cpp}
#include <iostream.h>
int main() {
std::string x = "this is a string";
std::cout << x << "\n";
// comment
return 0;
}
\end{minted}
\end{tcolorbox}

Pratically out-of-the-box.
Less work than with listings
multicol
Very simple concepts, just multiple column text in one page.
Look:
\begin{multicols}{2}
\lipsum[1-3]
\end{multicols}
Here with 2 columns, which is most common.

You can also manualy break the text to make it appear on the next column
\begin{multicols}{2}
This is col 1.
\lipsum[1]
\columnbreak
This is col 2.
\lipsum[2]
\end{multicols}

pgf-pie
Bring pie-charts to pgfplot API, we'll discuss later.
xstring
Wowww, okok this one is super duper powerfulll!!!
Basically, maybe i'm forshadowing a little about macro programming but fuck it, let's talk about that:
It basically brings some functions to compare string variables in LaTeX, such as:
- Comparisons
\def\a{Rémi} % variable definition -> \a = Rémi
\IfStrEq{\a}{Rémi}{Yes}{No} % -> Yes
Yep, you read it correctly string comparisons and ternary expression.
- Get if substr is present in another string
\IfSubStr{hello}{ell}{Yes}{No} % -> Yes
\IfSubStr{\a}{ell}{Yes}{No} % -> no
- Extract substring
\StrMid{abcd}{2}{4}{\result}
Now \result is bcd, yes we start from 1!
\StrLen{hello}{\len}
Now \len is 4
We can after compares number as we'll discuss later.
\StrSubstitute{helo world}world{}{LaTeX}{\resultb}
Now \resultb is helo LaTeX
chemfig
A must have for drawing molecules (organic chemists)
With \chemfig{...}
Look:
\chemfig{C-C-O}
Draw bonds wide wise between nodes C C and O

All 3 types of bonds (weakest to strongest):
\chemfig{C-C}
\chemfig{C=C}
\chemfig{C~C}

Of course, it would not be a proper molecules drawing package if there were not a way to control angles between nodes.
\chemfig{-[:30]C-[:60]=O}
\chemfig{(H-)(H-)C(-H)(-[:55]H)-[:30]C=[:60]O}
\chemfig{C(=[:30]O)
(=[:270]O)
(=[:300]
(H-)
I
(-H))
-C
}
Isopropanol:
\chemfig{
CH_3-CH(-[:90]OH)-CH_3
}
Basically you add this [:angle] after each bond to dictate the angle
And yess, as you see of course a node can be linked to multiple nodes, we just, at the same level, defines all its connected nodes.

Do not waste time to tweak bonds angle and add nodes to draw cycles, you can just simply do it with the *N(-...-) synthax.
Cyclohexane:
\chemfig{
*6(------)
}

Here we alternate link type.
Benzene:
\chemfig{
*6(-=-=-=)
}

Another example:
\chemfig{
*6(-(-CH_3)=-(-OH)-=-)
}

And of course, painfulless draw charges.
\chemfig{N^\oplus}
\chemfig{O^\ominus}
% to not collide with specific chemfig DSL link synthax, group the minus like "{-}"
% so now "-" is just a character, not a special chemfig synthax
\chemfig{O^{-}}
\chemfig{O^{+}}

pgfplotstable
Ok, hear me out !
This is the feature that made me realize i could do some basic dataframe transformation inside LaTeX, whih is absurdly cool.
But before diving to the table thing, first, it is just a simple way to bring data into plots, which is already... you guessed it , cool.
Take a look at this simple code:
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
grid style=gray!20,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[name path = f,
color=blue,
thick]{x^2};
\addplot[name path = g,
color=red,
thick]{x^3};
\draw[->] (axis cs:-1,1) -- (axis cs:1,2) node[right] {Point 2};
\draw[->] (axis cs:-1,0) node[right] {Point 1} -- (axis cs:1,-2);
\addplot[gray,
fill opacity = 0.3
] fill between [
of = f and g
];
% the order of legend correspond to the order of the \addplot
\addlegendentry{$x^2$}
\addlegendentry{$x^3$}
\end{axis}
\end{tikzpicture}

Alright, here we just draw 2 functions:
x^2x^3
with \addplot
The options of each plot is located inside [...]
This is why we see x^2 as blue and x^3 as red.
We can also vary the width of the lines using thick, thin..., here it is thick
Also, nice thing e can name each plot, f -> x^2 and g -> x^3
Why name it ?
because of the integral fill between those 2 functions we do with:
\addplot[gray,
fill opacity = 0.3
] fill between [
of = f and g
];
If we would just draw the integral of x^2 let's say, we would just draw a ghost function like 0 naming it g, name it and then draw like we did.
we would just add the option [draw=none] to make g invisible
like:
\addplot[name path = g,
draw=none]{0};
You also see that we put legends, simple enough, just:
\addlegendentry{$x^2$}
\addlegendentry{$x^3$}
Note that here the legend match the color of what they represent, blue and then red.
This is coherent, because we first plotted x^2 -> blue and then x^3 -> red, and put the legends in the same order
Now, where the hell do the arrows come from ????
From:
\draw[->] (axis cs:-1,1) -- (axis cs:1,2) node[right] {Point 2};
\draw[->] (axis cs:-1,0) node[right] {Point 1} -- (axis cs:1,-2);
In fact \draw is a TikZ primitive allowing to draw all kind of stuff, shapes...
For arrow, we use [->] as draw option
As you preshot, coordinates of arrow is (x_start, y_start) -- (x_end, y_end)
Here it is a little different because we draw arrow in pgfplot coordinate system that is not scaled with TikZ coordinate system, so we just tell it putting:
axis cs:
before each coordinate, cs -> coordinate system
You can also print something next to each coordinate, like a node (more on that later)
So in that code for example:
\draw[->] (axis cs:-1,0) node[right] {Point 1} -- (axis cs:1,-2);
At the right of the starting point of the arrow, we print "Point 1".
Now, more on parameters options inside [...]
Why i want to discuss more about that ?
Because experimenting with this made me realize something really strange, look at that:
[color=red!90, thick]
is the same as:
[thick, color=red!90]
Why ?
Because in fact, LaTeX expands thick to line width = 0.8pt, so there is always an explicit parameter name assigment even if you do not see it!
And that overwhelming powerfull for quick graphs in the urge !
Btw, diferent line width can be:
ultra thinvery thinthinsemithickthickvery thickultra thick
Now, what about the axis ?
So as you se, to defne a plot we first need to define a tikzpicture, because a pgfpot needs it.
Then we need to define an axis, this is...the axis, yeahh !
But like any scene in LaTeX, we can give it properties inside [...]
So here we did:
- define the labels on each axis
xlabel/ylabel, here this isxandyrespectively (math font) - the domain over which the function is sampled with
domain
We could also do that with:
xmin/xmax
And equivalently for y domain:
ymin/ymax
Now the grid:
We show it with grid=both, we could do grid=none to not display a grid.
to add specific y or x axis grid, we do it with these options:
xmajorgridsymajorgridsxminorgridsyminorgrids
And how do we anchor the legend ?
Justo doing:
north westsouth westnorth eastsouth east
And we can define the width and the height of the plot itself.
Here another plot:
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
axis lines=right,
axis line style={->},
grid style=gray!20,
legend pos=north west,
width=10cm,
height=6cm]
% axis ine options:
% left
% right
% middle
% center
% box
% none
\addplot[name path = f,
color=blue,
thick,
dotted]{x^2 - 2};
\addplot[dashed]{1 + x^2};
\addplot[dotted]{2 + x^2};
\addplot[dashdotted]{x^2};
% Custom dash
\addplot[
dash pattern=on 5pt off 2pt,
color=blue
]{x^1};
\end{axis}
\end{tikzpicture}

What's new ?
First, we shifted the axis to the rigt:
axis lines=right
Added the arrow as the direction axis end:
axis line style={->}
We could have done that to change the direction:
axis line style={<-}
And modified the grid style color:
grid style=gray!20
Also, you see that we can change furtherly the style of the line, with the dashed option, that is expanded to dash pattern = on 3pt off 3pt
Then you can agan frther customize it with:
dash pattern=on 5pt off 2pt,
Now, we come closer to what's interesting in this topic, the tables.
For now, waht to do if we want to plot real data coordinates ?
Just use coordinates lol
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[only marks,
mark=*,
color=purple] coordinates {
(0, 0)
(1, 1)
(2, 4)
};
\addplot[mark=*,
color=green!40!black,
smooth] coordinates {
(-2, -3)
(1, 0.75)
(1.5, 5)
(2, 3)
};
\node at (axis cs:1,1.8) {Hello};
\end{axis}
\end{tikzpicture}

Here, instead of printing a continuous function like \addplot[...]{FUNCTION}, the synthax is:
\addplot[...] coordinates { POINT1,
POINT2,
... }
expanded to:
\addplot[...] coordinates { (x1, y1),
(x2, Y2),
... }
Here, we can either print only points, with only marks or link them with not putting only marks option.
If we want a smooth line, to make the intermediates values more visualy expressive, just put smooth.
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[only marks,
mark=diamond*,
color=purple] coordinates {
(0, 0)
(1, 1)
(2, 4)
};
\addplot[mark=triangle,
color=green!40!black] coordinates {
(-2, -3)
(1, 0.75)
(1.5, 5)
(2, 3)
};
\node at (axis cs:1,1.8) {Hello};
\end{axis}
\end{tikzpicture}

Note that we can also change the mark shape, like:
*+Xsquare-> empty squaretriangle-> empty squarediamond-> empty squarepentagon-> empty pentagonstar-> empty starsquare*-> filled squaretriangle*-> filled squarediamond*-> filled squarepentagon*-> filled pentagonstar*-> filled staro-> hollowoplus-> hollow with plus signotimes-> hollow with cross sign
And even more whangling the triangle orientation:
triangle
triangle*
triangle down
triangle down*
triangle left
triangle right
Note: those requires \usetikzlibrary{shapes.geometric}.
Heeere we are my friends, the moment you were waiting, or maybe on of the moment, we still ave not talk about freaking DOOOOOM on LaTeX, don't worry it will come.
So for now table !!!!
You remember of coordinates ?
I hope so, it is just the section above lol ;)
Yess, it is great to have the ability to give realworld coordinates to construct a plot, but we all know that in... real world (haha), the data are big, scattered around different sources and the only one that can unite them is a reallllly strong format, the infamous CSV !!!!!
So in an ideal world, we would have a tool that could parse a CSV and stock it in memory to feed it to pgfplot.
We may are not in an ideal world, but we have this tool, just look!
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[mark=*,
only marks,
color=red!40!black] table[col sep=comma,
x=x,
y=y] {scatterplot.csv};
\end{axis}
\end{tikzpicture}

The options are:
col sep = comma-> CSV column separatorx=colanme_corresponding_to_xy=colanme_corresponding_to_y
here the csv is scatterplot.csv:
x, y, y2
-2, -3, 4
-2, 2, 4
1, 0.75, 4
1, 1, 4
2, 3, 4
2, 2.4, 4
In the previous example, y2 column was not used, but not there:
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[mark=*,
only marks,
color=red!40!black] table[col sep=comma,
x=x,
y expr=\thisrow{y} * 2 + \thisrow{y2}] {scatterplot.csv};
\addplot[mark=*,
only marks,
color=blue!45] table[col sep=comma,
x=x,
y expr=\thisrow{y} * 2 * \thisrow{y2}] {scatterplot.csv};
\addplot[mark=*,
only marks,
color=green!40] table[col sep=comma,
x=x,
y expr=\thisrow{y} * 2 + 2 * \thisrow{y2},
restrict expr to domain={\thisrow{x}}{0:2}] {scatterplot.csv};
% `restrict expr to domain` expects two arguments:
% 1) an expression (here: \thisrow{x})
% 2) a domain interval (here: 0:2)
% Braces are required to delimit each argument explicitly,
% especially since \thisrow{x} is itself a macro with its own argument.
% So we write {\thisrow{x}}{0:2} to avoid ambiguity in TeX parsing.
\end{axis}
\end{tikzpicture}

Hoo, what am i seeing ?
Transformations ?
YESSSS, this is it, with y expr option
You do:
y expr = Y OPERATOR Y2 ...
or whatever, that expands to:
y expr = \thisrow{y} OPERATOR \thisrow{y2} ...
Think of it as transformations are under the hood, happening row per row.
And you noticed ?
The domain filtering for a specific plot!!
restrict expr to domain={\thisrow{x}}{0:2}
Only f(x) which x belongs to 0 to 2 will be plotted for this plot.
Hohoho, but that is not done, in table, you can even filter by the y values, with a custom logic, that is what i call REAL MASK FILTERING
Leeeeeets's Gooo
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[mark=*,
only marks,
color=red!40] table[col sep=comma,
y filter/.code = {
\ifnum\thisrow{y}>2
\def\pgfmathresult{nan}
\fi
},
x=x,
y expr=\thisrow{y} * 2 + 2 * \thisrow{y2}] {scatterplot.csv};
\end{axis}
\end{tikzpicture}

It is introduced with:
y filter/.code = {
\ifnum\thisrow{y}>2
\def\pgfmathresult{nan}
\fi
}
in the table option (and yess, a litte forshadowing of what is programming in LaTeX with \ifnum\varOPERATORvalue)
So, by just assigning special variable of pgfplot \pgfmathresult to nan with:
\def\pgfmathresult{nan}
I'm intentially omiting certain values.
But here i'm just filtering on raw CSV Y values, what if i want to filter on the transformation i'm aplying ?
Recall, the transformation is:
y expr=\thisrow{y} * 2 + 2 * \thisrow{y2}
Hmmmm, that is in fact totaly possible!
In fact the output of table if outputed to the input of \addplot, and that is there where we can aplly filter on the newly computed y
Then we do:
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
domain=-2:2,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
\addplot[
mark=*,
only marks,
color=blue!40,
y filter/.expression={y > 10 ? nan : y},
unbounded coords=discard
] table[
col sep=comma,
x=x,
y expr=\thisrow{y} * 2 + 2 * \thisrow{y2}
] {scatterplot.csv};
\end{axis}
\end{tikzpicture}

You see it ?
Right here in the addplot options:
y filter/.expression={y > 10 ? nan : y}
A super usefull ternary expression that returns nan if y is superior to 10
And after we put the option:
unbounded coords=discard
That tells to dot show coordinates that are nan, inf and -inf
That's neat
But now, what if multiple plots uses the same CSV, it would be a waste of computational ressources to parse it for each plot.
Don't worry:
\begin{tikzpicture}
\begin{axis}[title={Title Yess, a title},
xlabel=$x$,
ylabel=$y$,
domain=-2:8,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
% global tables
\pgfplotstableread[col sep=comma]{scatterplot.csv}\mytable
\pgfplotstableread[col sep=comma]{scatterplot2.csv}\mytableB
%concat mytableB to mytable
\pgfplotstablevertcat{\mytable}{\mytableB}
\pgfplotstablecreatecol[
create col/expr={\thisrow{y}^2 - \thisrow{y2}}
]{y3}{\mytable}
\addplot[mark=*,
only marks,
color=blue!45] table[col sep=comma,
x=x,
y expr=\thisrow{y3} * 2\thisrow{y2}] {\mytable};
\end{axis}
\end{tikzpicture}

Note, here we added a title with option title = {...}
scatterplot2.csv:
x, y, y2
3, -3, 4
3, 2, 4
4, 0.75, 4
4, 1, 4
5, 3, 4
6, 2.4, 4
And yess we can define table object doing so:
\pgfplotstableread[col sep=comma]{scatterplot.csv}\mytable
\pgfplotstableread[col sep=comma]{scatterplot2.csv}\mytableB
We can even concatenate by row / vertialy (vertcat):
%concat mytableB to mytable
\pgfplotstablevertcat{\mytable}{\mytableB}
Now \mytable has rows of \mytableB concatenated.
That'not even done yet, we can modify this object creating a column as a transformation for example:
\pgfplotstablecreatecol[
create col/expr={\thisrow{y}^2 - \thisrow{y2}}
]{y3}{\mytable}
and we could even filter the column creation by a mask:
\begin{tikzpicture}
\begin{axis}[title={Title Yess, a title},
xlabel=$x$,
ylabel=$y$,
domain=-2:8,
grid=both,
legend pos=north west,
width=10cm,
height=6cm]
% global tables
\pgfplotstableread[col sep=comma]{scatterplot.csv}\mytable
\pgfplotstableread[col sep=comma]{scatterplot2.csv}\mytableB
%concat mytableB to mytable
\pgfplotstablevertcat{\mytable}{\mytableB}
\pgfplotstablecreatecol[
create col/expr={
\thisrow{y} < 2 ? (\thisrow{y}^2 - \thisrow{y2}) : nan
}
]{y3}{\mytable}
\addplot[mark=*,
only marks,
color=blue!45,
unbounded coords=discard
] table[col sep=comma,
x=x,
y expr=\thisrow{y3} * 2\thisrow{y2}] {\mytable};
\end{axis}
\end{tikzpicture}

That is some dataframe operation direclty inside LaTeX ----> AWESOME
intersections
Here, it is a TikZ library that we import:
\usetikzlibrary{intersections}
Allowing to do that in pgfplot for example:
\begin{tikzpicture}
\begin{axis}[domain=-1:2]
\addplot[name path=f, blue]{x^2};
\addplot[name path=g, red]{x};
% create the intersections "intersection-N"
\path[name intersections={of=f and g}];
\fill (intersection-1) circle (2pt);
\fill (intersection-2) circle (2pt);
\node at (intersection-1) [above] {$x=0$};
\node at (intersection-2) [above] {$x=1$};
\end{axis}
\end{tikzpicture}

So nothing really new, namin plots, and after we just create ALL the intersections:
% create the intersections "intersection-N"
\path[name intersections={of=f and g}];
Whose name will be intersection-INTEGER.
After that we can do whatever we want with those intersections like creatng filed black (default color) circles.
\fill (intersection-1) circle (2pt);
\fill (intersection-2) circle (2pt);
Anotating them:
\node at (intersection-1) [above] {$x=0$};
\node at (intersection-2) [above] {$x=1$};
Note that it is an TikZ primitive, it means we can use it with TikZ shapes creation like so:
\begin{tikzpicture}
% Define square
\draw[name path=mysquare]
(-1,-1) rectangle (1,1);
% Define circle
\draw[name path=mycircle]
(0,0) circle (1.15);
% Compute intersections
\path[name intersections={of=mysquare and mycircle}];
% Draw intersection points
\foreach \i in {1,2,3,4,5,6,7,8} {
\fill (intersection-\i) circle (2pt);
\node at (intersection-\i) [above] {\i};
}
\end{tikzpicture}

Again some BIG foreshadowing when it comes to variables / lists and especialy loops...
:=)
Note that writing the loop, you have to be sure to not be out of the actual intersections. Here, there are 8 (i looked the shape before), so i stopped 8, not 9.
It would have bee another story if the diameter of the circle changed obviously.
In fact here because the center of the square and the center of the circle coincide, so when circle diameter is small, 0 intersections, then there is a value of the diameter where there are 4 intersections points, then if we increase again, it increases to 8 intersections points, then 8, then 0.
trees & graphs & graphdrawing
Ok, one time or anotheryou will need trees, everybody loves tree, i even see trees just by my window, always was surounded by trees...
hmmHmm
Enough cheap talking, here are the basics of trees - TikZ native:
You got to understand 3 simple rules to get TikZ trees:
-
start a tree
\node{NODENAME} -
a
nodecan havenchilds, written contiguously -
a child synthax is
child{NODE} -
nodesynthax isnode{NODENAME}
So a simple tree looks like:
\begin{tikzpicture}
\node{N1} child{ node{MM} } child{ node{V2} };
\end{tikzpicture}

Look, it's evolving !
\begin{tikzpicture}
\node{N1}
child{ child{node{N2}} }
child{
node{N3}
node{N4}
child {
node{N5}
}
}
child {
node{N6} child {node{N7}} child {node{N8}}
};
\end{tikzpicture}

Not convinced, you are a Haskell fundamentalist and study Graph Theory, and you are asking:
"okok, nice stuff, but i need a more abstract way to represent links between nodes, i want to represent GRAPH!! Nodes that that are linked without an hierarchical order GODAMN !!!"
Wow wow wow, i get it and have exactly the right abstraction model for you!
But you got to use lualatex engine to compile to have this feature.
And also import those graph package in the preambule (yess, package from graph which is a package from TikZ lol).
\usegdlibrary{trees} % from graphdrawing
\usegdlibrary{force}
\usegdlibrary{layered}
Introducing \graph
\begin{tikzpicture}
\graph[spring layout]{
A -- B -- C -- D -- A;
A -- C;
};
\end{tikzpicture}

You literally just represent the link between nodes.
Here in a tree layout:
\begin{tikzpicture}
\graph[tree layout]{
A -- B -- C -- D -- A;
A -- C;
};
\end{tikzpicture}

Of course you can make directed graph, or part of graph with -> or <-.
\begin{tikzpicture}
\graph[spring layout]{
A <- B -- C -- D -- A;
A -> C;
};
\end{tikzpicture}

Or you can make undirected more explicit using <->.
\begin{tikzpicture}
\graph[spring layout]{
A <-> B -- C -- D -- A;
A -> C;
};
\end{tikzpicture}

And going back to trees, you can draw it without pain like.
\begin{tikzpicture}
\graph [tree layout] {
A -> {B, C, D};
B -> {E, F};
};
\end{tikzpicture}

No node / child concerns.
3D Tikz Lib
More on that later.
booktabs
Tabs, tabs, tabs.
Let's start.
\begin{tabular}{|c|c|}
\hline
A & B \\
\hline
C & D \\
\hline
\end{tabular}

Just defining an appropriate scop for it (tabular), and enter the values:
|c|c|
or it could slightly differe:
\begin{tabular}{|c|c|}
\hline
A & B \\
\hline
C & D \\
\hline
\end{tabular}

\begin{tabular}{|c|c|}
\hline
A & B \\
\hline
C & D \\
\hline
\end{tabular}

You can also color a specific cell using \cellcolor{COLOR}
\begin{tabular}{|c|c|}
\hline
\cellcolor{red!30} A & B \\
\hline
C & \cellcolor{blue!30} D \\
\hline
\end{tabular}

Or color an entire row:
\begin{tabular}{|c|c|}
\hline
\rowcolor{red!30}
A & B \\
\hline
\rowcolor{blue!30}
C & D \\
\hline
\end{tabular}

Or also column, with >\columncolor{COLOR}
\begin{tabular}{|>{\columncolor{blue!30}}c|>{\columncolor{red!30}}c|}
\hline
A & B \\
\hline
C & D \\
\hline
\end{tabular}

You can alternate row color.
So you define:
\rowcolors{PATTERNLINESTART}{COLOR1}{COLOR2}
expanding to:
\rowcolors{1}{gray!20}{white}
for example.
And after just define a normal table:
\begin{tabular}{|c|c|}
\hline
A & B \\
\hline
C & D \\
\hline
E & F \\
\hline
\end{tabular}
Note, you see \hline, just an horizontal line that can not be be used elsewhere.
It is not like \hrule.
dfd
\hrule
sfdf
\hrule

And after please reset the patter, to not conflict other codes, such as math matrices as we will see later.
\rowcolors{0}{}{} % RESET

Another example (full).
\rowcolors{2}{blue!20}{red!20}
\begin{tabular}{|c|c|}
\hline
A & B \\
\hline
C & D \\
\hline
E & F \\
\hline
G & H \\
\hline
\end{tabular}
\rowcolors{0}{}{} % RESET

Now, booktabs, finally !
It just bring those things:
\toprule\midrule\bottomrule
that have better style than \hline for respectively:
- top line
- head separation
- botom line
\begin{tabular}{|cc|}
\toprule
A & B \\
\midrule
C & D \\
\hline
E & F \\
\hline
C & D \\
\hline
E & F \\
\hline
C & D \\
\hline
E & F \\
\hline
C & D \\
\hline
E & F \\
\hline
C & D \\
\hline
E & F \\
\bottomrule
\end{tabular}

Note here the |cc| -> No col separation, kind of weird but possible.
Configurations
%%%%%%% hyperref %%%%%%%
\hypersetup{colorlinks = true,
linkcolor=blue,
urlcolor=blue
}
%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%% fancyhdr %%%%%%%
\fancyhf{}
\pagestyle{fancy}
%%% page headers %%%
\fancyhead[L]{Doc}
\fancyhead[R]{J LP}
\fancyfoot[C]{\thepage}
\setlength{\headheight}{15pt}
%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%% titlesec %%%%%%%%%
\titleformat{\section}{\large\bfseries}{\thesection}{1em}{}
%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% listings configurations %%%%
%\lstset{ % define globally, but risks of flickering
% basicstyle=\ttfamily\small,
% keywordstyle=\color{blue},
% commentstyle=\color{red!70!black},
% stringstyle=\color{green!50!black},
% breaklines=true,
% keepspaces=true,
% showstringspaces=false,
% backgroundcolor=\color{gray!50},
% frame=single
%}
% or define a style variable
\tcbuselibrary{listings}
% no flickering
\newtcblisting{codebox1}{
listing only,
colback=gray!5,
colframe=gray!30,
arc=4pt,
boxrule=0.5pt,
listing options={
language=C++,
basicstyle=\ttfamily\small,
keywordstyle=\color{blue},
commentstyle=\color{gray},
stringstyle=\color{green!50!black},
breaklines=true,
keepspaces=true,
columns=fullflexible,
showstringspaces=false
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%% minted %%%%%%
\usemintedstyle{friendly}
% friendly
% colorful
% murphy
% native
% monokai
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%% Multi-Column spacing %%%%%%%
\setlength{\columnsep}{1cm}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%% Footnote spacing %%%%%%%
\setlength{\skip\footins}{2em}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepgfplotslibrary{fillbetween}
\usepgfplotslibrary{statistics}
% \usepgfplotslibrary{colormaps} %cool theme colormap/themename
\pgfplotsset{compat=1.18}
\pgfplotsset{ %define custom pgfplot theme, heatmap
colormap={inferno}{
rgb255(0cm)=(0,0,4);
rgb255(1cm)=(31,12,72);
rgb255(2cm)=(85,15,109);
rgb255(3cm)=(136,34,106);
rgb255(4cm)=(186,54,85);
rgb255(5cm)=(227,89,51);
rgb255(6cm)=(249,140,10);
rgb255(7cm)=(249,201,50);
rgb255(8cm)=(252,255,164);
}
}
\title{Doc}
\author{J LP}
\date{\today}
%%%% VARIABLES REGISTRATION %%%
\newcommand{\mybloglink}{https://julienlargetpiet.tech}
\newcommand{\mybloglinkraw}{\url{https://julienlargetpiet.tech}}
\definecolor{mycolor1}{HTML}{1E90FF}
\definecolor{linkcolor1}{HTML}{4F9AD6}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% FUNCTIONS REGISTRATION %%%
\newcommand{\link}[2]{\href{#1}{#2}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\includeonly{ici}
% Declare custom maths operators - symbols
\DeclareMathOperator{\Var}{VarCustom}
\DeclareMathOperator{\E}{ECustom}
%%%%%%%%%%%%%%%%%%%%%%
Hyperlinks
\hypersetup{colorlinks = true,
linkcolor=blue,
urlcolor=blue
}
As you see, here we define the style of the hyperlinks.
colorlinks
If false (default behavior), then links are surrounded by colored boxes and text stays black.
If true, no boxes and text itself is colored
linkcolor
Controls internal links:
- table of contents
\ref{...}\section links- more on that in\maketitle/ TOC section- figure references
Example:
\ref{fig:myfig}
--> will appear in blue
urlcolor
Controls external links:
\url{...}\href{...}{...}
Example:
\url{https://example.com}
The link will appear in blue.
PageStyle
After we define the format of each page, with fancyhdr configuration.
\pagestyle{fancy}
%%% page headers %%%
\fancyhead[L]{Doc}
\fancyhead[R]{J LP}
\fancyfoot[C]{\thepage}
\setlength{\headheight}{15pt}
So we define what is displayed at the top-left/header-left 'Doc', what is displayed at the top-right/header-right 'JLP'
And as its name does not suggest it, we can even define what is displayed at the footer.
Then here at the bottom-center, we put \thepage which is a special variable that display the current page number.
So you get this style:

Notice the horizontal top line that comes from \pagestyle{fancy}
Sections
\titleformat{\section}{\large\bfseries}{\thesection}{1em}{}
Here an important concept, the sections.
Sections are... sections of your document (wow, sherlock level here)
You can have sections, subsections and subsubsections and more (discussed later)
They are used to create the automatic Table Of Content (TOC), we will return on that later.
But here we just define their style. We want them to be written in \large which comes from the LaTeX font size system.
We also want them to use the \bfseries font.
TOC
How the Table Of Contents is built ?
Like seen before, just using the sections.
But we can choose where to pu here, ususally just after \begin{document}, like that:
{ % here we just do a scoping to define temporary hyperefsetup just used by \tableofcontents
\hypersetup{linkcolor = black}
\tableofcontents
}
Wow, wait a minute, why is that wrapped inside brackets ???
Simple enough.
In fact, remember this before ?
\hypersetup{colorlinks = true,
linkcolor=blue,
urlcolor=blue
}
Yeah, it appears we define the link color...
But do you knwo what is a link to in TOC and that should not be blue ??
Right, TOC itself...
Si in fact we just create a temporary context where we redefine the link color, and just after, in he same context, we generate the TOC.
Bom, all links are black, what is intended.
You just learn that LaTeX acts more an more as a "programing language", that's right, scoping
Multicol
This one is straightforward, we spoke about multicol, but how to define column spacing ?
Just.
\setlength{\columnsep}{1cm}
But you get it ?
This demonstration brings a new concept --> defining a length !!
Hre it is global for current scope not sub-scope, (a bit subtle), but can be redifined later.
Like with scoping:
{
\setlength{\columnsep}{2cm}
\begin{multicols}{2}
Content...
\end{multicols}
}
First, here all the existing units, and there are for all, normal educated people unsing metric system, and weirdos, approximatly 300M people using disgusting inches and al those dumb things...
I think this is an abstraction skill isuue imo.
Like seriously WTF !!
mm-> milimiter (of course) -> 1/1000 of a metercm-> centimeter, 1/100 of a meter ;)pt-> LaTeX special measurmeent unit (still better than inches)bp-> PostScript measurmeent unitsin-> unfortunately
And look:
1in -> 72.27pt
1in -> 72bp
Specigic European typography units:
dd-> Didot pointcc-> Cicero point
Math units:
mu
special variable describing the dimensions of the curent document page:
\textwidth-> width of the text area, set once by document typearticle...+geometry\columnwidth-> width of 1 column, normally equals to\textwidth, but depends on the context it is called, like inmulticols/figures/minipage
And look, we can even do maths with length units with \dimexpr:
\setlength{\parskip}{\dimexpr 1em + 2pt\relax}
\parslip is the default length between 2 paragraphs.
If you want to cretae you onw dimension, it is possible:
\newdimen\customdim
\customdim=2cm
And after use it:
\setlength{\parskip}{\dimexpr 2\customdim\relax}
or some more math on it:
Ho you can do division with non integer, so instead of:
\setlength{\parskip}{\dimexpr 2\customdim / 1.5cm + 1cm\relax}
do:
\setlength{\parskip}{\dimexpr 2\customdim*2 / 3 + 1cm\relax}
Even in TikZ:
\draw (0,0) -- (\dimexpr 2\customdim\relax, 0)
Metadata, informations about the doc
The author, the date and the document title are set like that in the preambule:
\title{DocYess}
\author{J LP Yess}
\date{\today}

You see he variabke \today performs a system call under the hood asking for the current date (Month Day Year)
Includes
Here, we go from one file -> one document to a really structured project to output a ...PDF, yeah !!
Imagine your work is so big it can not fit in one file...
It is usrely the worst description to annouce the importance of file and flder separation for a project.
But you get it, everyone gets it.
When a project gets so big, we start separating the concerns to different location.
So here it is:
\include{ici.tex}
where ici.tex is a normal tex file, not defining an article, but just some tex code that fits inside a Tex document.
Je suis inclu
In the preambule you can define the infamous \includeonly list variable like that:
\includeonly{ici,ici2}
To only includes those files for example ici.tex and ici2.tex.
Then if you do:
\include{ici.tex}
\include{ici2.tex}
But have:
\includeonly{ici}
Only ici will be displayed.
Here, even if the content in each included file is just one line, an include will at least take one entire page.
To solve this problem you can just use raw \input.
\input{ici.tex}
\input{ici2.tex}
Note: there is no \inputonly native concept.

More on basic yet important stuffs
Internal Links: Citations & References
You saw hyperlink:
-> someone click on the link and suddenly he is transported in the INTERNET to the websites the link is referencing woow!
But let's do something less fancy.
Just refenrence areas on the same PDF page, still usefull when PDF is big right ?
We do it like that:
\hyperlink{ID}{DISOPLAYTEXT1}
...
\hypertarget{ID}{DISPLAYTEXT2}
expanding to for example:
\hyperlink{citationID1}{my first citation}
...
\hypertarget{citationID1}{Citatttttttion1}
Is is very usefull for citations.
But in LaTeX citations are conceptualy simple but pratically just horrible, we have to use bibtex that is a tool that kind of structure your citation, like autmatically increment all the citations id.
But to be fair, that is where LaTeX engineering faled misearably.
WE DO NOT NEED BIBTEX!
hopefully
Look at what we can simply do:
\newcount\citecounter
\citecounter=0
\newcommand{\mycite}[1]{%
\advance\citecounter by 1
\edef\temp{\the\citecounter}%
\hyperlink{#1}{[\temp]}
}
So we just use it as:
\mycite{ID1}
\mycite{ID2}
expanding to, for exaple:
\mycite{cit1}
\mycite{cit2}

And at th end of our document, for instance after a \newpage, that creates a newpage (lol):
\hypertarget{cit1}{Citatttttttion1}
\hypertarget{cit2}{Citatttttttion2}
And after that you tell bibtex is not a scam, common !!
We just define a global counter, and define a command/function that will automatically increment this counter when used before using it as a display citation reference with the inputed parameter which is the id #1 -> first paramter an only.
In fact you just learn the structure of function in LaTeX:
\newcommand{\FUNCTIONNAME}[NUMBER OF ARGUMENTS]{
FUNCTION LOGIC
}
And you use parameters as #1, #2 ...
Sections, subsections...
Again again, some basic but unavoidable concepts, the compartimentin of you document by sections:
The TOC, with \maketitle will lookk to those sections, subsections... to create the TOC.
So you heve:
N1 \section{TEXT} containing N2 \subsection{TEXT} containing N3 \subsubsections{TEXT}.
And iy is not yet the end.
You can even got deeper !!
You can even give more or ess importance to your paragraphs inside sub/subsub/sections, doing so:
\paragraph{Important paragraph}
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
Comon we do it again
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
\subparagraph{Important sub-paragraph}
A sub-paragraph yeah a sub-paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
Comon we do it again
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
So an end result can look like that:
\section{Basics - sections, subsections, paragraphs...}
\subsection{Normal}
Hello Normal
\subsubsection{Normal}
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
\subsubsection{Normal2}
Comon we do it again
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
\paragraph{Important paragraph}
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
Comon we do it again
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
\subparagraph{Important sub-paragraph}
A sub-paragraph yeah a sub-paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.
Comon we do it again
A paragraph yeah a paragraph haha, lol i dk what to write here so i rpetend just to write sentences that make sens whil it is pure nonsens.

You find it at the TOC level here:

Paragraphs
Hmmm, lol more than 2K lines and we have not talked about the most basiv thing, the textual representation model of LaTeX, basically:
This is a sentence.
This is another a sentence.

This is a sentenceinside a par.
This is a sentence inside a par.

This is a sentenceinside a par too. This is a sentence inside a par too.

*This is not like HTML, it is more visual than it
It is more like markdown for this particular concept.
Also more space is not equal more space...
This is a sentenceinside a par.
This is a sentence inside a par.
This is a sentenceinside a par too. This is a sentence inside a par too.

You can break a paragraph with \\.
This is a sentenceinside a par too.\\ This is a sentence inside a par too.

Or same:
This is a sentenceinside a par too.
\\
This is a sentence inside a par too.

And you can double break it like so:
This is a sentenceinside a par too. \\
This is a sentence inside a par too.

Or same:
This is a sentenceinside a par too. \\
This is a sentence inside a par too.

But you can break only what can be broke (wow, neat sentence):
This is a sentenceinside a par too.
\\
This is a sentence inside a par too.
-> ERROR
But look at this weird thing:
This is a sentenceinside a par too. \\ \\ \\
This is a sentence inside a par too.
Separation
This is a sentenceinside a par too. \\ \\ \\ \\
This is a sentence inside a par too.

Why does it work as intended ??
Because \\ is allowed inside a paragraph, but not outside
That is why this worked:
This is a sentenceinside a par too.
\\
This is a sentence inside a par too.
Because remmber:
sentence1
sentence2
Are the same paragraph :)
Also \\ does not realy give the same amount of spaces than natural paragraphs separation, so:
sentence1
sentence2
Gives \parskip separation length. -> Annouces another paragraph.
Not like
sentence1 \\
sentence2
Gives \baselineskip -> Typographic spacing but actually in the same paragraph.
So recall that:
Blank line -> NEW PARAGRAPH
Spaces
Vertical
This is straightforward, just:
\vspace{LENGTH}
So like:
Ok
\vspace{1cm}
Ok

Note that this does not work because on the same paragraph:
Ok
\vspace{1cm}
Ok
Or
Ok \vspace{1cm} Ok

Horizontal
This is as straightforward as vertical spaces.
Ok \hspace{1cm} Ok

Ans for the next paragraph, the horizontal space is of course canceled.
Ok \hspace{1cm} Ok
Ok

Text style
Bold
Just:
\textbf{Hello in bold}

Italic
\textit{Hello in italic}

Underline
\underline{Hello underlined}

Combinations of style
\underline{\textbf{\textit{Hello all}}}

Font Sizes
Predefined font sizes
LaTeX is generous and comes with predefined variable you can use to tweak font sizes.
{\tiny tiny}
{\footnotesize footnotesize}
{\small small}
{\normalsize normalsize}
{\large large}
{\Large Large}
{\huge huge}
{\Huge Huge}

Note that i always scoped the call of changing tthe font size because one call of any of those macros affects the rest of the text.
Look an example:
\tiny tiny
\normalsize
Mee
\footnotesize footnotesize
\normalsize
Mee
\small small
\normalsize
Mee
\normalsize normalsize
Mee
\large large
\normalsize
Mee
\Large Large
\normalsize
Mee
\huge huge
\normalsize
Mee
\Huge Huge
\normalsize
Mee

Because look if i had not did it:
\tiny tiny
Mee
\footnotesize footnotesize
Mee
\small small
Mee
\normalsize normalsize
Mee
\large large
Mee
\Large Large
Mee
\huge huge
Mee
\Huge Huge
Mee
\normalsize

Custom font sizes
So a fontsize is defined by those 2 variables:
size-> actual size of the fontbaselineskip-> the infamous\\value
So we do a scoping like that:
{\fontsize{FONTSIZE}{BASELINESKIPSIZE}\selectfont
This is a sentence with my custom font !!!
}
exapnding to for example:
{\fontsize{14pt}{18pt}\selectfont
This is a sentence with my custom font !!!
}
So you get that this:
\fontsize{FONTSIZE}{BASELINESKIPSIZE} -> prepares the font, sets the configuration, and the call to \selectfont actually activate the font for the next texts.
FootNotes
Just:
CONTENT1\footnote{DEFINITION1}
CONTENT2\footnote{DEFINITION2}
expanding to, for example:
Hell0\footnote{this is a first footnote}
Hell02\footnote{this is a second footnote}

And at the bottom of the page, the associated definitions:

Lists
Unnumbered
We do unordered lists with itemize context.
\begin{itemize}
\item First
\item Second
\end{itemize}

Numbered
\begin{enumarate}
\item First
\item Second
\end{enumerate}

Horizontal Lines
Very direct:
dfd
\hrule
sfdf
\hrule

Maths
Hoooo, now we enter the section that was the motivation for the creation of TeX
To have special maths notations, special math font etcetera etcetera.
This is the maths you put inside normal text:
here some inlined maths $f(x) = x^2$

Here you see that to declare an exponent, we do ^ -> very common.
Now when we want to grat the honors to maths, we need to center it right ?
That's done with:
\[
MATHS HERE
\]
expanding to, for example:
\[
f(x) = x^2
\]

Now, more about notations:
\[
x^2,\quad x_1,\quad x^{10},\quad x_{i,j}
\]

Wait, what's going on here ??
First, what are \quad ??
They are simple horizontal spaces, from a greater family of horizontal spaces in math mode that we'll encounter later.
Juts to tell you that we can have indices with _
And if we want to make the exponent or indices more complex, make sure to scope them with {}.
That's why we got:
x_{i,j}
For example
A multiplication is expressed with \cdot.
\[
3 \cdot 2 + 1 - 1 = 6
\]

Fractions now:
\[
\frac{DIVIDED}{DIVIDER}
\]
expanding to, for example:
\[
\frac{a}{b}
\]

You want some integrals ?
\int_START^END
here ^ is not an exponent, but rather meaning "to"
So, for example, it expands to:
\[
\int_0^1 x^2 \, dx
\]

OR
\[
\int_{0}^{\frac{a}{b}} x^2 \, dx
\]

\int -> not like type but as abreviation for "integral" :)
Now Sum ;)
\[
\sum_{i=1}^{n} i^2
\]

Same semantics...
Now some limits, yeahhh !!
\[
\lim_{x \to \infty} \frac{1}{x} = 0
\]

And what about parenthesis ?
That comes with \left and \right.
\[
\left( \frac{1}{2} \right)
\]
\[
\left[ \frac{1}{2} \right]
\]

You see, we announce the parenthesis with either \left or \right, and after we put the symbol "(", ")", "[" or "]".
What would be math without matrices ?
We certianly would not have linear algebra as we know today, what an horror right ??
So here we are, matrices:
\[
\begin{matrix}
1 & 2 \\
3 & 4
\end{matrix}
\]

With parenthesis ;)
\[
\begin{pmatrix}
1 & 2 \\
3 & 4
\end{pmatrix}
\]

Now with "[".
\[
\begin{bmatrix}
1 & 2 \\
3 & 4
\end{bmatrix}
\]

Or you can do it manualy, but seriously ??
\[
\left(
\begin{matrix}
1 & 2 \\
3 & 4
\end{matrix}
\right)
\]
\[
\left[
\begin{matrix}
1 & 2 \\
3 & 4
\end{matrix}
\right]
\]

Oh, almost forgot, but you can make them with bars too:
\[
\begin{vmatrix}
1 & 2 \\
3 & 4
\end{vmatrix}
\]

and its manual equivalent...
\[
\left|
\begin{matrix}
1 & 2 \\
3 & 4
\end{matrix}
\right|
\]

Now, speaking about equations developmenent !!
A great environment to develop an equation is the align environment.
\begin{align}
f(x) &= x^2 + 1 \\
&= (x+1)(x-1) + 2
\end{align}

You see each development is numbered at the right, very practical !
Now conditional outputs from function, youpi, algorithms ;)
The environment we use is called cases, explicit enough, each line is apossible output.
Like:
\[
f(x) =
\begin{cases}
OUTPUT1 & CONDITION1 \\
OUTPUT2 & CONDITION2 \\
...
...
...
\end{cases}
\]
expanding to, for example:
\[
f(x) =
\begin{cases}
x^2 & \text{if } x > 0 \\
x & \text{if } x == 2 \\
0 & \text{otherwise}
\end{cases}
\]

It now brings the text inside math context, it is the contrary as $some maths$ in text mode.
And as already described it is using \text{...}:
\[
x^2 \text{ is positive}
\]

There are also many horizontal spacing commons we can use:
Small:
\[
x^2 \, x
\]
Just \,

Medium:
\[
x^2 \; x
\]
Just \;

Large:
\[
x^2 \quad x
\]
Just \quad

Would you mind take some maths symbols ?
I'll assume, "YES"
\begin{align}
\alpha, \beta \\
\lambda, \pi
\end{align}

Note, for whatever reason i used align environment, i do random stuff sometimes...
And for number theorists, you will love those:
\begin{align}
\mathbb{N}, \mathbb{R} \\
\mathbb{Q}, \mathbb{Z}
\end{align}

Some derivatives, with \partial
\[
\frac{\partial f}{\partial x}
\]

You can also box maths !
EMPHASING TIIIME, with \boxed{SOMEMATHS}
\[
\boxed{E = mc^2}
\]

Technically, it work even in normal context, not only in math mode:
\boxed{BOOOOXE}
And finally, you can even define your custom maths symbols in the prembule doing so:
\DeclareMathOperator{VARIABLENAME1}{CONTENT}
\DeclareMathOperator{VARIABLENAME2}{CONTENT}
expanding to, for example:
\DeclareMathOperator{\Var}{VarCustom}
\DeclareMathOperator{\E}{ECustom}
Now we can use them like any other symbol.
\[
\Var(X), \quad \E[X]
\]

Structure
fbox & makebox
First, \makebox[...]{...}, what is it ?
Think of it like a div n HTML.
You can stack them and they will appear stacked to the right.
Look:
\makebox[5cm][l]{Hello}
\makebox[5cm][c]{Hello}
\makebox[5cm][r]{Hello}

Ho, maybe you do not see it yet, so i will wrap them inside \fbox{...}.
\fbox{\makebox[5cm][l]{Hello}}
\fbox{\makebox[5cm][c]{Hello}}
\fbox{\makebox[5cm][r]{Hello}}

Here you see !
So you can control the centering, left (l) center (c) or right (r) in the second option context of the \makebox
And also the width in the first option context.
Here what it does if i increase it on an A4 type document.
\makebox[8cm][l]{Hello}
\makebox[8cm][c]{Hello}
\makebox[8cm][r]{Hello}

You may ask why not all in 1 option context like [].
That is a good question that i also asked !
Because here that is just [opt1][opt2].
Which is TeX desing, the fundation of LaTeX.
TeX was developped in the 1970s, so at this time we even should think not only in term of runtime cost, but also COMPILE costs.
And guess what, a simple parsing like [opt1][opt2] is way less compute intensive than something non positional like [opt1=..., opt2=...] that can be [opt2=..., opt1=...] etcetera...
So yeah in LaTeX, you will still see some legacy TeX functions that have this design haha.
Hoo alsmost forgot, of course you are not forced to put boxes on the same paragraph lol:
\fbox{\makebox[5cm][l]{Hello}}
\fbox{\makebox[5cm][c]{Hello}}
\fbox{\makebox[5cm][r]{Hello}}

Minipage
It is a bit lie multicol, but in a greater way.
Let me explain.
In fact in multicol, it as very easy to use, but you could just integrated text, now in minipage, you can also integrate figures, like TikZ pictures...
\begin{minipage}{0.48\textwidth}
\lipsum[1]
\end{minipage}
\hfill
\begin{minipage}{0.48\textwidth}
\centering
\includegraphics[width=0.35\textwidth]{lynxcute.jpg}
%\vspace{1cm}
\bigskip
\begin{tikzpicture}
\begin{axis}
\addplot{x^2};
\end{axis}
\end{tikzpicture}
\end{minipage}

What's going on here ?
We just define a first minipage environment!
\begin{minipage}{0.48\textwidth}
\lipsum[1]
\end{minipage}
With a width of 48% of the total page width.
where we put some text from lipsum.
After that we, on the same paragraph, make a call to \hfill, we'll discuss after what it is doing currently.
And, again, on the same paragraph, we define a second minipage environment of also 48% of total page width.
Where we put a picture and a plot.
\begin{minipage}{0.48\textwidth}
\centering
\includegraphics[width=0.35\textwidth]{lynxcute.jpg}
\bigskip
\begin{tikzpicture}
\begin{axis}
\addplot{x^2};
\end{axis}
\end{tikzpicture}
\end{minipage}
So technically, 4% of width space reminds, that is why between those 2 minipage environment, we introduced \hfill that fills the remaining spaces, in theis case 4% of width sae between those 2 minipage environments.
More on PGFPlot
So we'll start where we lastly end the discussion on PGFPlot.
BarPlot
Lets's talk about barplot.
here an example:
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C},
xtick=data
]
\addplot coordinates {
(A,10)
(B,3)
(C,15)
};
\end{axis}
\end{tikzpicture}

So you notice that we must precise the type of the plot direclty in the axis, here it is a barplot, it will show bar, vertically, so we just put ybar.
Because that is a plotbar, so that is quantitative values over qualitative ones, we must tell the axis, the qualitative values, in order.
Here it is symbolic x coords={A,B,C}, note that that is all the set containing all the possible qualitative values we have in coordinates.
After we do this xtick=data.
Why ?
Because default tick accuracy is maybe like 0 -> 0.5 -> 1 -> 1.5 ...
Then, ok at this point it knows it whould use set (1,B,C) to name ticks but at what accuracy ??
Look what hapens if we do not provide this option:
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C}
]
\addplot coordinates {
(A,10)
(B,3)
(C,15)
};
\end{axis}
\end{tikzpicture}

In fact it does this:
-
get the default x interval, let's say [0, 2]
-
then gets all the symbolic coords -> A,B,C
-
interpolate xtick naming, and map it
So it is like undefined behaviour a bit, but here we see it did:
0 -> A
0.5 -> ?
1 -> B
1.5 -> ?
2 -> C
And replaced the "?" with interpolated qualitative value.
Haa lets' do another try with a much bigger set of qualitative values and get the interpolation.
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C,D,E,F,G,H,I,J}
]
\addplot coordinates {
(A,10)
(B,3)
(C,15)
(D,10)
(E,3)
(F,15)
(G,10)
(H,3)
(I,15)
(J,15)
};
\end{axis}
\end{tikzpicture}

Okok weird, but still interpolation, we just do not see the full accuracy.
Also look at that, if a value is not used but still defined in the possible symbolic x coords, it is not used in graph.
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C,D,E,F,G,H,I,J}
]
\addplot coordinates {
(A,10)
(B,3)
(C,15)
};
\end{axis}
\end{tikzpicture}

Here with CSV -> table:
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C},
xtick=data
]
\addplot[color=blue!50,
fill=blue!50] table[col sep=comma,
x=label,
y=value] {barplot.csv};
\end{axis}
\end{tikzpicture}
barplot.csv:
label,value
A,10
B,3
C,15

Now horizontal barplot, you may have guessed it, we'll just use xbar.
And change to symbolic y coords and ytick=data and change tabel parameters in consequence.
\begin{tikzpicture}
\begin{axis}[
xbar,
symbolic y coords={A,B,C},
ytick=data
]
\addplot[color=blue!50,
fill=blue!50] table[col sep=comma,
y=label,
x=value] {barplot.csv};
\end{axis}
\end{tikzpicture}

Now, how to display groups ?
It is a groupe barplot !!
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C},
xtick=data,
enlargelimits=0.15
]
\addplot[color=blue!50,
fill=blue!50] coordinates {
(A,10)
(B,3)
(C,15)
};
\addplot[color=mycolor1,
fill=mycolor1] coordinates {
(A,4)
(B,8)
(C,5)
};
\addplot[color=red!50,
fill=red!50] coordinates {
(A,14)
(B,18)
(C,15)
};
\node at (axis cs:A,14) [above] {Point 1};
\node at (axis cs:B,18) [above] {Point 2};
\draw[->] (axis cs:B,18) -- (axis cs:C,15) node[below] {Point 3};
\end{axis}
\end{tikzpicture}

You literally just add more \addplot and change colors.
Here i just added some node anotations for fun haha, i like having fun doi some random stuff...
Btw, note that enlargelimits ?
Look what happens at default enlargelimuts, default to 0.
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C},
xtick=data,
enlargelimits=0
]
\addplot[color=blue!50,
fill=blue!50] coordinates {
(A,10)
(B,3)
(C,15)
};
\addplot[color=mycolor1,
fill=mycolor1] coordinates {
(A,4)
(B,8)
(C,5)
};
\addplot[color=red!50,
fill=red!50] coordinates {
(A,14)
(B,18)
(C,15)
};
\node at (axis cs:A,14) [above] {Point 1};
\node at (axis cs:B,18) [above] {Point 2};
\draw[->] (axis cs:B,18) -- (axis cs:C,15) node[below] {Point 3};
\end{axis}
\end{tikzpicture}

That's right, awful interval cutting !!
So we just provides some breathing space for each plot, it increses height breathing space, we do not care but why not, but especially width space for each plot, which we care about to have good plots !
Yess that is something weird about PGFPlot engine...
And here an horizontal grouped barplot.
\begin{tikzpicture}
\begin{axis}[
xbar,
symbolic y coords={A,B,C},
ytick=data,
enlargelimits=0.15
]
\addplot[color=blue!50,
fill=blue!50] coordinates {
(10,A)
(3,B)
(15,C)
};
\addplot[color=mycolor1,
fill=mycolor1] coordinates {
(4,A)
(8,B)
(5,C)
};
\addplot[color=red!50,
fill=red!50] coordinates {
(14,A)
(18,B)
(15,C)
};
\end{axis}
\end{tikzpicture}

Also, note tha because we shifted to horizontal barlot, the coordinates are shifted.
So instead of (A,10) we got (10,A) and so on.
Histogram
Here we want to represent quantitative values over quantitatives values.
More precisely density over quantitives values.
Maybe like Probability Density Function (PDF lol, i crack some jokes sometimes).
here is the file, histogramm.csv:
value
1
2
2
2.5
3
3.5
3.6
3.6
4
4
5
6
7
And an example.
\begin{tikzpicture}
\begin{axis}
\addplot[
hist={bins=5, data min=1, data max=7, density},
fill=blue!30,
draw=black,
] table[col sep=comma,
y=value] {histogramm.csv};
\end{axis}
\end{tikzpicture}

What is going on here ?
The sum of the area of the bins is equal to 1.
With density option, all is normalized between 0 and 1.
We got some bars, but nothing requires modifying the axis options, why is that ?
Because of course it is quantitatives over quantitatives.
So do not even try defining a set of possible values at x axis, it is impossible, there are an infinity.
For that the \addplot has a very special option, as you may have spotted, the hist.
What's in that ?
You just tell the number of bins -> represnet the accuracy, not too many, because it will flatten, not not enough -> loose of accuracy
data min - data max represents the x interval, here it is not defined direclty in axis environment option, but directly via this option.
Why we do like that ?
Because that s the most predictable and accurate way, look again the histogramm.csv file, there is no notion of x values here, just y values, so using this hist options is the right way to do it, it fixes boudaries for compute !
Here, we draw bins lines in black draw=black.
and of course, you can add Kernel Density Estimation (KDE, i got no joke here sadly... :( ).
\begin{tikzpicture}
\begin{axis}
\addplot+[
hist={bins=5, data min=1, data max=7, density},
fill=blue!30,
draw=black,
mark=none
] table[col sep=comma,
y=value] {histogramm.csv};
\addplot[
smooth, thick, color=red
] table[
col sep=comma, x=x, y=density
]{histogramm_kde.csv}; % never escapes "_" in filenames, only in text where we do "\_"
\end{axis}
\end{tikzpicture}

That is very manual, just adding a smooth plot from a precomputed KDE file values (with R or Python).
histogramm_kde.csv:
x,density
1.5,0.230769230769231
2.5,0.153846153846154
3.5,0.384615384615385
4.5,0.0769230769230769
5.5,0.0769230769230769
6.5,0.0769230769230769
Constant plot
Good way to display Cumulative Probability Distribution for example.
cnst.csv
x,y
0,0.1
0.1,0.15
0.2,0.5
0.3,0.62
0.4,0.66
0.5,0.68
0.6,0.75
0.7,0.8
0.8,0.88
0.9,0.95
1,1
Code.
\begin{tikzpicture}
\begin{axis}
\addplot[const plot]
table [col sep=comma, x=x, y=y] {cnst.csv};
\end{axis}
\end{tikzpicture}

Or we can make it less awfull:
\begin{tikzpicture}
\begin{axis}
\addplot[const plot,
mark=square*,
color=blue]
table [col sep=comma, x=x, y=y] {cnst.csv};
\end{axis}
\end{tikzpicture}

const plot is in fact just expanded to a bunch of options.
Internaly it does something like that.
(1,2)
(2,3)
(3,1)
(1,2)
(2,2)
(2,3)
(3,3)
(3,1)
And link those points with straingt line.
Thats all.
pgfplotsset
Look we can declare our own options name !
Here we wrapp const plot and add other options.
\begin{tikzpicture}
\begin{axis}
\pgfplotsset{
STYLENAME/.style={
STYLE1,
STYLE2,
...
...
...
}
}
\addplot[my step plot]
table [col sep=comma, x=x, y=y] {cnst.csv};
\end{axis}
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\begin{axis}
\pgfplotsset{
my step plot/.style={
const plot,
mark=*,
color=blue,
thick
}
}
\addplot[my step plot]
table [col sep=comma, x=x, y=y] {cnst.csv};
\end{axis}
\end{tikzpicture}

We will discuss more about pgfplotsset and TikZ equivalent later.
BoxPlots
BoxPlots are used to display Quantiles - Q1, median, Q3 and outliers, no surprise the default is horizontal, like for the hisogramm (representing for example Probability Density Function), but here, Quantiles...
\begin{tikzpicture}
\begin{axis}
\addplot[
boxplot
] table[col sep=comma,
y=value] {boxplot.csv};
\end{axis}
\end{tikzpicture}

boxplot.csv
value
1
2
2
3
4
4
5
6
7
Here you see that some values have different occurences.
Btw, same story as hist here but with boxplot.
And there is no density option, their purpose diverges here.
Here some grouped horizontal boxplots.
\begin{tikzpicture}
\begin{axis}[
ytick={1,2,3},
yticklabels={A,B,C}
]
\addplot[
boxplot,
boxplot/draw position=1,
fill=blue!20
] table[col sep=comma,
y=value] {boxplot.csv};
\addplot[
boxplot,
boxplot/draw position=2,
fill=red!20
] table[col sep=comma,
y=value] {boxplot.csv};
\addplot[
boxplot,
boxplot/draw position=3,
fill=orange!20
] table[col sep=comma,
y=value] {boxplot.csv};
\end{axis}
\end{tikzpicture}

Hooooo, what am i seeiiing ????
Yess, we can in fact define ticks accuracy ytick={1,2,3} - convention, could be anything evenly spaced, i omited this point earlier....
And by doing that, we can easily labelize it, mapping them to names.
Doing so:
yticklabels={A,B,C}
- 1 -> A
- 2 -> B
- 3 -> C
Youpiiii !
And the infamous addplot option:
boxplot/draw position=N
where N is one value of ytick
Map them to the plot.
Here at y = 1, we got the blue one, at y = 2, the red one and finally at y=3, the orange one.
Now, some vertical boxplots, more common.
\begin{tikzpicture}
\begin{axis}[
xtick={1,2,3},
xticklabels={A,B,C}
]
\addplot[
boxplot,
boxplot/draw direction=y,
boxplot/draw position=1,
fill=blue!20
] table[col sep=comma,
y=value] {boxplot.csv};
\addplot[
boxplot,
boxplot/draw direction=y,
boxplot/draw position=2,
fill=red!20
] table[col sep=comma,
y=value] {boxplot.csv};
\addplot[
boxplot,
boxplot/draw direction=y,
boxplot/draw position=3,
fill=orange!20
] table[col sep=comma,
y=value] {boxplot.csv};
\end{axis}
\end{tikzpicture}

Same semantics, we just invert axis, relacing ytick by xtick and so on...
And most importantly we add the option boxplot/draw direction=y -> Make them vertical.
Pie Chart
Approximately the same goal as barplot...
Look:
\begin{tikzpicture}
\pie[
color={blue!20, red!20,purple!20},
text=inside
] {10/A, 35/B, 15/C}
\end{tikzpicture}

So, that's done with \pie.
You see ?
-
It is not anymore in an
axisenvironment, because in fact there is no axis, that is just a shape... -
We just map color to the proportions.
such as:
color={blue!20, red!20, purple!20},
maps to:
{10/A, 35/B, 15/C}
The whole default annotations text are A/PERCENTAGE, B/PERCENTAGE and so on...
We deliberately put in inside what's called text, That is A, B, C.
If we have not, with text=pin:
\begin{tikzpicture}
\pie[
color={blue!20, red!20,purple!20},
text=pin,
explode=0.1
]{10/A, 35/B, 55/C}
\end{tikzpicture}

Hoo of course, you just noted that we can draw incomplete circles, the first was just 10+35+15 = 60 % of a tour -> 1Pi + 10%PI
But here the second is complete because 10 + 35 + 55 = 100% -> whole tour -> 2Pi !
Also note that we can emphase each part with explode=0.1, that is a value approximately "detaching" each part more and more when they get bigger.
In fact it is more like, if 2 parts are big -> they will look more far appart than 2 small parts.
You guess what triggers me ??
\pie does not support table, what a shame !!! BHOOOOOO!!
We can not do the following:
\begin{tikzpicture}
\pie[
color={blue!20, red!20,purple!20},
text=pin,
explode=0.1
] table[col sep=comma, label=label, value=value] {pie.csv}
\end{tikzpicture}
-> ERROR
BHOOOOO!!! Again
So at this point, and it is very common in latex, we have to pull up an external scripting language like Python or Bash to generate the LaTeX Code and put it in an include or input Tex File... Sadly.
But hopefully, pie charts often does not represent much qualitative values ;)
Multi Kind Plots - overlayed
What about plotting different kind of plot together, that could be useful in a barplot for example, when we also want to represent the mean of each plot at each value.
\begin{tikzpicture}
\begin{axis}[
ybar,
symbolic x coords={A,B,C},
xtick=data,
enlargelimits=0.2,
bar width=10pt,
ymin=0
]
\addplot[fill=blue!50] coordinates {(A,10) (B,3) (C,15)};
\addplot[fill=orange!70] coordinates {(A,4) (B,8) (C,5)};
\addplot[fill=red!50] coordinates {(A,14) (B,18) (C,15)};
\addplot[
blue,
thick,
mark=*,
smooth
] coordinates {
(A,9.33)
(B,9.67)
(C,11.67)
};
\addplot[
orange,
thick,
mark=*,
smooth
] coordinates {
(A,8.33)
(B,9.07)
(C,10.67)
};
\addplot[
red,
thick,
mark=*,
smooth
] coordinates {
(A,8.93)
(B,7.07)
(C,12.67)
};
\end{axis}
\end{tikzpicture}

Here, that's done with the:
\addplot[
blue,
thick,
mark=*,
smooth
] coordinates {
(A,9.33)
(B,9.67)
(C,11.67)
};
...
...
...
Look, thanks to symbolic x coords we can use them as real x coordinates:
coordinates {
(A,9.33)
(B,9.67)
(C,11.67)
}
Hmmm, and what about plotting in batch, the evolutions of values, yess, that is for you finance people...
\begin{tikzpicture}
\begin{axis}[
width=12cm,
height=8cm,
xtick={1,2,3},
xticklabels={[0--1],[1--2],[2--3]},
xlabel={X bins},
ylabel={Y values},
]
\addplot[
boxplot,
boxplot/draw direction=y,
boxplot/draw position=1,
fill=blue!20
] table[col sep=comma, y=y] {bin1.csv};
\addplot[
boxplot,
boxplot/draw direction=y,
boxplot/draw position=2,
fill=red!20
] table[col sep=comma, y=y] {bin2.csv};
\addplot[
boxplot,
boxplot/draw direction=y,
boxplot/draw position=3,
fill=orange!20
] table[col sep=comma, y=y] {bin3.csv};
\addplot[
only marks,
mark=*,
opacity=0.6
]
table[
col sep=comma,
x expr=floor(\thisrow{x}) + 1 + 0.15*(rand-0.5),
y=y
] {data.csv};
\end{axis}
\end{tikzpicture}

bin1.csv
y
5
7
6
3
4
bin2.csv
y
8
6
7
5
9
bin3.csv
y
4
3
6
5
7
data.csv
x,y
0.1,5
0.2,7
0.4,6
0.8,3
0.9,4 <-- END OF BIN1
1.1,8
1.2,6
1.4,7
1.7,5
1.9,9 <-- END OF BIN2
2.1,4
2.2,3
2.5,6
2.7,5
2.9,7 <-- END OF BIN3
Yeah, yeah, that is very manual, a lot of pre-word to do it, bit still possible...
With manual scripting generating LaTeX code in an input or include tex file.
But that is an excuse to show you the floor and rand functions.
Yess, because look:
-
the boxplots takes a batch of values
-
those values have an x values associated with them in
data.csv -
but they loose those informations in binN.csv, what a drama !
So how do i convert the boxplots coordinate system with scatterplot one ?
I just go over the x values \thisrow{x}, floor them floor(\thisrow{x}) and add some noises with rand.
rand gives random values between 0 and 1, and you see that i substract 0.5 to those generaed values, so noises belongs to -0.5, 0.5 --> Illusion of local scatterplot, which they are, but we just recreated the local scatterlot with x axis noises.
HeatMaps
HeatMaps, heatmaps, heatmaps...
Here we need an axis context, of course.
\begin{tikzpicture}
\begin{axis}[colorbar,
colormap name = viridis]
% matrix plot* do color interpolation, it means that a cell colored is given
% but still can get influenced by neighboors
\addplot[matrix plot*,
mesh/cols=3,
point meta=explicit] coordinates {
(0,0) [4] (1,0) [14] (2,0) [13]
(0,1) [13] (1,1) [13] (2,1) [14]
(0,2) [13] (1,2) [4] (2,2) [5]
};
\end{axis}
\end{tikzpicture}

There are a lot going on here.
First mesh/cols=3 -> data should be interpredted as a grid with 3 column per row
Then, point meta=explicit means that i provide manually the color, look in coordinates:
coordinates {
(X1,Y1) [COLOR1] (X2,Y2) [COLOR2] ...
(X3,Y3) [COLOR3] ... ...
(X4,Y4) [COLOR4] ... ...
}
expands to:
coordinates {
(0,0) [4] (1,0) [14] (2,0) [13]
(0,1) [13] (1,1) [13] (2,1) [14]
(0,2) [13] (1,2) [4] (2,2) [5]
}
Color value are normalized considering the min and max of your input color value.
And importantly matrix plot* -> means do color interpolation
Meaning do not take the exact coor of a cell, but check its neighboor and iterpolates its color, if neighboor got high color value, it will interpolate a pretty high coor value even thos its current color is mid.
To display true color, and not do color interpolation, we do just matrix plot.
Now the options in the axis !
\begin{axis}[colorbar,
colormap name = viridis]
colorbar just print at the right the infamous ... colorbar heat
And we can change the theme, so here we assign viridis to colormap name.
Look without color interpolation and using table (huura!! it supports it):
\begin{tikzpicture}
\begin{axis}[colorbar,
colormap name=inferno]
\addplot[matrix plot,
mesh/cols=3,
point meta=explicit
] table[col sep=comma,
x=x,
y=y,
meta=value] {heatmap.csv};
\end{axis}
\end{tikzpicture}
meta-> tells the associated color

heatmap.csv
x,y,value
0,0,4
1,0,14
2,0,13
0,1,13
1,1,13
2,1,14
0,2,13
1,2,4
2,2,5
Custom themes
You can define your own theme doing so with, yet again pgfplotsset.
\pgfplotsset{ %define custom pgfplot theme, heatmap
colormap={myinferno}{
rgb255(0cm)=(0,0,4);
rgb255(1cm)=(31,12,72);
rgb255(2cm)=(85,15,109);
rgb255(3cm)=(136,34,106);
rgb255(4cm)=(186,54,85);
rgb255(5cm)=(227,89,51);
rgb255(6cm)=(249,140,10);
rgb255(7cm)=(249,201,50);
rgb255(8cm)=(252,255,164);
}
}
Here i defined a gradient.
So from the bottom of the color gradient bar (0cm), the lowest color value is: (0,0,4)
Meaning 0 Red, 0 Blue, 4 Green
It is the RGB space, so each values has 256 values in the range of 0 -> 255 -> 256 bits ;)
I could furtherly fine tune my gradient defining more intermediate color values, like at 0.5cm, 1.5cm...
Then use it in heatmap for example.
\begin{tikzpicture}
\begin{axis}[colorbar,
colormap name=myinferno]
\addplot[matrix plot,
mesh/cols=3,
point meta=explicit
] table[col sep=comma,
x=x,
y=y,
meta=value] {heatmap.csv};
\end{axis}
\end{tikzpicture}

3D Tikz Lib & TikZ - Finally
Soo finally, we come closer to realizing Doom in LaTeX - DooMTeX !
So first let's talsk about basics 2D shapes.
First define a tikz environment, what a spoil !!
And, another spoil, use the \draw command.
"Hoooooo, never thought about it! That is not what we saw in N examples before."
You may say.
And you'll be wrong of course.
Little piece of sh\asterisk\asterisk
Now i'll stop being skizophrenic and start being normal.
\begin{tikzpicture}
\draw (0, 0) -- (1,1) -- (2,0) -- (0,0);
%% or cycle back automatically
\draw (0, -2) -- (1,-1) -- (2,-2) -- cycle;
\end{tikzpicture}
You see, that is literally:
\begin{tikzpicture}
\draw POINT1 -- POINT2 -- ...;
\end{tikzpicture}

expanding to:
\begin{tikzpicture}
\draw (x1, y1) -- (x2,y2) -- ...;
\end{tikzpicture}
Drawing lines betwen points.
And if you want the last line to go back to the fist point, you want to do a cycle, so use cycle, neat !
\begin{tikzpicture}
\draw POINT1 -- POINT2 -- ... -- cycle;
\end{tikzpicture}
expanding to...you know what ;)
So for drawing a rectangle you just add another points and tweaks coordinates.
\begin{tikzpicture}
\draw (0, 0) -- (0,2) -- (3,2) -- (3,0) -- cycle;
\end{tikzpicture}

By this time we just draw straight lines, but how to draw ga., euh round lines ?
You know to do something called a cirlce.
Hmm, when we got a good default code we use it, for this purpose we just have to defne the circle center and after use circle.
\begin{tikzpicture}
\draw STARTPOINT circle RADIUS;
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\draw (0, 0) circle (2);
\end{tikzpicture}

Special keywords is something you come accross often in latex to help you, like also rectangle..
Yeah, prev rectangle was more complicated than it needed to be.
\begin{tikzpicture}
\draw LEFTBOTTOMPOINT rectangle TOPRIGHTPOINT;
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\draw (0, 0) rectangle (3,2);
\end{tikzpicture}

In fact when some point can be infered, you can be sure to find a shape keyword for it.
This is a good pental model.
Look, we can define our own macro for TikZ shape, a simple one is for rectangle.
We'll use the good TikZ coordinate parsing synthax, the infamous |-.
A|-B
Where A is (xA,yA) and B is (xB,yB)
Meaning, take xA and yB.
So B|-A means take xB and yA.
And also, A-|B -> takes yA and xB.
Sothis works:
\newcommand{\myrectangle}[2]{
\draw (#1) -- (#2|-#1) -- (#2) -- (#1|-#2) -- cycle;
}
\begin{tikzpicture}
\myrectangle{0,0}{3,2};
\end{tikzpicture}

But we can go further and make a more perfect clone of rectangle macro using tikzset.
\makeatletter
\tikzset{
my rectangle/.style={
to path={
-- (\tikztotarget|- \tikztostart)
-- (\tikztotarget)
-- (\tikztostart|- \tikztotarget)
-- cycle
}
}
}
\makeatother
\begin{tikzpicture}
\draw (0,0) to[my rectangle] (3,2);
\end{tikzpicture}

What is that ?
First, you recognize the pattern:
-- (COORDINATES2|-COORDINATES1)
-- (COORDINATES2)
-- (COORDINATES1|-COORDINATES2)
-- cycle
expanding to:
-- (\tikztotarget|- \tikztostart)
-- (\tikztotarget)
-- (\tikztostart|- \tikztotarget)
-- cycle
Now you can also infere that \tikztostart -> COORDINATES1 and \tikztotarget -> COORDINATES2.
Now you can say:
"Yess, i infered correctly, but pleeaseee , i'm begging you, tell me why the fuck do we need to wrap this code between those macro call \makeatother ?"
And you'll be right, especially for the begging part.
Internally TikZ (and LaTeX) use @ in macro names.
\makeatletter tells TeX to treat "@" as a letter during tokenization, so those internal macros can be read correctly.
This happens before TikZ processes anything.
Since my code does not use any macros containing "@", \makeatletter is not strictly required here.
\tikzset{
my rectangle/.style={
to path={
-- (\tikztotarget|- \tikztostart)
-- (\tikztotarget)
-- (\tikztostart|- \tikztotarget)
-- cycle
}
}
}
\begin{tikzpicture}
\draw (0,0) to[my rectangle] (3,2);
\end{tikzpicture}
Now some fun example so you start getting when we'll speak about "programming in TikZ", the *EXPANSION.
This works.
\newcommand{\mysuperrectangle}{
to[my rectangle]
}
\begin{tikzpicture}
\draw (0,0) \mysuperrectangle (3,2);
\end{tikzpicture}
Or even.
\def\mysuperrectangleb{
to[my rectangle]
}
\begin{tikzpicture}
\draw (0,0) \mysuperrectangleb (3,2);
\end{tikzpicture}
because in fact each:
\draw (0,0) \mysuperrectangleb (3,2);
Just expands to:
\draw (0,0) to[my rectangle] (3,2);
Which of course works like we've seen previously.
But this won't work:
\newcommand{\mysuperrectangle}{
\newcommand{\mysuperrectangle}{
\tikzset{
my rectangle/.style={
to path={
-- (\tikztotarget|- \tikztostart)
-- (\tikztotarget)
-- (\tikztostart|- \tikztotarget)
-- cycle
}
}
}
}
}
\begin{tikzpicture}
\draw (0,0) \mysuperrectangle (3,2);
\end{tikzpicture}
Or with \def.
Why because it expands to:
\draw (0,0) \tikzset... (3,2);
Which is nonsense in TikZ perspective.
Because in TikZ, we define something, like A is X, the use A, but not using direclty X in a tikzpicture, which is what TeX expansion with \newcommand, \def etcetera (basically all TeX definition) literally do.
So here, we define some style, macro the style as intended to be used, and use this macro.
You knwo that \newcommand is just a fancy, with extra logic for arguments, \def :)
Wowowow, we did already massive foreshadowing for what is coming after, so we go back to shapes, just shapes haha.
So now Ellispe !
Look:
\begin{tikzpicture}
\draw CENTERPOINT ellipse (XRADIUS and YRADIUS);
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\draw (0, 0) ellipse (3 and 1);
\end{tikzpicture}

Nothing too complicated, i dare say nothing complicated !
But can we tel the same thing about the arcs ??
What is an arc... an arc.
Okok, maybe that is not the right question.
What are the minimum coordinates we can provide to a system to draw whatever arcs we want, to make a system in fact arc-turing-complete, kind of haha.
Hmm, so we need to have the radius and the angle !
Okok, but now we got to place the arc.
So yeah we got the intuition to provide a starting point, like we did for basically al shapes.
But here it is complicating, we need to provide the radius and to draw it everywhere possible from the starting point that we also, btw placed everywhere we want.
So now what, just provides its length and what ?
"Its ... angle ?"
Yup, can you developp ?
Its angle from the starting point that is placed on an imaginary horizontal plane, so this is a standard trigonometric circle angle.
after we provided that, we can be proud of being able to draw a ... line!
Wow !
But let's not forget the goal, the arc.
So now Einstein time !
Yup make use of relativity, or empathy or chatever is the concept that describes the best the fact of considering the perspective of the ending point of the newly drawed line / radius.
Now that "you are" at the ending point of the radius. You can visualize this point just circling around of the central point, like a pendulum that circles lol.
so this is key, because this is now where you can define the arc path, with angle, the line you just draw and the future endig line !
Here the example, you'll see some redundances in value, but its TikZ being himself, don't blame it, he's just...different, poor kid.
\begin{tikzpicture}
\draw[fill=blue!20] CENTERPOINT -- (STARTANGLE:RADIUS) arc (STARTINGANGLE:ENDINGANGLE:RADIUS) -- cycle;
\end{tikzpicture}
Expanding to, for example:
\begin{tikzpicture}
\draw[fill=blue!20] (0,0) -- (80:2) arc (80:90:2) -- cycle;
\end{tikzpicture}

or
\begin{tikzpicture}
\draw[fill=blue!20] (0,0) -- (0:2) arc (0:20:2) -- cycle;
\end{tikzpicture}

you can see the fill parameter in action, coloring the interior of the shape, in fact the shape, because des a shape has an interior ?
I mean is this a property it automatically inherits ?
I think yes - no proof just trust be bro.
Here a more complete example.
\begin{tikzpicture}
% starts at 0,0, go to angle 0, radius 2, shape the arc from angle 0 to angle 90 with radius 2
\draw[fill=blue!20] (0,0) -- (0:2) arc (0:90:2) -- cycle;
\draw[fill=red!20] (0,0) -- (90:2) arc (90:180:2) -- cycle;
\draw[fill=orange!20, shift={(4,0)}] (0,0) -- (180:2) arc (180:270:2) -- cycle;
\node at (4,0.1) {Point 1};
\end{tikzpicture}

Hmm let's create a macro that actually makes sense for arc.
\newcommand{\myarc}[3]{
(#1:#2) arc (#1:#3:#2) -- cycle
}
and use it like:
\begin{tikzpicture}
\draw[fill=blue!20] (0,0) -- \myarc{STARTANGLE}{RADIUS}{ENDANGLE};
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\draw[fill=blue!20] (0,0) -- \myarc{0}{2}{20};
\end{tikzpicture}

Like that, we just define start angle, radius, end angle. -- Macro commands are just expansions !
We can connect Shapes very easily, not ending mentaly hilled after tweaking for hours the arrow coordinates for the pixel perfect arrow starting from shape A to B and so on.
remember, there is \draw, but also \node, and \node can be named to better manipulate them.
And we can also provide node a shape, inheriting from draw properties that we put in node options.
We then define its shape in shae option.
Those 2 properrties make them perfect for constructing easily a diagramm !
Look:
\begin{tikzpicture}
\node[draw,
shape=circle,
minimum size=2.1cm,
inner sep=0pt] (Z) at (0,0) {A};
\node[draw,
shape=rectangle,
minimum size=2.1cm,
inner sep=0pt] (Y) at (6,0) {B};
\draw[->] (Z) -- (Y);
\end{tikzpicture}

If we do not precise the shape, it defaults to square.
\begin{tikzpicture}
\node[draw,
minimum size=2.1cm,
inner sep=0pt] (Z) at (0,0) {A};
\node[draw,
minimum size=2.1cm,
inner sep=0pt] (Y) at (6,0) {B};
\draw[->] (Z) -- (Y);
\end{tikzpicture}

And if we do not even precise draw in options, shapes has no effetc because no shapes are even draw.
\begin{tikzpicture}
\node[shape=circle,
minimum size=2.1cm,
inner sep=0pt] (Z) at (0,0) {A};
\node[shape=rectangle,
minimum size=2.1cm,
inner sep=0pt] (Y) at (6,0) {B};
\draw[->] (Z) -- (Y);
\end{tikzpicture}

-
inner sep=xcm-> the node will be at minimum x cm wide -
inner sep=xpt-> the padding between the text and the border of the node
In fact node size is content size + 2 * inner sep.
If content size is smaler than controled size with minimum size and inner sep equals to 0, then the node size will be exactly minimum size.
Here a last example concerning that subject:
\begin{tikzpicture}[
% Global style for all nodes
every node/.style={
draw,
minimum size=2.1cm,
inner sep=0pt,
align=center
},
edgeLabel/.style={
draw=none,
fill=none,
minimum size=0pt,
inner sep=2pt,
font=\small
},
% Custom styles
circleNode/.style={circle, fill=blue!20},
rectNode/.style={rectangle, fill=green!20},
diamondNode/.style={diamond, aspect=2, fill=orange!20},
arrow/.style={->, thick}
]
% Main nodes
\node[circleNode] (Z) at (0,0) {Start};
\node[diamondNode] (D) at (4,0) {Condition};
\node[rectNode] (Y) at (8,2) {Action 1};
\node[rectNode] (W) at (8,-2) {Action 2};
% Extra node
\node[rectNode] (End) at (12,0) {End};
% Connections
\draw[arrow] (Z) -- (D);
\draw[arrow] (D) -- node[edgeLabel, above]{Yes} (Y);
\draw[arrow] (D) -- node[edgeLabel, below]{No} (W);
\draw[arrow] (Y) -- (End);
\draw[arrow] (W) -- (End);
\end{tikzpicture}

You see that we can define lobal style in tikzpicture option.
every node/.style={
draw,
minimum size=2.1cm,
inner sep=0pt,
align=center
}
Nothing new here apart from the align=center option definition that does what you think, center text content inside the node.
And what about ?
edgeLabel/.style={
draw=none,
fill=none,
minimum size=0pt,
inner sep=2pt,
font=\small
}
This is specifically for those nodes:
\draw[arrow] (D) -- node[edgeLabel, above]{Yes} (Y);
\draw[arrow] (D) -- node[edgeLabel, below]{No} (W);
Not for this one for example:
\draw[arrow] (Z) -- (D);
At this point you tell me.
"Wait, but after expansion, i do not see the difference !"
You are right but here that is not quite the right mental model.
You have to think again, about definition, then usage, not just pure expansion.
And for the last one i already defined the node here:
\node[circleNode] (Z) at (0,0) {Start};
\node[diamondNode] (D) at (4,0) {Condition};
So, i repeat but edgeLabel options aplies only on nodes that are knd of defined "on the fly" using the draw command !
And at this point there is no new options we have not seen.
Geometric Transformations
Now geometric transfrmations !!!
Yessss !!!
Look:
\begin{tikzpicture}
\draw[shift={(4,0)}, rotate=45, scale=0.5]
(0,0) ellipse (3 and 1);
\draw[shift={(12,0)}, rotate=45, scale=0.5]
(0,0) ellipse (3 and 1);
\end{tikzpicture}

shift={(COORDINATES)} -> shift={x,y} is just an internal option way to choose the starting point of a draw
Instead of doing precising the coordinates after:
\begin{tikzpicture}
\draw[rotate=45, scale=0.5]
(4,0) ellipse (3 and 1);
\end{tikzpicture}

rotate is just te rotation of the figure, (following trigonometri circle).
This is a key part of TikZ, allows extremely more easily way to draw some shapes in space.
scale -> Fancy way to ... scale / change dimensions proportionaly of a shape, 1 is the base scale value.
Look at this example emphasing the role of scale:
\begin{tikzpicture}
\draw[shift={(4,0)}, rotate=45, scale=0.5]
(0,0) ellipse (3 and 1);
\draw[shift={(12,0)}, rotate=135, scale=1]
(0,0) ellipse (3 and 1);
\end{tikzpicture}

Instead of:
\begin{tikzpicture}
\draw[shift={(4,0)}, rotate=45, scale=0.5]
(0,0) ellipse (3 and 1);
\draw[shift={(12,0)}, rotate=135, scale=0.5]
(0,0) ellipse (6 and 2);
\end{tikzpicture}

3D
Yess, 3D !!!
Look at that 3D axis demo:
\begin{tikzpicture}
\draw[->] (X1,Y1,Z1) -- (X2,Y1,Z1); % x axis
\draw[->] (X1,Y1,Z1) -- (X1,Y2,Z1); % y axis
\draw[->] (X1,Y1,Z1) -- (X1,Y1,Z2); % z axis
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\draw[->] (0,0,0) -- (2,0,0); % x axis
\draw[->] (0,0,0) -- (0,2,0); % y axis
\draw[->] (0,0,0) -- (0,0,2); % z axis
\end{tikzpicture}

Yup, thanks to \usetikzlibrary{3d} in the preambule, TikZ interprets 3D coordinates systems (internally it does a take those 3D coordinates, and projects it on a 2D plane)
Look another exampe -> the cube !
\begin{tikzpicture}
\fill[gray!20] (0,0,0) -- (2,0,0) -- (2,2,0) -- (0,2,0) -- cycle;
\draw (0,0,0) -- (2,0,0) -- (2,2,0) -- (0,2,0) -- cycle;
\draw (0,0,2) -- (2,0,2) -- (2,2,2) -- (0,2,2) -- cycle;
\draw (0,0,0) -- (0,0,2);
\draw (2,0,0) -- (2,0,2);
\draw (2,2,0) -- (2,2,2);
\draw (0,2,0) -- (0,2,2);
\end{tikzpicture}

You see it is technically possible to do it in raw 2D coordinate system, but at the cost of much more work. And a cube is the simplest 3D shape...
Here, the introduction of \fill that acts like draw for everything apart that it fills a closed area, not drawing any shapes.
By the way we can name coordinates, also posible in 2D of course, but it may be more usefull in 3D, look.
\begin{tikzpicture}
\begin{scope}
\coordinate (NAME1) at (POINT1);
\coordinate (NAME2) at (POINT2);
\coordinate (NAME3) at (POINT3);
\coordinate (NAME4) at (POINT4);
\coordinate (NAME5) at (POINT5);
\fill[gray!20] (A) -- (B) -- (C) -- (D) -- cycle;
\fill[gray!30] (S) -- (A) -- (B) -- cycle;
\fill[gray!40] (S) -- (B) -- (C) -- cycle;
\fill[gray!25] (S) -- (C) -- (D) -- cycle;
\draw (A) -- (B) -- (C) -- (D) -- cycle;
\draw (S) -- (A);
\draw (S) -- (B);
\draw (S) -- (C);
\draw[dashed] (S) -- (D); % hidden edge
\end{scope}
\end{tikzpicture}
Expanding to, for example:
\begin{tikzpicture}
\begin{scope}
\coordinate (A) at (0,0,0);
\coordinate (B) at (2,0,0);
\coordinate (C) at (2,2,0);
\coordinate (D) at (0,2,0);
\coordinate (S) at (1,1,2);
\fill[gray!20] (A) -- (B) -- (C) -- (D) -- cycle;
\fill[gray!30] (S) -- (A) -- (B) -- cycle;
\fill[gray!40] (S) -- (B) -- (C) -- cycle;
\fill[gray!25] (S) -- (C) -- (D) -- cycle;
\draw (A) -- (B) -- (C) -- (D) -- cycle;
\draw (S) -- (A);
\draw (S) -- (B);
\draw (S) -- (C);
\draw[dashed] (S) -- (D); % hidden edge
\end{scope}
\end{tikzpicture}

Usefull, when we want to reuse coordinates.
Why do we define a scope environment ?
Look at this:
\begin{tikzpicture}
\begin{scope}[rotate around x = 45, rotate around y = 45, rotate around z = 45]
\coordinate (A) at (0,0,0);
\coordinate (B) at (2,0,0);
\coordinate (C) at (2,2,0);
\coordinate (D) at (0,2,0);
\coordinate (S) at (1,1,2);
\fill[gray!20] (A) -- (B) -- (C) -- (D) -- cycle;
\fill[gray!30] (S) -- (A) -- (B) -- cycle;
\fill[gray!40] (S) -- (B) -- (C) -- cycle;
\fill[gray!25] (S) -- (C) -- (D) -- cycle;
\draw (A) -- (B) -- (C) -- (D) -- cycle;
\draw (S) -- (A);
\draw (S) -- (B);
\draw (S) -- (C);
\draw[dashed] (S) -- (D); % hidden edge
\end{scope}
\end{tikzpicture}

We can rotate the sceeene !!
Think of it like defining an axis in PGFPlot.
Massive PGFPlot 3D foreshadowing here:
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
zlabel=$z$,
colorbar,
colormap name=myinferno]
\addplot3[surf,
domain=-2:2,
y domain = -2:2,
samples=30, % samples -> how accurate it is (you can choose x and y samples / intervals)
samples y=30
]{sin(deg(x)) * cos(deg(x))};
\end{axis}
\end{tikzpicture}

Keep in mid, the x axis, is the "width", the y axis is the "depth" and the z axis is the "height".
And we use \addplot3 for 3D plot in PGFPlot.
Sme infrmations about this plot, you are discovering just these new option: samples and samples y.
They are like the number of intervals the engine takes in count to draw this surface, the more there are the more accurate it is.
-
samples-> x samples -
samples y-> y samples
When does the samples are used in the PGFPlot engine ?
BEFORE the projection on the 2D plan.
Look, we are defining a surface:
sin(deg(x)) * cos(deg(x))
HERE, it is sampling, that is why we got x and y samples but not z samples.
Take a look at how the resolution gets worse here:
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
zlabel=$z$,
colorbar,
colormap name=myinferno]
\addplot3[surf,
domain=-2:2,
y domain = -2:2,
samples=15,
samples y=30,
]{sin(deg(x)) * cos(deg(x))};
\end{axis}
\end{tikzpicture}

So now that we have the axis direction in mind, we go back to the scope rotation for the shapes.
Here a simple example, rotating a line.
\begin{tikzpicture}[rotate around x=45,
rotate around y=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

\begin{tikzpicture}[rotate around x=0,
rotate around y=0,
rotate around z=45
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

\begin{tikzpicture}[rotate around x=0,
rotate around y=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

\begin{tikzpicture}[rotate around y=45,
rotate around x=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

At this point you are trying to emergeinvariants in your head about what the rotations actually do.
We are aligned that we draw a straight line perfectly parallel to the x axis.
So a rotation of X degree around this axis does nothing, that's right, but just fr this particular rotation.
You'll se later.
You also notice that the rotations have an order we can control, like so:
\begin{tikzpicture}[rotate around x=0,
rotate around y=45,
rotate around z=0
...
-> Rotate around x then around y
And:
\begin{tikzpicture}[rotate around y=45,
rotate around x=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
...
-> Rotate around y then around x
And you also note that rotation ARE NOT COMMUTATIVE.
R1 * R2 != R2 * R1
Look this:
\begin{tikzpicture}[rotate around x=45,
rotate around y=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

Does not equal:
\begin{tikzpicture}[rotate around y=45,
rotate around x=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

Why ??
It is not simply because, "straight line aligned to x, so x rotation does nothing first and then y, so yeah different than y rotation first and then x".
That was also my first interpretation but here this mental model breaks hard, if that was true then those would output the same thing:
\begin{tikzpicture}[rotate around x=45,
rotate around y=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

\begin{tikzpicture}[rotate around x=0,
rotate around y=45,
rotate around z=0
]
\draw (0,0,0) -- (2,0,0);
\end{tikzpicture}

But that is obviously not the case !
So what ?
In fact, this is not a rotation of the object arround the axis, but a rotation of the ENTIIIIRE AXISES around a particular axis, that is the game changer, and freaking counter intuitive and particularly dumb, one of the dumbest shit TikZ provides, that is ridiculously dumb design choice --> that totaly breaks easy predictability of geometric transformation...
That is not rotation in a fixed coordinate system.
In both case, rotations are not comutatives, but at least, in a fixed coordinate system, it is often far easizer to predict the output of a sequence of rotations.
I got an enormous amount of crystal hate for this design choice, i will train to the gym and come back.
...
Here i am !
I'll pretend this never happened and continue.
Look at that we can also define the literal meaning of the axis, in fact the direction of the axis, thanks to scope x, y and z options.
\begin{tikzpicture}
\begin{scope}[x={(MOOVERIGHT1,MOOVEUP1)}, % moving by 1 X unit -> moves right by 1cm and do not moves up or down
y={(MOOVERIGHT2,MOOVEUP2)}, % moving by one Y unit -> moves right by 0.5cm and up by 0.5cm
z={(MOOVERIGHT3,MOOVEUP3)}] % moving by 1 Z unit -> moves right by 0cm and up by 1cm
\coordinate (A) at (0,0,0);
\coordinate (B) at (2,0,0);
\coordinate (C) at (2,2,0);
\coordinate (D) at (0,2,0);
\coordinate (S) at (1,1,2);
\fill[gray!20] (A) -- (B) -- (C) -- (D) -- cycle;
\fill[gray!30] (S) -- (A) -- (B) -- cycle;
\fill[gray!40] (S) -- (B) -- (C) -- cycle;
\fill[gray!25] (S) -- (C) -- (D) -- cycle;
\draw (A) -- (B) -- (C) -- (D) -- cycle;
\draw (S) -- (A);
\draw (S) -- (B);
\draw (S) -- (C);
\draw[dashed] (S) -- (D); % hidden edge
\end{scope}
\end{tikzpicture}
expanding to, for example:
\begin{tikzpicture}
\begin{scope}[x={(1.2cm,0cm)}, % moving by 1 X unit -> moves right by 1cm and do not moves up or down
y={(0.5cm,0.5cm)}, % moving by one Y unit -> moves right by 0.5cm and up by 0.5cm
z={(0cm,1cm)}] % moving by 1 Z unit -> moves right by 0cm and up by 1cm
\coordinate (A) at (0,0,0);
\coordinate (B) at (2,0,0);
\coordinate (C) at (2,2,0);
\coordinate (D) at (0,2,0);
\coordinate (S) at (1,1,2);
\fill[gray!20] (A) -- (B) -- (C) -- (D) -- cycle;
\fill[gray!30] (S) -- (A) -- (B) -- cycle;
\fill[gray!40] (S) -- (B) -- (C) -- cycle;
\fill[gray!25] (S) -- (C) -- (D) -- cycle;
\draw (A) -- (B) -- (C) -- (D) -- cycle;
\draw (S) -- (A);
\draw (S) -- (B);
\draw (S) -- (C);
\draw[dashed] (S) -- (D); % hidden edge
\end{scope}
\end{tikzpicture}

Yup, we can do that :)
Shades
Now, spheres !
\begin{tikzpicture}
\shade[shape=ball, color=red!20!white] (0,0) circle (2cm);
\shade[shape=ball, color=red!20!white] (8cm,0) circle (4cm);
\end{tikzpicture}

\begin{tikzpicture}
\shade[color=red!20!white] (0,0) circle (2cm);
\shade[color=red!20!white] (8cm,0) circle (4cm);
\end{tikzpicture}

\begin{tikzpicture}
\shade[ball color=red!20!white] (0,0) circle (2cm);
\shade[ball color=red!20!white] (8cm,0) circle (4cm);
\end{tikzpicture}

\begin{tikzpicture}
\shade[shape=ball, ball color=red!20!white] (0,0) circle (2cm);
\shade[shape=ball, ball color=red!20!white] (8cm,0) circle (4cm);
\end{tikzpicture}

Okok, that is A LOT.
First, \shade is a fancy \fill.
\fill just declare outputs a color onto a closed area, \shade outputs a controled variation of colors onto a closed area.
We will learn how to control the variations later.
Second, about parameters, this is where it first gets confusing.
The first example, made TikZ shade engine ignore the shade color, because we declared the option color, that makes it behave weirdly and just use default greyish shade color --> Just API bad design IMO. So it still render the shade as a ball surface area, but not with intended color.
Same problem in second example.
To actually make it use the intended color, we need to use the option ball color.
So that is why 3 and 3 examples works as intended.
And why the example 4 is actually redundant, we provide the shape with shape=ball, and redeclare shape in ball color.
So 3 wins.
The synthax is actually:
\begin{tikzpicture}
\shade[SHADEAPPLICATIONDEFINITION] AREADEFINITION;
\end{tikzpicture}
So where it is applied as in the actual "draw" and how it is applied (algorithm) in the options.
We can also provide cool parameters, like how the color must be on the outer and on the inner:
\begin{tikzpicture}
\shade[inner color=red!20,
outer color=blue!20] (0,0) circle (2cm);
\end{tikzpicture}

Now, one of the last thing we should be able to control, is "how the color spread".
First, we need to define the coordinate system we are working on, for a ball, so a circle area, it is a radial.
So we define our custom shading as defining a custom coor gradient and a starting point:
\pgfplotdeclareradialshading{STARTPOINT}{
color(DISTANCEFROMSTARTPOINT1)=(COLOR1);
color(DISTANCEFROMSTARTPOINT2)=(COLOR2)
}
expanding to, for example:
\pgfdeclareradialshading{myshade}{\pgfpoint{0.5cm}{0.5cm}}{
color(0cm)=(red!40);
color(1cm)=(blue!50)
}
and using it like:
\begin{tikzpicture}
\shade[shading=myshade] (0,0) circle (2cm);
\end{tikzpicture}

We define a radial with \pgfplotdeclareradialshading, because that tells the shading algorithm the gradient of color must "sparse" according to a radial coordinate system.
That is why the starting point is normal 2D point (x,y).
But what if we want to shift the ball ?
like if we shift x doing so:
\begin{tikzpicture}
\shade[shading=myshade] (8cm,0) circle (2cm);
\end{tikzpicture}
Dos this works ?
No
This is weird but nothing changes here.
In fact we need to also proved the shading transform option with the same shift, and we do not touch our custom shade myshade.
\begin{tikzpicture}
\shade[
shading=myshade,
transform canvas={shift={(8cm,0)}}
] (8cm,0) circle (2cm);
\end{tikzpicture}

Now, all is coherent according to TikZ API.
That is some good stuff, but in fact shade can be applied in any way, so yess, next thing to do is apply them in a rectangle, why not ?
So here we work with shading=axis.
Here an example that is the equivalent of the inner / outer color shading one for the ball.
Of course, geometrically different but you get the idea.
here with shading angle = 0.
\begin{tikzpicture}
\shade[shading=axis,
left color=red,
right color=blue,
shading angle=0]
(0,0) rectangle (3,2);
\end{tikzpicture}

Here with shading angle=40.
\begin{tikzpicture}
\shade[shading=axis,
left color=red,
right color=blue,
shading angle=40]
(0,0) rectangle (3,2);
\end{tikzpicture}

Here with shading angle=90.
\begin{tikzpicture}
\shade[shading=axis,
left color=red,
right color=blue,
shading angle=90]
(0,0) rectangle (3,2);
\end{tikzpicture}

Here with shading angle=190.
\begin{tikzpicture}
\shade[shading=axis,
left color=red,
right color=blue,
shading angle=190]
(0,0) rectangle (3,2);
\end{tikzpicture}

You get the idea, an x axis we rotate (angle according to a tigonmetric circle).
If you want bilinear shading, a cool trick is to do the following overlay.
\begin{tikzpicture}
% base gradient
\shade[shading=axis, left color=blue, right color=red]
(0,0) rectangle (4,3);
% overlay vertical gradient with transparency
\shade[shading=axis, top color=yellow, bottom color=green, opacity=0.5]
(0,0) rectangle (4,3);
\end{tikzpicture}

Which is equivalent of:
\begin{tikzpicture}
\shade[shading=axis, top color=yellow, bottom color=green]
(0,0) rectangle (4,3);
\shade[shading=axis, left color=blue, right color=red, opacity=0.5]
(0,0) rectangle (4,3);
\end{tikzpicture}

Because that is sad, but mixing left / right color with top / bottom color does not work in TikZ, what a shame, look at that !
\begin{tikzpicture}
\shade[shading=axis,
top color=yellow,
bottom color=green,
left color=blue,
right color=red]
(0,0) rectangle (4,3);
\end{tikzpicture}

\begin{tikzpicture}
\shade[shading=axis,
left color=blue,
right color=red,
top color=yellow,
bottom color=green
]
(0,0) rectangle (4,3);
\end{tikzpicture}

Only two last parameters are taken in count.
Hmm, wonder what will hapen if:
\begin{tikzpicture}
\shade[shading=axis,
left color=blue,
top color=yellow,
bottom color=green,
right color=red
]
(0,0) rectangle (4,3);
\end{tikzpicture}

WTF...
Just want to shut down my brain sometimes and stop seing theses disturbing things...
!!!!! Dumb, dumb, dumb !!!!!
Woooo some spanish punctations now !
Again Some 3D Plots
Now, we're going back to shapes, and while we've seen tha using a 3D coordinate system abstraction can be valuable when it comes to creating certain shapes, for some other shapes it can be vastly counter-productive and counter-efficient.
The cone example.
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},
y={(0.5cm,0.5cm)},
z={(0cm,1cm)}]
\def\rx{1.5}
\pgfmathsetmacro{\startangle}{180} % min = 180
\pgfmathsetmacro{\endangle}{300} % max = 360
\pgfmathsetmacro{\baselength}{(cos(\startangle - 180) + cos(360 - \endangle)) * \rx}
\pgfmathsetmacro{\xapex}{\baselength / 2}
\pgfmathsetmacro{\yapex}{2}
\coordinate (S) at (\xapex, \yapex, 3);
\fill [ color=red!60
] (0,0,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
\fill [ color=gray!60
] (0,0,0) arc[start angle = \startangle,
end angle = \endangle,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
\end{scope}
\end{tikzpicture}

Wow, there is A LOT going on there.
First, some macro definitions.
The radius for the cone base -> arc.
\def\rx{1.5}
Second, we define the arc start and end angle of the arc?
\pgfmathsetmacro{\startangle}{180}
\pgfmathsetmacro{\endangle}{300}
After, we will do something very weird, but in fact it is to keep the apex exactly at the center of the arc base.
so, we just compulte the total length of the base with the angles chosen.
\pgfmathsetmacro{\baselength}{(cos(\startangle - 180) + cos(360 - \endangle)) * \rx}
This is the length for the left part of the arc.
cos(\startangle - 180)
\startangle belongs to 180 - 270, so the greater it is, the closer \startangle - 180 is to 90, so the closer cos(\startangle - 180) is to 0.
We just apply the same logic for the second part of the arc.
cos(360 - \endangle))
But here, obviously, the greater \endangle is, the greater the distance is, so we do this substraction 360 - \endangle.
Because \endangle belongs to 270 to 360.
And of course the apex x is:
\pgfmathsetmacro{\xapex}{\baselength / 2}
And y is fixed to 2, for example.
You see that this motiv repeats itself 2 times.
\fill [ color=red!60
] (0,0,0) arc[start angle = ANGLE1,
end angle = ANGLE2,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
With, of course, ANGLE2 > ANGLE1.
There is in fact an overlay of 2 shapes.
We first create a full red base cone:
\fill [ color=red!60
] (0,0,0) arc[start angle = 0,
end angle = 360,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
And then overlay the greyish cone that is at maximum as wide as the first, but often narrower, according to the angles chosen.
\fill [ color=gray!60
] (0,0,0) arc[start angle = \startangle,
end angle = \endangle,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
To mimic a rotation, we just tweak the angles of the base.
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},
y={(0.5cm,0.5cm)},
z={(0cm,1cm)}]
\def\rx{1.5}
\pgfmathsetmacro{\startangle}{180} % min = 180
\pgfmathsetmacro{\endangle}{350} % max = 360
\pgfmathsetmacro{\baselength}{(cos(\startangle - 180) + cos(360 - \endangle)) * \rx}
\pgfmathsetmacro{\xapex}{\baselength / 2}
\pgfmathsetmacro{\yapex}{2}
\coordinate (S) at (\xapex, \yapex, 3);
\fill[ color=red!60
] (0,0,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
\fill[ color=gray!60
] (0,0,0) arc[start angle = \startangle,
end angle = \endangle,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
\end{scope}
\end{tikzpicture}

But you see ?
The result is not really convincing.
So here, that is an examle where a good plain 2D coordinate system is vastly superior to mimic 3D.
But just before doing that, did you see this ?
\fill[ color=red!60
] (0,0,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
Woow, the arc API inside the \fill function is much more eleguant than what we have for the same shape but in the \draw command !!!!
No redundances, all informations insideoptions.
Btw, we can also use it in draw, that is not specific, here just the interesting part lol.
\begin{tikzpicture}
\def\rx{2}
\def\ry{0.6}
\def\h{3}
\coordinate (S) at (0,\h);
\coordinate (O) at (0,0);
\draw (-\rx,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\end{tikzpicture}

Also, you see that each node of a shape, can either be a simple point, or a shape itself !!!
POINT SHAPE -- POINT -- ...
Expanding to, for example:
(0,0,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \rx cm]
-- (S)
-- cycle;
--> "FORMIDABLE !"
Cone now !
\begin{tikzpicture}
\def\rx{2}
\def\ry{0.6}
\def\h{3}
\coordinate (S) at (0,\h);
\coordinate (O) at (0,0);
\shade[
left color=gray!50,
right color=gray!50
]
(-\rx,0) arc[start angle = 180,
end angle = 270,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\shade[
left color=red!50,
right color=red!50,
]
(\rx,0) arc[start angle = 0,
end angle = -90,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\draw (-\rx,0) arc(180:360:\rx cm and \ry cm);
\draw[dashed] (\rx,0) arc(0:180:\rx cm and \ry cm);
% edges
\draw (S) -- (-\rx,0);
\draw (S) -- (\rx,0);
\end{tikzpicture}

Same good arc API than for \fill, but here with \shade, because why not.
This is pretty much the exact same principle than before, but here no weird scoping rules defining the meaning of x, y and z axis.
Just raw 2D coordinates.
Which simplifies A LOT the APEX x coordinate.
Btw, TikZ exposes a rotate option.
\begin{tikzpicture}[rotate=45]
\def\rx{2}
\def\ry{0.6}
\def\h{3}
\coordinate (S) at (0,\h);
\coordinate (O) at (0,0);
\shade[
left color=gray!50,
right color=gray!50
]
(-\rx,0) arc[start angle = 180,
end angle = 270,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\shade[
left color=red!50,
right color=red!50,
]
(\rx,0) arc[start angle = 0,
end angle = -90,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\draw (-\rx,0) arc(180:360:\rx cm and \ry cm);
\draw[dashed] (\rx,0) arc(0:180:\rx cm and \ry cm);
% edges
\draw (S) -- (-\rx,0);
\draw (S) -- (\rx,0);
\end{tikzpicture}

But, more importantly, we can rotate around our own point in the tikZ picture, which is insanely good !
Check this, we rotate around the apex that we already named S.
\begin{tikzpicture}[rotate around={45:(S)}]
\def\rx{2}
\def\ry{0.6}
\def\h{3}
\coordinate (S) at (0,\h);
\coordinate (O) at (0,0);
\shade[
left color=gray!50,
right color=gray!50
]
(-\rx,0) arc[start angle = 180,
end angle = 270,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\shade[
left color=red!50,
right color=red!50,
]
(\rx,0) arc[start angle = 0,
end angle = -90,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\draw (-\rx,0) arc(180:360:\rx cm and \ry cm);
\draw[dashed] (\rx,0) arc(0:180:\rx cm and \ry cm);
% edges
\draw (S) -- (-\rx,0);
\draw (S) -- (\rx,0);
\end{tikzpicture}

But how to mimic a rotation "in deph" --> around x axis.
Look at that, a mimic to a negative rotation around x axis, approximately 45 degrees, (not exact maths).
\begin{tikzpicture}
\def\rx{2}
\def\ry{0.7}
\def\h{2}
\coordinate (S) at (0,\h);
\coordinate (O) at (0,0);
\fill[
color=white
]
(-\rx,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\draw[thin] (-\rx,0) arc(180:360:\rx cm and \ry cm);
\draw[thick] (\rx,0) arc(0:180:\rx cm and \ry cm);
% edges
\draw (S) -- (-\rx,0);
\draw (S) -- (\rx,0);
\draw[thick] (S) -- (0,\ry);
\draw[thick, dashed] (0, \ry) -- (0,-\ry);
\end{tikzpicture}

We just tweak the apex coordinates and the x and y radius of the base, to give them approximated coordinates after a rotation around x by 45 degrees.
If we want the exact maths:
Because height is 3, so here it is cos(PI / 4) * 3 (in general case, but can be sin(PI / 4) * 3 here, because of special rotation value where cos(PI / 4) = sin(PI / 4)) approximately 2.12.
And x radius does not change, obviously.
But \ry goes from 0.6 to 0.6 * (1 + sin(PI / 4)), so approximately 1.02.
\begin{tikzpicture}
\def\rx{2}
\def\ry{1.02}
\def\h{2.12}
\coordinate (S) at (0,\h);
\coordinate (O) at (0,0);
\fill[
color=white
]
(-\rx,0) arc[start angle = 180,
end angle = 360,
x radius = \rx cm,
y radius = \ry cm]
-- (S)
-- cycle;
\draw[thin] (-\rx,0) arc(180:360:\rx cm and \ry cm);
\draw[thick] (\rx,0) arc(0:180:\rx cm and \ry cm);
% edges
\draw (S) -- (-\rx,0);
\draw (S) -- (\rx,0);
\draw[thick] (S) -- (0,\ry);
\draw[thick, dashed] (0, \ry) -- (0,-\ry);
\end{tikzpicture}

--> Much more convincing ! -- now you just have to fil some area with more or les dark color to make full illusion
And, remember your geometry courses, all rotations we can do aound x, y and z axis in a fixed or not fixed coordinate system CAN be done in a sequence of rotations on simply x and y axis !!
We've seen we can do y rotation, and now x rotation, so this is actually rotation complete.
Isn't that beautiful ?
Now, some other shapes.
Cylinder.
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},
y={(0.5cm,0.5cm)},
z={(0cm,1cm)}]
\coordinate (O) at (0,0,0);
\coordinate (T) at (0,0,3);
\def\rx{1.5}
\def\ry{0.5}
\draw (O) ellipse (\rx cm and \ry cm);
\draw (T) ellipse (\rx cm and \ry cm);
\draw (-\rx, 0, 0) -- (-\rx, 0, 3);
\draw (\rx, 0, 0) -- (\rx, 0, 3);
\end{scope}
\end{tikzpicture}

Nothing to add, you now understand all of this code.
Another cylinder example.
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},
y={(0.5cm,0.5cm)},
z={(0cm,1cm)}]
\coordinate (O) at (0,0,0);
\coordinate (T) at (6,1,1);
\def\rx{0.65}
\def\ry{1}
\fill[color=gray!80]
(0, 0, \ry)
arc[start angle = 90,
end angle = 270,
x radius = \rx cm,
y radius = \ry cm]
-- (6, 1, 1 - \ry )
arc[start angle = -90,
end angle = 90,
x radius = \rx cm,
y radius = \ry cm]
-- (0, 0, \ry);
\draw (6, 1, \ry + 1)
arc[start angle=90,
end angle=-90,
x radius=\rx cm,
y radius=\ry cm]
-- (6, 1, 1 - \ry);
\draw[fill=black,
opacity=0.5] (O) ellipse (\rx cm and \ry cm);
\draw (0, 0, \ry)
-- (6, 1, \ry + 1);
\draw (6, 1, 1 - \ry)
-- (0, 0, -\ry);
\end{scope}
\end{tikzpicture}

Again, overlays.
The shape.
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},
y={(0.5cm,0.5cm)},
z={(0cm,1cm)}]
\coordinate (O) at (0,0,0);
\coordinate (T) at (6,1,1);
\def\rx{0.65}
\def\ry{1}
\draw (6, 1, \ry + 1)
arc[start angle=90,
end angle=-90,
x radius=\rx cm,
y radius=\ry cm]
-- (6, 1, 1 - \ry);
\draw[fill=black,
opacity=0.5] (O) ellipse (\rx cm and \ry cm);
\draw (0, 0, \ry)
-- (6, 1, \ry + 1);
\draw (6, 1, 1 - \ry)
-- (0, 0, -\ry);
\end{scope}
\end{tikzpicture}

And, the "Texture".
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},
y={(0.5cm,0.5cm)},
z={(0cm,1cm)}]
\coordinate (O) at (0,0,0);
\coordinate (T) at (6,1,1);
\def\rx{0.65}
\def\ry{1}
\fill[color=gray!80]
(0, 0, \ry)
arc[start angle = 90,
end angle = 270,
x radius = \rx cm,
y radius = \ry cm]
-- (6, 1, 1 - \ry )
arc[start angle = -90,
end angle = 90,
x radius = \rx cm,
y radius = \ry cm]
-- (0, 0, \ry);
\end{scope}
\end{tikzpicture}

PGFPlot, again
Now, we can speak more about 3D PGFPLOT.
Look.
\begin{tikzpicture}
\begin{axis}[
hide axis,
]
\addplot3[
surf,
domain=0:180,
y domain=0:180,
]
({cos(x)},
{sin(x)},
{1});
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
hide axis,
]
\addplot3[
surf,
domain=0:180,
y domain=0:180,
]
({cos(x)},
{sin(x)},
{cos(y)});
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
hide axis,
]
\addplot3[
surf,
domain=0:180,
y domain=0:180,
]
({cos(x)},
{sin(x)},
{sin(y)});
\end{axis}
\end{tikzpicture}

What is going on here ?
Well, yo just defining Surface points.
In fact that is basically:
-
FX(input) = X -->
cos(x) -
FY(input) = Y -->
sin(x)
And here Z is just a constant 1, this is why first exampe just output, not a surface but a demi-circle.
But the key to surfaces is Z axis.
That is why in the second example, we got a surface.
Multiple points on Z axis are computed for each points on x and y axis. --> Surface.
And we got a nice color gradient indicating the z axis, even if not visually indicated elsewhere because of hide axis option in axis environment.
Now, why the second example looks like it output the same surface in different camera angle.
In fact that is exactly the same angle.
But the illusion is PGFPlot painter algorithm ORDER
Look, in the second example, we provided for z, cos(y).
So at first y is sin(x) -> 0.
Then, at first cos(y) -> tends to 1.
So the top lines lines / meshes are painted first.
That is exactly the opposite order of the third example where z is defined as: sin(y).
Now, i want to make this article sort of "interractive", could you explain what is going on here ?
\begin{tikzpicture}
\begin{axis}[
hide axis,
]
\addplot3[
surf,
domain=0:180,
y domain=0:180,
]
({sin(x)},
{cos(x)},
{sin(y)});
\end{axis}
\end{tikzpicture}

Camera angles !
First look at this surface.
\begin{tikzpicture}
\begin{axis}
\addplot3[surf,
samples = 30,
samples y = 30] {x^2 + y^2};
\end{axis}
\end{tikzpicture}

By the way , we got an hint on how the samples are created, it first is segmanted according to the distance on the concenred axis, x for samples and y for samples y. Then, the meshes are distorted following the other axis values.
That is why meshes at the edges of the x axis looks wider then the meshes in the center.
Around x = -4.

Around x = 0.

But, we are here to discuss the camera angles of a PGFPlot.
Take a look.
\begin{tikzpicture}
\begin{axis}[view={50}{50}]
\addplot3[surf] {x^2 + y^2};
\end{axis}
\end{tikzpicture}

Maybe that you get it, you surely do because you are smart, how do i know that ? -- you are reading my article, that's enough.
It is:
\begin{axis}[view={Z_AXIS_ROTATION}{X_AXIS_ROTATION}]
Expanding to, for example.
\begin{axis}[view={50}{50}]
Another example witth x = -50 degrees.
\begin{tikzpicture}
\begin{axis}[view={50}{-50}]
\addplot3[surf] {x^2 + y^2};
\end{axis}
\end{tikzpicture}

3D Plots
BarPlots
Nothing new, you already should be able to read this like it's your native language.
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
zlabel=$z$]
\addplot3[only marks,
scatter,
scatter src = explicit,
mark=*,
colormap name=myinferno] coordinates {
(1,2,3) [0.6]
(2,1,4) [0.2]
(3,3,2) [0.9]
(4,2,5) [0.4]
};
\end{axis}
\end{tikzpicture}

Ooor, maybe not.
Yess, what is scatter src = explicit ?
And why the gradient option with colormap name=myinferno.
Recall that myinferno is a preambule defined colormap gradient as:
\pgfplotsset{ %define custom pgfplot theme, heatmap
colormap={myinferno}{
rgb255(0cm)=(0,0,4);
rgb255(1cm)=(31,12,72);
rgb255(2cm)=(85,15,109);
rgb255(3cm)=(136,34,106);
rgb255(4cm)=(186,54,85);
rgb255(5cm)=(227,89,51);
rgb255(6cm)=(249,140,10);
rgb255(7cm)=(249,201,50);
rgb255(8cm)=(252,255,164);
}
}
Great !
We can anwser those questions with the same response.
You see that in coordinates, we defined points not only with their coordinates, but with an attached value between "[" and "]".
That is the coor scale, that (recall) is normalized by the engine taking in count the min and max value.
So putting the scatter src = explicit tells that WE control the color of EACH point.
That is not the engine responsability here to infere their color based on their location on the coordinate system.
Or with the infamous table.
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
zlabel=$z$]
\addplot3[only marks,
mark=*,
scatter,
scatter src = explicit
] table[col sep=comma,
y=y,
x=x,
z=z,
meta=color] {scatterplot3D.csv};
\end{axis}
\end{tikzpicture}

scatterplot3D.csv:
x,y,z,color
1,2,3,0.1
2,1,4,0.6
3,3,2,0.2
4,2,5,0.9
The color is a metadata information, that's why we used meta=color in option of table function.
In the following, this is the engine responsability to map color to each points.
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
zlabel=$z$]
\addplot3[only marks,
scatter,
mark=*,
colormap name=myinferno] coordinates {
(1,2,3)
(2,1,4)
(3,3,2)
(4,2,5)
};
\end{axis}
\end{tikzpicture}

You see that we see a lot of the gradient color.
In fact what it does is very straight forward and very coherent from what we've seen so far.
Computes the lower and uper bounds of the z axis, samples the colors of the gradient between these bounds, and just map the gradient color to the points according to their z coordinates.
Experimenting with this plot, i found that it can be very good for representing the evolution of the positions of an object. Just adding a smooth line between contiguous points.
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,
ylabel=$y$,
zlabel=$z$]
\addplot3[mark=*,
scatter,
scatter src = explicit,
smooth
] table[col sep=comma,
y=y,
x=x,
z=z,
meta=color] {scatterplot3D2.csv};
\end{axis}
\end{tikzpicture}

We've seen surfaces before, but the meshes were filled, here a surface where meshes arenot filled !
We do that by putting the option mesh.
\begin{tikzpicture}
\begin{axis}[grid=major,view={210}{30}]
\addplot3+[mesh,
samples=10,domain=0:1]
{5*x*sin(2*deg(x)) * y*(1-y)};
\end{axis}
\end{tikzpicture}

You se that the edges color of the meshes are also computes according to z coordinate.
We have to add the parameter scatter to make also the points color behave like the edges color.
\begin{tikzpicture}
\begin{axis}[grid=major,view={210}{30}]
\addplot3+[mesh,
scatter,
samples=10,domain=0:1]
{5*x*sin(2*deg(x)) * y*(1-y)};
\end{axis}
\end{tikzpicture}

3D BarPlots
Now, some 3D barplots.
\begin{tikzpicture}
\begin{axis}[
xlabel=$x axis$,
zlabel=$values$,
ylabel=$y axis$,
symbolic x coords={A,B,C},
symbolic y coords={X,Y,Z},
xtick=data,
ytick=data,
enlargelimits=0.15
]
\addplot3[
ybar,
fill=blue!50,
]
table[
col sep=comma,
x=xlabel,
y=zlabel,
z=value
] {barplot3D.csv};
\end{axis}
\end{tikzpicture}

In fact the only thing new here, is the combination of the ybar option in the \addplot3 function.
barplot3D.csv
xlabel,zlabel,value
A,X,33
A,Y,2
A,Z,67
B,X,23
B,Y,12
B,Z,17
C,X,32
C,Y,22
C,Z,37
Ternary Diagramm
Now, some memories of when i was chemist, the infamous ternary diagramms.
I found this example on Christian Feuersänger website: https://pgfplots.net/author/christian/, the author of PGFPlot.
\begin{tikzpicture}
\begin{ternaryaxis}[
title=Want--be--Stainless Steel,
xlabel=Weight Percent Chromium,
ylabel=Weight Percent Iron,
zlabel=Weight Percent Nickel,
label style=sloped,
area style,
]
\addplot3 table {
1 0 0
0.5 0.4 0.1
0.45 0.52 0.03
0.36 0.6 0.04
0.1 0.9 0
};
\addlegendentry{Cr}
\addplot3 table {
1 0 0
0.5 0.4 0.1
0.28 0.35 0.37
0.4 0 0.6
};
\addlegendentry{Cr+$\gamma$FeNi}
\addplot3 table {
0.4 0 0.6
0.28 0.35 0.37
0.25 0.6 0.15
0.1 0.9 0
0 1 0
0 0 1
};
\addlegendentry{$\gamma$FeNi}
\addplot3 table {
0.1 0.9 0
0.36 0.6 0.04
0.25 0.6 0.15
};
\addlegendentry{Cr+$\gamma$FeNi}
\addplot3 table {
0.5 0.4 0.1
0.45 0.52 0.03
0.36 0.6 0.04
0.25 0.6 0.15
0.28 0.35 0.37
};
\addlegendentry{$\sigma$+$\gamma$FeNi}
\node[inner sep=0.5pt,
circle,
draw,
fill=white,
pin=-15:\footnotesize Stainless Steel
] at (axis cs:0.18,0.74,0.08) {};
\end{ternaryaxis}
\end{tikzpicture}

First, what does this represent ?
It represent the compositions (in percentage) of a "solution" by 3 elements.
One elemnt at each apex of the triangle.
How to determine the composition of a solution if i pin point you a random point on the triangle area ?
Take this point for example:

Now, i want to get its composition.
For this, you have to associate its lines directions to an element.
You see ?
There are 3 lines directions.
One horizontal, this is perrfectly parallel to the base,
Now, to which element does it map ?
Easy one, you just look at when this line crosses the 0 of one of the elment (edge).
For this one it is the bottom right apex, it maps to Chromium.
So we got the information that this solution is made of 20% of mass of Chromium.
The same logic applies for the 2 remaining lines direction.
The line that has a "negative" (top to bottom) direction maps to Iron.
So the element is made of 40% of Iron.
We can deduce that this solution is also made of 40% of Nickel (to make up to 100%).
And to get the "properties" / "details" of this solution, just look at the legend of the color the solution point is in.
Here it is beige, so gammaFeNi, whatever it means, don't ask me lol.
Now let's dissect the code.
The new thing is this ternaryaxis environment, required for drawing this.
This is also very comon to add it the option area style which is much better for results interpretations, because if not provided, areas are not filled.
\begin{tikzpicture}
\begin{ternaryaxis}[
title=Want--be--Stainless Steel,
xlabel=Weight Percent Chromium,
ylabel=Weight Percent Iron,
zlabel=Weight Percent Nickel,
label style=sloped,
]
\addplot3 table {
1 0 0
0.5 0.4 0.1
0.45 0.52 0.03
0.36 0.6 0.04
0.1 0.9 0
};
\addlegendentry{Cr}
\addplot3 table {
1 0 0
0.5 0.4 0.1
0.28 0.35 0.37
0.4 0 0.6
};
\addlegendentry{Cr+$\gamma$FeNi}
\addplot3 table {
0.4 0 0.6
0.28 0.35 0.37
0.25 0.6 0.15
0.1 0.9 0
0 1 0
0 0 1
};
\addlegendentry{$\gamma$FeNi}
\addplot3 table {
0.1 0.9 0
0.36 0.6 0.04
0.25 0.6 0.15
};
\addlegendentry{Cr+$\gamma$FeNi}
\addplot3 table {
0.5 0.4 0.1
0.45 0.52 0.03
0.36 0.6 0.04
0.25 0.6 0.15
0.28 0.35 0.37
};
\addlegendentry{$\sigma$+$\gamma$FeNi}
\node[inner sep=0.5pt,
circle,
draw,
fill=white,
pin=-15:\footnotesize Stainless Steel
] at (axis cs:0.18,0.74,0.08) {};
\end{ternaryaxis}
\end{tikzpicture}

And now look at that it will make sense for the area drawing:
xlabel=Weight Percent Chromium,
ylabel=Weight Percent Iron,
zlabel=Weight Percent Nickel,
Now you get the mapping of element to axis.
so you can easily undertand the blue area definition (the first one, the one that is long and not wide at the left edge).
\addplot3 table {
1 0 0
0.5 0.4 0.1
0.45 0.52 0.03
0.36 0.6 0.04
0.1 0.9 0
};
\addlegendentry{Cr}
We put enough point entries to samle the area as precisely aswe can (data from experiments).
The label style=sloped option is aso very common, it make the label parallel to the axis, if not set, it can easily become a mess.
PolarAxis
for this one, you have to import the polar PGFPlot library.
\usepgfplotslibrary{polar}
Code:
\begin{tikzpicture}
\begin{polaraxis}
\addplot[mark=none,domain=0:180,samples=600]
{sin(x)};
\end{polaraxis}
\end{tikzpicture}

Some maths did not kill anyone right ? Right ?
Basically, we are in a polar axis.
X (as in sin(x)) is the angle theta.
What we have control of here is the formula that computes the radius r, and here we put sin(x) = theta.
"Okok, wtf, theta, r whatever, how is that linked to the 2D plots, because at the end of the day the engine must compute actual x and y coordinates in a cartesian coordinate system."
You are right.
Simple enough the relation is:
-
x (hidden cartesian coordinate system)->r * cos(theta) -
y (hidden cartesian coordinate system)->r * sin(theta)
So in the particular case where theta = sin(x), that is:
-
x = sin(theta) * cos(theta) -
y = sin^2(theta)
Look, you see the absolute max x values are 0.5, because at PI / 4 approx 0.70 we have x = 0.70*0.70 = 0.5.
That's all.
We already drew the right half of the circle just with theta being between 0 and 90.
And with theta being between 90 and 180, we just draw the left half of the circle.
Look, if we want to draw the first quarter:
\begin{tikzpicture}
\begin{polaraxis}
\addplot[mark=none,domain=0:45,samples=600]
{sin(x)};
\end{polaraxis}
\end{tikzpicture}

Look at the evolution of the x coordinates:
\begin{tikzpicture}
\begin{axis}[domain=-3.14:3.14]
\addplot[samples = 200] {sin(deg(x)) * cos(deg(x))};
\end{axis}
\end{tikzpicture}

Here, because the cos and sin functions takes degrees, we convert radians (-3.14 to 3.14) to degrees with deg(...).
If we zoom in from 0 to PI / 2 approx 1.57, we see that it has the range to do a full pattern, from y = 0 to y = 0.
\begin{tikzpicture}
\begin{axis}[domain=0:1.57]
\addplot[samples = 200] {sin(deg(x)) * cos(deg(x))};
\end{axis}
\end{tikzpicture}

That is coherent with what was ouputed in the polaraxis.
Here, we have:
sin(x) * cos(x) -> sin(x) * sin(PI / 2 - x)
We got the identity:
sinA * sinB = 1/2[cos(A - B) - cos(A + B)]
So we just replace.
1/2 * [cos(x - (PI / 2 - x)) - cos(x + (PI / 2 - x))]
-> 1/2 * [cos(-(PI / 2) + 2x) - cos(PI / 2)]
-> 1/2 * cos(-(PI / 2) + 2x)
-> 1/2 * cos(2x - (PI / 2))
again the first relation we used...
-> 1/2 * sin(PI / 2 - (2x - (PI / 2)))
-> 1/2 * sin(PI - 2x)
And because of the mirroring that gives sin(PI - u) = sin(u), we have:
-> 1/2 * sin(2x)
It has a greater frequence (but smaller amplitude) than standard sin(x).
Look, on the same domain -5:5.
\begin{tikzpicture}
\begin{axis}[domain=-5:5]
\addplot[samples=200] {sin(deg(x))};
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[domain=-5:5]
\addplot[samples=200] {0.5 * sin(deg(2 * x))};
\end{axis}
\end{tikzpicture}

I'm gonna give you another example.
Now you can think about this beautifull example.
\begin{tikzpicture}
\begin{polaraxis}
\addplot[mark=none,domain=0:720,samples=600]
{sin(x) * cos(x)};
\end{polaraxis}
\end{tikzpicture}

Or this one.
\begin{tikzpicture}
\begin{polaraxis}
\addplot[mark=none,domain=0:720,samples=600]
{sin(2*x) * cos(2*x)};
\end{polaraxis}
\end{tikzpicture}

LaTeX is more than just markup
Even if i have massively anouced what we can do in LaTeX macro, here we'll go further.
First, recall the basics.
\def\a{Rémi}
\def\b{Julien}
Then, use it as:
Bonjour \a\ et \b.
Bonjour \a{} et \b.
Each one outputs the same result.
"Bonjour Rémi et Julien."
And yess, that is strange that we can call the variable like a comand with empty {}.
Speaking of commands, they are in fact, like said before, fancy variables with fancy logic.
\newcommand{\hello}[3]{Hello #1, #2 et #3}
Used like:
\hello{Rémi}{Julien}{Lucas}
Output: "Hello rémi, julien et Lucas"
This stays pure expansions...
Now most confusing part of LaTeX.
How to reassign a value to a variable ?
Maybe, you think this is done simply by.
\def\a{\b}
It works if you just use the \a variable after just to outputs its value, it does raw expansion.
\a
Expands to "Julien".
BUT !
When you use it in comparisons functions such as:
\ifx\a\b
OUI
\else
NO
\fi
Is \a definitions equals to \b. -> "NO"
It is another thing entirely.
In fact this function does not expand any of the variabe, but just checks for the last definition value.
So, the right way to REDEFINE, that's the word lol, a variable, is using \edef.
Example:
\edef\a{\b}
\ifx\a\b
OUI
\else
NO
\fi
Outputs "OUI".
\gdef is like \def but survives any scope {...}
\xdef is like \edef but survives any scope {...}
I already introduced you to comparisons function with \ifx.
Its synthax is:
\ifx\VAR\OTHERVAR
CODE1
\else
CODE2
\fi
Or just.
\ifx\VAR\OTHERVAR
CODE1
\fi
From xstring package we can use this function too:
\IfStrEq{CONTENT1}{CONTENT2}{CODESUCCESS}{CODEFAILURE}
Expanding, for example to:
\IfStrEq{\a}{Rémi}{YES}{NO}
Often better practice.
"For now, that is just for variable raw definition comparison, but would'nt it be cool if we had smarter comparisons functions that gets the type of what we are comparing and accept operators ??"
"Idk, maybe like comparing variables that can be interpreted as numbers right ?"
It EXISTS !
Introducing \ifnum.
\ifnum 5 > 3
OUI
\else
NO
\fi
--> "OUI"
\ifnum 5 = 3
OUI
\else
NO
\fi
--> "NO"
\ifnum 5 < 3
OUI
\else
NO
\fi
--> "NO"
You can also compare length, neat, but i can not find a comon scenario where it is necessary.
Maybe when you have a work and that you change dimensions (stored in a variable) on the fly to see what formating works the best.
\ifdim 2cm>1cm
OUI
\else
NO
\fi
--> "OUI"
Now introducing the most basic if comparison function... the \ifBOOLEAN.
\iftrue
OUI\_A
\fi
--> "OUI_A"
\iffalse
OUI\_B
\fi
--> NOTHING
Why am i bringing that onto the table, because of a way to manipulate boolean variables.
We declare them like that:
\newif\ifcool
The variable name is cool.
The synthax is weird:
\newif\ifVARNAME
Now we set its boolean value doing so:
\VARNAMEBOOLEANVALUE
Expanding to, for example:
\cooltrue
And after with its expansions that does not even require the infamous \, we can use it in basic boolean comparison if.
\ifcool
OUI
\else
NO
\fi
--> "OUI"
After.
\coolfalse
\ifcool
OUI
\else
NO
\fi
--> "NO"
Now look at that.
\def\coolbtrue{\let\coolb\iftrue}
\def\coolbfalse{\let\coolb\iffalse}
\coolbtrue
\coolb
OUIA
\else
NOA
\fi
\coolbfalse
\coolb
OUIB
\else
NONB
\fi
First, outputs "OUIA" then "NONB".
Why ?
Because we used \let.
\let\a\b
Tells teX to make \a behave exactly the same as \b. --> SAME TOKEN
Now a basic thing, check emptyness of variable.
\def\x{}
\ifx\x\empty
EMPTY
\else
NOT EMPTY
\fi
--> "EMPTY"
Loops
\foreach \xb in {1,2,3,4} {
\IfStrEq{\xb}{4}{END}{Value: \xb \\}
}
Outputs:
Value: 1
Value: 2
Value: 3
END
Or we can also define the variable list we will iterate on.
\def\lst{1A,2B,3C,4E}
\foreach \xb in \lst {
\IfStrEq{\xb}{4}{END}{Value: \xb \\}
}
Outputs:
Value: 1A
Value: 2B
Value: 3C
Value: 4D
So, you get it, elements must be separated by a comma.
You can even append to a list, look we create \lstb list and append elements to it using the expansion property of \edef.
\def\lstb{}
\edef\lstb{\lstb 1}
\edef\lstb{\lstb,2}
\edef\lstb{\lstb,2}
\edef\lstb{\lstb,3}
\foreach \xb in \lstb {
\IfStrEq{\xb}{4}{END}{Value: \xb \\}
}
Outputs:
Value: 1
Value: 2
Value: 3
Value: 4
Neat !
But, wait wait wait, there is so much more, hope you are ready !
Pattern Matching
Hang up your belt, because here we enter a special zone.
Look at this:
We first define a list containing key values pairs, defined as (key/value).
Note the / --> IMPORTANT !!!
\def\pairs{{A/1},{B/2},{C/3},{D/4}}
Then the loop.
\foreach \x/\y in \pairs {
\x : \y \\
}
Outputs:
A: 1
B: 2
C: 3
D: 4
YESSS, Pattern matching, that's right !!
That opens an enormous amount of possibilities !
At this point it is a bit like haskell haha.
To emphasize this concept i made this example.
\def\pairsb{{A/1/A1},{B/2/B2},{C/3/C3},{D/4/D4}}
\foreach \x/\y/\z in \pairsb {
\x : \y : \z \\
}
Outputs:
A: 1: A1
B: 2: B2
C: 3: C3
D: 4: D4
Or this one.
\def\pairsb{{A/{1/A1}},{B/{2/B2}},{C/{3/C3}},{D/{4/D4}}}
Note that here, we don't mind \edef because what matters in the loop is the value, not the last definition, because the pattern matching automatically expands the element.
Also note that here instead of having all on the same level, we scoped the inner level between {...} allowing for the TeX tokenizer to match a whole group as one entity and to pass this entity to a function (\splittemp) that will discover further subgroups with pattern matching (decomposition).
Then, we declare a macro that does pattern matching on its input literally, not even a \newcommand, no just plain old \def.
\def\splittemp#1/#2-{
\x : #1 - #2 \\
}
It actually splits its input by the pattern matching in finds and assign a variable position to each group it made after the patter match (#1 and #2).
So, finaly the loop:
\foreach \x/\temp in \pairsb {
\expandafter\splittemp\temp-
}
Yess it is literaly giving the input to the macro expanding the group pattern matched by the loop, so it expands \temp to its actual value.
Normally when we call a macro, we expects it to be automatically expanded, but here \expandafter is an insurance.
Thanks to \expandafter\A\B that does expands \B before giving it to \A.
Here:
\expandafter\splittemp\temp-
Note that we gave a last separator, being - at the end to correcty create the group #2.
Ouputs:
A: 1 - A1
B: 2 - B2
C: 3 - C3
D: 4 - D4
We could have done the - trick with a token that is used often to do that, it has no visual existance, it just exists in the TeX tokenizer.
Introducing \relax.
\def\splittemp#1/#2\relax{
\x : #1 - #2 \\
}
\foreach \x/\temp in \pairsb {
\expandafter\splittemp\temp\relax
}
Ouputs:
A: 1 - A1
B: 2 - B2
C: 3 - C3
D: 4 - D4
Tree Expansion Example
Okok, here is a list of trees:
\def\pairsc{{N1/{L/V1}},{N2/{R/V2}},{N3/{{L/V3}/{R/V4}}},{N4/{{L/{{L/V5}/{R/V6}}}/{R/V7}}}}
Each tree is:
{NODE/{(L/NODE)/(R/NODE)}}
Where a NODE is a subtree, so it is also:
{NODE/{(L/NODE)/(R/NODE)}}
Expanding to, for example:
{N4/{{L/{{L/V5}/{R/V6}}}/{R/V7}}}
You note that each subtree has its own scope.
Now, the recursivity traversal, how do we think about it ?
First, we think about what is going on when we encounter a leaf, the end path for the tree.
There are two possibilities for a leaf with this tree semantics, wether we encounter the final Side or Value.
So the macro should be.
\newcommand{\treeleaf}[1]{
\IfStrEq{#1}{L}
{Side: #1}
{
\IfStrEq{#1}{R}
{Side: #1}
{Value: #1}
}
}
If L -> that is a Side, so we output "Side: " and its side, wether "L" (Left) or "R" (Right).
And if no "L" or "R", then that's the value, so "Value: " and its value is outputed.
So the missing piece for enabling a recursivity is a macro that cals itself with, as input the subhroup it just find after the patter matching, or calls \treeleaf if it detects that the subgroup is a leaf.
It is exactly what we are going to do except that we will declare two macros that will call eachother following this logic.
\newcommand{\treesplit}[1]{
\IfSubStr{#1}{/}
{
\expandafter\treesplitaux#1\relax
}
{
\treeleaf{#1}
}
}
\def\treesplitaux#1/#2\relax{
(
\treesplit{#1}
/
\treesplit{#2}
)
}
Nothing more to add, you should be able to understand what is going on.
"Wait a minute, are you sure about that?"
"Think again, about the distinction between scoping and raw toekns."
And yess, the subtelty, if we keep this code unchanged, we make a big mistake.
at this stage, you are maybe thinking, that it makes perfect sense, the grouping decomposition made by the patter matching here is fine:
\expandafter\treesplitaux#1\relax
Where \treesplitaux is just:
\def\treesplitaux#1/#2\relax{
(
\treesplit{#1}
/
\treesplit{#2}
)
}
But in fact this is not.
In fact, here the \expandafter is necessary but not sufficient.
It correctly is an insurance to make #1 expands to its value to something like: {1/A1}.
But, it stays scoped !
So this part:
\treesplitaux#1/#2\relax
Never sees the /, so it can not do a proper group decomposition.
Then, the chance we have is that { and } are character, like others.
So, we can manually descope the content to make the function behave as intended.
Because, if we do not do that, we will have weird results, and maybe even outputing some unconsumed tokens --> not in the expected formating.
The correct code is:
\newcommand{\treesplit}[1]{%
\def\TreeTmp{#1}
\IfBeginWith{\TreeTmp}{\{}{
\StrGobbleLeft{\TreeTmp}{1}[\TreeTmpA]
\StrGobbleRight{\TreeTmpA}{1}[\TreeTmp]
}{}
\IfSubStr{\TreeTmp}{/}
{
\expandafter\treesplitaux\TreeTmp\relax
}
{
\treeleaf{\TreeTmp}
}
}
\def\treesplitaux#1/#2\relax{%
( \treesplit{#1} | \treesplit{#2} )%
}
No changes to \treesplitaux, but what are the changes brought to \treesplit?
First we just assign the parameter to a value:
\def\TreeTmp{#1}
And what do we do with it ?
If it begins with { --> scoped --> need to descope manualy removing manualy first (left) and last (right) char.
That's why we got this in the conditional code.
\StrGobbleLeft{\TreeTmp}{1}[\TreeTmpA]
\StrGobbleRight{\TreeTmpA}{1}[\TreeTmp]
We assign to newly created variable \TreeTmpA the \TreeTmp variable without its first character (1 and Left) ({).
Then we assign \TreeTmpA back to \TreeTmp without its last character (1 and Right).
After, we apply logic to get if we are at leaf or not, so we continue recursive call.
For this, we have to check if / is a substring of \TreeTmp.
\IfSubStr{\TreeTmp}{/}
{
\expandafter\treesplitaux\TreeTmp\relax
}
{
\treeleaf{\TreeTmp}
}
Now, the real question "What came first ? The egg or the chicken ?"
Idk, but the analogy for those 2 macros is of course \treesplit, because we theorically could have a tree composed only with a leaf.
So, in the loop for traversing all the trees, we do the following:
\foreach \x/\temp in \pairsc {
\x : \expandafter\treesplit\temp \\
}
Hmm, not exactly right.
Why because here incorrect argument passing, it is like this example:
\def\B{123}
\def\A#1{[#1]}
\expandafter\A\B
Which outputs:
[1]23
Why, because it has no meaning of what the argument is, because ther is no scoping for that argument which is as we know 123.
But here acts weirdly, at first thinks it is the first letter 1 and for the second call, gets the rest of the letters 23.
Then maybe try.
\foreach \x/\temp in \pairsc {
\x : \treesplit{\temp}\par
}
--> FAILS
In fact in \foreach (pgffor package), the passing of macro created by pgffor are a little weird so when we pass it to a \newcommand, we do that:
\foreach \x/\temp in \pairsc {
\x : \expandafter\treesplit\expandafter{\temp} \\
}
Expands \temp after the token { and then add token }. --> Literally like a \treesplit{...} arg passing but here we just assure that the expansion hapens on \temp.
Final beautifull tree output:
N1: ( Side: L | Value: V1 )
N2: ( Side: R | Value: V2 )
N3: ( ( Side: L | Value: V3 ) | ( Side: R | Value: V4 ) )
N4: ( ( Side: L | ( ( Side: L | Value: V5 ) | ( Side: R | Value: V6
) ) ) | ( Side: R | Value: V7 ) )
WOW, traversing a Tree in LateX, something i will remember !
Finally Doom and other in LaTeX
How did i create the game ?
First, the architecture.
We have a bash loop script (loop.sh) that waits for inputs.
When it receives input, it updates a state.tex variables.
This file is in fact an \input{...} of the main LaTeX file main.tex.
We won't focus on the bash file, but here is its code:
#!/bin/bash
# --- INPUT SETUP ---
exec 3</dev/tty
stty -icanon -echo
trap "stty sane" EXIT
# --- STATE ---
step=0
scaleval=0.5
shoot=0
demon=0
gameover=0
lst="0,1,2"
score=0
# --- SCALE PER STEP ---
update_scale() {
case $step in
0) scaleval=0.5 ;;
1) scaleval=0.9 ;;
2) scaleval=1.4 ;;
esac
}
# --- DEMON SPAWN ---
spawn_demon() {
# 30% chance
if (( RANDOM % 100 < 70 )); then
demon=1
echo "DEMON SPAWN"
else
demon=0
fi
}
# --- RESET ---
reset_game() {
step=0
shoot=0
demon=0
gameover=0
turndir=0
lst="0,1,2"
score=0
update_scale
}
# --- WRITE STATE ---
write_state() {
cat > state.tex <<EOF
\def\step{$step}
\def\lst{$lst}
\def\scaleval{$scaleval}
\def\shoot{$shoot}
\def\demon{$demon}
\def\gameover{$gameover}
\def\score{$score}
\def\turndir{$turndir}
EOF
}
# --- RENDER ---
render() {
pdflatex -interaction=nonstopmode main.tex > /dev/null < /dev/null
}
# --- INIT ---
reset_game
update_scale
write_state
render
while true; do
update=0
key=""
read -u 3 -rsn1 -t 0.1 key
# reset shoot each frame
shoot=0
turndir=0
case "$key" in
k) # forward
if [ "$gameover" -eq 0 ]; then
if [ "$step" -lt 2 ]; then
step=$((step + 1))
echo "FORWARD -> step=$step"
if [ "$step" -eq 2 ]; then
spawn_demon
fi
fi
fi
update=1
;;
j) # backward
if [ "$gameover" -eq 0 ]; then
if [ "$step" -gt 0 ]; then
# leaving step 2 -> check demon
if [ "$step" -eq 2 ] && [ "$demon" -eq 1 ]; then
echo "DEMON GOT YOU"
gameover=1
fi
step=$((step - 1))
echo "BACK -> step=$step"
fi
fi
update=1
;;
l) # right turn
if [ "$step" -eq 2 ] && [ "$gameover" -eq 0 ]; then
if [ "$demon" -eq 1 ]; then
echo "TURNED WITH DEMON -> DEAD"
gameover=1
else
echo "TURN RIGHT"
turndir=2
write_state
render
turndir=0
sleep 0.3
step=0
fi
fi
update=1
;;
h) # left turn
if [ "$step" -eq 2 ] && [ "$gameover" -eq 0 ]; then
if [ "$demon" -eq 1 ]; then
echo "TURNED WITH DEMON -> DEAD"
gameover=1
else
echo "TURN LEFT"
turndir=1
write_state
render
turndir=0
sleep 0.5
step=0
fi
fi
update=1
;;
s) # shoot
if [ "$step" -eq 2 ] && [ "$demon" -eq 1 ]; then
echo "DEMON KILLED"
demon=0
shoot=1
score=$((score+1))
fi
update=1
;;
r)
echo "RESET"
reset_game
update=1
;;
q)
echo "QUIT"
exit 0
;;
esac
if [[ "$step" -eq 0 ]]; then
lst="0,1,2"
fi
if [[ "$step" -eq 1 ]]; then
lst="0,1"
fi
if [[ "$step" -eq 2 ]]; then
lst="0"
fi
if [[ "$update" -eq 1 ]]; then
update_scale
write_state
render
sleep 0.1
fi
done
Now the LaTeX file.
\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{xcolor}
\usepackage{graphicx}
\pgfplotsset{compat=1.18}
\pagecolor{red!20!black}
\begin{document}
\input{state.tex}
\begin{center}
\begin{tikzpicture}[scale=\scaleval]
\pgfmathsetmacro{\W}{15}
\pgfmathsetmacro{\H}{8}
%\fill[red!20!black] (-0.0 * \W, -0.9 * \H) rectangle (\W + 0.0 * \W, \H + 0.9 * \H);
\pgfmathsetmacro{\N}{9 - 2*\step}
\pgfmathsetmacro{\cell}{\W / \N}
\pgfmathsetmacro{\mid}{(\N - 1) / 2}
\pgfmathsetmacro{\xA}{\mid * \cell}
\pgfmathsetmacro{\xB}{(\mid + 1) * \cell}
% make it square
\pgfmathsetmacro{\size}{\xB - \xA}
\pgfmathsetmacro{\yA}{(\H - \size)/2}
\pgfmathsetmacro{\yB}{\yA + \size}
\draw[thick, fill=red!15!black] (\xA,\yA) rectangle (\xB,\yB);
% drawing wall
\pgfmathsetmacro{\sizeRef}{\size}
\pgfmathsetmacro{\xALast}{\xA}
\pgfmathsetmacro{\xBLast}{\xB}
\pgfmathsetmacro{\yALast}{\yA}
\pgfmathsetmacro{\yBLast}{\yB}
\foreach \i in \lst {
\pgfmathsetmacro{\offset}{\size * (2^\i)}
\pgfmathsetmacro{\yext}{\offset / 2}
\ifcase\i
\def\wallcolor{black}
\else
\pgfmathsetmacro{\shade}{int(2 + 15*\i)}
\edef\wallcolor{red!\shade!black}
\fi
% LEFT
\pgfmathsetmacro{\xAi}{\xALast - \offset}
\fill[fill=\wallcolor, draw=black]
(\xAi,\yALast-\yext)
-- (\xAi,\yBLast+\yext)
-- (\xALast,\yBLast)
-- (\xALast,\yALast)
-- cycle;
% RIGHT
\pgfmathsetmacro{\xBi}{\xBLast + \offset}
\fill[fill=\wallcolor, draw=black]
(\xBi,\yALast-\yext)
-- (\xBi,\yBLast+\yext)
-- (\xBLast,\yBLast)
-- (\xBLast,\yALast)
-- cycle;
% GROUND
\fill[fill=red!20!black, draw=black]
(\xALast,\yALast)
-- (\xBLast,\yALast)
-- (\xBi,\yALast - \yext)
-- (\xAi,\yALast - \yext)
-- cycle;
% CEILING
\fill[fill=red!20!black, draw=black]
(\xALast,\yBLast)
-- (\xBLast,\yBLast)
-- (\xBi,\yBLast + \yext)
-- (\xAi,\yBLast + \yext)
-- cycle;
\pgfmathparse{\xALast - \offset}
\xdef\xALast{\pgfmathresult}
\pgfmathparse{\xBLast + \offset}
\xdef\xBLast{\pgfmathresult}
\pgfmathparse{\yALast - \yext}
\xdef\yALast{\pgfmathresult}
\pgfmathparse{\yBLast + \yext}
\xdef\yBLast{\pgfmathresult}
}
\pgfmathsetmacro{\weaponY}{\yALast / \scaleval}
\pgfmathsetmacro{\demonY}{\weaponY + 0.1 * \H}
\ifnum\demon=1
\node at ({\W/2}, {\demonY}) {
\includegraphics[width=6 cm]{demon.png}
};
\fi
\ifnum\shoot=0
\node at ({\W/2}, {\weaponY}) {
\includegraphics[width=6 cm]{weapon.png}
};
\else
\node at ({\W/2}, {\weaponY}) {
\includegraphics[width=6 cm]{weapon_shoot.png}
};
\fi
\ifnum\gameover=1
\node[white, scale=3] at ({\W/2}, {\H/2}) {GAME OVER};
\node[red!70!black, scale=3] at ({\W/2}, {\H/2 + 1}) {SCORE: \score};
\fi
\ifnum\turndir=1
\fill[white]
({\W/2 - 2}, {\H/2})
-- ({\W/2}, {\H/2 + 1})
-- ({\W/2}, {\H/2 - 1})
-- cycle;
\fi
\ifnum\turndir=2
\fill[white]
({\W/2 + 2}, {\H/2})
-- ({\W/2}, {\H/2 + 1})
-- ({\W/2}, {\H/2 - 1})
-- cycle;
\fi
\end{tikzpicture}
\end{center}
\end{document}
There is really no new thing when it comes to the synthax apart from:
\pagecolor{red!20!black}
Allowing to change the ENTIRE background color of the document --> redish here.
All is based on vanishing line to create depth illusion.
So the basic idea is to draw a centered square, and 4 vanishing lines that starts at each square corner and that ... vanishes to the exterior.
-
top-left corner -> vanishing line that goes to top-left
-
top-right corner -> vanishing line that goes to top-right
-
bottom-left corner -> vanishing line that goes to bottom-left
-
bottom-right corner -> vanishing line that goes to bottom-right
First, we declare a Width (W) and a Height (H) variables, assign them respectively max Width and respectable Height value.
\pgfmathsetmacro{\W}{15}
\pgfmathsetmacro{\H}{8}
After that we calculates N.
\pgfmathsetmacro{\N}{9 - 2*\step}
What is N ?
Its value whole purpose is to compute the coordinates of the centered square.
I explain.
If you are in front of a wall, it will apear bigger (width and height proportionally) than when you are farer from it.
Because we will use N as:
\pgfmathsetmacro{\cell}{\W / \N}
Which gives us width of units (called \cell) we can work with.
The more there are units, the less wide they become (\W is a constant = 15).
Also, note that the more steps we have done, the closer we get to the wall / square.
Then, the lower is N the less width units are and they are wider.
I spoke about units, so now, the trick is to compute the middle that tells, how many units i need to get to the middle unit.
\pgfmathsetmacro{\mid}{(\N - 1) / 2}
Here is the thing, i do not mean middle, i said the unit that is in the middle, like the median of you will.
This is key, because the start coordinate of the middle unit when i'm close to the wall (so step is high), is the coordinate of one of the firsts units when i'm far from the wall (step made lower).
After realizing that, it's simple, i just compute the x coordinate of the startig unit and ending x of the width --> x start and end of the square.
\pgfmathsetmacro{\xA}{\mid * \cell}
\pgfmathsetmacro{\xB}{(\mid + 1) * \cell}
You see, x end of the square is just the x start of the next width unit.
(\mid + 1) * \cell
So, the size of the edges of the square is just the difference.
\pgfmathsetmacro{\size}{\xB - \xA}
Now we compute y start and y end.
\pgfmathsetmacro{\yA}{(\H - \size)/2}
\pgfmathsetmacro{\yB}{\yA + \size}
So (\xA,\yA) is actually bottom-left of the square.
After that, we draw the square.
\draw[thick, fill=red!15!black] (\xA,\yA) rectangle (\xB,\yB);
Wall - Vanishing lines
Now most interesting part.
Look at the state.tex file:
\def\step{1}
\def\lst{0,1}
\def\scaleval{0.9}
\def\shoot{0}
\def\demon{1}
\def\gameover{1}
\def\score{2}
\def\turndir{0}
What is important is the evolution of \step, \lst and \scaleval
For \step == 0.
\scaleval= 0.5\lst= 0,1,2 --> 3 walls
For \step == 1.
\scaleval= 0.9\lst= 0,1 --> 2 walls
For \step == 2.
\scaleval= 1.4\lst= 0,1,2 --> 1 wall
\lst is just a list of numbers, what is important is its length, so it defines the iteration number in the next loop.
\scaleval is also important, because wo so not want the user to zoom in the pdf viewer (like zathura) we scale appropriately the scenes.
The \scaleval are "trust me bros" variables, but works.
The only "trust me bro" part in this article :)
Now the drawing walls part.
\pgfmathsetmacro{\xALast}{\xA}
\pgfmathsetmacro{\xBLast}{\xB}
\pgfmathsetmacro{\yALast}{\yA}
\pgfmathsetmacro{\yBLast}{\yB}
\foreach \i in \lst {
\pgfmathsetmacro{\offset}{\size * (2^\i)}
\pgfmathsetmacro{\yext}{\offset / 2}
\ifcase\i
\def\wallcolor{black}
\else
\pgfmathsetmacro{\shade}{int(2 + 15*\i)}
\edef\wallcolor{red!\shade!black}
\fi
% LEFT
\pgfmathsetmacro{\xAi}{\xALast - \offset}
\fill[fill=\wallcolor, draw=black]
(\xAi,\yALast-\yext)
-- (\xAi,\yBLast+\yext)
-- (\xALast,\yBLast)
-- (\xALast,\yALast)
-- cycle;
% RIGHT
\pgfmathsetmacro{\xBi}{\xBLast + \offset}
\fill[fill=\wallcolor, draw=black]
(\xBi,\yALast-\yext)
-- (\xBi,\yBLast+\yext)
-- (\xBLast,\yBLast)
-- (\xBLast,\yALast)
-- cycle;
% GROUND
\fill[fill=red!20!black, draw=black]
(\xALast,\yALast)
-- (\xBLast,\yALast)
-- (\xBi,\yALast - \yext)
-- (\xAi,\yALast - \yext)
-- cycle;
% CEILING
\fill[fill=red!20!black, draw=black]
(\xALast,\yBLast)
-- (\xBLast,\yBLast)
-- (\xBi,\yBLast + \yext)
-- (\xAi,\yBLast + \yext)
-- cycle;
\pgfmathparse{\xALast - \offset}
\xdef\xALast{\pgfmathresult}
\pgfmathparse{\xBLast + \offset}
\xdef\xBLast{\pgfmathresult}
\pgfmathparse{\yALast - \yext}
\xdef\yALast{\pgfmathresult}
\pgfmathparse{\yBLast + \yext}
\xdef\yBLast{\pgfmathresult}
}
In fact, it computes x offset and y offset that is the half of the first.
x offset evolves as 2^step, and that is just the offset from the last wall ! --> Strong vanishing lines
\pgfmathsetmacro{\offset}{\size * (2^\i)}
\pgfmathsetmacro{\yext}{\offset / 2}
"Why are they computed ?"
To compuet wall coordinates and drawing them.
% LEFT
\pgfmathsetmacro{\xAi}{\xALast - \offset}
\fill[fill=\wallcolor, draw=black]
(\xAi,\yALast-\yext)
-- (\xAi,\yBLast+\yext)
-- (\xALast,\yBLast)
-- (\xALast,\yALast)
-- cycle;
After that, the variables are of course updated thanks to \pgfmathparse that alows to compute formulas, and \xdef for the definition.
\pgfmathparse{\xALast - \offset}
\xdef\xALast{\pgfmathresult}
\pgfmathparse{\xBLast + \offset}
\xdef\xBLast{\pgfmathresult}
\pgfmathparse{\yALast - \yext}
\xdef\yALast{\pgfmathresult}
\pgfmathparse{\yBLast + \yext}
\xdef\yBLast{\pgfmathresult}
We also compute a color gradient of the right and left walls by their depth - step made.
\ifcase\i
\def\wallcolor{black}
\else
\pgfmathsetmacro{\shade}{int(2 + 15*\i)}
\edef\wallcolor{red!\shade!black}
\fi
At this point, i discovered that if i do the same for the top and bottom, it really gets awfull visually, so i keep the same color for whole bottom and top and just apply gradient for walls.
For other stuffs.
We got some basics boolean logic.
Add the deamon png.
\ifnum\demon=1
\node at ({\W/2}, {\demonY}) {
\includegraphics[width=6 cm]{demon.png}
};
\fi
When firering the weapon, we replace the png for certain amounts of frames by the a variant png.
\ifnum\shoot=0
\node at ({\W/2}, {\weaponY}) {
\includegraphics[width=6 cm]{weapon.png}
};
\else
\node at ({\W/2}, {\weaponY}) {
\includegraphics[width=6 cm]{weapon_shoot.png}
};
\fi
Same for making appear a left or right arrow when choosing a direction.
\ifnum\turndir=1
\fill[white]
({\W/2 - 2}, {\H/2})
-- ({\W/2}, {\H/2 + 1})
-- ({\W/2}, {\H/2 - 1})
-- cycle;
\fi
\ifnum\turndir=2
\fill[white]
({\W/2 + 2}, {\H/2})
-- ({\W/2}, {\H/2 + 1})
-- ({\W/2}, {\H/2 - 1})
-- cycle;
\fi
And gameover screen, with score.
\ifnum\gameover=1
\node[white, scale=3] at ({\W/2}, {\H/2}) {GAME OVER};
\node[red!70!black, scale=3] at ({\W/2}, {\H/2 + 1}) {SCORE: \score};
\fi
Hope you found this article usefull !
!!! Ciao Ciao !!!