Aller au contenu

📐 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 de Figure 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.

###
def secretpy-und1337py-undmotifpy-undcarrepy-und4(x, y, a, n):bksl-nl if n > 0:bksl-nl fig.draw(square(x, y, a))bksl-nl a /= 2bksl-nl for dx, dy in [(-a, -a), (a, -a), (-a, a), (a, a)]:bksl-nl secretpy-und1337py-undmotifpy-undcarrepy-und4(x + dx, y + dy, a, n - 1)bksl-nlbksl-nlbksl-nldef sontpy-undproches(x, y):bksl-nl return abs(x - y) < 10py-strpy-str-9bksl-nlbksl-nlbksl-nlfor X, Y, A, N in [bksl-nl (0, 0, 4, 1),bksl-nl (0, 0, 4, 3),bksl-nl (0, 0, 5, 4),bksl-nl (2, 3, 4, 4),bksl-nl (0, 0, 4, 7),bksl-nl]:bksl-nl fig = Figure(xpy-undmin=-4, ypy-undmin=-4, xpy-undmax=+4, ypy-undmax=+4, width=256)bksl-nl motifpy-undcarrepy-und4(X, Y, A, N)bksl-nl psolver = sorted(fig.prog)bksl-nlbksl-nl fig = Figure(xpy-undmin=-4, ypy-undmin=-4, xpy-undmax=+4, ypy-undmax=+4, width=256)bksl-nl secretpy-und1337py-undmotifpy-undcarrepy-und4(X, Y, A, N)bksl-nl psetter = sorted(fig.prog)bksl-nlbksl-nl lastpy-unda = Nonebksl-nl i = 0bksl-nl for (a, k, x, y), (apy-und, kpy-und, xpy-und, ypy-und) in zip(psolver, psetter):bksl-nl if (lastpy-unda is None) or not sontpy-undproches(a, lastpy-unda):bksl-nl i += 1bksl-nl if not sontpy-undproches(a, apy-und):bksl-nl if a < apy-und:bksl-nl assert (bksl-nl Falsebksl-nl ), f"Pour (x, y, a, n) = {(X, Y, A, N)}, il manque un carré de taille {apy-und}"bksl-nl else:bksl-nl assert (bksl-nl Falsebksl-nl ), f"Pour (x, y, a, n) = {(X, Y, A, N)}, il a un carré de taille {apy-und} en trop"bksl-nl if not (sontpy-undproches(x, xpy-und) and sontpy-undproches(y, ypy-und)):bksl-nl assert (bksl-nl Falsebksl-nl ), f"Pour (x, y, a, n) = {(X, Y, A, N)}, il manque un carré de taille {apy-und} en ({xpy-und}, {ypy-und})"bksl-nl if len(psetter) > len(psolver):bksl-nl (apy-und, kpy-und, xpy-und, ypy-und) = psetter[len(psolver)]bksl-nl assert (bksl-nl Falsebksl-nl ), f"Pour (x, y, a, n) = {(X, Y, A, N)}, il manque un carré de taille {apy-und} en ({xpy-und}, {ypy-und})"bksl-nlbksl-nl# un test sur la récursivitébksl-nl# import sysbksl-nlbksl-nl# sys.setrecursionlimit(50)bksl-nlbksl-nl# fig = Figure()bksl-nl# try:bksl-nl# motifpy-undcarrepy-und4(X, Y, A, N)bksl-nl# except RecursionError:bksl-nl# passbksl-nl# except:bksl-nl# assert False, "Votre fonction doit être récursive"bksl-nlbksl-nl 5/5

# --- 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 = ['&lt?xml version="1.0" encoding="UTF-8"?>']bksl-nl ans.append(bksl-nl f'&ltsvg 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'&ltrect x="{j}" y="{i}" rx="{r}" ry="{r}" width="{l}" height="{l}" stroke-width="{e}" />'bksl-nl )bksl-nl ans.append("&lt/svg>")bksl-nl return "\n".join(ans).replace("&lt", "<")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 = ['&lt?xml version="1.0" encoding="UTF-8"?>']bksl-nl ans.append(bksl-nl f'&ltsvg 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'&ltrect x="{j}" y="{i}" rx="{r}" ry="{r}" width="{l}" height="{l}" stroke-width="{e}" />'bksl-nl )bksl-nl ans.append("&lt/svg>")bksl-nl return "\n".join(ans).replace("&lt", "<")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 variable b 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é.

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)