\section{Constructions géométriques}

Dans cette section sont regroupées les fonctions construisant des figures géométriques sans méthode graphique dédiée.

\subsection{Cercle circonscrit, cercle inscrit : circumcircle3d(), incircle3d()}

\begin{itemize}
    \item La fonction \cmd{ld.circumcircle3d(A, B, C)}, où \argu{A}, \argu{B} et \argu{C} sont trois points 3D non alignés, renvoie le cercle circonscrit au triangle formé par ces trois points, sous la forme d'une séquence: $O,R,n$, où $O$ est le centre du cercle, $R$ son rayon, et $n$ un vecteur normal au plan du cercle.
    \item La fonction \cmd{ld.incircle3d(A, B, C)}, où \argu{A}, \argu{B} et \argu{C} sont trois points 3D non alignés, renvoie le cercle inscrit dans le triangle formé par ces trois points, sous la forme d'une séquence: $I,R,n$, où $I$ est le centre du cercle, $R$ son rayon, et $n$ un vecteur normal au plan du cercle.    
\end{itemize}

\subsection{Enveloppe convexe : cvx\_hull3d()}

La fonction \cmd{ld.cvx\_hull3d(L)} où \argu{L} est une liste de points 3D \textbf{distincts}, calcule et renvoie l'enveloppe convexe de \argu{L} sous la forme d'une liste de facettes.

\begin{demo}{Utilisation de cvx\_hull3d()}
\begin{luadraw}{name=cvx_hull3d}
local ld = luadraw
local pt3d = ld.pt3d
local Origin, vecI, vecJ, vecK, M = pt3d.Origin, pt3d.vecI, pt3d.vecJ, pt3d.vecK, pt3d.M

local g = ld.graph3d:new{window={-2,4,-6,1},bbox=false,size={10,10}}
local L = {Origin, 4*vecI, M(4,4,0), 4*vecJ}
ld.insert(L, ld.shift3d(L,-3*vecK))
ld.insert(L, {M(2,1,2), M(2,3,2)})
local V = ld.cvx_hull3d(L)
local P = ld.facet2poly(V)
g:Dpoly(P , {color="cyan",mode=ld.mShadedHidden})
g:Show()
\end{luadraw}
\end{demo}

\paragraph{Cas particulier}: lorsque tous les points de \argu{L} sont dans un même plan, on peut utiliser la fonction \cmd{ld.cvx\_hull3dcoplanar(L, n)} où \argu{n} est un vecteur orthogonal au plan. Cette fonction renvoie une facette (liste de points 3D).

\subsection{Plans : plane(), planeEq(), orthoframe(), plane2ABC()}

Un plan de l'espace est une table de la forme $\{A,n\}$ où $A$ est un point du plan (point 3D) et $n$ un vecteur normal au plan (point 3D non nul).
\begin{itemize}
    \item La fonction \cmd{ld.plane(A, B, C)} envoie le plan passant par les trois points 3D \argu{A}, \argu{B} et \argu{C} (s'ils sont non alignés, sinon le résultat est \nil).
    
    \item La fonction \cmd{ld.planeEq(a, b, c, d \fac{, inequality})} renvoie le plan dont une équation cartésienne est $ax+by+cz+d=0$ (si les coefficients \argu{a}, \argu{a} et \argu{a} ne sont pas tous nuls, sinon le résultat est \nil). L'argument optionnel \argu{inequality} (\nil par défaut) peut aussi prendre comme valeur \val{'<'} ou \val{'>'}, le vecteur normal au plan est alors choisi de telle sorte qu'il soit dans le demi-espace vérifiant l'inégalité $ax+by+c<0$ (ou $ax+by+c>0$ dans l'autre cas).
    
    \item La fonction \cmd{ld.plane2ABC(P)} où \argu{P}$=\{A,n\}$ désigne un plan, renvoie une séquence de trois points 3D $A,B,C$, appartenant au plan, et tels que $(A,\vec{AB},\vec{AC})$ soit un repère orthonormal direct de ce plan.
    
    \item La fonction \cmd{ld.orthoframe(P \fac{, u})} où \argu{P}$=\{A,n\}$ désigne un plan, renvoie une séquence de trois points 3D $A,u,v$, tels que $(A,u,v)$ soit un repère orthonormal direct de ce plan. L'argument optionnel \argu{u}, s'il est présent, doit être un vecteur non nul du plan, ce sera le premier vecteur de base une fois normalisé.
\end{itemize}

\begin{demo}{Faces d'un cube trouées avec un hexagone régulier}
\begin{luadraw}{name=plans}
local ld = luadraw
local pt3d = ld.pt3d
local Origin, vecI, vecJ, vecK, M = pt3d.Origin, pt3d.vecI, pt3d.vecJ, pt3d.vecK, pt3d.M

local g = ld.graph3d:new{window={-3,3,-3.25,3.25}, margin={0,0,0,0},
    viewdir={"central",20,60}, bg="LightGray", size={10,10}}
ld.Hiddenlines = true; ld.Hiddenlinestyle = "dashed"
local p = ld.polyreg(0,1,6)
local P = ld.parallelep(M(-2,-2,-2),4*vecI,4*vecJ,4*vecK)
local V = g:Sortpolyfacet(P)
local list = {}
g:Filloptions("full","Crimson",1,true); -- true pour le mode evenodd
g:Lineoptions("solid","Gold",8)
for _, F in ipairs(V) do
    local P1 = ld.plane(pt3d.isobar3d(F),F[1],F[2]) -- plan de la facette F
    local A, u, v = ld.orthoframe(P1) -- repère orthonormé sur la facette avec centre de gravité comme origine
    local p1 = ld.map(function(z) return A+z.re*u+z.im*v end,p) -- hexagone reproduit sur la facette
    table.insert(p1,2,"m")
    local color = "Crimson"
    if not g:Isvisible(F) then color = "Crimson!60!black" end
    g:Dpath3d( ld.concat(F,{"l"},p1,{"l","cl"}),"fill="..color ) -- dessin de la facette "trouée" avec l'hexagone
end
g:Show()
\end{luadraw}
\end{demo}

\subsection{Sphère circonscrite, Sphère inscrite : circumsphere(), insphere()}

\begin{itemize}
    \item La fonction \cmd{ld.circumsphere(A, B, C, D)}, où \argu{A}, \argu{B}, \argu{C} et \argu{D} sont quatre points 3D non coplanaires, renvoie la sphère circonscrite au tétraèdre formé par ces quatre points, sous la forme d'une séquence: $I,R$, où $I$ est le centre de la sphère, et $R$ son rayon.
    
    \item La fonction \cmd{ld.insphere(A, B, C, D)}, où \argu{A}, \argu{B}, \argu{C} et \argu{D} sont quatre points 3D non coplanaires, renvoie la sphère inscrite dans le tétraèdre formé par ces quatre points, sous la forme d'une séquence: $I,R$, où $I$ est le centre de la sphère, et $R$ son rayon.
\end{itemize}

\subsection{Tétraèdre à longueurs fixées : tetra\_len()}

La fonction \cmd{ld.tetra\_len(ab, ac, ad, bc, bd, cd)} calcule les sommets $A,B,C,D$ d'un tétraèdre dont les longueurs des arêtes sont données, c'est à dire tels que $AB=$\argu{ab}, $AC=$\argu{ac}, $AD=$\argu{ad}, $BC=$\argu{bc}, $BD=$\argu{bd} et $CD=$\argu{cd}. La fonction renvoie la séquence de quatre points $A,B,C,D$. Le sommet $A$ est toujours le point $M(0,0,0)$ (\varglob{pt3d.Origin}) et le sommet $B$ est toujours le point \code{ab*pt3d.vecI} et le sommet $C$ dans le plan $xy$. Le tétraèdre en tant que polyèdre peut ensuite être construit avec la fonction \cmd{ld.tetra(A, B-A, C-A, D-A)}.

\begin{demo}{Un tétraèdre avec la longueur des arêtes fixée}
\begin{luadraw}{name=tetra_len}
local ld = luadraw
local g = ld.graph3d:new{window={-4,4,-4,4},margin={0,0,0,0},viewdir={25,65},size={10,10}}
ld.Hiddenlines = true; ld.Hiddenlinestyle = "dashed"
require 'luadraw_spherical'
local R = 4
local A,B,C,D = ld.tetra_len(R,R,R,R,R,R)
local T = ld.tetra(A,B-A,C-A,D-A)
g:Define_sphere({radius=R})
g:DSpolyline( ld.facetedges(T), {color="DarkGreen"})
g:DSbigcircle( {B,C},{color="Blue"} )
g:DSbigcircle( {B,D},{color="Blue"} )
g:DSbigcircle( {C,D},{color="Blue"}  )
g:DSlabel("$R$",(2*A+C)/3,{pos="S"})
g:Dspherical()
g:Ddots3d({A,B,C,D})
g:Dlabel3d("$A$",A,{pos="S"},"$B$",B,{pos="SW"},"$C$",C,{},"$D$",D,{pos="N"} )
g:Show()
\end{luadraw}
\end{demo}

\subsection{Triangles : sss\_triangle3d(), sas\_triangle3d(), asa\_triangle3d()}

Ces fonctions sont la version 3D des fonctions  sss\_triangle(), sas\_triangle(), asa\_triangle() déjà décrites.
\begin{itemize}
    \item La fonction \cmd{ld.sss\_triangle3d(ab, bc, ca)} où \argu{ab}, \argu{bc} et \argu{ca} sont trois longueurs, calcule et renvoie une liste de trois points 3D $\{A,B,C\}$ formant les sommets d'un triangle direct dans le plan $xOy$ dont les longueurs des côtés sont les arguments, c'est à dire $AB=$\argu{ab}, $BC=$\argu{bc} et $CA=$\argu{ca}, lorsque cela est possible. Le sommet $A$ est toujours le point $M(0,0,0)$ (\varglob{pt3d.Origin}) et le sommet $B$ est toujours le point \code{ab*pt3d.vecI}. Ce triangle peut être dessiné avec la méthode \cmd{g:Dpolyline3d()}.
    
    \item La fonction \cmd{ld.sas\_triangle3d(ab, alpha, ca)} où \argu{ab} et \argu{ca} sont deux longueurs, \argu{alpha} un angle en degrés, calcule et renvoie une liste de trois points 3D $\{A,B,C\}$ formant les sommets d'un triangle dans le plan $xOy$ tel que $AB=$\argu{ab}, $CA=$\argu{ca}, et tel que l'angle $(\vec{AB},\vec{AC})$ a pour mesure \argu{alpha}, lorsque cela est possible. Le sommet $A$ est toujours le point $M(0,0,0)$ (\varglob{pt3d.Origin}) et le sommet $B$ est toujours le point \code{ab*pt3d.vecI}. Ce triangle peut être dessiné avec la méthode \cmd{g:Dpolyline3d()}.
    
    \item La fonction \cmd{ld.asa\_triangle3d(alpha, ab, beta)} où \argu{ab} est une longueur, \argu{alpha} et \argu{beta} deux angles en degrés, calcule et renvoie une liste de trois points 3D $\{A,B,C\}$ formant les sommets d'un triangle dans le plan $xOy$ tel que $AB=$\argu{ab}, tel que l'angle $(\vec{AB},\vec{AC})$ a pour mesure \argu{alpha}, et tel que l'angle $(\vec{BA},\vec{BC})$ a pour mesure \argu{beta}, lorsque cela est possible. Le sommet $A$ est toujours le point $M(0,0,0)$ (\varglob{pt3d.Origin}) et le sommet $B$ est toujours le point \code{ab*pt3d.vecI}. Ce triangle peut être dessiné avec la méthode \cmd{g:Dpolyline3d()}.
\end{itemize}
