ourocode 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ourocode might be problematic. Click here for more details.

Files changed (53) hide show
  1. ourocode/__init__.py +0 -0
  2. ourocode/__version__.py +1 -0
  3. ourocode/data/caracteristique_meca_acier.csv +33 -0
  4. ourocode/data/caracteristique_meca_bois.csv +59 -0
  5. ourocode/data/carte_action_region.csv +36722 -0
  6. ourocode/data/coeff_psy.csv +13 -0
  7. ourocode/data/exploitation.csv +17 -0
  8. ourocode/data/gammaM.csv +14 -0
  9. ourocode/data/kdef.csv +11 -0
  10. ourocode/data/kfi.csv +10 -0
  11. ourocode/data/kmod.csv +16 -0
  12. ourocode/data/limite_fleche.csv +9 -0
  13. ourocode/data/qualite_acier.csv +18 -0
  14. ourocode/data/screenshot/C90_def.png +0 -0
  15. ourocode/data/screenshot/Kv_def.png +0 -0
  16. ourocode/data/screenshot/fleche.png +0 -0
  17. ourocode/data/screenshot/sign_convention.png +0 -0
  18. ourocode/data/section_boulon.csv +12 -0
  19. ourocode/data/vent/vent_Cp_toiture_isolee_1_versant.csv +22 -0
  20. ourocode/data/vent/vent_Cp_toiture_isolee_1_versant.png +0 -0
  21. ourocode/data/vent/vent_Cp_toiture_isolee_2_versants.csv +31 -0
  22. ourocode/data/vent/vent_Cp_toiture_isolee_2_versants.png +0 -0
  23. ourocode/data/vent/vent_Cpe_mur_verticaux.csv +11 -0
  24. ourocode/data/vent/vent_Cpe_mur_verticaux.png +0 -0
  25. ourocode/data/vent/vent_Cpe_toiture_1_versant.png +0 -0
  26. ourocode/data/vent/vent_Cpe_toiture_1_versant_0_degres.csv +13 -0
  27. ourocode/data/vent/vent_Cpe_toiture_1_versant_180_degres.csv +13 -0
  28. ourocode/data/vent/vent_Cpe_toiture_1_versant_90_degres.csv +13 -0
  29. ourocode/data/vent/vent_Cpe_toiture_2_versants.png +0 -0
  30. ourocode/data/vent/vent_Cpe_toiture_2_versants_0_degres.csv +21 -0
  31. ourocode/data/vent/vent_Cpe_toiture_2_versants_90_degres.csv +21 -0
  32. ourocode/data/vent/vent_Cpe_toiture_terrasse.csv +21 -0
  33. ourocode/data/vent/vent_Cpe_toiture_terrasse.png +0 -0
  34. ourocode/data/vent/vent_Ffr.png +0 -0
  35. ourocode/eurocode/A0_Projet.py +1408 -0
  36. ourocode/eurocode/EC0_Combinaison.py +1763 -0
  37. ourocode/eurocode/EC1_Exploitation.py +103 -0
  38. ourocode/eurocode/EC1_Neige.py +385 -0
  39. ourocode/eurocode/EC1_Vent.py +1388 -0
  40. ourocode/eurocode/EC3_Assemblage.py +466 -0
  41. ourocode/eurocode/EC3_Element_droit.py +302 -0
  42. ourocode/eurocode/EC5_Assemblage.py +1760 -0
  43. ourocode/eurocode/EC5_Element_droit.py +1740 -0
  44. ourocode/eurocode/EC5_Feu.py +922 -0
  45. ourocode/eurocode/EC8_Sismique.py +2 -0
  46. ourocode/eurocode/__init__.py +0 -0
  47. ourocode/eurocode/logical.py +83 -0
  48. ourocode/eurocode/objet.py +263 -0
  49. ourocode-1.6.0.dist-info/METADATA +331 -0
  50. ourocode-1.6.0.dist-info/RECORD +53 -0
  51. ourocode-1.6.0.dist-info/WHEEL +5 -0
  52. ourocode-1.6.0.dist-info/licenses/LICENSE +201 -0
  53. ourocode-1.6.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1388 @@
1
+ #! env\Scripts\python.exe
2
+ # Encoding in UTF-8 by Anthony PARISOT
3
+ import os
4
+ import sys
5
+ from PIL import Image
6
+
7
+ import math as mt
8
+ from math import *
9
+ from copy import copy
10
+
11
+ import pandas as pd
12
+ import forallpeople as si
13
+ from handcalcs.decorator import handcalc
14
+
15
+ # sys.path.append(os.path.join(os.getcwd(), "ourocode"))
16
+ # from eurocode.A0_Projet import Batiment
17
+ from ourocode.eurocode.A0_Projet import Batiment
18
+
19
+ si.environment("structural")
20
+
21
+
22
+ def interpolation_lineaire(x, xa, xb, ya, yb):
23
+ """Fait une interpolation linéaire pour trouver un résultat y entre deux valeur xa et xb"""
24
+ y = ya + (x - xa) * ((yb - ya) / (xb - xa))
25
+ return y
26
+
27
+
28
+ def interpolation_logarithmique(x, xa, xb, ya, yb):
29
+ """Fait une interpolation linéaire pour trouver un résultat y entre deux valeur xa et xb"""
30
+ y = (
31
+ (x > xb) * yb
32
+ + (x < xa) * ya
33
+ + (x <= xb) * (x >= 1) * (ya - (ya - yb) * mt.log10(x))
34
+ )
35
+ return y
36
+
37
+
38
+ class Vent(Batiment):
39
+ """Créer une classe qui permet de calculer l'action de vent.
40
+ Cette classe est hérité de la classe Batiment du module A0_Projet.py.
41
+ """
42
+
43
+ RHO_AIR = 1.225 * si.kg / si.m**3
44
+ CPI = [0.2, -0.3]
45
+ VB0 = {
46
+ "1": 22,
47
+ "2": 24,
48
+ "3": 26,
49
+ "4": 28,
50
+ "Guadeloupe": 36,
51
+ "Guyane": 17,
52
+ "Martinique": 32,
53
+ "Mayotte": 30,
54
+ "Réunion": 34,
55
+ }
56
+
57
+ CAT_TERRAIN = {
58
+ "0": {"Z0": 0.005, "Zmin": 1},
59
+ "II": {"Z0": 0.05, "Zmin": 2},
60
+ "IIIa": {"Z0": 0.2, "Zmin": 5},
61
+ "IIIb": {"Z0": 0.5, "Zmin": 9},
62
+ "IV": {"Z0": 1, "Zmin": 15},
63
+ }
64
+
65
+ CAT_ORO = {"Aucun": 1, "Cas 1": "1", "Cas 2": "2"}
66
+ CFR = {"Lisse": 0.01, "Rugueuse": 0.02, "Très rugueuse": 0.04}
67
+
68
+ def __init__(self, z: si.m, terrain: str = CAT_TERRAIN, oro: str = CAT_ORO, CsCd: float = 1, **kwargs):
69
+ """
70
+ Args:
71
+ z (float): hauteur en m sur le bâtiment ou est étudié le vent (Ze suivant EN 1991-1-4 §7.2.2).
72
+ alt (int): altitude du batiment étudié en m.
73
+ cat_terrain (str): Catégorie de terrain du projet.
74
+ cat_oro (str): Catégorie orographique. Default to "Aucun".
75
+ """
76
+ super().__init__(**kwargs)
77
+ self.terrain = terrain
78
+ self.oro = oro
79
+ self.z = z * si.m
80
+ self.CsCd = CsCd
81
+
82
+ @property
83
+ def cat_terrain(self):
84
+ return __class__.CAT_TERRAIN[self.terrain]
85
+
86
+ @property
87
+ def cat_oro(self):
88
+ return __class__.CAT_ORO[self.oro]
89
+
90
+ @property
91
+ def zone_vent(self):
92
+ file = "carte_action_region.csv"
93
+ df = self._data_from_csv(file, index_col=1)
94
+ return int(df.loc[str(self.code_INSEE)]["Zone_vent"])
95
+
96
+ @property
97
+ def Vb_0(self):
98
+ """Vb,0 est la valeur de base de la vitesse de référence du vent en m/s
99
+
100
+ Returns:
101
+ int: vitesse de référence du vent en m/s
102
+ """
103
+ return self.VB0[str(self.zone_vent)] * si.m / si.s
104
+
105
+ @property
106
+ def Vb(self):
107
+ """Retourne la vitesse de référence du vent en m/s fonction de cette dernière et de la période de l'année
108
+ à une hauteur de 10 m au-dessus d'un sol relevant de la catégorie de terrain II
109
+
110
+ Args:
111
+ Cdir (float): coefficient de direction. Defaults to 1.
112
+ Cseason (float): coefficient de saison. Defaults to 1.
113
+
114
+ Returns:
115
+ float: vitesse de référence du vent en m/s
116
+ """
117
+ V_b_0 = self.Vb_0
118
+ Cdir = 1
119
+ Cseason = 1
120
+
121
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
122
+ def val():
123
+ V_b = V_b_0 * Cdir * Cseason
124
+ return V_b
125
+
126
+ return val()
127
+
128
+ @property
129
+ def rayon_secteur_angu(self):
130
+ """Retourne le rayon du secteur angulaire dans lequel la rugosité de terrain est à qualifier fonction de la hauteur du bâtiment étudier
131
+
132
+ Returns:
133
+ float: max entre 300m et R
134
+ """
135
+ z = self.z.value
136
+
137
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
138
+ def val():
139
+ rayon_secteur_angu = max(23 * z**1.2, 300) * si.m
140
+ return rayon_secteur_angu
141
+
142
+ return val()
143
+
144
+ @property
145
+ def _Kr(self) -> float:
146
+ z0II = self.CAT_TERRAIN["II"]["Z0"]
147
+ return 0.19 * (self.cat_terrain["Z0"] / z0II) ** 0.07
148
+
149
+ @property
150
+ def _Cr_z(self):
151
+ """Retourne le coefficient de rugosité, c r ( z ), tient compte de la variabilité de la vitesse moyenne du vent sur le site de la
152
+ construction
153
+
154
+ Returns:
155
+ float: le coef de rugosité fonction de la hauteur au niveau du sol et de la rugosité de terrain
156
+ """
157
+
158
+ if self.cat_terrain["Zmin"] <= self.z.value <= 200:
159
+ Cr_z = self._Kr * mt.log(self.z.value / self.cat_terrain["Z0"])
160
+ else:
161
+ Cr_z = self._Kr * mt.log(self.cat_terrain["Zmin"] / self.cat_terrain["Z0"])
162
+
163
+ # print("Kr :", self._Kr)
164
+ # print("Cr_z :", Cr_z)
165
+ return Cr_z
166
+
167
+ @property
168
+ def Co_z(self):
169
+ """Retourne le coeficient orographique du terrain suivant la catégorie orographique et la hauteur z du bâtiment
170
+
171
+ Returns:
172
+ float: coef orographique
173
+ """
174
+ # ATTENTION vérifier le z et zmin si toujours comptatible quand ajout du cas 2 !!!
175
+ if self.z.value < self.cat_terrain["Zmin"]:
176
+ z = self.cat_terrain["Zmin"]
177
+ else:
178
+ z = self.z.value
179
+
180
+ match self.cat_oro:
181
+ case "1":
182
+ dict_alti = {
183
+ "An1": "",
184
+ "An2": "",
185
+ "Ae1": "",
186
+ "Ae2": "",
187
+ "As1": "",
188
+ "As2": "",
189
+ "Ao1": "",
190
+ "Ao2": "",
191
+ }
192
+
193
+ for cle, value in dict_alti.items():
194
+ dict_alti[cle] = int(input("Altitude {0} en m: ".format(cle)))
195
+
196
+ Am = (
197
+ 2 * self.alt
198
+ + dict_alti["An1"]
199
+ + dict_alti["An2"]
200
+ + dict_alti["Ae1"]
201
+ + dict_alti["Ae2"]
202
+ + dict_alti["As1"]
203
+ + dict_alti["As2"]
204
+ + dict_alti["Ao1"]
205
+ + dict_alti["Ao2"]
206
+ ) / 10
207
+
208
+ delta_AC = self.alt - Am
209
+
210
+ if self.z.value >= 10:
211
+ C0_z = 1 + 0.004 * delta_AC * mt.exp(z - 10)
212
+ else:
213
+ C0_z = 1 + 0.004 * delta_AC * mt.exp(0)
214
+
215
+ case "2":
216
+ pass
217
+ case _:
218
+ C0_z = 1
219
+ # print("C0_z :", C0_z)
220
+ return max(C0_z, 1)
221
+
222
+ @property
223
+ # @handcalc(override="params", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
224
+ def Vm_z(self):
225
+ """Retourne la vitesse moyenne du vent à une hauteur z au dessus du sol en fonction de la rugosité de terrain,
226
+ de l'orographie et de la vitesse de référence du vent Vb
227
+
228
+ Returns:
229
+ float: vitesse moyenne du vent en m/s
230
+ """
231
+ C_r_z = self._Cr_z
232
+ C_o_z = self.Co_z
233
+ V_b = self.Vb[1]
234
+
235
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
236
+ def val():
237
+ V_m_z = C_r_z * C_o_z * V_b
238
+ return V_m_z
239
+ return val()
240
+
241
+ @property
242
+ def _Kl(self):
243
+ """Retourne le coefficient de turbulence
244
+
245
+ Returns:
246
+ float: coef de turbulence
247
+ """
248
+ match self.cat_oro:
249
+ case "1":
250
+ return self.Co_z * (
251
+ 1 - 2 * 10**-4 * (mt.log10(self.cat_terrain["Z0"]) + 3) ** 6
252
+ ) # 4.19NA
253
+ case _:
254
+ return (
255
+ 1 - 2 * 10**-4 * (mt.log10(self.cat_terrain["Z0"]) + 3) ** 6
256
+ ) # 4.20NA
257
+
258
+ @property
259
+ def _sigma_v(self):
260
+ """Retourne l'écart type de turbulence
261
+
262
+ Returns:
263
+ float: écart type
264
+ """
265
+ return self._Kr * self.Vb[1] * self._Kl # 4.6
266
+
267
+ @property
268
+ def _Iv_z(self):
269
+ """Retourne l'intensité de turbulence à la hauteur z
270
+
271
+ Returns:
272
+ float: intensité de la turbulence
273
+ """
274
+ if (
275
+ self.cat_terrain["Zmin"] <= self.z.value <= 200
276
+ or self.z.value < self.cat_terrain["Zmin"]
277
+ ):
278
+ return self._sigma_v / self.Vm_z[1] # 4.7
279
+ else:
280
+ print(
281
+ """Erreur la hauteur max du bâtiment ne peut dépasser 200m,
282
+ impossible de calculer l'intensité de turbulence Iv"""
283
+ )
284
+
285
+ @property
286
+ def Qb(self):
287
+ """Retour la pression dynamique de référence (informatif)
288
+
289
+ Returns:
290
+ float: pression en N/m²
291
+ """
292
+ V_b = self.Vb[1]
293
+ rho_air = self.RHO_AIR
294
+
295
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
296
+ def val():
297
+ Q_b = 0.5 * rho_air * V_b**2 # 4.10
298
+ return Q_b
299
+
300
+ return val()
301
+
302
+ @property
303
+ def Qp_z(self):
304
+ """Retour la pression dynamique de pointe à la hauteur z qui est induite par la vitesse moyenne
305
+ et les fluctuation rapides de vitesse
306
+
307
+ Returns:
308
+ float: pression en N/m²
309
+ """
310
+ I_v_z = self._Iv_z
311
+ rho_air = self.RHO_AIR
312
+ V_m_z = self.Vm_z[1]
313
+
314
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
315
+ def val():
316
+ Q_p_z = (1 + 7 * I_v_z) * 0.5 * rho_air * V_m_z**2 # 4.8
317
+ return Q_p_z
318
+
319
+ return val()
320
+
321
+ @property
322
+ def Ce_z(self):
323
+ """Retourne le coefficient d'exposition à la hauteur z (informatif)
324
+
325
+ Returns:
326
+ float: coef d'expo
327
+ """
328
+ Q_p_z = self.Qp_z[1]
329
+ Q_b = self.Qb[1]
330
+
331
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
332
+ def val():
333
+ Ce_z = Q_p_z / Q_b # 4.9
334
+ return Ce_z
335
+
336
+ return val()
337
+
338
+ def We(self, Cpe: float):
339
+ """Retourne la pression aérodynamique sur les surfaces extérieures
340
+
341
+ Args:
342
+ Cpe (float): coefficient de pression extérieure
343
+
344
+ Returns:
345
+ float: pression en N/m²
346
+ """
347
+ Q_p_z = self.Qp_z[1]
348
+ C_pe = Cpe
349
+
350
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
351
+ def val():
352
+ W_e = Q_p_z * C_pe # 5.1
353
+ return W_e
354
+
355
+ return val()
356
+
357
+ def Wi(self, Cpi: float):
358
+ """Retourne la pression aérodynamique sur les surfaces intérieures
359
+
360
+ Args:
361
+ Cpi (float): coefficient de pression intérieure
362
+
363
+ Returns:
364
+ float: pression en N/m²"""
365
+ Q_p_z = self.Qp_z[1]
366
+ C_pi = Cpi
367
+
368
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
369
+ def val():
370
+ W_e = Q_p_z * C_pi # 5.2
371
+ return W_e
372
+
373
+ return val()
374
+
375
+ def Fw_e(self, Aref: float):
376
+ self.CsCd
377
+ pass # 5.5
378
+
379
+ def Fw_i(self, Aref: float):
380
+ pass # 5.6
381
+
382
+ def Ffr(self, Afr: float, Cfr: str = CFR):
383
+ """Retourne les forces de frottement sur le bâtiment en N selon l'EN 1991-1-4 §5.7/7.5.
384
+
385
+ Args:
386
+ Afr (float): aire de référence en m² correspondant à la surface d'application des forces de frottement.
387
+ Il convient d'appliquer les forces de frottement sur la partie des surfaces extérieures
388
+ parallèle au vent, située au-delà d'une certaine distance des bords au vent ou des angles
389
+ au vent de la toiture, distance égale à la plus petite valeur de 2 · b ou 4 · h .
390
+
391
+ Cfr (str): type de surface de frottement
392
+ - Lisse / exemple: acier, béton lisse
393
+ - Rugueuse / exemple: béton brut, bardeaux bitumés(shingles)
394
+ - Très rugueuse / exemple: ondulation, nervures, pliures
395
+
396
+ Returns:
397
+ float: effort en N
398
+ """
399
+ A_fr = Afr * si.m**2
400
+ C_fr = self.CFR[Cfr]
401
+ Q_p_z = self.Qp_z[1]
402
+
403
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
404
+ def val():
405
+ F_fr = C_fr * Q_p_z * A_fr
406
+ return F_fr
407
+
408
+ return val()
409
+
410
+ def show_Ffr(self):
411
+ """Affiche l'image du zonage pour un effet d'entrainement en toiture"""
412
+ file = os.path.join(Vent.PATH_CATALOG, "data", "vent", "vent_Ffr.png")
413
+ image = Image.open(file)
414
+ image.show()
415
+
416
+ def K_red_U(self):
417
+ """Retourne le coefficient de défaut de corrélation entre les pressions aérodynamiques au vent et sous le vent,
418
+ uniquement pour les faces D et E. §7.2.2(3)
419
+
420
+ Args:
421
+ h_bat (float): hauteur du bâtiment en m
422
+ d_bat (float): longeur parallèle à la direction du vent en m
423
+ """
424
+ if self.h_bat / self.d_bat >= 5:
425
+ self.Kred_U = 1
426
+ elif self.h_bat / self.d_bat <= 1:
427
+ self.Kred_U = 0.85
428
+ else:
429
+ self.Kred_U = 0.85 + 0.15 * (((self.h_bat / self.d_bat) - 1) / 4)
430
+
431
+
432
+ class Murs_verticaux(Vent):
433
+ def __init__(self, load_area: float, *args, **kwargs):
434
+ """Créer une classe permettant le calcul des voiles verticaux au vent selon l'EN 1991-1-4 §7.2.2
435
+
436
+ Args:
437
+ load_area (float): aire chargée pour le calcul des éléments ou des fixations
438
+ """
439
+ super().__init__(*args, **kwargs)
440
+ self.load_area = load_area
441
+ self._wind_direction = {"0°": {}, "90°": {}}
442
+
443
+ for cle in self._wind_direction.keys():
444
+ match cle:
445
+ case "0°":
446
+ self.e = min(self.b_bat, self.h_bat * 2)
447
+ case "90°":
448
+ self.e = min(self.d_bat, self.h_bat * 2)
449
+ d_bat = copy(self.d_bat)
450
+ b_bat = copy(self.b_bat)
451
+ self.b_bat = d_bat
452
+ self.d_bat = b_bat
453
+
454
+ self._wind_direction[cle]["geometrie"] = self._geo()
455
+ self._wind_direction[cle]["Cpe"] = self._Cpe(cle)
456
+
457
+ def _geo(self):
458
+ """Calcul les dimensions du zonage des parois verticale"""
459
+ self._df = self._data_from_csv(
460
+ os.path.join("vent", "vent_Cpe_mur_verticaux.csv")
461
+ )
462
+ self._df.reset_index(drop=False, inplace=True)
463
+
464
+ if self.e < self.d_bat:
465
+ geometrie = {"A": self.e / 5, "B": 0.8 * self.e, "C": self.d_bat - self.e}
466
+
467
+ elif self.e >= 5 * self.d_bat:
468
+ geometrie = {"A": self.d_bat}
469
+ else:
470
+ geometrie = {"A": self.e / 5, "B": self.d_bat - self.e / 5}
471
+ geometrie["D"] = self.b_bat
472
+ geometrie["E"] = self.b_bat
473
+
474
+ return geometrie
475
+
476
+ def _Cpe(self, cle: str):
477
+ """Calcul les Cpe des parois verticales
478
+
479
+ Args:
480
+ cle (str): sens du vent sur le bâtiment 0° ou 90°
481
+ """
482
+ h_d = self.h_bat / self.d_bat
483
+ list_CPE_line = []
484
+ borne_inf = None
485
+ if h_d > 0.25 and h_d < 1:
486
+ df_index = [3, 4]
487
+ borne_inf = 0.25
488
+ borne_sup = 1
489
+
490
+ elif h_d > 1 and h_d < 5:
491
+ df_index = [2, 3]
492
+ borne_inf = 1
493
+ borne_sup = 5
494
+
495
+ elif h_d <= 0.25:
496
+ self._df = self._df[["Zone", "Cpe", "0.25"]]
497
+
498
+ elif h_d >= 5:
499
+ self._df = self._df[["Zone", "Cpe", "5"]]
500
+
501
+ else:
502
+ self._df = self._df[["Zone", "Cpe", "1"]]
503
+
504
+ if borne_inf:
505
+ for i in range(self._df.shape[0]):
506
+ list_CPE_line.append(
507
+ interpolation_lineaire(
508
+ h_d,
509
+ borne_inf,
510
+ borne_sup,
511
+ self._df.iloc[i, df_index[1]],
512
+ self._df.iloc[i, df_index[0]],
513
+ )
514
+ )
515
+ self._df[round(h_d, 3)] = list_CPE_line
516
+ self._df = self._df[["Zone", "Cpe", round(h_d, 3)]]
517
+
518
+ if self.load_area > 1 and self.load_area < 10:
519
+ for i in range(self._df.shape[0]):
520
+ if i % 2 == 0:
521
+ self._df.loc[self._df.shape[0]] = [
522
+ self._df.iloc[i, 0],
523
+ "CPE " + str(round(self.load_area, 2)),
524
+ interpolation_logarithmique(
525
+ self.load_area,
526
+ 1,
527
+ 10,
528
+ self._df.iloc[i + 1, 2],
529
+ self._df.iloc[i, 2],
530
+ ),
531
+ ]
532
+
533
+ self._df.set_index("Zone", inplace=True)
534
+ self._df = self._df.loc[
535
+ [zone for zone in self._wind_direction[cle]["geometrie"].keys()]
536
+ ]
537
+ return self._df
538
+
539
+ def get_wind_dict(self) -> dict:
540
+ return self._wind_direction
541
+
542
+ def get_geo(self, dir=("0°", "90°")):
543
+ """Retourne les caractéristiques géométrique pour la direction de vent donnée.
544
+
545
+ Args:
546
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
547
+ """
548
+ return self._wind_direction[dir]["geometrie"]
549
+
550
+ def get_Cpe(self, dir=("0°", "90°")):
551
+ """Retourne les Cpe pour la direction de vent donnée.
552
+
553
+ Args:
554
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
555
+ """
556
+ return self._wind_direction[dir]["Cpe"]
557
+
558
+ def show_zonage(self):
559
+ """Affiche l'image du zonage pour les murs verticaux"""
560
+ file = os.path.join(
561
+ Vent.PATH_CATALOG, "data", "vent", "vent_Cpe_mur_verticaux.png"
562
+ )
563
+ image = Image.open(file)
564
+ image.show()
565
+
566
+ class Toiture_terrasse_acrotere(Vent):
567
+ def __init__(self, load_area:float, hp:si.m, h:si.m, *args, **kwargs):
568
+ """Créer une classe permetant le calcul d'une toiture terrasse au vent selon l'EN 1991-1-4 §7.2.3
569
+
570
+ Args:
571
+ load_area (float): aire chargée pour le calcul des éléments ou des fixations.
572
+ hp (si.m): hauteur de l'acrotère
573
+ h (si.m): hauteur sous l'acrotère
574
+ """
575
+ super().__init__(*args, **kwargs)
576
+ self.type_terrasse = "Acrotères"
577
+ self.load_area = load_area
578
+ self.hp = hp * si.m
579
+ self.h = h * si.m
580
+ self._hp_h = self.hp/self.h
581
+ self._wind_direction = {"0°": {}}
582
+
583
+ self.e = min(self.b_bat, self.h_bat * 2)
584
+
585
+ self._wind_direction["0°"]["geometrie"] = self._geo()
586
+ self._wind_direction["0°"]["Cpe"] = self._Cpe()
587
+
588
+ def _geo(self):
589
+ """Calcul les surfaces du zonage de la toiture
590
+ """
591
+ geometrie = {
592
+ "F": {
593
+ "Longueur": self.e / 4,
594
+ "Largeur": self.e / 10,
595
+ "Surface": (self.e / 4) * (self.e / 10) / mt.cos(mt.radians(self.alpha_toit)),
596
+ },
597
+ "G": {
598
+ "Longueur": self.b_bat - (self.e / 4 * 2),
599
+ "Largeur": self.e / 10,
600
+ "Surface": (self.b_bat - (self.e / 4 * 2)) * (self.e / 10) / mt.cos(mt.radians(self.alpha_toit)),
601
+ },
602
+ "H": {
603
+ "Longueur": self.b_bat,
604
+ "Largeur": self.e / 2 - self.e / 10,
605
+ "Surface": self.b_bat * (self.e / 2 - self.e / 10) / mt.cos(mt.radians(self.alpha_toit)),
606
+ },
607
+ "I": {
608
+ "Longueur": self.b_bat,
609
+ "Largeur": self.d_bat - self.e / 2,
610
+ "Surface": self.b_bat * (self.d_bat - self.e / 2) / mt.cos(mt.radians(self.alpha_toit)),
611
+ },
612
+ }
613
+ return geometrie
614
+
615
+ def _Cpe(self):
616
+ """Calcul les Cpe d'une toiture terrasse avec acrotère
617
+
618
+ Args:
619
+ direction (str): sens du vent sur le bâtiment 0° ou 90°
620
+ """
621
+ num_columns = 7
622
+ df = self._data_from_csv(
623
+ os.path.join("vent", "vent_Cpe_toiture_terrasse.csv")
624
+ )
625
+ name_csv_type = self.type_terrasse.replace("è", "e")
626
+ df = df.loc[name_csv_type]
627
+ df.reset_index(drop=False, inplace=True)
628
+ df.drop("Type", axis=1, inplace=True)
629
+ list_type_rapport = df["Rapport"].unique()
630
+
631
+ if self._hp_h > 0.1:
632
+ self._hp_h = 0.1
633
+ elif not self._hp_h in list_type_rapport:
634
+ minimum = list_type_rapport[list_type_rapport < self._hp_h].max()
635
+ maximum = list_type_rapport[list_type_rapport > self._hp_h].min()
636
+ df_min = df[df["Rapport"] == minimum]
637
+ df_max = df[df["Rapport"] == maximum]
638
+
639
+ df = df[df["Rapport"].isin([minimum, maximum])]
640
+ df.reset_index(drop=True, inplace=True)
641
+
642
+ df.reset_index(drop=True, inplace=True)
643
+ for i, cpe in enumerate(["CPE 10", "CPE 1"]):
644
+ row = [round(self._hp_h, 3), cpe]
645
+ for j in range(2, num_columns):
646
+ row.append(
647
+ interpolation_lineaire(
648
+ self._hp_h,
649
+ minimum,
650
+ maximum,
651
+ df_min.iloc[i, j],
652
+ df_max.iloc[i, j],
653
+ )
654
+ )
655
+ df.loc[df.shape[0]] = row
656
+
657
+ if self.load_area > 1 and self.load_area < 10:
658
+ for i in range(df.shape[0]):
659
+ if i % 2 == 0:
660
+ row = [df.iloc[i, 0], "CPE " + str(round(self.load_area, 2))]
661
+ for j in range(2, num_columns):
662
+ row.append(
663
+ interpolation_logarithmique(
664
+ self.load_area, 1, 10, df.iloc[i + 1, j], df.iloc[i, j]
665
+ )
666
+ )
667
+ print(row)
668
+ df.loc[df.shape[0]] = row
669
+ df.reset_index(drop=True, inplace=True)
670
+
671
+ df = df[df["Rapport"] == round(self._hp_h, 3)]
672
+ df.dropna(axis=1, how="all", inplace=True)
673
+ df.set_index("Rapport", inplace=True)
674
+ return df
675
+
676
+ def get_wind_dict(self) -> dict:
677
+ return self._wind_direction
678
+
679
+ def get_geo(self):
680
+ """Retourne les caractéristiques géométrique pour la direction de vent donnée.
681
+
682
+ Args:
683
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°", "180°").
684
+ """
685
+ return self._wind_direction["0°"]["geometrie"]
686
+
687
+ def get_Cpe(self):
688
+ """Retourne les Cpe pour la direction de vent donnée.
689
+
690
+ Args:
691
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°", "180°").
692
+ """
693
+ return self._wind_direction["0°"]["Cpe"]
694
+
695
+ def show_zonage(self):
696
+ """Affiche l'image du zonage pour une toiture à 1 versant"""
697
+ file = os.path.join(
698
+ Vent.PATH_CATALOG, "data", "vent", "vent_Cpe_toiture_terrasse.png"
699
+ )
700
+ image = Image.open(file)
701
+ image.show()
702
+
703
+
704
+ class Toiture_1_pant(Vent):
705
+ def __init__(self, load_area: float, *args, **kwargs):
706
+ """Créer une classe permetant le calcul d'une toiture à deux versant symétrique au vent selon l'EN 1991-1-4 §7.2.5
707
+ ATTENTION cette classe ne prend en compte que le premier alpha_toit,
708
+ les pentes doivent être les mêmes entre les deux pants et le faîtage centré.
709
+
710
+ Args:
711
+ load_area (int | float): aire chargée pour le calcul des éléments ou des fixations.
712
+ """
713
+ super().__init__(*args, **kwargs)
714
+ self.load_area = load_area
715
+ self._wind_direction = {"0°": {}, "180°": {}, "90°": {}}
716
+
717
+ for cle in self._wind_direction.keys():
718
+ match cle:
719
+ case "0°" | "180°":
720
+ self.e = min(self.b_bat, self.h_bat * 2)
721
+
722
+ case "90°":
723
+ self.e = min(self.d_bat, self.h_bat * 2)
724
+ d_bat = copy(self.d_bat)
725
+ b_bat = copy(self.b_bat)
726
+ self.b_bat = d_bat
727
+ self.d_bat = b_bat
728
+
729
+ self._wind_direction[cle]["geometrie"] = self._geo(cle)
730
+ self._wind_direction[cle]["Cpe"] = self._Cpe(cle)
731
+
732
+ def _geo(self, direction: str):
733
+ """Calcul les surfaces du zonage de la toiture
734
+ Attention on considère le faîtage centrée et les pentes égales entre les deux pants
735
+ """
736
+ match direction:
737
+ case "0°" | "180°":
738
+ geometrie = {
739
+ "F": {
740
+ "Longueur": self.e / 4,
741
+ "Largeur": self.e / 10,
742
+ "Surface": (self.e / 4)
743
+ * (self.e / 10)
744
+ / mt.cos(mt.radians(self.alpha_toit)),
745
+ },
746
+ "G": {
747
+ "Longueur": self.b_bat - (self.e / 4 * 2),
748
+ "Largeur": self.e / 10,
749
+ "Surface": (self.b_bat - (self.e / 4 * 2))
750
+ * (self.e / 10)
751
+ / mt.cos(mt.radians(self.alpha_toit)),
752
+ },
753
+ "H": {
754
+ "Longueur": self.b_bat,
755
+ "Largeur": self.d_bat - self.e / 10,
756
+ "Surface": self.b_bat
757
+ * (self.d_bat - self.e / 10)
758
+ / mt.cos(mt.radians(self.alpha_toit)),
759
+ },
760
+ }
761
+ case "90°":
762
+ geometrie = {
763
+ "F_up / F_low": {
764
+ "Longueur": self.e / 4,
765
+ "Largeur": self.e / 10,
766
+ "Surface": (self.e / 10)
767
+ * (self.e / 4)
768
+ / mt.cos(mt.radians(self.alpha_toit)),
769
+ },
770
+ "G": {
771
+ "Longueur": self.b_bat - (self.e / 4 * 2) / 2,
772
+ "Largeur": self.e / 10,
773
+ "Surface": (self.e / 10)
774
+ * (self.b_bat - (self.e / 4 * 2) / 2)
775
+ / mt.cos(mt.radians(self.alpha_toit)),
776
+ },
777
+ "H": {
778
+ "Longueur": self.b_bat / 2,
779
+ "Largeur": self.e / 2 - self.e / 10,
780
+ "Surface": (self.e / 2 - self.e / 10)
781
+ * (self.b_bat / 2)
782
+ / mt.cos(mt.radians(self.alpha_toit)),
783
+ },
784
+ "I": {
785
+ "Longueur": self.b_bat,
786
+ "Largeur": self.d_bat - self.e / 2,
787
+ "Surface": (self.d_bat - self.e / 2)
788
+ * self.b_bat
789
+ / mt.cos(mt.radians(self.alpha_toit)),
790
+ },
791
+ }
792
+ return geometrie
793
+
794
+ def _Cpe(self, direction: str):
795
+ """Calcul les Cpe d'une toiture 2 versants
796
+
797
+ Args:
798
+ direction (str): sens du vent sur le bâtiment 0° ou 90°
799
+ """
800
+ match direction:
801
+ case "0°":
802
+ num_columns = 8
803
+ df = self._data_from_csv(
804
+ os.path.join("vent", "vent_Cpe_toiture_1_versant_0_degres.csv")
805
+ )
806
+ case "90°":
807
+ num_columns = 7
808
+ df = self._data_from_csv(
809
+ os.path.join("vent", "vent_Cpe_toiture_1_versant_90_degres.csv")
810
+ )
811
+ case "180°":
812
+ num_columns = 5
813
+ df = self._data_from_csv(
814
+ os.path.join("vent", "vent_Cpe_toiture_1_versant_180_degres.csv")
815
+ )
816
+
817
+ df.reset_index(drop=False, inplace=True)
818
+ list_alpha_toit = df["alpha_toit"].unique()
819
+ if not self.alpha_toit in list_alpha_toit:
820
+ minimum = list_alpha_toit[list_alpha_toit < self.alpha_toit].max()
821
+ maximum = list_alpha_toit[list_alpha_toit > self.alpha_toit].min()
822
+ df_min = df[df["alpha_toit"] == minimum]
823
+ df_max = df[df["alpha_toit"] == maximum]
824
+
825
+ df = df[df["alpha_toit"].isin([minimum, maximum])]
826
+ df.reset_index(drop=True, inplace=True)
827
+
828
+ df.reset_index(drop=True, inplace=True)
829
+ for i, cpe in enumerate(["CPE 10", "CPE 1"]):
830
+ row = [round(self.alpha_toit, 2), cpe]
831
+ for j in range(2, num_columns):
832
+ row.append(
833
+ interpolation_lineaire(
834
+ self.alpha_toit,
835
+ minimum,
836
+ maximum,
837
+ df_min.iloc[i, j],
838
+ df_max.iloc[i, j],
839
+ )
840
+ )
841
+ df.loc[df.shape[0]] = row
842
+
843
+ if self.load_area > 1 and self.load_area < 10:
844
+ for i in range(df.shape[0]):
845
+ if i % 2 == 0:
846
+ row = [df.iloc[i, 0], "CPE " + str(round(self.load_area, 2))]
847
+ for j in range(2, num_columns):
848
+ row.append(
849
+ interpolation_logarithmique(
850
+ self.load_area, 1, 10, df.iloc[i + 1, j], df.iloc[i, j]
851
+ )
852
+ )
853
+ df.loc[df.shape[0]] = row
854
+ df.reset_index(drop=True, inplace=True)
855
+
856
+ df = df[df["alpha_toit"] == round(self.alpha_toit, 2)]
857
+ df.dropna(axis=1, how="all", inplace=True)
858
+ df.set_index("alpha_toit", inplace=True)
859
+ return df
860
+
861
+ def get_wind_dict(self) -> dict:
862
+ return self._wind_direction
863
+
864
+ def get_geo(self, direction=("0°", "90°", "180°")):
865
+ """Retourne les caractéristiques géométrique pour la direction de vent donnée.
866
+
867
+ Args:
868
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°", "180°").
869
+ """
870
+ return self._wind_direction[direction]["geometrie"]
871
+
872
+ def get_Cpe(self, direction=("0°", "90°", "180°")):
873
+ """Retourne les Cpe pour la direction de vent donnée.
874
+
875
+ Args:
876
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°", "180°").
877
+ """
878
+ return self._wind_direction[direction]["Cpe"]
879
+
880
+ def show_zonage(self):
881
+ """Affiche l'image du zonage pour une toiture à 1 versant"""
882
+ file = os.path.join(
883
+ Vent.PATH_CATALOG, "data", "vent", "vent_Cpe_toiture_1_versant.png"
884
+ )
885
+ image = Image.open(file)
886
+ image.show()
887
+
888
+
889
+ class Toiture_2_pants(Vent):
890
+ def __init__(self, load_area: float, *args, **kwargs):
891
+ """Créer une classe permetant le calcul d'une toiture à deux versant symétrique au vent selon l'EN 1991-1-4 §7.2.5
892
+ ATTENTION cette classe ne prend en compte que le premier alpha_toit,
893
+ les pentes doivent être les mêmes entre les deux pants et le faîtage centré.
894
+
895
+ Args:
896
+ load_area (int | float): aire chargée pour le calcul des éléments ou des fixations.
897
+ """
898
+ super().__init__(*args, **kwargs)
899
+ self.load_area = load_area
900
+ self._wind_direction = {"0°": {}, "90°": {}}
901
+
902
+ for cle in self._wind_direction.keys():
903
+ match cle:
904
+ case "0°":
905
+ self.e = min(self.b_bat, self.h_bat * 2)
906
+
907
+ case "90°":
908
+ self.e = min(self.d_bat, self.h_bat * 2)
909
+ d_bat = copy(self.d_bat)
910
+ b_bat = copy(self.b_bat)
911
+ self.b_bat = d_bat
912
+ self.d_bat = b_bat
913
+
914
+ self._wind_direction[cle]["geometrie"] = self._geo(cle)
915
+ self._wind_direction[cle]["Cpe"] = self._Cpe(cle)
916
+
917
+ def _geo(self, direction: str = "0°"):
918
+ """Calcul les surfaces du zonage de la toiture
919
+ Attention on considère le faîtage centrée et les pentes égales entre les deux pants
920
+ """
921
+ match direction:
922
+ case "0°":
923
+ geometrie = {
924
+ "F": {
925
+ "Longueur": self.e / 4,
926
+ "Largeur": self.e / 10,
927
+ "Surface": (self.e / 4)
928
+ * (self.e / 10)
929
+ / mt.cos(mt.radians(self.alpha_toit)),
930
+ },
931
+ "G": {
932
+ "Longueur": self.b_bat - (self.e / 4 * 2),
933
+ "Largeur": self.e / 10,
934
+ "Surface": (self.b_bat - (self.e / 4 * 2))
935
+ * (self.e / 10)
936
+ / mt.cos(mt.radians(self.alpha_toit)),
937
+ },
938
+ "H": {
939
+ "Longueur": self.b_bat,
940
+ "Largeur": self.d_bat / 2 - self.e / 10,
941
+ "Surface": self.b_bat
942
+ * (self.d_bat / 2 - self.e / 10)
943
+ / mt.cos(mt.radians(self.alpha_toit)),
944
+ },
945
+ "I": {
946
+ "Longueur": self.b_bat,
947
+ "Largeur": self.d_bat / 2 - self.e / 10,
948
+ "Surface": self.b_bat
949
+ * (self.d_bat / 2 - self.e / 10)
950
+ / mt.cos(mt.radians(self.alpha_toit)),
951
+ },
952
+ "J": {
953
+ "Longueur": self.b_bat,
954
+ "Largeur": self.e / 10,
955
+ "Surface": self.b_bat
956
+ * (self.e / 10)
957
+ / mt.cos(mt.radians(self.alpha_toit)),
958
+ },
959
+ }
960
+ case "90°":
961
+ geometrie = {
962
+ "F": {
963
+ "Longueur": self.e / 4,
964
+ "Largeur": self.e / 10,
965
+ "Surface": (self.e / 10)
966
+ * (self.e / 4)
967
+ / mt.cos(mt.radians(self.alpha_toit)),
968
+ },
969
+ "G": {
970
+ "Longueur": (self.b_bat - (self.e / 4 * 2)) / 2,
971
+ "Largeur": self.e / 10,
972
+ "Surface": (self.e / 10)
973
+ * (self.b_bat - (self.e / 4 * 2) / 2)
974
+ / mt.cos(mt.radians(self.alpha_toit)),
975
+ },
976
+ "H": {
977
+ "Longueur": self.b_bat / 2,
978
+ "Largeur": self.e / 2 - self.e / 10,
979
+ "Surface": (self.e / 2 - self.e / 10)
980
+ * (self.b_bat / 2)
981
+ / mt.cos(mt.radians(self.alpha_toit)),
982
+ },
983
+ "I": {
984
+ "Longueur": self.b_bat / 2,
985
+ "Largeur": self.d_bat - self.e / 2,
986
+ "Surface": (self.d_bat - self.e / 2)
987
+ * (self.b_bat / 2)
988
+ / mt.cos(mt.radians(self.alpha_toit)),
989
+ },
990
+ }
991
+ return geometrie
992
+
993
+ def _Cpe(self, direction: str):
994
+ """Calcul les Cpe d'une toiture 2 versants
995
+
996
+ Args:
997
+ direction (str): sens du vent sur le bâtiment 0° ou 90°
998
+ """
999
+ match direction:
1000
+ case "0°":
1001
+ num_columns = 12
1002
+ df = self._data_from_csv(
1003
+ os.path.join("vent", "vent_Cpe_toiture_2_versants_0_degres.csv")
1004
+ )
1005
+ case "90°":
1006
+ num_columns = 6
1007
+ df = self._data_from_csv(
1008
+ os.path.join("vent", "vent_Cpe_toiture_2_versants_90_degres.csv")
1009
+ )
1010
+
1011
+ df.reset_index(drop=False, inplace=True)
1012
+ list_alpha_toit = df["alpha_toit"].unique()
1013
+ if not self.alpha_toit in list_alpha_toit:
1014
+ minimum = list_alpha_toit[list_alpha_toit < self.alpha_toit].max()
1015
+ maximum = list_alpha_toit[list_alpha_toit > self.alpha_toit].min()
1016
+ df_min = df[df["alpha_toit"] == minimum]
1017
+ df_max = df[df["alpha_toit"] == maximum]
1018
+
1019
+ df = df[df["alpha_toit"].isin([minimum, maximum])]
1020
+ df.reset_index(drop=True, inplace=True)
1021
+
1022
+ df.reset_index(drop=True, inplace=True)
1023
+ for i, cpe in enumerate(["CPE 10", "CPE 1"]):
1024
+ row = [round(self.alpha_toit, 2), cpe]
1025
+ for j in range(2, num_columns):
1026
+ row.append(
1027
+ interpolation_lineaire(
1028
+ self.alpha_toit,
1029
+ minimum,
1030
+ maximum,
1031
+ df_min.iloc[i, j],
1032
+ df_max.iloc[i, j],
1033
+ )
1034
+ )
1035
+ print(row)
1036
+ df.loc[df.shape[0]] = row
1037
+
1038
+ if self.load_area > 1 and self.load_area < 10:
1039
+ for i in range(df.shape[0]):
1040
+ if i % 2 == 0:
1041
+ row = [df.iloc[i, 0], "CPE " + str(round(self.load_area, 2))]
1042
+ for j in range(2, num_columns):
1043
+ row.append(
1044
+ interpolation_logarithmique(
1045
+ self.load_area, 1, 10, df.iloc[i + 1, j], df.iloc[i, j]
1046
+ )
1047
+ )
1048
+ df.loc[df.shape[0]] = row
1049
+ df.reset_index(drop=True, inplace=True)
1050
+
1051
+ df = df[df["alpha_toit"] == round(self.alpha_toit, 2)]
1052
+ df.dropna(axis=1, how="all", inplace=True)
1053
+ df.set_index("alpha_toit", inplace=True)
1054
+ return df
1055
+
1056
+ def get_wind_dict(self) -> dict:
1057
+ return self._wind_direction
1058
+
1059
+ def get_geo(self, dir=("0°", "90°")):
1060
+ """Retourne les caractéristiques géométrique pour la direction de vent donnée.
1061
+
1062
+ Args:
1063
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
1064
+ """
1065
+ return self._wind_direction[dir]["geometrie"]
1066
+
1067
+ def get_Cpe(self, dir=("0°", "90°")):
1068
+ """Retourne les Cpe pour la direction de vent donnée.
1069
+
1070
+ Args:
1071
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
1072
+ """
1073
+ return self._wind_direction[dir]["Cpe"]
1074
+
1075
+ def show_zonage(self):
1076
+ """Affiche l'image du zonage pour une toiture à 2 versants"""
1077
+ file = os.path.join(
1078
+ Vent.PATH_CATALOG, "data", "vent", "vent_Cpe_toiture_2_versants.png"
1079
+ )
1080
+ image = Image.open(file)
1081
+ image.show()
1082
+
1083
+
1084
+ class Toiture_isolee_1_pant(Vent):
1085
+ def __init__(self, phi: float, load_area: float, *args, **kwargs):
1086
+ """Créer une classe permetant le calcul d'une toiture isolée à un versant au vent selon l'EN 1991-1-4 §7.3
1087
+
1088
+ Args:
1089
+ phi (int | float): le degré d'obstruction sous une toiture isolée entre 0 et 1.
1090
+ load_area (int | float): aire chargée pour le calcul des éléments ou des fixations.
1091
+ """
1092
+ super().__init__(*args, **kwargs)
1093
+ self.phi = phi
1094
+ self.load_area = load_area
1095
+ self._wind_direction = {"0°": {}, "90°": {}}
1096
+
1097
+ for cle in self._wind_direction.keys():
1098
+ match cle:
1099
+ case "90°":
1100
+ d_bat = copy(self.d_bat)
1101
+ b_bat = copy(self.b_bat)
1102
+ self.b_bat = d_bat
1103
+ self.d_bat = b_bat
1104
+
1105
+ self._wind_direction[cle]["geometrie"] = self._geo()
1106
+ self._wind_direction[cle]["Cp"] = self._Cp()
1107
+
1108
+ def _geo(self):
1109
+ """Calcul les surfaces du zonage de la toiture"""
1110
+ self._df = self._data_from_csv(
1111
+ os.path.join("vent", "vent_Cp_toiture_isolee_1_versant.csv")
1112
+ )
1113
+ self._df.reset_index(drop=False, inplace=True)
1114
+
1115
+ geometrie = {
1116
+ "A": {
1117
+ "Longueur": self.b_bat - self.b_bat / 10 * 2,
1118
+ "Largeur": self.d_bat - self.d_bat / 10 * 2,
1119
+ "Surface": (self.d_bat - self.d_bat / 10 * 2)
1120
+ * (self.b_bat - self.b_bat / 10 * 2)
1121
+ / mt.cos(mt.radians(self.alpha_toit)),
1122
+ },
1123
+ "B": {
1124
+ "Longueur": self.d_bat - self.d_bat / 10 * 2,
1125
+ "Largeur": self.b_bat / 10,
1126
+ "Surface": ((self.d_bat - self.d_bat / 10 * 2) * self.b_bat / 10)
1127
+ / mt.cos(mt.radians(self.alpha_toit)),
1128
+ },
1129
+ "C": {
1130
+ "Longueur": self.b_bat - self.b_bat / 10 * 2,
1131
+ "Largeur": self.d_bat / 10,
1132
+ "Surface": ((self.b_bat - self.b_bat / 10 * 2) * self.d_bat / 10)
1133
+ / mt.cos(mt.radians(self.alpha_toit)),
1134
+ },
1135
+ }
1136
+ return geometrie
1137
+
1138
+ def _Cp(self):
1139
+ """Calcul les Cp d'une toiture isolée
1140
+
1141
+ Args:
1142
+ cle (str): sens du vent sur le bâtiment 0° ou 90°
1143
+ """
1144
+
1145
+ if self.phi > 0 and self.phi < 1:
1146
+ for i in range(0, self._df.shape[0], 3):
1147
+ row = [self._df.iloc[i, 0], self.phi]
1148
+ for j in range(2, 6):
1149
+ row.append(
1150
+ interpolation_lineaire(
1151
+ self.phi,
1152
+ 0,
1153
+ 1,
1154
+ self._df.iloc[i + 1, j],
1155
+ self._df.iloc[i + 2, j],
1156
+ )
1157
+ )
1158
+ self._df.loc[self._df.shape[0]] = row
1159
+ self._df = self._df[self._df["phi"].isin([self.phi, "max"])]
1160
+
1161
+ elif self.phi >= 1:
1162
+ self._df = self._df[self._df["phi"].isin(["1", "max"])]
1163
+ else:
1164
+ self._df = self._df[self._df["phi"].isin(["0", "max"])]
1165
+
1166
+ list_alpha_toit = self._df["alpha_toit"].unique()
1167
+
1168
+ if not self.alpha_toit in list_alpha_toit:
1169
+ minimum = list_alpha_toit[list_alpha_toit < self.alpha_toit].max()
1170
+ maximum = list_alpha_toit[list_alpha_toit > self.alpha_toit].min()
1171
+ df_min = self._df[self._df["alpha_toit"] == minimum]
1172
+ df_max = self._df[self._df["alpha_toit"] == maximum]
1173
+
1174
+ self._df.reset_index(drop=True, inplace=True)
1175
+ for i, phi in enumerate(["max", self.phi]):
1176
+ row = [round(self.alpha_toit, 2), phi]
1177
+ for j in range(2, 6):
1178
+ row.append(
1179
+ interpolation_lineaire(
1180
+ self.alpha_toit,
1181
+ minimum,
1182
+ maximum,
1183
+ df_min.iloc[i, j],
1184
+ df_max.iloc[i, j],
1185
+ )
1186
+ )
1187
+ self._df.loc[self._df.shape[0]] = row
1188
+ self._df = self._df[self._df["phi"].isin([self.phi, "max"])]
1189
+
1190
+ self._df = self._df[self._df["alpha_toit"] == round(self.alpha_toit, 2)]
1191
+ self._df.set_index("alpha_toit", inplace=True)
1192
+ return self._df
1193
+
1194
+ def get_wind_dict(self) -> dict:
1195
+ return self._wind_direction
1196
+
1197
+ def get_geo(self, dir=("0°", "90°")):
1198
+ """Retourne les caractéristiques géométrique pour la direction de vent donnée.
1199
+
1200
+ Args:
1201
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
1202
+ """
1203
+ return self._wind_direction[dir]["geometrie"]
1204
+
1205
+ def get_Cp(self, dir=("0°", "90°")):
1206
+ """Retourne les Cp pour la direction de vent donnée.
1207
+
1208
+ Args:
1209
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
1210
+ """
1211
+ return self._wind_direction[dir]["Cp"]
1212
+
1213
+ def show_zonage(self):
1214
+ """Affiche l'image du zonage pour une toiture isolée un versant"""
1215
+ file = os.path.join(
1216
+ Vent.PATH_CATALOG, "data", "vent", "vent_Cp_toiture_isolee_1_versant.png"
1217
+ )
1218
+ image = Image.open(file)
1219
+ image.show()
1220
+
1221
+
1222
+ class Toiture_isolee_2_pants(Vent):
1223
+ def __init__(self, phi: float, load_area: float, *args, **kwargs):
1224
+ """Créer une classe permetant le calcul d_bat'une toiture isolée à deux versants au vent selon l'EN 1991-1-4 §7.3
1225
+ ATTENTION : Il ne semble pas y avoir d'inversion de zonage quand le vent est à 0° ou 90° mais une inversion des longueurs de surface A VALIDER !
1226
+
1227
+ Args:
1228
+ phi (int | float): le degré d'obstruction sous une toiture isolée entre 0 et 1.
1229
+ load_area (int | float): aire chargée pour le calcul des éléments ou des fixations.
1230
+ """
1231
+ super().__init__(*args, **kwargs)
1232
+ self.phi = phi
1233
+ self.load_area = load_area
1234
+ self._wind_direction = {"0°": {}, "90°": {}}
1235
+
1236
+ for cle in self._wind_direction.keys():
1237
+ match cle:
1238
+ case "90°":
1239
+ d_bat = copy(self.d_bat)
1240
+ b_bat = copy(self.b_bat)
1241
+ self.b_bat = d_bat
1242
+ self.d_bat = b_bat
1243
+
1244
+ self._wind_direction[cle]["geometrie"] = self._geo()
1245
+ self._wind_direction[cle]["Cp"] = self._Cp()
1246
+
1247
+ def _geo(self):
1248
+ """Calcul les surfaces du zonage de la toiture"""
1249
+ self._df = self._data_from_csv(
1250
+ os.path.join("vent", "vent_Cp_toiture_isolee_2_versants.csv")
1251
+ )
1252
+ self._df.reset_index(drop=False, inplace=True)
1253
+
1254
+ geometrie = {
1255
+ "A": {
1256
+ "Longueur": self.d_bat - self.d_bat / 10 * 2,
1257
+ "Largeur": self.d_bat - (2 * self.d_bat / 10) - self.d_bat / 5,
1258
+ "Surface": (
1259
+ (self.d_bat - self.d_bat / 10 * 2)
1260
+ * (self.d_bat - (2 * self.d_bat / 10) - self.d_bat / 5)
1261
+ )
1262
+ / mt.cos(mt.radians(self.alpha_toit)),
1263
+ },
1264
+ "B": {
1265
+ "Longueur": self.d_bat - self.d_bat / 10 * 2,
1266
+ "Largeur": self.b_bat / 10,
1267
+ "Surface": ((self.d_bat - self.d_bat / 10 * 2) * self.b_bat / 10)
1268
+ / mt.cos(mt.radians(self.alpha_toit)),
1269
+ },
1270
+ "C": {
1271
+ "Longueur": self.b_bat - self.b_bat / 10 * 2,
1272
+ "Largeur": self.d_bat / 10,
1273
+ "Surface": ((self.b_bat - self.b_bat / 10 * 2) * self.d_bat / 10)
1274
+ / mt.cos(mt.radians(self.alpha_toit)),
1275
+ },
1276
+ "D": {
1277
+ "Longueur": (self.b_bat - self.b_bat / 10 * 2) / 2,
1278
+ "Largeur": (self.d_bat / 5) / 2,
1279
+ "Surface": (
1280
+ ((self.b_bat - self.b_bat / 10 * 2) * self.d_bat / 5)
1281
+ / mt.cos(mt.radians(self.alpha_toit))
1282
+ / 2
1283
+ ),
1284
+ },
1285
+ }
1286
+ return geometrie
1287
+
1288
+ def _Cp(self):
1289
+ """Calcul les Cp d'une toiture isolée
1290
+
1291
+ Args:
1292
+ cle (str): sens du vent sur le bâtiment 0° ou 90°
1293
+ """
1294
+ if self.phi > 0 and self.phi < 1:
1295
+ for i in range(0, self._df.shape[0], 3):
1296
+ row = [self._df.iloc[i, 0], self.phi]
1297
+ for j in range(2, 7):
1298
+ row.append(
1299
+ interpolation_lineaire(
1300
+ self.phi,
1301
+ 0,
1302
+ 1,
1303
+ self._df.iloc[i + 1, j],
1304
+ self._df.iloc[i + 2, j],
1305
+ )
1306
+ )
1307
+ self._df.loc[self._df.shape[0]] = row
1308
+ self._df = self._df[self._df["phi"].isin([self.phi, "max"])]
1309
+
1310
+ elif self.phi >= 1:
1311
+ self._df = self._df[self._df["phi"].isin(["1", "max"])]
1312
+ else:
1313
+ self._df = self._df[self._df["phi"].isin(["0", "max"])]
1314
+
1315
+ list_alpha_toit = self._df["alpha_toit"].unique()
1316
+
1317
+ if not self.alpha_toit in list_alpha_toit:
1318
+ minimum = list_alpha_toit[list_alpha_toit < self.alpha_toit].max()
1319
+ maximum = list_alpha_toit[list_alpha_toit > self.alpha_toit].min()
1320
+ df_min = self._df[self._df["alpha_toit"] == minimum]
1321
+ df_max = self._df[self._df["alpha_toit"] == maximum]
1322
+
1323
+ self._df.reset_index(drop=True, inplace=True)
1324
+ for i, phi in enumerate(["max", self.phi]):
1325
+ row = [round(self.alpha_toit, 2), phi]
1326
+ for j in range(2, 7):
1327
+ row.append(
1328
+ interpolation_lineaire(
1329
+ self.alpha_toit,
1330
+ minimum,
1331
+ maximum,
1332
+ df_min.iloc[i, j],
1333
+ df_max.iloc[i, j],
1334
+ )
1335
+ )
1336
+ self._df.loc[self._df.shape[0]] = row
1337
+ self._df = self._df[self._df["phi"].isin([self.phi, "max"])]
1338
+
1339
+ self._df = self._df[self._df["alpha_toit"] == round(self.alpha_toit, 2)]
1340
+ self._df.set_index("alpha_toit", inplace=True)
1341
+ return self._df
1342
+
1343
+ def get_wind_dict(self) -> dict:
1344
+ return self._wind_direction
1345
+
1346
+ def get_geo(self, dir=("0°", "90°")):
1347
+ """Retourne les caractéristiques géométrique pour la direction de vent donnée.
1348
+
1349
+ Args:
1350
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
1351
+ """
1352
+ return self._wind_direction[dir]["geometrie"]
1353
+
1354
+ def get_Cp(self, dir=("0°", "90°")):
1355
+ """Retourne les Cp pour la direction de vent donnée.
1356
+
1357
+ Args:
1358
+ direction (str): direction du vent vis à vis du bâtiment. Defaults to ("0°", "90°").
1359
+ """
1360
+ return self._wind_direction[dir]["Cp"]
1361
+
1362
+ def show_zonage(self):
1363
+ """Affiche l'image du zonage pour une toiture isolée un versant"""
1364
+ file = os.path.join(
1365
+ Vent.PATH_CATALOG, "data", "vent", "vent_Cp_toiture_isolee_2_versants.png"
1366
+ )
1367
+ image = Image.open(file)
1368
+ image.show()
1369
+
1370
+
1371
+ if __name__ == "__main__":
1372
+ building = Batiment(
1373
+ h_bat=5, d_bat=15, b_bat=13.1, alpha_toit=15, alt=400, code_INSEE=73215
1374
+ )
1375
+ Action_wind = Vent._from_parent_class(building, terrain="IIIa", oro="Aucun", z=5)
1376
+ print(si.environment())
1377
+ print(Action_wind.Vb[1])
1378
+ qpz = Action_wind.Qp_z
1379
+ print(qpz)
1380
+ ffr = Action_wind.Ffr(15, "Lisse")
1381
+ print(ffr)
1382
+ print(Action_wind.rayon_secteur_angu)
1383
+ # Action_wind.show_Ffr()
1384
+ vertical = Toiture_terrasse_acrotere._from_parent_class(
1385
+ Action_wind, load_area=10, hp= 1, h= 10.5
1386
+ )
1387
+ # vertical.show_zonage()
1388
+ print(vertical.get_Cpe())