📐 Carrés aux 4 coins⚓︎
Un exercice de construction de figure géométrique dans le plan.
Classe Figure
fig = Figure(x_min=-4, y_min=-4, x_max=+4, y_max=+4, width=256)
On peut alors dessiner dans le plan euclidien avec un repère orthonormé.
- On indique une zone de dessin.
- On indique aussi la taille de l'image produite, en pixels, soit en largeur (
width
), soit en hauteur (height
). Le ratio est conservé.
Cette classe Figure
est spécifique à cet exercice.
Pour cet exercice, seule la fonction de construction square
est disponible.
La fonction square
square(x, y, a)
définit un carré de centre \((x, y)\) et de côté \(a\)
- les coins des carrés sont arrondis, uniquement dans un but esthétique
- l'épaisseur du trait est automatiquement proportionnelle au côté
Un exemple
- La méthode
draw
deFigure
ajoute un élément au dessin. - La méthode
done
construit et affiche le dessin de la figure. - Le résultat est une image vectorielle.
Par exemple, le script
fig = Figure(x_min=-4, y_min=-4, x_max=+4, y_max=+4, width=256)
fig.draw(square(0, 0, 4))
fig.done()
dessine un carré de centre \((0, 0)\) et de côté \(4\), ce qui produit l'image suivante
Exercice
On vous demande de compléter la fonction récursive motif_carre_4
telle que le script à compléter produise l'image suivante
- Le plus grand carré est de côté 4, de centre \((0, 0)\).
- Les centres des petits carrés sont aux coins du grand carré associé,
- le rapport de réduction est alors \(\frac12\).
- Il y a 4 tailles différentes de carrés.
La fonction sera obligatoirement récursive.
# --- HDR ---#bksl-nlfrom js import documentbksl-nlbksl-nlbksl-nlclass Figure:bksl-nl def py-undpy-undinitpy-undpy-und(bksl-nl self, py-str, xpy-undmin=None, ypy-undmin=None, xpy-undmax=None, ypy-undmax=None, width=None, height=Nonebksl-nl ):bksl-nl """xpy-undmin, ypy-undmin, xpy-undmax py-strpy-stretpy-strpy-str ypy-undmax en paramètres nommés obligatoiresbksl-nl width py-strpy-stroupy-strpy-str height en paramètres nommés obligatoiresbksl-nl """bksl-nl assert xpy-undmin is not None, "Il faut préciser xpy-undmin"bksl-nl assert xpy-undmax is not None, "Il faut préciser xpy-undmax"bksl-nl assert ypy-undmin is not None, "Il faut préciser ypy-undmin"bksl-nl assert ypy-undmax is not None, "Il faut préciser ypy-undmax"bksl-nl self.xpy-undmin = float(xpy-undmin)bksl-nl self.xpy-undmax = float(xpy-undmax)bksl-nl self.ypy-undmin = float(ypy-undmin)bksl-nl self.ypy-undmax = float(ypy-undmax)bksl-nl assert self.xpy-undmin < self.xpy-undmaxbksl-nl assert self.ypy-undmin < self.ypy-undmaxbksl-nlbksl-nl if width is None:bksl-nl assert height is not None, "Il faut préciser soit width, soit height"bksl-nl self.height = round(height)bksl-nl self.width = round(bksl-nl self.height py-str (self.xpy-undmax - self.xpy-undmin) / (self.ypy-undmax - self.ypy-undmin)bksl-nl )bksl-nl else:bksl-nl self.width = round(width)bksl-nl self.height = round(bksl-nl self.width py-str (self.ypy-undmax - self.ypy-undmin) / (self.xpy-undmax - self.xpy-undmin)bksl-nl )bksl-nlbksl-nl self.prog = []bksl-nlbksl-nl def py-undreprpy-undsvgpy-und(self):bksl-nl BASE = 2py-strpy-str20 # 1048576bksl-nl if self.width < self.height:bksl-nl WIDTH = BASE # coordonnéesbksl-nl HEIGHT = BASE py-str self.height // self.widthbksl-nl k = HEIGHT / (self.ypy-undmax - self.ypy-undmin)bksl-nl assert k > 0bksl-nl else:bksl-nl HEIGHT = BASE # coordonnéesbksl-nl WIDTH = BASE py-str self.width // self.heightbksl-nl k = WIDTH / (self.xpy-undmax - self.xpy-undmin)bksl-nl assert k > 0bksl-nlbksl-nl def py-undj(x):bksl-nl j = round((x - self.xpy-undmin) py-str k)bksl-nl assert 0 <= j <= WIDTH, f"{j} {WIDTH}"bksl-nl return jbksl-nlbksl-nl def py-undi(y):bksl-nl i = round((self.ypy-undmax - y) py-str k)bksl-nl assert 0 <= i <= HEIGHT, f"{i} {HEIGHT} {WIDTH} {y} {k}"bksl-nl return ibksl-nlbksl-nl def py-undl(a):bksl-nl return round(a py-str k)bksl-nlbksl-nl ans = ['<?xml version="1.0" encoding="UTF-8"?>']bksl-nl ans.append(bksl-nl f'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{self.width}px" height="{self.height}px" viewBox="0 0 {WIDTH} {HEIGHT}" fill="none" stroke="black" >'bksl-nl )bksl-nl if self.prog != []:bksl-nl for a, py-und, x, y in self.prog:bksl-nl i = py-undi(y + a / 2)bksl-nl j = py-undj(x - a / 2)bksl-nl r = py-undl(a / 8)bksl-nl l = py-undl(a)bksl-nl e = py-undl(a / 16)bksl-nl ans.append(bksl-nl f'<rect x="{j}" y="{i}" rx="{r}" ry="{r}" width="{l}" height="{l}" stroke-width="{e}" />'bksl-nl )bksl-nl ans.append("</svg>")bksl-nl return "\n".join(ans).replace("<", "<")bksl-nlbksl-nl def draw(self, truc):bksl-nl x, y, a = trucbksl-nl assert a > 0, "Le côté doit être strictement positif"bksl-nl self.prog.append((a, 13 py-str x + 7 py-str y, x, y))bksl-nlbksl-nl def done(self, eltpy-undid="figpy-undgeometry"):bksl-nl elt = document.getElementById(eltpy-undid)bksl-nl elt.innerHTML = self.py-undreprpy-undsvgpy-und()bksl-nlbksl-nlbksl-nldef square(x, y, a):bksl-nl return (x, y, a)bksl-nlbksl-nlbksl-nl# --- HDR ---#bksl-nldef motifpy-undcarrepy-und4(x, y, a, n):bksl-nl ... # À compléterbksl-nlbksl-nlbksl-nlfig = Figure(xpy-undmin=-4, ypy-undmin=-4, xpy-undmax=+4, ypy-undmax=+4, width=256)bksl-nlbksl-nlmotifpy-undcarrepy-und4(0, 0, 4, 4)bksl-nlbksl-nlfig.done()bksl-nlbksl-nl# --- HDR ---#bksl-nlfrom js import documentbksl-nlbksl-nlbksl-nlclass Figure:bksl-nl def py-undpy-undinitpy-undpy-und(bksl-nl self, py-str, xpy-undmin=None, ypy-undmin=None, xpy-undmax=None, ypy-undmax=None, width=None, height=Nonebksl-nl ):bksl-nl """xpy-undmin, ypy-undmin, xpy-undmax py-strpy-stretpy-strpy-str ypy-undmax en paramètres nommés obligatoiresbksl-nl width py-strpy-stroupy-strpy-str height en paramètres nommés obligatoiresbksl-nl """bksl-nl assert xpy-undmin is not None, "Il faut préciser xpy-undmin"bksl-nl assert xpy-undmax is not None, "Il faut préciser xpy-undmax"bksl-nl assert ypy-undmin is not None, "Il faut préciser ypy-undmin"bksl-nl assert ypy-undmax is not None, "Il faut préciser ypy-undmax"bksl-nl self.xpy-undmin = float(xpy-undmin)bksl-nl self.xpy-undmax = float(xpy-undmax)bksl-nl self.ypy-undmin = float(ypy-undmin)bksl-nl self.ypy-undmax = float(ypy-undmax)bksl-nl assert self.xpy-undmin < self.xpy-undmaxbksl-nl assert self.ypy-undmin < self.ypy-undmaxbksl-nlbksl-nl if width is None:bksl-nl assert height is not None, "Il faut préciser soit width, soit height"bksl-nl self.height = round(height)bksl-nl self.width = round(bksl-nl self.height py-str (self.xpy-undmax - self.xpy-undmin) / (self.ypy-undmax - self.ypy-undmin)bksl-nl )bksl-nl else:bksl-nl self.width = round(width)bksl-nl self.height = round(bksl-nl self.width py-str (self.ypy-undmax - self.ypy-undmin) / (self.xpy-undmax - self.xpy-undmin)bksl-nl )bksl-nlbksl-nl self.prog = []bksl-nlbksl-nl def py-undreprpy-undsvgpy-und(self):bksl-nl BASE = 2py-strpy-str20 # 1048576bksl-nl if self.width < self.height:bksl-nl WIDTH = BASE # coordonnéesbksl-nl HEIGHT = BASE py-str self.height // self.widthbksl-nl k = HEIGHT / (self.ypy-undmax - self.ypy-undmin)bksl-nl else:bksl-nl HEIGHT = BASE # coordonnéesbksl-nl WIDTH = BASE py-str self.width // self.heightbksl-nl k = WIDTH / (self.xpy-undmax - self.xpy-undmin)bksl-nlbksl-nl def py-undj(x):bksl-nl j = round((x - self.xpy-undmin) py-str k)bksl-nl return jbksl-nlbksl-nl def py-undi(y):bksl-nl i = round((self.ypy-undmax - y) py-str k)bksl-nl return ibksl-nlbksl-nl def py-undl(a):bksl-nl return round(a py-str k)bksl-nlbksl-nl ans = ['<?xml version="1.0" encoding="UTF-8"?>']bksl-nl ans.append(bksl-nl f'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{self.width}px" height="{self.height}px" viewBox="0 0 {WIDTH} {HEIGHT}" fill="none" stroke="black" >'bksl-nl )bksl-nl if self.prog != []:bksl-nl for a, py-und, x, y in self.prog:bksl-nl i = py-undi(y + a / 2)bksl-nl j = py-undj(x - a / 2)bksl-nl r = py-undl(a / 8)bksl-nl l = py-undl(a)bksl-nl e = py-undl(a / 16)bksl-nl ans.append(bksl-nl f'<rect x="{j}" y="{i}" rx="{r}" ry="{r}" width="{l}" height="{l}" stroke-width="{e}" />'bksl-nl )bksl-nl ans.append("</svg>")bksl-nl return "\n".join(ans).replace("<", "<")bksl-nlbksl-nl def draw(self, truc):bksl-nl x, y, a = trucbksl-nl assert a > 0, "Le côté doit être strictement positif"bksl-nl self.prog.append((a, 13 py-str x + 7 py-str y, x, y))bksl-nlbksl-nl def done(self, eltpy-undid="figpy-undgeometry"):bksl-nl elt = document.getElementById(eltpy-undid)bksl-nl elt.innerHTML = self.py-undreprpy-undsvgpy-und()bksl-nlbksl-nlbksl-nldef square(x, y, a):bksl-nl return (x, y, a)bksl-nlbksl-nlbksl-nl# --- HDR ---#bksl-nldef motifpy-undcarrepy-und4(x, y, a, n):bksl-nl if n > 0:bksl-nl fig.draw(square(x, y, a))bksl-nl b = a / 2bksl-nl for dx, dy in [(-b, -b), (b, -b), (-b, b), (b, b)]:bksl-nl motifpy-undcarrepy-und4(x + dx, y + dy, b, n - 1)bksl-nlbksl-nlbksl-nlfig = Figure(xpy-undmin=-4, ypy-undmin=-4, xpy-undmax=+4, ypy-undmax=+4, width=256)bksl-nlbksl-nlmotifpy-undcarrepy-und4(0, 0, 4, 4)bksl-nlbksl-nlfig.done()bksl-nlbksl-nl
A
Commentaires⚓︎
{{ IDE('exo_corr') }}
b = a / 2
, la variableb
est à la fois- le décalage pour rejoindre un sommet du carré
- le côté des prochains carrés à construire
for dx, dy in [(-b, -b), (b, -b), (-b, b), (b, b)]:
- prépare la construction des 4 motifs de niveau
n - 1
dans les 4 coins du carré.
- prépare la construction des 4 motifs de niveau
Z
Votre image sera ici
Indice
motif_carre_4(0, 0, 4, 1)
motif_carre_4(0, 0, 4, 2)
motif_carre_4(0, 0, 4, 3)
motif_carre_4(0, 0, 4, 4)