Prérequis Python et Algèbre Linéaire pour la 3D
1. Installer Python : Votre Laboratoire de Travail
La première étape est de disposer d'un environnement Python propre et reproductible. En 2026, Miniconda reste la référence pour la data science et le calcul scientifique, car il gère nativement les dépendances compilées (C++, CUDA, Fortran).
# 1. Télécharger Miniconda (Linux/macOS/Windows)
# https://docs.conda.io/en/latest/miniconda.html
# 2. Créer un environnement dédié
conda create -n prereq-3d python=3.11 -y
conda activate prereq-3d
# 3. Installer les bibliothèques essentielles
pip install numpy matplotlib
Miniconda (léger, ~80 Mo) à Anaconda (lourd, ~4 Go). Vous installerez uniquement les paquets dont vous avez besoin, ce qui réduit les conflits de dépendances.
Vérifiez que tout fonctionne en lançant python --version dans votre terminal. Vous devez obtenir Python 3.11.x. Passons maintenant aux briques fondamentales du langage.
2. Les Fondamentaux Python en 30 Minutes
Inutile de lire un livre de 500 pages. Pour la 3D, vous avez besoin de maîtriser un sous-ensemble précis du langage. Voici l'essentiel, condensé.
2.1 Variables et Types
Python est un langage à typage dynamique. Les types fondamentaux pour la 3D sont int, float, str, bool et list.
# Variables numériques (coordonnées d'un point 3D)
x = 1.5
y = -3.2
z = 0.8
# Chaîne de caractères
label = "bâtiment"
# Booléen
est_classifie = True
# Vérifier le type
print(type(x)) # <class 'float'>
print(type(label)) # <class 'str'>
2.2 Listes et Dictionnaires
Les listes stockent des séquences ordonnées. Les dictionnaires associent des clés à des valeurs. En 3D, une liste de coordonnées et un dictionnaire de métadonnées sont omniprésents.
# Liste : un point 3D
point = [1.5, -3.2, 0.8]
print(point[0]) # 1.5 (indexation commence à 0)
# Liste de points (nuage simplifié)
nuage = [
[1.5, -3.2, 0.8],
[2.1, 0.4, 1.2],
[-0.3, 1.7, 0.1],
]
# Dictionnaire : métadonnées d'un scan
scan_info = {
"source": "LiDAR Terrestre",
"nb_points": 5_000_000,
"format": "LAZ",
"crs": "EPSG:2154",
}
print(scan_info["nb_points"]) # 5000000
2.3 Boucles et Conditions
Les boucles for parcourent des séquences. Les conditions if/elif/else contrôlent le flux. En 3D, on itère souvent sur des points pour les filtrer ou les transformer.
# Filtrer les points au-dessus de z = 0.5
points_hauts = []
for point in nuage:
if point[2] > 0.5:
points_hauts.append(point)
print(f"Points au-dessus de 0.5m : {len(points_hauts)}")
# Compréhension de liste (syntaxe compacte)
points_hauts = [p for p in nuage if p[2] > 0.5]
# Boucle avec index (enumerate)
for i, p in enumerate(nuage):
print(f"Point {i} : x={p[0]}, y={p[1]}, z={p[2]}")
2.4 Fonctions
Les fonctions encapsulent une logique réutilisable. Dans un pipeline 3D, chaque étape de traitement est typiquement une fonction.
def distance_3d(p1, p2):
"""Calcule la distance euclidienne entre deux points 3D."""
dx = p1[0] - p2[0]
dy = p1[1] - p2[1]
dz = p1[2] - p2[2]
return (dx**2 + dy**2 + dz**2) ** 0.5
a = [0, 0, 0]
b = [1, 1, 1]
print(f"Distance : {distance_3d(a, b):.4f} m")
# Distance : 1.7321 m
3. NumPy : Le Moteur de Calcul Vectoriel
NumPy est la bibliothèque fondamentale pour le calcul numérique en Python. En 3D, vous manipulez des millions de points : les boucles Python sont trop lentes. NumPy effectue les opérations en C compilé, offrant des gains de performance de x100 à x1000.
3.1 Créer et Manipuler des Arrays
import numpy as np
# Créer un array à partir d'une liste
point = np.array([1.5, -3.2, 0.8])
print(point.shape) # (3,) — vecteur 3D
# Nuage de 5 points (matrice 5x3)
nuage = np.array([
[1.5, -3.2, 0.8],
[2.1, 0.4, 1.2],
[-0.3, 1.7, 0.1],
[0.0, 0.0, 0.0],
[3.4, -1.1, 2.5],
])
print(nuage.shape) # (5, 3) — 5 points, 3 dimensions
# Accéder à toutes les coordonnées Z
z_coords = nuage[:, 2]
print(z_coords) # [0.8, 1.2, 0.1, 0.0, 2.5]
3.2 Opérations Vectorisées et Broadcasting
Le broadcasting est la capacité de NumPy à appliquer une opération entre des arrays de formes différentes. C'est ce qui rend le calcul 3D possible sans boucles.
# Translation : déplacer tout le nuage de (+10, +20, +5)
translation = np.array([10, 20, 5])
nuage_deplace = nuage + translation # Broadcasting automatique !
# Centrer le nuage sur son barycentre
centroid = np.mean(nuage, axis=0)
nuage_centre = nuage - centroid
# Calculer la distance de chaque point à l'origine
distances = np.linalg.norm(nuage, axis=1)
print(distances) # [3.61, 2.44, 1.73, 0.00, 4.38]
# Filtrage vectorisé : points à moins de 3m de l'origine
masque = distances < 3.0
points_proches = nuage[masque]
print(f"Points proches : {len(points_proches)}")
for sur un array NumPy, il y a probablement une opération vectorisée plus rapide. La règle d'or : pas de boucle Python sur des données 3D.
4. Lecture et Écriture de Fichiers
En 3D, les données transitent souvent sous forme de fichiers texte (CSV, TXT) ou structurés (JSON). Savoir les lire et les écrire est un prérequis non négociable.
import numpy as np
import json
# ---- CSV : charger un nuage de points ----
# Fichier points.csv contient : x,y,z
nuage = np.loadtxt("points.csv", delimiter=",", skiprows=1)
print(f"Chargé {nuage.shape[0]} points")
# Sauvegarder un nuage filtré
np.savetxt("points_filtres.csv", nuage, delimiter=",",
header="x,y,z", comments="")
# ---- JSON : métadonnées de projet ----
with open("projet.json", "r") as f:
config = json.load(f)
print(config["crs"]) # EPSG:2154
# Écrire un JSON
resultat = {"nb_points": 1234, "bbox": [0, 0, 100, 100]}
with open("resultat.json", "w") as f:
json.dump(resultat, f, indent=2)
5. Visualisation avec Matplotlib
Matplotlib permet de créer des graphiques 2D et 3D. Indispensable pour vérifier visuellement vos données avant de les injecter dans un pipeline de traitement.
import matplotlib.pyplot as plt
import numpy as np
# Générer un nuage de points aléatoire
np.random.seed(42)
nuage = np.random.randn(200, 3)
# Visualisation 3D
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(nuage[:, 0], nuage[:, 1], nuage[:, 2],
c=nuage[:, 2], cmap='viridis', s=5)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Nuage de Points 3D')
plt.show()
6. Mini Exercice Python : Charger et Afficher des Coordonnées 3D
Mettez en pratique tout ce que vous venez d'apprendre. L'objectif : créer un fichier CSV de coordonnées, le charger avec NumPy, calculer des statistiques, et afficher le résultat en 3D.
import numpy as np
import matplotlib.pyplot as plt
# 1. Créer un fichier CSV de test
np.random.seed(0)
points = np.random.uniform(-10, 10, size=(500, 3))
np.savetxt("nuage_test.csv", points, delimiter=",",
header="x,y,z", comments="")
# 2. Charger le fichier
data = np.loadtxt("nuage_test.csv", delimiter=",", skiprows=1)
print(f"Nombre de points : {data.shape[0]}")
# 3. Statistiques
print(f"Barycentre : {np.mean(data, axis=0)}")
print(f"Étendue Z : {data[:, 2].min():.2f} à {data[:, 2].max():.2f}")
# 4. Filtrer : garder seulement les points avec z > 0
data_filtre = data[data[:, 2] > 0]
print(f"Points avec z > 0 : {len(data_filtre)}")
# 5. Visualiser
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121, projection='3d')
ax1.scatter(data[:, 0], data[:, 1], data[:, 2],
c=data[:, 2], cmap='coolwarm', s=2)
ax1.set_title('Nuage complet')
ax2 = fig.add_subplot(122, projection='3d')
ax2.scatter(data_filtre[:, 0], data_filtre[:, 1], data_filtre[:, 2],
c=data_filtre[:, 2], cmap='coolwarm', s=2)
ax2.set_title('Filtré (z > 0)')
plt.tight_layout()
plt.show()
7. Vecteurs 2D et 3D : La Brique Élémentaire
Un vecteur est une quantité qui a une direction et une magnitude. En 3D, un vecteur est un triplet (x, y, z). Les opérations sur les vecteurs sont le fondement de toute géométrie computationnelle.
import numpy as np
# Définir deux vecteurs 3D
u = np.array([3, 1, 4])
v = np.array([1, 5, -2])
# Addition et soustraction
somme = u + v # [4, 6, 2]
diff = u - v # [2, -4, 6]
# Multiplication par un scalaire
double_u = 2 * u # [6, 2, 8]
# Norme (longueur) du vecteur
norme_u = np.linalg.norm(u)
print(f"||u|| = {norme_u:.4f}") # 5.0990
# Vecteur unitaire (normalisation)
u_hat = u / norme_u
print(f"Direction de u : {u_hat}")
print(f"Vérification : ||u_hat|| = {np.linalg.norm(u_hat):.1f}") # 1.0
| Opération | Notation | NumPy | Résultat |
|---|---|---|---|
| Addition | u + v | u + v |
Vecteur |
| Soustraction | u - v | u - v |
Vecteur |
| Scalaire | k * u | k * u |
Vecteur |
| Norme | ||u|| | np.linalg.norm(u) |
Scalaire |
8. Produit Scalaire (Dot Product)
Le produit scalaire de deux vecteurs donne un nombre (scalaire). Il mesure à quel point deux vecteurs pointent dans la même direction. Son application 3D principale : calculer l'angle entre deux vecteurs.
import numpy as np
u = np.array([1, 0, 0]) # Axe X
v = np.array([0, 1, 0]) # Axe Y
w = np.array([1, 1, 0]) # Diagonale XY
# Produit scalaire
print(np.dot(u, v)) # 0 — vecteurs perpendiculaires !
print(np.dot(u, w)) # 1
# Angle entre u et w
cos_angle = np.dot(u, w) / (np.linalg.norm(u) * np.linalg.norm(w))
angle_rad = np.arccos(cos_angle)
angle_deg = np.degrees(angle_rad)
print(f"Angle entre u et w : {angle_deg:.1f}°") # 45.0°
9. Produit Vectoriel (Cross Product) et Normale à un Plan
Le produit vectoriel de deux vecteurs donne un troisième vecteur perpendiculaire aux deux premiers. C'est l'outil fondamental pour calculer la normale d'une surface en 3D.
import numpy as np
# Trois points définissent un plan
A = np.array([0, 0, 0])
B = np.array([1, 0, 0])
C = np.array([0, 1, 0])
# Deux vecteurs dans le plan
AB = B - A # [1, 0, 0]
AC = C - A # [0, 1, 0]
# Normale au plan = produit vectoriel
normale = np.cross(AB, AC)
print(f"Normale : {normale}") # [0, 0, 1] — pointe vers le haut
# Normaliser pour obtenir un vecteur unitaire
normale_unit = normale / np.linalg.norm(normale)
print(f"Normale unitaire : {normale_unit}")
# Aire du triangle ABC
aire = 0.5 * np.linalg.norm(normale)
print(f"Aire du triangle : {aire} m²") # 0.5 m²
u x v = -(v x u). Cela détermine le sens de la normale (vers le haut ou vers le bas).
10. Matrices : Multiplication, Transposée et Inverse
Les matrices sont des tableaux 2D de nombres. En 3D, elles servent à représenter des transformations géométriques (rotation, mise à l'échelle) et à résoudre des systèmes d'équations.
import numpy as np
# Créer une matrice 3x3
M = np.array([
[2, 0, 0],
[0, 3, 0],
[0, 0, 1],
])
# Multiplication matrice x vecteur
v = np.array([1, 1, 1])
resultat = M @ v # Opérateur @ = multiplication matricielle
print(resultat) # [2, 3, 1] — mise à l'échelle !
# Transposée
print(M.T)
# Inverse (si elle existe)
M_inv = np.linalg.inv(M)
print(M_inv @ M) # Matrice identité (aux erreurs flottantes près)
# Déterminant
det = np.linalg.det(M)
print(f"Déterminant : {det}") # 6.0
| Opération | NumPy | Signification Géométrique |
|---|---|---|
| Multiplication | A @ B |
Composition de transformations |
| Transposée | A.T |
Miroir par rapport à la diagonale |
| Inverse | np.linalg.inv(A) |
Transformation inverse (annuler) |
| Déterminant | np.linalg.det(A) |
Facteur de changement de volume |
11. Transformations 3D : Rotation, Translation, Échelle
Toute manipulation géométrique en 3D se ramène à une combinaison de trois opérations fondamentales. Comprendre comment les appliquer avec des matrices est essentiel pour travailler avec des nuages de points.
11.1 Matrice de Rotation
Une rotation autour de l'axe Z d'un angle theta s'exprime par une matrice 3x3. Les rotations autour de X et Y suivent le même principe.
import numpy as np
def rotation_z(theta_deg):
"""Matrice de rotation autour de l'axe Z."""
theta = np.radians(theta_deg)
c, s = np.cos(theta), np.sin(theta)
return np.array([
[ c, -s, 0],
[ s, c, 0],
[ 0, 0, 1],
])
def rotation_x(theta_deg):
"""Matrice de rotation autour de l'axe X."""
theta = np.radians(theta_deg)
c, s = np.cos(theta), np.sin(theta)
return np.array([
[1, 0, 0],
[0, c, -s],
[0, s, c],
])
def rotation_y(theta_deg):
"""Matrice de rotation autour de l'axe Y."""
theta = np.radians(theta_deg)
c, s = np.cos(theta), np.sin(theta)
return np.array([
[ c, 0, s],
[ 0, 1, 0],
[-s, 0, c],
])
# Rotation de 45° autour de Z
R = rotation_z(45)
point = np.array([1, 0, 0])
point_tourne = R @ point
print(f"Avant : {point}")
print(f"Après : {point_tourne}") # [0.707, 0.707, 0]
11.2 Translation et Changement d'Échelle
# Translation : simple addition vectorielle
nuage = np.random.randn(100, 3)
translation = np.array([10, 20, 5])
nuage_deplace = nuage + translation
# Changement d'échelle : multiplication par une matrice diagonale
S = np.diag([2.0, 2.0, 0.5]) # Double en X/Y, moitié en Z
nuage_scale = (S @ nuage.T).T
# Combinaison : d'abord rotation, puis translation
R = rotation_z(30)
nuage_transforme = (R @ nuage.T).T + translation
12. Systèmes de Coordonnées et Projections
En géospatial, les données proviennent de capteurs utilisant différents systèmes de coordonnées. Il est crucial de savoir passer d'un repère à un autre.
| Système | Type | Usage Typique | Unité |
|---|---|---|---|
| WGS84 (EPSG:4326) | Géographique | GPS, données mondiales | Degrés |
| Lambert 93 (EPSG:2154) | Projeté | France métropolitaine | Mètres |
| UTM | Projeté | Universel par zones | Mètres |
| Local / Scanner | Cartésien | LiDAR terrestre, BIM | Mètres |
Le passage d'un repère local à un repère géoréférencé se fait par une transformation rigide (rotation + translation), souvent via une matrice 4x4 obtenue par recalage de cibles connues.
import numpy as np
# Projection orthogonale d'un vecteur u sur un vecteur v
def projection(u, v):
"""Projette u sur v."""
return (np.dot(u, v) / np.dot(v, v)) * v
u = np.array([3, 4, 0])
v = np.array([1, 0, 0]) # Axe X
proj = projection(u, v)
print(f"Projection de u sur X : {proj}") # [3, 0, 0]
# Composante perpendiculaire
perp = u - proj
print(f"Composante perpendiculaire : {perp}") # [0, 4, 0]
13. Mini Exercice : Rotation 3D d'un Nuage de Points
Exercice de synthèse : générez un nuage de points en forme de "L", appliquez une rotation de 90 degrés autour de l'axe Z, puis visualisez le résultat avant/après.
import numpy as np
import matplotlib.pyplot as plt
# 1. Créer un nuage en forme de L
branche_h = np.random.uniform([0, 0, 0], [5, 1, 1], size=(200, 3))
branche_v = np.random.uniform([0, 0, 0], [1, 4, 1], size=(200, 3))
nuage = np.vstack([branche_h, branche_v])
# 2. Matrice de rotation (90° autour de Z)
theta = np.radians(90)
R = np.array([
[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[0, 0, 1],
])
# 3. Appliquer la rotation à chaque point
# nuage.T = (3, 400), R @ nuage.T = (3, 400), .T = (400, 3)
nuage_tourne = (R @ nuage.T).T
# 4. Visualiser avant / après
fig = plt.figure(figsize=(14, 6))
ax1 = fig.add_subplot(121, projection='3d')
ax1.scatter(nuage[:, 0], nuage[:, 1], nuage[:, 2],
c='#8b5cf6', s=3)
ax1.set_title('Original')
ax1.set_xlabel('X'); ax1.set_ylabel('Y'); ax1.set_zlabel('Z')
ax2 = fig.add_subplot(122, projection='3d')
ax2.scatter(nuage_tourne[:, 0], nuage_tourne[:, 1], nuage_tourne[:, 2],
c='#d946ef', s=3)
ax2.set_title('Après rotation 90° (Z)')
ax2.set_xlabel('X'); ax2.set_ylabel('Y'); ax2.set_zlabel('Z')
plt.tight_layout()
plt.show()
# Vérification : le barycentre a-t-il bien tourné ?
c_avant = np.mean(nuage, axis=0)
c_apres = np.mean(nuage_tourne, axis=0)
print(f"Barycentre avant : {c_avant}")
print(f"Barycentre après : {c_apres}")
print(f"Distance conservée : {np.linalg.norm(c_avant):.4f} vs {np.linalg.norm(c_apres):.4f}")
14. QCM de Positionnement
Ce questionnaire vous permet d'évaluer votre niveau avant de rejoindre la formation. 20 questions, 4 choix, une seule bonne réponse. Répondez honnêtement : il n'y a aucun piège, juste une vérification de vos acquis.
Test de Positionnement
10 questions Python + 10 questions Algèbre Linéaire. Durée estimée : 10 minutes.
1 Quel est le résultat de type(3.14) en Python ?
2 Comment accéder au troisième élément d'une liste L ?
3 Quelle instruction crée un dictionnaire en Python ?
4 Que retourne len([1, 2, 3, 4]) ?
5 Quelle est la sortie de : [x**2 for x in range(4)] ?
6 Quelle bibliothèque utilise-t-on pour charger un fichier CSV sous forme de tableau numérique ?
7 Quel est le résultat de np.array([1,2,3]).shape ?
8 Comment sélectionner toutes les lignes de la deuxième colonne d'un array A de shape (100, 3) ?
9 Que fait np.mean(A, axis=0) sur un array de shape (100, 3) ?
10 Quelle fonction Python permet de définir un bloc de code réutilisable ?
11 Quelle est la norme du vecteur (3, 4, 0) ?
12 Quel est le produit scalaire de (1, 0, 0) et (0, 1, 0) ?
13 Que signifie un produit scalaire nul entre deux vecteurs non nuls ?
14 Quel est le produit vectoriel de (1, 0, 0) et (0, 1, 0) ?
15 Quelle est la dimension du résultat de la multiplication d'une matrice (3x3) par un vecteur (3x1) ?
16 Que représente la matrice identité (I) en géométrie 3D ?
17 Si une matrice de rotation R tourne un objet de 30 degrés, que fait R inverse ?
18 Quelle matrice effectue un changement d'échelle qui double toutes les dimensions ?
19 Quelle propriété est conservée par une matrice de rotation ?
20 En NumPy, quel opérateur effectue une multiplication matricielle ?
Votre Score
Prêt à passer à la vitesse supérieure ?
Ce guide couvre les prérequis. La formation vous emmène de ces fondations vers la maîtrise complète des systèmes 3D en production.
Découvrir la Formation (120h)