Coverage for src/ensae_teaching_cs/special/image/image_synthese_base.py: 88%

168 statements  

« prev     ^ index     » next       coverage.py v7.1.0, created at 2023-01-27 05:44 +0100

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief définition des objets permettant de construire une image de synthèse 

5""" 

6import math 

7import copy 

8 

9 

10class Vecteur: 

11 """définit ce qu'est un point""" 

12 __slots__ = "x", "y", "z" 

13 

14 def __str__(self): 

15 """pour l'affichage""" 

16 return f"({self.x:3.2f},{self.y:3.2f},{self.z:3.2f})" 

17 

18 def __init__(self, x, y, z): 

19 """initialisation""" 

20 self.x, self.y, self.z = float(x), float(y), float(z) 

21 

22 def __add__(self, p): 

23 """addition de deux points""" 

24 return Vecteur(self.x + p.x, self.y + p.y, self.z + p.z) 

25 

26 def __neg__(self): 

27 """retourne l'opposé d'un vecteur""" 

28 return Vecteur(-self.x, -self.y, -self.z) 

29 

30 def __iadd__(self, p): 

31 """addition de deux points""" 

32 self.x += p.x 

33 self.y += p.y 

34 self.z += p.z 

35 return self 

36 

37 def __sub__(self, p): 

38 """soustraction de deux points""" 

39 return Vecteur(self.x - p.x, self.y - p.y, self.z - p.z) 

40 

41 def __isub__(self, p): 

42 """soustraction de deux points""" 

43 self.x -= p.x 

44 self.y -= p.y 

45 self.z -= p.z 

46 return self 

47 

48 def __mul__(self, x): 

49 """multiplication par un scalaire""" 

50 return Vecteur(self.x * x, self.y * x, self.z * x) 

51 

52 def __imul__(self, x): 

53 """multiplication par un scalaire""" 

54 self.x *= x 

55 self.y *= x 

56 self.z *= x 

57 return self 

58 

59 def __truediv__(self, x): 

60 """division par un scalaire""" 

61 return Vecteur(self.x / x, self.y / x, self.z / x) 

62 

63 def __itruediv__(self, x): 

64 """division par un scalaire""" 

65 self.x /= x 

66 self.y /= x 

67 self.z /= x 

68 return self 

69 

70 def norme2(self): 

71 """retourne la norme du vecteur au carré""" 

72 return self.x * self.x + self.y * self.y + self.z * self.z 

73 

74 def scalaire(self, v): 

75 """calcule le produit scalaire entre self et v""" 

76 return self.x * v.x + self.y * v.y + self.z * v.z 

77 

78 def vectoriel(self, v): 

79 """calcule le produit vectoriel entre self et v""" 

80 res = Vecteur(0, 0, 0) 

81 res.x = self.y * v.z - self.z * v.y 

82 res.y = self.z * v.x - self.x * v.z 

83 res.z = self.x * v.y - self.y * v.x 

84 return res 

85 

86 def norme(self): 

87 """retourne la norme du vecteur""" 

88 return math.sqrt(self.norme2()) 

89 

90 def renorme(self): 

91 """renorme ce vecteur""" 

92 n = self.norme() 

93 if n > 0: 

94 return self / n 

95 else: 

96 return copy.copy(self) 

97 

98 def cosinus(self, v): 

99 """retourne le cosinus de entre le vecteur self et le vecteur r""" 

100 sc = self.scalaire(v) 

101 n1 = self.norme() 

102 n2 = v.norme() 

103 n = n1 * n2 

104 if n == 0: 

105 return 0 

106 return float(sc) / float(n) 

107 

108 def sinus(self, v, norm): 

109 """retourne le sinus de entre le vecteur self et le vecteur r, 

110 norm est un vecteur normal et de norme 1 permettant d'orienter 

111 le plan dans lequel se trouve les deux vecteurs dont il faut mesurer le sinus""" 

112 sc = self.vectoriel(v) 

113 n1 = self.norme() 

114 n2 = v.norme() 

115 n = n1 * n2 

116 if n == 0: 

117 return 0 

118 return sc.scalaire(norm) / float(n) 

119 

120 def angle(self, v, norm): 

121 """retourne l'angle entre les vecteur self et v, 

122 retourne un angle compris entre -pi et pi, 

123 norm est la direction du vecteur normal au plan des deux vecteurs""" 

124 cos = self.cosinus(v) 

125 sin = self.sinus(v, norm) 

126 angle = math.atan2(sin, cos) 

127 if angle > math.pi: 

128 angle -= math.pi * 2 

129 return angle 

130 

131 def diff_abs(self, v): 

132 """retourne la somme des valeurs absolues des différentes entre coordonnées""" 

133 r = abs(self.x - v.x) 

134 r += abs(self.y - v.y) 

135 r += abs(self.z - v.z) 

136 return r 

137 

138 def __eq__(self, v): 

139 """définit l'égalité entre deux vecteurs""" 

140 if v is None: 

141 return False 

142 return self.diff_abs(v) < 1e-10 

143 

144 def __ne__(self, v): 

145 """définit l'égalité entre deux vecteurs""" 

146 if v is None: 

147 return True 

148 return self.diff_abs(v) > 1e-10 

149 

150 

151class Couleur (Vecteur): 

152 """une couleur est un vecteur dont les coordonnées sont comprises entre 0 et 1, 

153 x <--> rouge, y <--> vert, z <--> bleu""" 

154 

155 def __init__(self, x, y, z): 

156 Vecteur.__init__(self, x, y, z) 

157 self.borne() 

158 

159 def borne(self): 

160 """si une couleur est hors bornes, réajuste la couleur, prend le maximum devient 1, 

161 les autres intensités sont ajustées selon ce facteur d'échelle""" 

162 if self.x < 0: 

163 self.x = 0 

164 if self.y < 0: 

165 self.y = 0 

166 if self.z < 0: 

167 self.z = 0 

168 m = max(self.x, self.y) 

169 m = max(m, self.z) 

170 if m > 1: 

171 self.x /= m 

172 self.y /= m 

173 self.z /= m 

174 

175 def __add__(self, p): 

176 """addition de deux couleurs""" 

177 return Couleur(self.x + p.x, self.y + p.y, self.z + p.z) 

178 

179 def produit_terme(self, v): 

180 """effectue un produit terme à terme""" 

181 return Couleur(self.x * v.x, self.y * v.y, self.z * v.z) 

182 

183 def __mul__(self, x): 

184 """multiplication par un scalaire""" 

185 return Couleur(self.x * x, self.y * x, self.z * x) 

186 

187 

188class Repere: 

189 """définition d'un repère orthonormé""" 

190 

191 def __init__(self, origine=Vecteur(0, 0, 0), 

192 axex=Vecteur(1, 0, 0), 

193 axey=Vecteur(0, 1, 0), 

194 axez=Vecteur(0, 0, 1)): 

195 """initialisation, origine et les trois axes""" 

196 self.origine = origine 

197 self.x = axex 

198 self.y = axey 

199 self.z = axez 

200 

201 def coordonnees(self, v): 

202 """on suppose que les coordonnées de v sont exprimées dans ce repère, 

203 calcule les coordonnées de v dans le repère d'origine""" 

204 res = copy.copy(self.origine) 

205 res.x += v.x * self.x.x + v.y * self.y.x + v.z * self.z.x 

206 res.y += v.x * self.x.y + v.y * self.y.y + v.z * self.z.y 

207 res.z += v.x * self.x.z + v.y * self.y.z + v.z * self.z.z 

208 return res 

209 

210 def __str__(self): 

211 """affichage""" 

212 s = "origine : " + str(self.origine) + "\n" 

213 s += "axe des x : " + str(self.x) + "\n" 

214 s += "axe des y : " + str(self.y) + "\n" 

215 s += "axe des z : " + str(self.z) + "\n" 

216 return s 

217 

218 

219class Pixel: 

220 """définit ce qu'est un pixel""" 

221 __slots__ = "x", "y" 

222 

223 def __init__(self, x, y): 

224 """initialisation""" 

225 self.x, self.y = int(x), int(y) 

226 

227 def __str__(self): 

228 """pour l'affichage""" 

229 return "(%d, %d)" % (self.x, self.y) 

230 

231 

232class Rayon: 

233 """définit ce qu'est un rayon""" 

234 __slots__ = "origine", "direction", "pixel", "couleur" 

235 

236 def __init__(self, origine, direction, pixel, couleur): 

237 """initialisation""" 

238 self.origine, self.direction, self.pixel, self.couleur = origine, direction, pixel, couleur 

239 

240 def __str__(self): 

241 """pour l'affichage""" 

242 s = "origine : " + str(self.origine) 

243 s += " direction : " + str(self.direction) 

244 s += " pixel : " + str(self.pixel) 

245 s += " couleur : " + str(self.couleur) 

246 return s 

247 

248 

249class Objet: 

250 """définit l'interface pour un objet à dessiner dans une image de synthese""" 

251 

252 def intersection(self, r): 

253 """retourne le point d'intersection avec le rayon r, 

254 retourne None s'il n'y pas d'intersection""" 

255 return None 

256 

257 def normale(self, p, rayon): 

258 """retourne la normale au point de coordonnée p, et connaissant le rayon""" 

259 return None 

260 

261 def couleur_point(self, p): 

262 """retourne la couleur au point de coordonnée p""" 

263 return None 

264 

265 def rayon_refracte(self, rayon, p): 

266 """retourne le rayon réfracté au point p de la surface, 

267 si aucune, retourne None""" 

268 return None 

269 

270 def rayon_reflechi(self, rayon, p): 

271 """retourne le rayon réfléchi au point p de la surface, 

272 si aucune, retourne None""" 

273 return None 

274 

275 def phong_coefficient(self): 

276 """retourne un coefficient propre à l'objet pour 

277 le modèle d'illumination de Phong""" 

278 return float(0) 

279 

280 

281class Source: 

282 """définition d'une source ponctuelle""" 

283 __slots__ = "origine", "couleur" 

284 

285 def __init__(self, origine, couleur): 

286 """initialisation""" 

287 self.origine, self.couleur = origine, couleur 

288 

289 def __str__(self): 

290 """affichage""" 

291 return "source : " + str(self.origine) + " couleur : " + str(self.couleur)