Code source de ensae_teaching_cs.special.image.image_synthese_base

# -*- coding: utf-8 -*-
"""
définition des objets permettant de construire une image de synthèse


:githublink:`%|py|6`
"""
import math
import copy


[docs]class Vecteur: """ définit ce qu'est un point :githublink:`%|py|11` """ __slots__ = "x", "y", "z"
[docs] def __str__(self): """ pour l'affichage :githublink:`%|py|15` """ return "(%3.2f,%3.2f,%3.2f)" % (self.x, self.y, self.z)
[docs] def __init__(self, x, y, z): """ initialisation :githublink:`%|py|19` """ self.x, self.y, self.z = float(x), float(y), float(z)
[docs] def __add__(self, p): """ addition de deux points :githublink:`%|py|23` """ return Vecteur(self.x + p.x, self.y + p.y, self.z + p.z)
[docs] def __neg__(self): """ retourne l'opposé d'un vecteur :githublink:`%|py|27` """ return Vecteur(-self.x, -self.y, -self.z)
[docs] def __iadd__(self, p): """ addition de deux points :githublink:`%|py|31` """ self.x += p.x self.y += p.y self.z += p.z return self
[docs] def __sub__(self, p): """ soustraction de deux points :githublink:`%|py|38` """ return Vecteur(self.x - p.x, self.y - p.y, self.z - p.z)
[docs] def __isub__(self, p): """ soustraction de deux points :githublink:`%|py|42` """ self.x -= p.x self.y -= p.y self.z -= p.z return self
[docs] def __mul__(self, x): """ multiplication par un scalaire :githublink:`%|py|49` """ return Vecteur(self.x * x, self.y * x, self.z * x)
[docs] def __imul__(self, x): """ multiplication par un scalaire :githublink:`%|py|53` """ self.x *= x self.y *= x self.z *= x return self
[docs] def __truediv__(self, x): """ division par un scalaire :githublink:`%|py|60` """ return Vecteur(self.x / x, self.y / x, self.z / x)
[docs] def __itruediv__(self, x): """ division par un scalaire :githublink:`%|py|64` """ self.x /= x self.y /= x self.z /= x return self
[docs] def norme2(self): """ retourne la norme du vecteur au carré :githublink:`%|py|71` """ return self.x * self.x + self.y * self.y + self.z * self.z
[docs] def scalaire(self, v): """ calcule le produit scalaire entre self et v :githublink:`%|py|75` """ return self.x * v.x + self.y * v.y + self.z * v.z
[docs] def vectoriel(self, v): """ calcule le produit vectoriel entre self et v :githublink:`%|py|79` """ res = Vecteur(0, 0, 0) res.x = self.y * v.z - self.z * v.y res.y = self.z * v.x - self.x * v.z res.z = self.x * v.y - self.y * v.x return res
[docs] def norme(self): """ retourne la norme du vecteur :githublink:`%|py|87` """ return math.sqrt(self.norme2())
[docs] def renorme(self): """ renorme ce vecteur :githublink:`%|py|91` """ n = self.norme() if n > 0: return self / n else: return copy.copy(self)
[docs] def cosinus(self, v): """ retourne le cosinus de entre le vecteur self et le vecteur r :githublink:`%|py|99` """ sc = self.scalaire(v) n1 = self.norme() n2 = v.norme() n = n1 * n2 if n == 0: return 0 return float(sc) / float(n)
[docs] def sinus(self, v, norm): """ retourne le sinus de entre le vecteur self et le vecteur r, norm est un vecteur normal et de norme 1 permettant d'orienter le plan dans lequel se trouve les deux vecteurs dont il faut mesurer le sinus :githublink:`%|py|111` """ sc = self.vectoriel(v) n1 = self.norme() n2 = v.norme() n = n1 * n2 if n == 0: return 0 return sc.scalaire(norm) / float(n)
[docs] def angle(self, v, norm): """ retourne l'angle entre les vecteur self et v, retourne un angle compris entre -pi et pi, norm est la direction du vecteur normal au plan des deux vecteurs :githublink:`%|py|123` """ cos = self.cosinus(v) sin = self.sinus(v, norm) angle = math.atan2(sin, cos) if angle > math.pi: angle -= math.pi * 2 return angle
[docs] def diff_abs(self, v): """ retourne la somme des valeurs absolues des différentes entre coordonnées :githublink:`%|py|132` """ r = abs(self.x - v.x) r += abs(self.y - v.y) r += abs(self.z - v.z) return r
[docs] def __eq__(self, v): """ définit l'égalité entre deux vecteurs :githublink:`%|py|139` """ if v is None: return False return self.diff_abs(v) < 1e-10
[docs] def __ne__(self, v): """ définit l'égalité entre deux vecteurs :githublink:`%|py|145` """ if v is None: return True return self.diff_abs(v) > 1e-10
[docs]class Couleur (Vecteur): """ une couleur est un vecteur dont les coordonnées sont comprises entre 0 et 1, x <--> rouge, y <--> vert, z <--> bleu :githublink:`%|py|153` """
[docs] def __init__(self, x, y, z): Vecteur.__init__(self, x, y, z) self.borne()
[docs] def borne(self): """ si une couleur est hors bornes, réajuste la couleur, prend le maximum devient 1, les autres intensités sont ajustées selon ce facteur d'échelle :githublink:`%|py|161` """ if self.x < 0: self.x = 0 if self.y < 0: self.y = 0 if self.z < 0: self.z = 0 m = max(self.x, self.y) m = max(m, self.z) if m > 1: self.x /= m self.y /= m self.z /= m
[docs] def __add__(self, p): """ addition de deux couleurs :githublink:`%|py|176` """ return Couleur(self.x + p.x, self.y + p.y, self.z + p.z)
[docs] def produit_terme(self, v): """ effectue un produit terme à terme :githublink:`%|py|180` """ return Couleur(self.x * v.x, self.y * v.y, self.z * v.z)
[docs] def __mul__(self, x): """ multiplication par un scalaire :githublink:`%|py|184` """ return Couleur(self.x * x, self.y * x, self.z * x)
[docs]class Repere: """ définition d'un repère orthonormé :githublink:`%|py|189` """
[docs] def __init__(self, origine=Vecteur(0, 0, 0), axex=Vecteur(1, 0, 0), axey=Vecteur(0, 1, 0), axez=Vecteur(0, 0, 1)): """ initialisation, origine et les trois axes :githublink:`%|py|195` """ self.origine = origine self.x = axex self.y = axey self.z = axez
[docs] def coordonnees(self, v): """ on suppose que les coordonnées de v sont exprimées dans ce repère, calcule les coordonnées de v dans le repère d'origine :githublink:`%|py|203` """ res = copy.copy(self.origine) res.x += v.x * self.x.x + v.y * self.y.x + v.z * self.z.x res.y += v.x * self.x.y + v.y * self.y.y + v.z * self.z.y res.z += v.x * self.x.z + v.y * self.y.z + v.z * self.z.z return res
[docs] def __str__(self): """ affichage :githublink:`%|py|211` """ s = "origine : " + str(self.origine) + "\n" s += "axe des x : " + str(self.x) + "\n" s += "axe des y : " + str(self.y) + "\n" s += "axe des z : " + str(self.z) + "\n" return s
[docs]class Pixel: """ définit ce qu'est un pixel :githublink:`%|py|220` """ __slots__ = "x", "y"
[docs] def __init__(self, x, y): """ initialisation :githublink:`%|py|224` """ self.x, self.y = int(x), int(y)
[docs] def __str__(self): """ pour l'affichage :githublink:`%|py|228` """ return "(%d, %d)" % (self.x, self.y)
[docs]class Rayon: """ définit ce qu'est un rayon :githublink:`%|py|233` """ __slots__ = "origine", "direction", "pixel", "couleur"
[docs] def __init__(self, origine, direction, pixel, couleur): """ initialisation :githublink:`%|py|237` """ self.origine, self.direction, self.pixel, self.couleur = origine, direction, pixel, couleur
[docs] def __str__(self): """ pour l'affichage :githublink:`%|py|241` """ s = "origine : " + str(self.origine) s += " direction : " + str(self.direction) s += " pixel : " + str(self.pixel) s += " couleur : " + str(self.couleur) return s
[docs]class Objet: """ définit l'interface pour un objet à dessiner dans une image de synthese :githublink:`%|py|250` """
[docs] def intersection(self, r): """ retourne le point d'intersection avec le rayon r, retourne None s'il n'y pas d'intersection :githublink:`%|py|254` """ return None
[docs] def normale(self, p, rayon): """ retourne la normale au point de coordonnée p, et connaissant le rayon :githublink:`%|py|258` """ return None
[docs] def couleur_point(self, p): """ retourne la couleur au point de coordonnée p :githublink:`%|py|262` """ return None
[docs] def rayon_refracte(self, rayon, p): """ retourne le rayon réfracté au point p de la surface, si aucune, retourne None :githublink:`%|py|267` """ return None
[docs] def rayon_reflechi(self, rayon, p): """ retourne le rayon réfléchi au point p de la surface, si aucune, retourne None :githublink:`%|py|272` """ return None
[docs] def phong_coefficient(self): """ retourne un coefficient propre à l'objet pour le modèle d'illumination de Phong :githublink:`%|py|277` """ return float(0)
[docs]class Source: """ définition d'une source ponctuelle :githublink:`%|py|282` """ __slots__ = "origine", "couleur"
[docs] def __init__(self, origine, couleur): """ initialisation :githublink:`%|py|286` """ self.origine, self.couleur = origine, couleur
[docs] def __str__(self): """ affichage :githublink:`%|py|290` """ return "source : " + str(self.origine) + " couleur : " + str(self.couleur)