Baccalauréat — Épreuve pratique — 2026 — NSI
Épreuve pratique NSI 2026 — Sujet 09 : objets 3D et estimation d'impression
Sujet
Épreuve pratique de NSI, session 2026 — sujet n°09 de la banque nationale. Durée : 1 heure, sur ordinateur. Le candidat dispose de l'énoncé et de fichiers de code et de données ; il agit en autonomie et, aux « appels professeur » indiqués, présente son travail à l'examinateur ou le sollicite en cas de difficulté.
Objets 3D et impression
Les fichiers OBJ constituent l'un des formats les plus utilisés dans le domaine de la modélisation 3D. Étant donné un repère orthonormé, ils servent à décrire une forme géométrique en listant ses sommets (les points dans l'espace) et ses faces (les surfaces reliant ces points). Grâce à ce principe, il est possible de représenter aussi bien des objets simples, comme un cube, que des modèles complexes issus de logiciels de modélisation.
Ce format est particulièrement apprécié parce qu'il est simple à lire, facile à manipuler et compatible avec la majorité des outils 3D. Cette simplicité vient du fait qu'un fichier OBJ n'est rien d'autre qu'un fichier texte, dans lequel on décrit ligne par ligne les différents éléments : le nom de l'objet (o), les sommets (v), les faces (f)…
Voici un exemple du contenu d'un fichier OBJ permettant de construire une seule face d'un cube (figure 1).
o cube
v 0.0 0.0 0.0
v 0.0 1.0 0.0
v 1.0 1.0 0.0
v 1.0 0.0 0.0
f 1 2 3 4Dans ce sujet, on ne considère que des coordonnées entières.
Représentation de l'information
Pour manipuler ces fichiers OBJ, nous avons à disposition trois classes Python :
- la classe
Sommet: elle représente un sommet, défini par trois entiers précisant les coordonnées , et du sommet ; - la classe
Face: elle représente une face d'un élément 3D, définie par une liste d'indices. Cet indice identifie un sommet présent dans la liste des sommets d'unObjet3D; - la classe
Objet3D: elle représente un élément 3D, défini par une liste d'objets de typeSommetet une liste d'objets de typeFace.
Chaque classe est définie dans son propre module Python. Ainsi, la classe Sommet est définie dans Sommet.py.
Calcul du volume d'un élément 3D
On s'intéresse au calcul du volume d'un objet afin d'obtenir une estimation du temps d'impression à l'aide d'une imprimante 3D. Pour cela, on va chercher l'arête la plus longue présente sur une de ses faces et approcher le volume de l'objet par celui d'un cube de même arête. Pour calculer la longueur d'une arête, il suffit de calculer la distance entre les deux sommets qui la composent.
Question 1. Écrire la méthode distance de la classe Sommet. Elle prend en paramètre un objet de type Sommet. La méthode renvoie la distance entre l'objet courant et l'objet de type Sommet passé en paramètre. On rappelle que la distance entre deux points et dans un repère choisi s'obtient grâce à la formule
avec les coordonnées du point et les coordonnées du point . Pour calculer le résultat d'une racine carrée en Python, on peut utiliser la fonction sqrt du module math.
Pour obtenir l'arête la plus longue, on va considérer tous les couples de sommets formant une arête et calculer le couple de plus grande longueur. Quand deux sommets sont les extrémités d'une arête d'une face, on dit qu'ils sont adjacents.
Question 2. Écrire la méthode sommets_adjacents de la classe Objet3D qui prend en entrée deux points donnés par leurs coordonnées et renvoie True s'ils représentent une arête de l'objet 3D et False sinon. Attention, on considère que les arêtes ne sont pas ordonnées, ainsi sommets_adjacents(s1, s2) == sommets_adjacents(s2, s1).
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
On dispose d'une méthode volume_cube_englobant dans la classe Objet3D qui utilise la fonction précédente pour estimer le volume d'un objet 3D.
Dans le fichier Imprimante3D.py, on définit une classe Imprimante3D qui contient deux attributs :
- l'attribut
remplissageprécise le taux de remplissage, flottant entre 0.0 et 1.0, du plastique lors de l'impression ; - l'attribut
vitesse_extrusionprécise la vitesse d'impression de l'imprimante. Elle est représentée sous la forme d'un entier, précisant la vitesse en mm³/s.
On considère que l'unité géométrique est de 1 mm. Ainsi, le sommet de coordonnées (2, 0, 0) est à 2 mm de l'origine du repère.
Question 3. Écrire une méthode estimation_impression pour la classe Imprimante3D qui prend en paramètre un Objet3D et renvoie une estimation de son temps d'impression en secondes en procédant ainsi :
- dans un premier temps, il faut calculer le volume d'impression de l'objet, c'est-à-dire en multipliant le volume réel par le taux de remplissage ;
- dans un second temps, il faut calculer le temps d'impression en secondes. On rappelle que le temps s'obtient en divisant le volume d'impression de l'objet par la vitesse d'extrusion de l'imprimante.
Manipulation d'objets 3D
On souhaite agrandir ou rétrécir un objet 3D selon un rapport (agrandissement ou réduction). On dispose dans la classe Objet3D de la méthode transformer, qui permet de transformer l'instance courante selon le rapport passé en paramètre.
Question 4. Utiliser cette méthode pour doubler la dimension du cube présent dans Objet3D.py en l'affichant avant et après l'appel. Le cube n'apparaît pas deux fois plus grand : analyser le fonctionnement de la méthode transformer et proposer une correction.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Fichiers fournis
Le dossier comporte une version PDF de l'énoncé et les fichiers de classes Objet3D.py, Face.py, Sommet.py et Imprimante3D.py. Les bibliothèques matplotlib et math doivent être disponibles.
Sommet.py
import math
class Sommet:
"""
Représente un sommet (point) dans l'espace 3D.
"""
def __init__(self, x, y, z):
"""
Initialise un sommet avec ses coordonnées.
"""
self.x = x
self.y = y
self.z = z
#############################################################################
# Écrire le code de la méthode distance de la question 1 #
#############################################################################
def distance(self, s):
return ((s.x-self.x)**2+(s.y-self.y)**2+(s.z-self.z)**2)**0.5
#############################################################################
# Programme pour tester votre méthode de la question 1 #
#############################################################################
s1 = Sommet(0, 0, 0)
s2 = Sommet(3, 4, 0)Face.py
class Face:
"""
Représente une face d'un objet 3D.
"""
def __init__(self, sommets):
self.sommets = sommetsObjet3D.py
from Sommet import Sommet
from Face import Face
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
class Objet3D:
"""
Représente un objet 3D composé de sommets, de faces et d'un nom.
"""
def __init__(self):
"""
Initialise un objet 3D vide.
"""
self.sommets = []
self.faces = []
self.nom = ""
def ajouter_sommet(self, x, y, z):
"""
Ajoute un sommet à l'objet 3D.
"""
self.sommets.append(Sommet(x, y, z))
def ajouter_face(self, liste_sommets):
"""
Ajoute une face à l'objet 3D.
"""
self.faces.append(Face([self.sommets[i] for i in liste_sommets]))
def __str__(self):
"""
Renvoie une représentation textuelle de l'objet 3D.
"""
return str({'nom': self.nom, 'sommets': len(self.sommets), 'faces': len(self.faces)})
def afficher(self):
"""
Affiche l'objet 3D à l'aide de matplotlib.
"""
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
f = []
for face in self.faces:
x = [(s.x, s.y, s.z) for s in face.sommets]
f.append(x)
mesh = Poly3DCollection(f, alpha=0.4, edgecolor='black')
ax.add_collection3d(mesh)
plt.show()
#############################################################################
# Méthode à modifier de la question 5 #
#############################################################################
def transformer(self, rapport):
"""
Applique une transformation d'échelle à l'objet 3D en modifiant directement ses sommets.
"""
sommets = []
for sommet in self.sommets:
sommets.append(
Sommet(sommet.x * rapport,
sommet.y * rapport, sommet.z * rapport))
self.sommets = sommets
#############################################################################
# Écrire le code de la méthode sommets_adjacents de la question 2 #
#############################################################################
def sommets_adjacents(self, s1, s2):
pass
def longueur_plus_longue_arete(self):
max_longueur = 0
for s1 in self.sommets:
for s2 in self.sommets:
if self.sommets_adjacents(s1, s2):
d = s1.distance(s2)
if d > max_longueur:
max_longueur = d
return max_longueur
def volume_cube_englobant(self):
longueur_max = self.longueur_plus_longue_arete()
return longueur_max ** 3
#############################################################################
# Cube pour tester votre méthode de la question 2 #
#############################################################################
cube = Objet3D()
cube.ajouter_sommet(0, 0, 0) # s0
cube.ajouter_sommet(1, 2, 2) # s1
cube.ajouter_sommet(3, 3, 0) # s2
cube.ajouter_sommet(2, 1, -2) # s3
cube.ajouter_sommet(-2, 2, -1) # s4
cube.ajouter_sommet(-1, 4, 1) # s5
cube.ajouter_sommet(1, 5, -1) # s6
cube.ajouter_sommet(0, 3, -3) # s7
cube.ajouter_face([0, 1, 2, 3])
cube.ajouter_face([4, 5, 6, 7])
cube.ajouter_face([0, 1, 5, 4])
cube.ajouter_face([1, 2, 6, 5])
cube.ajouter_face([2, 3, 7, 6])
cube.ajouter_face([3, 0, 4, 7])
# cube.afficher() # à décommenter pour afficher le cube en 3dImprimante3D.py
from Objet3D import Objet3D
#############################################################################
# Variables et fonctions fournies pour la question 3 #
#############################################################################
class Imprimante3D:
def __init__(self, remplissage, vitesse_extrusion):
self.remplissage = remplissage
self.vitesse_extrusion = vitesse_extrusion
#############################################################################
# Écrire le code de la méthode estimation_impression de la question 3 #
#############################################################################
def estimation_impression(self, objet):
pass
rhombi = Objet3D()
# Définition des 24 sommets
rhombi.ajouter_sommet(1, 1, 3) # s0
rhombi.ajouter_sommet(1, 1, -3) # s1
rhombi.ajouter_sommet(1, -1, 3) # s2
rhombi.ajouter_sommet(1, -1, -3) # s3
rhombi.ajouter_sommet(-1, 1, 3) # s4
rhombi.ajouter_sommet(-1, 1, -3) # s5
rhombi.ajouter_sommet(-1, -1, 3) # s6
rhombi.ajouter_sommet(-1, -1, -3) # s7
rhombi.ajouter_sommet(1, 3, 1) # s8
rhombi.ajouter_sommet(1, 3, -1) # s9
rhombi.ajouter_sommet(1, -3, 1) # s10
rhombi.ajouter_sommet(1, -3, -1) # s11
rhombi.ajouter_sommet(-1, 3, 1) # s12
rhombi.ajouter_sommet(-1, 3, -1) # s13
rhombi.ajouter_sommet(-1, -3, 1) # s14
rhombi.ajouter_sommet(-1, -3, -1) # s15
rhombi.ajouter_sommet(3, 1, 1) # s16
rhombi.ajouter_sommet(3, 1, -1) # s17
rhombi.ajouter_sommet(3, -1, 1) # s18
rhombi.ajouter_sommet(3, -1, -1) # s19
rhombi.ajouter_sommet(-3, 1, 1) # s20
rhombi.ajouter_sommet(-3, 1, -1) # s21
rhombi.ajouter_sommet(-3, -1, 1) # s22
rhombi.ajouter_sommet(-3, -1, -1) # s23
# Faces carrées principales (axiales)
rhombi.ajouter_face([0, 2, 6, 4]) # Z+
rhombi.ajouter_face([1, 5, 7, 3]) # Z-
rhombi.ajouter_face([16, 17, 19, 18]) # X+
rhombi.ajouter_face([20, 22, 23, 21]) # X-
rhombi.ajouter_face([8, 12, 13, 9]) # Y+
rhombi.ajouter_face([10, 11, 15, 14]) # Y-
# Faces carrées de jonction (arêtes)
rhombi.ajouter_face([0, 16, 18, 2]) # Z+/X+
rhombi.ajouter_face([4, 6, 22, 20]) # Z+/X-
rhombi.ajouter_face([1, 3, 19, 17]) # Z-/X+
rhombi.ajouter_face([5, 21, 23, 7]) # Z-/X-
rhombi.ajouter_face([0, 4, 12, 8]) # Z+/Y+
rhombi.ajouter_face([2, 10, 14, 6]) # Z+/Y-
rhombi.ajouter_face([1, 9, 13, 5]) # Z-/Y+
rhombi.ajouter_face([3, 7, 15, 11]) # Z-/Y-
rhombi.ajouter_face([8, 16, 17, 9]) # Y+/X+
rhombi.ajouter_face([12, 20, 21, 13]) # Y+/X-
rhombi.ajouter_face([10, 18, 19, 11]) # Y-/X+
rhombi.ajouter_face([14, 22, 23, 15]) # Y-/X-
# Faces triangulaires (sommets)
rhombi.ajouter_face([0, 8, 16]) # X+Y+Z+
rhombi.ajouter_face([4, 12, 20]) # X-Y+Z+
rhombi.ajouter_face([2, 10, 18]) # X+Y-Z+
rhombi.ajouter_face([6, 14, 22]) # X-Y-Z+
rhombi.ajouter_face([1, 17, 9]) # X+Y+Z-
rhombi.ajouter_face([5, 13, 21]) # X-Y+Z-
rhombi.ajouter_face([3, 19, 11]) # X+Y-Z-
rhombi.ajouter_face([7, 15, 23]) # X-Y-Z-
# rhombi.afficher() # à décommenter pour afficher le rhombicuboctaèdre
imprimante = Imprimante3D(20, 1.2)
print(imprimante.estimation_impression(rhombi))Corrigé
Créez un compte gratuit : votre première correction est offerte.