\section{Calcul matriciel}

Si $f$ est une application affine du plan complexe, on appellera matrice de $f$ la liste (table) :
\codeln{\{f(0),Lf(1),Lf(i)\}}
où $Lf$ désigne la partie linéaire de $f$ (on a $Lf(1) = f(1)-f(0)$ et $Lf(i)=f(i)-f(0)$). La matrice identité est la variable globale notée \varglob{ID} dans le paquet \luadrawenv, elle correspond simplement à la liste $\{0,1,i\}$.

\subsection{Calculs sur les matrices}

\subsubsection{applymatrix et applyLmatrix}
\begin{itemize}
    \item La fonction \cmd{ld.applymatrix(z, M)} applique la matrice \argu{M} au complexe \argu{z} et renvoie le résultat (ce qui revient à calculer $f(z)$ si \argu{M} est la matrice de $f$). Lorsque \argu{z} est le complexe \val{cpx.Jump} alors le résultat est \val{cpx.Jump}. Lorsque \argu{z} est une chaîne de caractères alors la fonction renvoie \argu{z}.
    
    \item La fonction \textbf{ld.applyLmatrix(z, M)} applique la partie linéaire la matrice \argu{M} au complexe \argu{z} et renvoie le résultat (ce qui revient à calculer $Lf(z)$ si \argu{M} est la matrice de $f$). Lorsque \argu{z} est le complexe \val{cpx.Jump} alors le résultat est \val{cpx.Jump}.
\end{itemize}

\subsubsection{composematrix}
La fonction \cmd{ld.composematrix(M1, M2)} effectue le produit matriciel \argu{M1}$\times$\argu{M2} et renvoie le résultat.

\subsubsection{invmatrix}
La fonction \cmd{ld.invmatrix(M)} calcule et renvoie l'inverse de la matrice \argu{M} lorsque cela est possible.

\subsubsection{matrixof}
\begin{itemize}
    \item La fonction \cmd{ld.matrixof(f)} calcule et renvoie la matrice de \argu{f} (qui doit être une application affine du plan complexe).
    \item Exemple : \code{ld.matrixof(function(z) return ld.proj(z,{0,Z(1,-1)}) end)} renvoie \par
     \val{\{0,Z(0.5,-0.5),Z(-0.5,0.5)\}} (matrice de la projection orthogonale sur la deuxième bissectrice).
\end{itemize}

\subsubsection{mtransform et mLtransform}
\begin{itemize}
    \item La fonction \cmd{ld.mtransform(L, M)} applique la matrice \argu{M} à la liste \argu{L} et renvoie le résultat. \argu{L} doit être une liste de complexes ou une liste de listes de complexes, si l'un d'eux est le complexe \val{cpx.Jump} ou une chaîne de caractères alors il est renvoyé tel quel.
    
    \item La fonction \cmd{ld.mLtransform(L, M)} applique la partie linéaire la matrice \argu{M} à la liste \argu{L} et renvoie le résultat. \argu{L} doit être une liste de complexes ou une liste de listes de complexes, si l'un d'eux est le complexe \val{cpx.Jump} alors il est renvoyé tel quel.
\end{itemize}

\subsection{Matrice associée au graphe}

Lorsque l'on crée un graphe dans l'environnement \luadrawenv, par exemple :
\begin{Luacode}
local ld = luadraw
local g = ld.graph:new{window={-5,5,-5,5},size={10,10}}
\end{Luacode}
l'objet \emph{g} créé possède une matrice de transformation qui est initialement l'identité. Toutes les méthodes graphiques utilisées appliquent automatiquement la matrice de transformation du graphe. Cette matrice est désignée par \code{g.matrix}, mais pour manipuler celle-ci, on dispose des méthodes qui suivent.

\subsubsection{g:Composematrix()}
La méthode \textbf{g:Composematrix(M)} multiplie la matrice du graphe \emph{g} par la matrice \argu{M} (avec \argu{M} à droite) et le résultat est affecté à la matrice du graphe. L'argument \argu{M} doit donc être une matrice.

\subsubsection{g:Det2d()}
La méthode \cmd{g:Det2d()} envoie $1$ lorsque la matrice de transformation a un déterminant positif, et $-1$ dans le cas contraire. Cette information est utile lorsqu'on a besoin de savoir si l'orientation du plan a été changée ou non.

\subsubsection{g:IDmatrix()}
La méthode \cmd{g:IDmatrix()} réaffecte l'identité à la matrice du graphe \emph g.

\subsubsection{g:Mtransform()}
La méthode \cmd{g:Mtransform(L)} applique la matrice du graphe \emph g à \argu{L} et renvoie le résultat, l'argument \argu{L} doit être une liste de complexes, ou une liste de listes de complexes.

\subsubsection{g:MLtransform()}
La méthode \cmd{g:MLtransform(L)} applique la partie linéaire de la matrice du graphe \emph g à \argu{L} et renvoie le résultat, l'argument \argu{L} doit être une liste de complexes, ou une liste de listes de complexes.

\begin{demo}{Utilisation de la matrice du graphe}
\begin{luadraw}{name=Pythagore}
local ld = luadraw
local g = ld.graph:new{window={-15,15,0,22},size={10,10}}
local a, b, c = 3, 4, 5 -- un triplet de Pythagore
local i, arccos, exp = ld.cpx.I, math.acos, ld.cpx.exp
local f1 = function(z)
    return (z-c)*a/c*exp(-i*arccos(a/c))+c+i*c end
local M1 = ld.matrixof(f1)
local f2 = function(z)
    return z*b/c*exp(i*arccos(b/c))+i*c end
local M2 = ld.matrixof(f2)
local arbre
arbre = function(n)
    local color = ld.mixcolor(ld.ForestGreen,1,ld.Brown,n)
    g:Linecolor(color); g:Dsquare(0,c,1,"fill="..color)
    if n > 0 then
        g:Savematrix(); g:Composematrix(M1); arbre(n-1)
        g:Restorematrix(); g:Savematrix(); g:Composematrix(M2)
        arbre(n-1); g:Restorematrix()
    end
end
arbre(8)
g:Show()
\end{luadraw}
\end{demo}


\subsubsection{g:Rotate()}
La méthode \cmd{g:Rotate(angle \fac{, center})} modifie la matrice de transformation du graphe \emph g en la composant avec la matrice de la rotation d'angle \argu{angle} (en degrés) et de centre \argu{center}. L'argument \argu{center} est un complexe qui vaut $0$ par défaut.

\subsubsection{g:Scale()}
La méthode \cmd{g:Scale(factor \fac{, center})} modifie la matrice de transformation du graphe \emph g en la composant avec la matrice de l'homothétie de rapport \argu{factor} et de centre \argu{center}. L'argument \argu{center} est un complexe qui vaut $0$ par défaut.

\subsubsection{g:Savematrix() et g:Restorematrix()}
\begin{itemize}
    \item La méthode \cmd{g:Savematrix()} permet de sauvegarder dans une pile la matrice de transformation du graphe \emph g.
    \item La méthode \cmd{g:Restorematrix()} permet de restaurer la matrice de transformation du graphe \emph g à sa dernière valeur sauvegardée.
\end{itemize}

\subsubsection{g:Setmatrix()}
La méthode \cmd{g:Setmatrix(M)} permet d'affecter la matrice \argu{M} à la matrice de transformation du graphe \emph g.

\subsubsection{g:Shift()}
La méthode \cmd{g:Shift(v)} modifie la matrice de transformation du graphe \emph g en la composant avec la matrice de la translation de vecteur \argu{v} qui doit être un complexe.

\begin{demo}{Utilisation de Shift, Rotate et Scale}
\begin{luadraw}{name=free_art}
local ld = luadraw
local du = math.sqrt(2)/2
local g = ld.graph:new{window={1-du,4+du,1-du,4+du},
    margin={0,0,0,0},size={7,7}}
local i = ld.cpx.I
g:Linestyle("noline")
g:Filloptions("full","Navy",0.1)
for X = 1, 4 do
    for Y = 1, 4 do
        g:Savematrix()
        g:Shift(X+i*Y); g:Rotate(45)
        for k = 1, 25 do
            g:Dsquare((1-i)/2,(1+i)/2,1)
            g:Rotate(7); g:Scale(0.9)
        end
        g:Restorematrix()
    end
end
g:Show()
\end{luadraw}
\end{demo}

\subsection{Changement de vue. Changement de repère}

\paragraph{Changement de vue : } lors de la création d'un nouveau graphique, par exemple :
\begin{Luacode}
local ld = luadraw
local g = ld.graph:new{window={-5,5,-5,5},size={10,10}}
\end{Luacode}
L'option \opt{window=\{xmin,xmax,ymin,ymax\}} fixe la vue pour le graphique \emph{g}, ce sera le pavé $[x_{\mathrm{min}}; x_{\mathrm{max}}]\times [y_{\mathrm{min}}; y_{\mathrm{max}}]$ de $\mathbf R^2$, et tous les tracés vont être clippés par cette fenêtre (sauf les labels qui peuvent débordés dans les marges, mais pas au-delà).
Il est possible, à l'intérieur de ce pavé, de définir un autre pavé pour faire une nouvelle vue, avec la méthode \cmd{g:Viewport(x1, x2, y1, y2)}. Les valeurs de \argu{x1}, \argu{x2}, \argu{y1}, \argu{y2} se réfèrent la fenêtre initiale définie par l'option \opt{window}. À partir de là, tout ce qui sort de cette nouvelle zone va être clippé, et la matrice du graphe est réinitialisée à l'identité, par conséquent il faut sauvegarder auparavant les paramètres graphiques courants :
\begin{Luacode}
g:Saveattr()
g:Viewport(x1,x2,y1,y2)
\end{Luacode}
Pour revenir à la vue précédente avec la matrice précédente, il suffit d'effectuer une restauration des paramètres graphiques avec la méthode \cmd{g:Restoreattr()}.

\paragraph{Attention : } à chaque instruction \cmd{g:Saveattr()} doit correspondre une instruction \cmd{g:Restoreattr()}, sinon il y aura une erreur à la compilation.

\paragraph{Changement de repère : } on peut changer le système de coordonnées de la vue courante avec la méthode \cmdln{g:Coordsystem(x1, x2, y1, y2 \fac{, ortho}).}
Cette méthode va modifier la matrice du graphe de sorte que tout se passe comme si la vue courante correspondait au pavé $[x_1;x_2]\times[y_1;y_2]$, l'argument booléen facultatif \argu{ortho} indique si le nouveau repère doit être orthonormé ou non (\false par défaut). Comme la matrice du graphe est modifiée il est préférable de sauvegarder les paramètres graphiques avant, et de les restaurer ensuite. Cela peut servir par exemple à faire plusieurs figures dans le graphique en cours.

\begin{demo}{Classification des points d'une courbe paramétrée}
\begin{luadraw}{name=viewport_changewin}
local ld = luadraw
local g = ld.graph:new{window={-5,5,-5,5},size={10,10}}
local i, Z = ld.cpx.I, ld.cpx.Z
g:Labelsize("tiny")
local styleA = "\\tikzset{->-/.style={decoration={markings, mark="
local styleB = "at position #1 with {\\arrow{>}}}, postaction={decorate}}}"
g:Writeln(styleA..styleB)
g:Dline({0,1},"dashed,gray"); g:Dline({0,i},"dashed,gray")
local legende = {"Point ordinaire", "Point d'inflexion", "Rebroussement première espèce",
"Rebroussement seconde espèce"}
local A, B, C =(1+i)*0.75, 0.75, 0
local A2, B2 ={-1.25+i*0.5,-0.75-i*0.5,1.25-0.5*i, 0.5+i}, {-0.75,-0.75,0.75,0.75}
local u = {Z(-5,0),Z(0,0),-5-5*i,-5*i}
for k = 1, 4 do
    g:Saveattr(); g:Viewport(u[k].re,u[k].re+5,u[k].im,u[k].im+5)
    g:Coordsystem(-1.4,2.25,-1,1.25)
    g:Composematrix({0,1,1+i}) -- pour pencher l'axe Oy
    g:Dpolyline({{-1,1},{-i*0.5,i}}) -- axes
    g:Lineoptions(nil,"blue",8)
    g:Dpath({A2[k],(B2[k]+2*A2[k])/3,(C+5*B2[k])/6, C,"b"},"->-=0.5")
    g:Dpath({C,(C+5*B)/6,(B+2*A)/3,A,"b"},"->-=0.75")
    g:Dpolyline({{0,0.75},{0,0.75*i}},false,"->,red")
    g:Dlabel(
    legende[k],0.75-0.5*i, {pos="S"},
        "$f^{(p)}(t_0)$",1,{pos="E",node_options="red"},
        "$f^{(q)}(t_0)$",0.75*i,{pos="W",dist=0.05})
    g:Restoreattr()
end
g:Show()
\end{luadraw}
\end{demo}
