# -*- 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)