structuralcodes 0.5.0__py3-none-any.whl → 0.6.1__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 structuralcodes might be problematic. Click here for more details.

Files changed (48) hide show
  1. structuralcodes/__init__.py +1 -1
  2. structuralcodes/codes/ec2_2004/shear.py +3 -2
  3. structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +2 -2
  4. structuralcodes/core/base.py +138 -12
  5. structuralcodes/geometry/__init__.py +2 -8
  6. structuralcodes/geometry/_geometry.py +103 -19
  7. structuralcodes/geometry/_reinforcement.py +1 -3
  8. structuralcodes/geometry/profiles/__init__.py +33 -0
  9. structuralcodes/geometry/profiles/_base_profile.py +305 -0
  10. structuralcodes/geometry/profiles/_common_functions.py +307 -0
  11. structuralcodes/geometry/profiles/_hd.py +374 -0
  12. structuralcodes/geometry/profiles/_he.py +192 -0
  13. structuralcodes/geometry/profiles/_hp.py +319 -0
  14. structuralcodes/geometry/profiles/_ipe.py +130 -0
  15. structuralcodes/geometry/profiles/_ipn.py +329 -0
  16. structuralcodes/geometry/profiles/_l.py +528 -0
  17. structuralcodes/geometry/profiles/_li.py +217 -0
  18. structuralcodes/geometry/profiles/_u.py +173 -0
  19. structuralcodes/geometry/profiles/_ub.py +1356 -0
  20. structuralcodes/geometry/profiles/_ubp.py +227 -0
  21. structuralcodes/geometry/profiles/_uc.py +276 -0
  22. structuralcodes/geometry/profiles/_upe.py +133 -0
  23. structuralcodes/geometry/profiles/_upn.py +315 -0
  24. structuralcodes/geometry/profiles/_w.py +2157 -0
  25. structuralcodes/materials/basic/_elastic.py +18 -1
  26. structuralcodes/materials/basic/_elasticplastic.py +18 -1
  27. structuralcodes/materials/basic/_generic.py +18 -1
  28. structuralcodes/materials/concrete/__init__.py +3 -0
  29. structuralcodes/materials/concrete/_concrete.py +10 -1
  30. structuralcodes/materials/concrete/_concreteEC2_2004.py +15 -1
  31. structuralcodes/materials/concrete/_concreteEC2_2023.py +15 -1
  32. structuralcodes/materials/concrete/_concreteMC2010.py +20 -1
  33. structuralcodes/materials/constitutive_laws/__init__.py +3 -0
  34. structuralcodes/materials/constitutive_laws/_elasticplastic.py +2 -2
  35. structuralcodes/materials/constitutive_laws/_initial_strain.py +130 -0
  36. structuralcodes/materials/reinforcement/__init__.py +6 -0
  37. structuralcodes/materials/reinforcement/_reinforcement.py +10 -1
  38. structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +14 -0
  39. structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +14 -0
  40. structuralcodes/materials/reinforcement/_reinforcementMC2010.py +14 -0
  41. structuralcodes/sections/section_integrators/__init__.py +3 -1
  42. structuralcodes/sections/section_integrators/_marin_integrator.py +1 -1
  43. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/METADATA +2 -2
  44. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/RECORD +47 -30
  45. structuralcodes/geometry/_steel_sections.py +0 -2155
  46. /structuralcodes/{sections/section_integrators → core}/_marin_integration.py +0 -0
  47. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/WHEEL +0 -0
  48. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,2155 +0,0 @@
1
- """Utility functions for importing standard steel profiles."""
2
-
3
- import numpy as np
4
- from shapely import (
5
- LinearRing,
6
- LineString,
7
- Point,
8
- Polygon,
9
- get_geometry,
10
- polygonize,
11
- set_precision,
12
- )
13
- from shapely.affinity import rotate, scale, translate
14
- from shapely.geometry.polygon import orient
15
- from shapely.ops import linemerge, split, unary_union
16
-
17
- from structuralcodes.sections.section_integrators._marin_integration import (
18
- marin_integration,
19
- )
20
-
21
-
22
- class BaseProfile:
23
- """Base class representing a profile.
24
-
25
- Contains the common code for all sections.
26
- """
27
-
28
- def __init__(self):
29
- """Creates an empty base profile."""
30
- self._polygon: Polygon = None
31
- self._A: float = None
32
- self._Iy: float = None
33
- self._Iz: float = None
34
- self._Icsi: float = None
35
- self._Ieta: float = None
36
- self._Iyz: float = None
37
- self._Wely: float = None
38
- self._Welz: float = None
39
- self._iy: float = None
40
- self._iz: float = None
41
- self._Wply: float = None
42
- self._Wplz: float = None
43
-
44
- def _check_polygon_defined(self):
45
- """Just checks if polygon attribute is defined.
46
-
47
- If the polygon is not defined (it should never happen), an exception
48
- is Raised.
49
- """
50
- # The polygon attribute should be already defined
51
- if self._polygon is None:
52
- raise RuntimeError(
53
- 'The polygon for some reason was not correctly defined.'
54
- )
55
-
56
- def _find_plastic_neutral_axis_y(self) -> float:
57
- """Find posizion z of plastic neutral axes parallel to y.
58
-
59
- We use bisection algorithm within the section limits.
60
- """
61
- bounds = self.polygon.bounds
62
- zmin, zmax = bounds[1], bounds[3]
63
-
64
- zA = zmin
65
- zB = zmax
66
-
67
- daA = self._find_delta_area_above_minus_below(z=zA)
68
-
69
- ITMAX = 200
70
- it = 0
71
-
72
- while (it < ITMAX) and (abs(zB - zA) > (zmax - zmin) * 1e-10):
73
- zC = (zA + zB) / 2.0
74
- daC = self._find_delta_area_above_minus_below(z=zC)
75
- if abs(daC) < 1e-10:
76
- break
77
- if daA * daC < 0:
78
- # The solution is between A and C
79
- zB = zC
80
- else:
81
- # The solution is between C and B
82
- zA = zC
83
- daA = daC
84
- it += 1
85
- if it >= ITMAX:
86
- s = f'Last iteration reached a unbalance of {daC}'
87
- raise ValueError(f'Maximum number of iterations reached.\n{s}')
88
-
89
- return zC
90
-
91
- def _find_delta_area_above_minus_below(self, z: float) -> float:
92
- """Returns area difference between above and below parts.
93
-
94
- Above and below parts are computed splitting the polygon with a line
95
- parallel to Y axes at z coordinate.
96
- """
97
- bounds = self._polygon.bounds
98
- xmax = max(abs(bounds[0]), bounds[2])
99
- line = LineString([[-xmax * 1.05, z], [xmax * 1.05, z]])
100
-
101
- area_above = 0
102
- area_below = 0
103
- # divide polygons "above" and "below" line
104
- if line.intersects(self._polygon):
105
- result = split(self._polygon, line)
106
- # divide polygons "above" and "below" line
107
- for geom in result.geoms:
108
- if LinearRing(
109
- (line.coords[0], line.coords[1], geom.centroid.coords[0])
110
- ).is_ccw:
111
- area_above += geom.area
112
- else:
113
- area_below += geom.area
114
- else:
115
- # not intersecting, all the polygon is above or below the line
116
- geom = self.polygon
117
- if LinearRing(
118
- (line.coords[0], line.coords[1], geom.centroid.coords[0])
119
- ).is_ccw:
120
- area_above += geom.area
121
- else:
122
- area_below += geom.area
123
- return area_above - area_below
124
-
125
- def _find_principals_direction_and_moments(self):
126
- """Computes principal direction and second area moments."""
127
- eigres = np.linalg.eig(
128
- np.array([[self.Iy, self.Iyz], [self.Iyz, self.Iz]])
129
- )
130
- max_idx = np.argmax(eigres[0])
131
- min_idx = 0 if max_idx == 1 else 1
132
- self._Icsi = eigres[0][max_idx]
133
- self._Ieta = eigres[0][min_idx]
134
- self._theta = np.arccos(
135
- np.dot(np.array([1, 0]), eigres[1][:, max_idx])
136
- )
137
-
138
- @property
139
- def A(self) -> float:
140
- """Returns area of profile."""
141
- if self._A is None:
142
- # Check if the polygon is defined
143
- self._check_polygon_defined()
144
- # Get the polygon coordinates:
145
- xy = self._polygon.exterior.coords.xy
146
- # Compute area
147
- self._A = marin_integration(xy[0], xy[1], 0, 0)
148
- return self._A
149
-
150
- @property
151
- def Iy(self) -> float:
152
- """Returns second moment of area around y axis."""
153
- if self._Iy is None:
154
- # Check if the polygon is defined
155
- self._check_polygon_defined()
156
- # Get the polygon coordinates:
157
- xy = self._polygon.exterior.coords.xy
158
- # Compute second moments of inertia
159
- self._Iy = marin_integration(xy[0], xy[1], 0, 2)
160
- return self._Iy
161
-
162
- @property
163
- def Iz(self) -> float:
164
- """Returns second moment of area around z axis."""
165
- if self._Iz is None:
166
- # Check if the polygon is defined
167
- self._check_polygon_defined()
168
- # Get the polygon coordinates:
169
- xy = self._polygon.exterior.coords.xy
170
- # Compute second moments of inertia
171
- self._Iz = marin_integration(xy[0], xy[1], 2, 0)
172
- return self._Iz
173
-
174
- @property
175
- def Iyz(self) -> float:
176
- """Returns product moment of inertia."""
177
- if self._Iyz is None:
178
- # Check if the polygon is defined
179
- self._check_polygon_defined()
180
- # Get the polygon coordinates:
181
- xy = self._polygon.exterior.coords.xy
182
- # Compute product moment of area
183
- self._Iyz = marin_integration(xy[0], xy[1], 1, 1)
184
- return self._Iyz
185
-
186
- @property
187
- def Icsi(self) -> float:
188
- """Returns second moment of area around principal csi axis.
189
-
190
- It is assumed that Icsi is maximum second moment, while Ieta is the
191
- minimum one.
192
- """
193
- if self._Icsi is None:
194
- self._find_principals_direction_and_moments()
195
- return self._Icsi
196
-
197
- @property
198
- def Ieta(self) -> float:
199
- """Returns second moment of area around principal eta axis.
200
-
201
- It is assumed that Icsi is maximum second moment, while Ieta is the
202
- minimum one.
203
- """
204
- if self._Ieta is None:
205
- self._find_principals_direction_and_moments()
206
- return self._Ieta
207
-
208
- @property
209
- def theta(self) -> float:
210
- """Returns angle between x and principal eta axis.
211
-
212
- It is assumed that Icsi is maximum second moment, while Ieta is the
213
- minimum one.
214
-
215
- Returns:
216
- float: The angle in radians.
217
- """
218
- if self._theta is None:
219
- self._find_principals_direction_and_moments()
220
- return self._theta
221
-
222
- def _compute_elastic_moduli(self):
223
- """Compute elastic moduli Wely and Welz."""
224
- # Check if the polygon is defined
225
- self._check_polygon_defined()
226
- # For computing section modulus get bounds
227
- bounds = self._polygon.bounds
228
- xmax = max(abs(bounds[0]), bounds[2])
229
- ymax = max(abs(bounds[1]), bounds[3])
230
- # Then compute section modulus
231
- self._Wely = self.Iy / ymax
232
- self._Welz = self.Iz / xmax
233
-
234
- @property
235
- def Wely(self) -> float:
236
- """Returns section modulus in y direction."""
237
- if self._Wely is None:
238
- # Compute elastic moduli
239
- self._compute_elastic_moduli()
240
- return self._Wely
241
-
242
- @property
243
- def Welz(self) -> float:
244
- """Returns section modulus in z direction."""
245
- if self._Welz is None:
246
- # Compute elastic moduli
247
- self._compute_elastic_moduli()
248
- return self._Welz
249
-
250
- @property
251
- def Wply(self) -> float:
252
- """Returns plastic section modulus in y direction."""
253
- if self._Wply is None:
254
- # Check if the polygon is defined
255
- self._check_polygon_defined()
256
- # For computing section modulus get bounds
257
- bounds = self._polygon.bounds
258
- xmax = max(abs(bounds[0]), bounds[2])
259
- # Compute plastic section modulus
260
- # find plastic neutral axis parallel to y
261
- self._Wply = 0
262
- z_pna = self._find_plastic_neutral_axis_y()
263
- poly = translate(self._polygon, xoff=0, yoff=-z_pna)
264
- result = split(
265
- poly,
266
- LineString([[-xmax * 1.05, 0], [xmax * 1.05, 0]]),
267
- )
268
- for poly in result.geoms:
269
- xy = poly.exterior.coords.xy
270
- self._Wply += abs(marin_integration(xy[0], xy[1], 0, 1))
271
- return self._Wply
272
-
273
- @property
274
- def Wplz(self) -> float:
275
- """Returns plastic section modulus in z direction."""
276
- if self._Wplz is None:
277
- # Check if the polygon is defined
278
- self._check_polygon_defined()
279
- # For computing section modulus get bounds
280
- bounds = self._polygon.bounds
281
- ymax = max(abs(bounds[1]), bounds[3])
282
- # Compute plastic section modulus
283
- # # find plastic neutral axis parallel to z
284
- self._polygon = rotate(geom=self._polygon, angle=90, origin=(0, 0))
285
- self._Wplz = 0
286
- y_pna = self._find_plastic_neutral_axis_y()
287
- poly = translate(self._polygon, xoff=0, yoff=-y_pna)
288
- result = split(
289
- poly,
290
- LineString([[-ymax * 1.05, 0], [ymax * 1.05, 0]]),
291
- )
292
- for poly in result.geoms:
293
- xy = poly.exterior.coords.xy
294
- self._Wplz += abs(marin_integration(xy[0], xy[1], 0, 1))
295
- self._polygon = rotate(
296
- geom=self._polygon, angle=-90, origin=(0, 0)
297
- )
298
- return self._Wplz
299
-
300
- @property
301
- def iy(self) -> float:
302
- """Returns radius of inertia of profile."""
303
- # Compute radius of inertia
304
- self._iy = self._iy or (self.Iy / self.A) ** 0.5
305
- return self._iy
306
-
307
- @property
308
- def iz(self) -> float:
309
- """Returns radius of inertia of profile."""
310
- # Compute radius of inertia
311
- self._iz = self._iz or (self.Iz / self.A) ** 0.5
312
- return self._iz
313
-
314
-
315
- class IPE(BaseProfile):
316
- """Simple class for representing an IPE profile.
317
-
318
- IPE 80-600 in accordance with standard Euronorm 19-57.
319
- """
320
-
321
- parameters = {
322
- 'IPE80': {'h': 80.0, 'b': 46.0, 'tw': 3.8, 'tf': 5.2, 'r': 5.0},
323
- 'IPE100': {'h': 100.0, 'b': 55.0, 'tw': 4.1, 'tf': 5.7, 'r': 7.0},
324
- 'IPE120': {'h': 120.0, 'b': 64.0, 'tw': 4.4, 'tf': 6.3, 'r': 7.0},
325
- 'IPE140': {'h': 140.0, 'b': 73.0, 'tw': 4.7, 'tf': 6.9, 'r': 7.0},
326
- 'IPE160': {'h': 160.0, 'b': 82.0, 'tw': 5.0, 'tf': 7.4, 'r': 9.0},
327
- 'IPE180': {'h': 180.0, 'b': 91.0, 'tw': 5.3, 'tf': 8.0, 'r': 9.0},
328
- 'IPE200': {'h': 200.0, 'b': 100.0, 'tw': 5.6, 'tf': 8.5, 'r': 12.0},
329
- 'IPE220': {'h': 220.0, 'b': 110.0, 'tw': 5.9, 'tf': 9.2, 'r': 12.0},
330
- 'IPE240': {'h': 240.0, 'b': 120.0, 'tw': 6.2, 'tf': 9.8, 'r': 15.0},
331
- 'IPE270': {'h': 270.0, 'b': 135.0, 'tw': 6.6, 'tf': 10.2, 'r': 15.0},
332
- 'IPE300': {'h': 300.0, 'b': 150.0, 'tw': 7.1, 'tf': 10.7, 'r': 15.0},
333
- 'IPE330': {'h': 330.0, 'b': 160.0, 'tw': 7.5, 'tf': 11.5, 'r': 18.0},
334
- 'IPE360': {'h': 360.0, 'b': 170.0, 'tw': 8.0, 'tf': 12.7, 'r': 18.0},
335
- 'IPE400': {'h': 400.0, 'b': 180.0, 'tw': 8.6, 'tf': 13.5, 'r': 21.0},
336
- 'IPE450': {'h': 450.0, 'b': 190.0, 'tw': 9.4, 'tf': 14.6, 'r': 21.0},
337
- 'IPE500': {'h': 500.0, 'b': 200.0, 'tw': 10.2, 'tf': 16.0, 'r': 21.0},
338
- 'IPE550': {'h': 550.0, 'b': 210.0, 'tw': 11.1, 'tf': 17.2, 'r': 24.0},
339
- 'IPE600': {'h': 600.0, 'b': 220.0, 'tw': 12.0, 'tf': 19.0, 'r': 24.0},
340
- }
341
-
342
- @classmethod
343
- def get_polygon(cls, name: str) -> Polygon:
344
- """Returns a shapely polygon representing an IPE section."""
345
- if isinstance(name, (float, int)):
346
- name = f'IPE{int(name):0d}'
347
- parameters = cls.parameters.get(name)
348
- if parameters is None:
349
- raise ValueError(
350
- f"Profile '{name}' not found in IPE sections. "
351
- "Select a valid profile (available ones: "
352
- f"{cls.profiles()})"
353
- )
354
- return _create_I_section(**parameters)
355
-
356
- @classmethod
357
- def profiles(cls) -> list:
358
- """Returns a list containing all available profiles."""
359
- return list(cls.parameters.keys())
360
-
361
- def __init__(self, name: str) -> None:
362
- """Creates a new IPE object."""
363
- if isinstance(name, (float, int)):
364
- name = f'IPE{int(name):0d}'
365
- parameters = self.parameters.get(name)
366
- if parameters is None:
367
- raise ValueError(
368
- f"Profile '{name}' not found in IPE sections. "
369
- "Select a valid profile (available ones: "
370
- f"{self.profiles()})"
371
- )
372
- super().__init__()
373
- self._h = parameters.get('h')
374
- self._b = parameters.get('b')
375
- self._tw = parameters.get('tw')
376
- self._tf = parameters.get('tf')
377
- self._r = parameters.get('r')
378
- self._polygon = _create_I_section(**parameters)
379
-
380
- @property
381
- def polygon(self) -> Polygon:
382
- """Returns shapely Polygon of section.
383
-
384
- Returns:
385
- Polygon: The represention of the IPE section.
386
- """
387
- return self._polygon
388
-
389
- @property
390
- def h(self) -> float:
391
- """Returns height of IPE section.
392
-
393
- Returns:
394
- float: Height h of IPE section.
395
- """
396
- return self._h
397
-
398
- @property
399
- def b(self) -> float:
400
- """Returns width of IPE section.
401
-
402
- Returns:
403
- float: Width b of IPE section.
404
- """
405
- return self._b
406
-
407
- @property
408
- def tw(self) -> float:
409
- """Returns thickness of web of IPE section.
410
-
411
- Returns:
412
- float: Web thickness tw of IPE section.
413
- """
414
- return self._tw
415
-
416
- @property
417
- def tf(self) -> float:
418
- """Returns thickness of flange of IPE section.
419
-
420
- Returns:
421
- float: Flange thickness tw of IPE section.
422
- """
423
- return self._tf
424
-
425
- @property
426
- def r(self) -> float:
427
- """Returns fillet radius of IPE section.
428
-
429
- Returns:
430
- float: Fillet radius r of IPE section.
431
- """
432
- return self._r
433
-
434
-
435
- class HE(BaseProfile):
436
- """Simple class for representing an HE profile.
437
-
438
- HE A, HE B, HE M 100-1000 in accordance with Standard Euronorm 53-62.
439
- """
440
-
441
- parameters = {
442
- 'HEA100': {'h': 96.0, 'b': 100.0, 'tw': 5.0, 'tf': 8.0, 'r': 12.0},
443
- 'HEA120': {'h': 114.0, 'b': 120.0, 'tw': 5.0, 'tf': 8.0, 'r': 12.0},
444
- 'HEA140': {'h': 133.0, 'b': 140.0, 'tw': 5.5, 'tf': 8.5, 'r': 12.0},
445
- 'HEA160': {'h': 152.0, 'b': 160.0, 'tw': 6.0, 'tf': 9.0, 'r': 15.0},
446
- 'HEA180': {'h': 171.0, 'b': 180.0, 'tw': 6.0, 'tf': 9.5, 'r': 15.0},
447
- 'HEA200': {'h': 190.0, 'b': 200.0, 'tw': 6.5, 'tf': 10.0, 'r': 18.0},
448
- 'HEA220': {'h': 210.0, 'b': 220.0, 'tw': 7.0, 'tf': 11.0, 'r': 18.0},
449
- 'HEA240': {'h': 230.0, 'b': 240.0, 'tw': 7.5, 'tf': 12.0, 'r': 21.0},
450
- 'HEA260': {'h': 250.0, 'b': 260.0, 'tw': 7.5, 'tf': 12.5, 'r': 24.0},
451
- 'HEA280': {'h': 270.0, 'b': 280.0, 'tw': 8.0, 'tf': 13.0, 'r': 24.0},
452
- 'HEA300': {'h': 290.0, 'b': 300.0, 'tw': 8.5, 'tf': 14.0, 'r': 27.0},
453
- 'HEA320': {'h': 310.0, 'b': 300.0, 'tw': 9.0, 'tf': 15.5, 'r': 27.0},
454
- 'HEA340': {'h': 330.0, 'b': 300.0, 'tw': 9.5, 'tf': 16.5, 'r': 27.0},
455
- 'HEA360': {'h': 350.0, 'b': 300.0, 'tw': 10.0, 'tf': 17.5, 'r': 27.0},
456
- 'HEA400': {'h': 390.0, 'b': 300.0, 'tw': 11.0, 'tf': 19.0, 'r': 27.0},
457
- 'HEA450': {'h': 440.0, 'b': 300.0, 'tw': 11.5, 'tf': 21.0, 'r': 27.0},
458
- 'HEA500': {'h': 490.0, 'b': 300.0, 'tw': 12.0, 'tf': 23.0, 'r': 27.0},
459
- 'HEA550': {'h': 540.0, 'b': 300.0, 'tw': 12.5, 'tf': 24.0, 'r': 27.0},
460
- 'HEA600': {'h': 590.0, 'b': 300.0, 'tw': 13.0, 'tf': 25.0, 'r': 27.0},
461
- 'HEA650': {'h': 640.0, 'b': 300.0, 'tw': 13.5, 'tf': 26.0, 'r': 27.0},
462
- 'HEA700': {'h': 690.0, 'b': 300.0, 'tw': 14.5, 'tf': 27.0, 'r': 27.0},
463
- 'HEA800': {'h': 790.0, 'b': 300.0, 'tw': 15.0, 'tf': 28.0, 'r': 30.0},
464
- 'HEA900': {'h': 890.0, 'b': 300.0, 'tw': 16.0, 'tf': 30.0, 'r': 30.0},
465
- 'HEA1000': {'h': 990.0, 'b': 300.0, 'tw': 16.5, 'tf': 31.0, 'r': 30.0},
466
- 'HEB100': {'h': 100.0, 'b': 100.0, 'tw': 6.0, 'tf': 10.0, 'r': 12.0},
467
- 'HEB120': {'h': 120.0, 'b': 120.0, 'tw': 6.5, 'tf': 11.0, 'r': 12.0},
468
- 'HEB140': {'h': 140.0, 'b': 140.0, 'tw': 7.0, 'tf': 12.0, 'r': 12.0},
469
- 'HEB160': {'h': 160.0, 'b': 160.0, 'tw': 8.0, 'tf': 13.0, 'r': 15.0},
470
- 'HEB180': {'h': 180.0, 'b': 180.0, 'tw': 8.5, 'tf': 14.0, 'r': 15.0},
471
- 'HEB200': {'h': 200.0, 'b': 200.0, 'tw': 9.0, 'tf': 15.0, 'r': 18.0},
472
- 'HEB220': {'h': 220.0, 'b': 220.0, 'tw': 9.5, 'tf': 16.0, 'r': 18.0},
473
- 'HEB240': {'h': 240.0, 'b': 240.0, 'tw': 10.0, 'tf': 17.0, 'r': 21.0},
474
- 'HEB260': {'h': 260.0, 'b': 260.0, 'tw': 10.0, 'tf': 17.5, 'r': 24.0},
475
- 'HEB280': {'h': 280.0, 'b': 280.0, 'tw': 10.5, 'tf': 18.0, 'r': 24.0},
476
- 'HEB300': {'h': 300.0, 'b': 300.0, 'tw': 11.0, 'tf': 19.0, 'r': 27.0},
477
- 'HEB320': {'h': 320.0, 'b': 300.0, 'tw': 11.5, 'tf': 20.5, 'r': 27.0},
478
- 'HEB340': {'h': 340.0, 'b': 300.0, 'tw': 12.0, 'tf': 21.5, 'r': 27.0},
479
- 'HEB360': {'h': 360.0, 'b': 300.0, 'tw': 12.5, 'tf': 22.5, 'r': 27.0},
480
- 'HEB400': {'h': 400.0, 'b': 300.0, 'tw': 13.5, 'tf': 24.0, 'r': 27.0},
481
- 'HEB450': {'h': 450.0, 'b': 300.0, 'tw': 14.0, 'tf': 26.0, 'r': 27.0},
482
- 'HEB500': {'h': 500.0, 'b': 300.0, 'tw': 14.5, 'tf': 28.0, 'r': 27.0},
483
- 'HEB550': {'h': 550.0, 'b': 300.0, 'tw': 15.0, 'tf': 29.0, 'r': 27.0},
484
- 'HEB600': {'h': 600.0, 'b': 300.0, 'tw': 15.5, 'tf': 30.0, 'r': 27.0},
485
- 'HEB650': {'h': 650.0, 'b': 300.0, 'tw': 16.0, 'tf': 31.0, 'r': 27.0},
486
- 'HEB700': {'h': 700.0, 'b': 300.0, 'tw': 17.0, 'tf': 32.0, 'r': 27.0},
487
- 'HEB800': {'h': 800.0, 'b': 300.0, 'tw': 17.5, 'tf': 33.0, 'r': 30.0},
488
- 'HEB900': {'h': 900.0, 'b': 300.0, 'tw': 18.5, 'tf': 35.0, 'r': 30.0},
489
- 'HEB1000': {
490
- 'h': 1000.0,
491
- 'b': 300.0,
492
- 'tw': 19.0,
493
- 'tf': 36.0,
494
- 'r': 30.0,
495
- },
496
- 'HEM100': {'h': 120.0, 'b': 106.0, 'tw': 12.0, 'tf': 20.0, 'r': 12.0},
497
- 'HEM120': {'h': 140.0, 'b': 126.0, 'tw': 12.5, 'tf': 21.0, 'r': 12.0},
498
- 'HEM140': {'h': 160.0, 'b': 146.0, 'tw': 13.0, 'tf': 22.0, 'r': 12.0},
499
- 'HEM160': {'h': 180.0, 'b': 166.0, 'tw': 14.0, 'tf': 23.0, 'r': 15.0},
500
- 'HEM180': {'h': 200.0, 'b': 186.0, 'tw': 14.5, 'tf': 24.0, 'r': 15.0},
501
- 'HEM200': {'h': 220.0, 'b': 206.0, 'tw': 15.0, 'tf': 25.0, 'r': 18.0},
502
- 'HEM220': {'h': 240.0, 'b': 226.0, 'tw': 15.5, 'tf': 26.0, 'r': 18.0},
503
- 'HEM240': {'h': 270.0, 'b': 248.0, 'tw': 18.0, 'tf': 32.0, 'r': 21.0},
504
- 'HEM260': {'h': 290.0, 'b': 268.0, 'tw': 18.0, 'tf': 32.5, 'r': 24.0},
505
- 'HEM280': {'h': 310.0, 'b': 288.0, 'tw': 18.5, 'tf': 33.0, 'r': 24.0},
506
- 'HEM300': {'h': 340.0, 'b': 310.0, 'tw': 21.0, 'tf': 39.0, 'r': 27.0},
507
- 'HEM320': {'h': 359.0, 'b': 309.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
508
- 'HEM340': {'h': 377.0, 'b': 309.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
509
- 'HEM360': {'h': 395.0, 'b': 308.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
510
- 'HEM400': {'h': 432.0, 'b': 307.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
511
- 'HEM450': {'h': 478.0, 'b': 307.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
512
- 'HEM500': {'h': 524.0, 'b': 306.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
513
- 'HEM550': {'h': 572.0, 'b': 306.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
514
- 'HEM600': {'h': 620.0, 'b': 305.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
515
- 'HEM650': {'h': 668.0, 'b': 305.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
516
- 'HEM700': {'h': 716.0, 'b': 304.0, 'tw': 21.0, 'tf': 40.0, 'r': 27.0},
517
- 'HEM800': {'h': 814.0, 'b': 303.0, 'tw': 21.0, 'tf': 40.0, 'r': 30.0},
518
- 'HEM900': {'h': 910.0, 'b': 302.0, 'tw': 21.0, 'tf': 40.0, 'r': 30.0},
519
- 'HEM1000': {
520
- 'h': 1008.0,
521
- 'b': 302.0,
522
- 'tw': 21.0,
523
- 'tf': 40.0,
524
- 'r': 30.0,
525
- },
526
- }
527
-
528
- @classmethod
529
- def get_polygon(cls, name: str) -> Polygon:
530
- """Returns a shapely polygon representing an HE section."""
531
- parameters = cls.parameters.get(name)
532
- if parameters is None:
533
- raise ValueError(
534
- f"Profile '{name}' not found in HE sections. "
535
- "Select a valid profile (available ones: "
536
- f"{cls.profiles()})"
537
- )
538
- return _create_I_section(**parameters)
539
-
540
- @classmethod
541
- def profiles(cls) -> list:
542
- """Returns a list containing all available profiles."""
543
- return list(cls.parameters.keys())
544
-
545
- def __init__(self, name: str) -> None:
546
- """Creates a new HE object."""
547
- parameters = self.parameters.get(name)
548
- if parameters is None:
549
- raise ValueError(
550
- f"Profile '{name}' not found in HE sections. "
551
- "Select a valid profile (available ones: "
552
- f"{self.profiles()})"
553
- )
554
- super().__init__()
555
- self._h = parameters.get('h')
556
- self._b = parameters.get('b')
557
- self._tw = parameters.get('tw')
558
- self._tf = parameters.get('tf')
559
- self._r = parameters.get('r')
560
- self._polygon = _create_I_section(**parameters)
561
-
562
- @property
563
- def polygon(self) -> Polygon:
564
- """Returns shapely Polygon of section.
565
-
566
- Returns:
567
- Polygon: The represention of the HE section.
568
- """
569
- return self._polygon
570
-
571
- @property
572
- def h(self) -> float:
573
- """Returns height of HE section.
574
-
575
- Returns:
576
- float: Height h of HE section.
577
- """
578
- return self._h
579
-
580
- @property
581
- def b(self) -> float:
582
- """Returns width of HE section.
583
-
584
- Returns:
585
- float: Width b of HE section.
586
- """
587
- return self._b
588
-
589
- @property
590
- def tw(self) -> float:
591
- """Returns thickness of web of HE section.
592
-
593
- Returns:
594
- float: Web thickness tw of HE section.
595
- """
596
- return self._tw
597
-
598
- @property
599
- def tf(self) -> float:
600
- """Returns thickness of flange of HE section.
601
-
602
- Returns:
603
- float: Flange thickness tw of HE section.
604
- """
605
- return self._tf
606
-
607
- @property
608
- def r(self) -> float:
609
- """Returns fillet radius of HE section.
610
-
611
- Returns:
612
- float: Fillet radius r of HE section.
613
- """
614
- return self._r
615
-
616
-
617
- class UB(BaseProfile):
618
- """Simple class for representing a UB profile.
619
-
620
- Universal Beams.
621
- """
622
-
623
- parameters = {
624
- 'UB127x76x13': {'h': 127.0, 'b': 76.0, 'tw': 4.0, 'tf': 7.6, 'r': 8.0},
625
- 'UB152x89x16': {'h': 152.0, 'b': 89.0, 'tw': 4.5, 'tf': 7.7, 'r': 8.0},
626
- 'UB178x102x19': {
627
- 'h': 178.0,
628
- 'b': 101.0,
629
- 'tw': 4.8,
630
- 'tf': 7.9,
631
- 'r': 8.0,
632
- },
633
- 'UB203x102x23': {
634
- 'h': 203.0,
635
- 'b': 102.0,
636
- 'tw': 5.4,
637
- 'tf': 9.3,
638
- 'r': 8.0,
639
- },
640
- 'UB203x133x25': {
641
- 'h': 203.0,
642
- 'b': 133.0,
643
- 'tw': 5.7,
644
- 'tf': 7.8,
645
- 'r': 8.0,
646
- },
647
- 'UB203x133x30': {
648
- 'h': 207.0,
649
- 'b': 134.0,
650
- 'tw': 6.4,
651
- 'tf': 9.6,
652
- 'r': 8.0,
653
- },
654
- 'UB254x102x22': {
655
- 'h': 254.0,
656
- 'b': 102.0,
657
- 'tw': 5.7,
658
- 'tf': 6.8,
659
- 'r': 8.0,
660
- },
661
- 'UB254x102x25': {
662
- 'h': 257.0,
663
- 'b': 102.0,
664
- 'tw': 6.0,
665
- 'tf': 8.4,
666
- 'r': 8.0,
667
- },
668
- 'UB254x102x28': {
669
- 'h': 260.0,
670
- 'b': 102.0,
671
- 'tw': 6.3,
672
- 'tf': 10.0,
673
- 'r': 8.0,
674
- },
675
- 'UB254x146x31': {
676
- 'h': 251.0,
677
- 'b': 146.0,
678
- 'tw': 6.0,
679
- 'tf': 8.6,
680
- 'r': 8.0,
681
- },
682
- 'UB254x146x37': {
683
- 'h': 256.0,
684
- 'b': 146.0,
685
- 'tw': 6.3,
686
- 'tf': 10.9,
687
- 'r': 8.0,
688
- },
689
- 'UB254x146x43': {
690
- 'h': 260.0,
691
- 'b': 147.0,
692
- 'tw': 7.2,
693
- 'tf': 12.7,
694
- 'r': 8.0,
695
- },
696
- 'UB305x102x25': {
697
- 'h': 305.0,
698
- 'b': 102.0,
699
- 'tw': 5.8,
700
- 'tf': 7.0,
701
- 'r': 8.0,
702
- },
703
- 'UB305x102x28': {
704
- 'h': 309.0,
705
- 'b': 102.0,
706
- 'tw': 6.0,
707
- 'tf': 8.8,
708
- 'r': 8.0,
709
- },
710
- 'UB305x102x33': {
711
- 'h': 313.0,
712
- 'b': 102.0,
713
- 'tw': 6.6,
714
- 'tf': 10.8,
715
- 'r': 8.0,
716
- },
717
- 'UB305x127x37': {
718
- 'h': 304.0,
719
- 'b': 123.0,
720
- 'tw': 7.1,
721
- 'tf': 10.7,
722
- 'r': 9.0,
723
- },
724
- 'UB305x127x42': {
725
- 'h': 307.0,
726
- 'b': 124.0,
727
- 'tw': 8.0,
728
- 'tf': 12.1,
729
- 'r': 9.0,
730
- },
731
- 'UB305x127x48': {
732
- 'h': 311.0,
733
- 'b': 125.0,
734
- 'tw': 9.0,
735
- 'tf': 14.0,
736
- 'r': 9.0,
737
- },
738
- 'UB305x165x40': {
739
- 'h': 303.0,
740
- 'b': 165.0,
741
- 'tw': 6.0,
742
- 'tf': 10.2,
743
- 'r': 9.0,
744
- },
745
- 'UB305x165x46': {
746
- 'h': 307.0,
747
- 'b': 166.0,
748
- 'tw': 6.7,
749
- 'tf': 11.8,
750
- 'r': 9.0,
751
- },
752
- 'UB305x165x54': {
753
- 'h': 310.0,
754
- 'b': 167.0,
755
- 'tw': 7.9,
756
- 'tf': 13.7,
757
- 'r': 9.0,
758
- },
759
- 'UB356x171x45': {
760
- 'h': 351.0,
761
- 'b': 171.0,
762
- 'tw': 7.0,
763
- 'tf': 9.7,
764
- 'r': 13.0,
765
- },
766
- 'UB356x171x51': {
767
- 'h': 355.0,
768
- 'b': 172.0,
769
- 'tw': 7.4,
770
- 'tf': 11.5,
771
- 'r': 13.0,
772
- },
773
- 'UB356x171x57': {
774
- 'h': 358.0,
775
- 'b': 172.0,
776
- 'tw': 8.1,
777
- 'tf': 13.0,
778
- 'r': 13.0,
779
- },
780
- }
781
-
782
- @classmethod
783
- def get_polygon(cls, name: str) -> Polygon:
784
- """Returns a shapely polygon representing a UB section."""
785
- parameters = cls.parameters.get(name)
786
- if parameters is None:
787
- raise ValueError(
788
- f"Profile '{name}' not found in UB sections. "
789
- "Select a valid profile (available ones: "
790
- f"{cls.profiles()})"
791
- )
792
- return _create_I_section(**parameters)
793
-
794
- @classmethod
795
- def profiles(cls) -> list:
796
- """Returns a list containing all available profiles."""
797
- return list(cls.parameters.keys())
798
-
799
- def __init__(self, name: str) -> None:
800
- """Creates a new UB object."""
801
- parameters = self.parameters.get(name)
802
- if parameters is None:
803
- raise ValueError(
804
- f"Profile '{name}' not found in UB sections. "
805
- "Select a valid profile (available ones: "
806
- f"{self.profiles()})"
807
- )
808
- super().__init__()
809
- self._h = parameters.get('h')
810
- self._b = parameters.get('b')
811
- self._tw = parameters.get('tw')
812
- self._tf = parameters.get('tf')
813
- self._r = parameters.get('r')
814
- self._polygon = _create_I_section(**parameters)
815
-
816
- @property
817
- def polygon(self) -> Polygon:
818
- """Returns shapely Polygon of section.
819
-
820
- Returns:
821
- Polygon: The represention of the UB section.
822
- """
823
- return self._polygon
824
-
825
- @property
826
- def h(self) -> float:
827
- """Returns height of UB section.
828
-
829
- Returns:
830
- float: Height h of UB section.
831
- """
832
- return self._h
833
-
834
- @property
835
- def b(self) -> float:
836
- """Returns width of UB section.
837
-
838
- Returns:
839
- float: Width b of UB section.
840
- """
841
- return self._b
842
-
843
- @property
844
- def tw(self) -> float:
845
- """Returns thickness of web of UB section.
846
-
847
- Returns:
848
- float: Web thickness tw of UB section.
849
- """
850
- return self._tw
851
-
852
- @property
853
- def tf(self) -> float:
854
- """Returns thickness of flange of UB section.
855
-
856
- Returns:
857
- float: Flange thickness tw of UB section.
858
- """
859
- return self._tf
860
-
861
- @property
862
- def r(self) -> float:
863
- """Returns fillet radius of UB section.
864
-
865
- Returns:
866
- float: Fillet radius r of UB section.
867
- """
868
- return self._r
869
-
870
-
871
- class UC(BaseProfile):
872
- """Simple class for representing a UC profile.
873
-
874
- Universal Columns.
875
- """
876
-
877
- parameters = {
878
- 'UC152x152x23': {
879
- 'h': 152.0,
880
- 'b': 152.0,
881
- 'tw': 5.8,
882
- 'tf': 6.8,
883
- 'r': 8.0,
884
- },
885
- 'UC152x152x30': {
886
- 'h': 158.0,
887
- 'b': 153.0,
888
- 'tw': 6.5,
889
- 'tf': 9.4,
890
- 'r': 8.0,
891
- },
892
- 'UC152x152x37': {
893
- 'h': 162.0,
894
- 'b': 154.0,
895
- 'tw': 8.0,
896
- 'tf': 11.5,
897
- 'r': 8.0,
898
- },
899
- 'UC152x152x44': {
900
- 'h': 166.0,
901
- 'b': 156.0,
902
- 'tw': 9.5,
903
- 'tf': 13.6,
904
- 'r': 8.0,
905
- },
906
- 'UC152x152x51': {
907
- 'h': 170.0,
908
- 'b': 157.0,
909
- 'tw': 11.0,
910
- 'tf': 15.7,
911
- 'r': 8.0,
912
- },
913
- 'UC203x203x46': {
914
- 'h': 203.0,
915
- 'b': 204.0,
916
- 'tw': 7.2,
917
- 'tf': 11.0,
918
- 'r': 13.0,
919
- },
920
- 'UC203x203x52': {
921
- 'h': 206.0,
922
- 'b': 204.0,
923
- 'tw': 7.9,
924
- 'tf': 12.5,
925
- 'r': 13.0,
926
- },
927
- 'UC203x203x60': {
928
- 'h': 210.0,
929
- 'b': 206.0,
930
- 'tw': 9.4,
931
- 'tf': 14.2,
932
- 'r': 13.0,
933
- },
934
- 'UC203x203x71': {
935
- 'h': 216.0,
936
- 'b': 206.0,
937
- 'tw': 10.0,
938
- 'tf': 17.3,
939
- 'r': 13.0,
940
- },
941
- 'UC203x203x86': {
942
- 'h': 222.0,
943
- 'b': 209.0,
944
- 'tw': 12.7,
945
- 'tf': 20.5,
946
- 'r': 13.0,
947
- },
948
- 'UC203x203x100': {
949
- 'h': 229.0,
950
- 'b': 210.0,
951
- 'tw': 14.5,
952
- 'tf': 23.7,
953
- 'r': 13.0,
954
- },
955
- 'UC203x203x113': {
956
- 'h': 235.0,
957
- 'b': 212.0,
958
- 'tw': 16.3,
959
- 'tf': 26.9,
960
- 'r': 13.0,
961
- },
962
- 'UC203x203x127': {
963
- 'h': 241.0,
964
- 'b': 214.0,
965
- 'tw': 18.1,
966
- 'tf': 30.1,
967
- 'r': 13.0,
968
- },
969
- 'UC254x254x73': {
970
- 'h': 254.0,
971
- 'b': 255.0,
972
- 'tw': 8.6,
973
- 'tf': 14.2,
974
- 'r': 20.0,
975
- },
976
- 'UC254x254x81': {
977
- 'h': 256.0,
978
- 'b': 255.0,
979
- 'tw': 9.4,
980
- 'tf': 15.6,
981
- 'r': 20.0,
982
- },
983
- 'UC254x254x89': {
984
- 'h': 260.0,
985
- 'b': 256.0,
986
- 'tw': 10.3,
987
- 'tf': 17.3,
988
- 'r': 20.0,
989
- },
990
- 'UC254x254x101': {
991
- 'h': 264.0,
992
- 'b': 257.0,
993
- 'tw': 11.9,
994
- 'tf': 19.6,
995
- 'r': 20.0,
996
- },
997
- 'UC254x254x107': {
998
- 'h': 267.0,
999
- 'b': 259.0,
1000
- 'tw': 12.8,
1001
- 'tf': 20.5,
1002
- 'r': 20.0,
1003
- },
1004
- 'UC254x254x115': {
1005
- 'h': 269.0,
1006
- 'b': 259.0,
1007
- 'tw': 13.5,
1008
- 'tf': 22.1,
1009
- 'r': 20.0,
1010
- },
1011
- 'UC254x254x132': {
1012
- 'h': 276.0,
1013
- 'b': 261.0,
1014
- 'tw': 15.3,
1015
- 'tf': 25.3,
1016
- 'r': 20.0,
1017
- },
1018
- 'UC254x254x149': {
1019
- 'h': 282.0,
1020
- 'b': 263.0,
1021
- 'tw': 17.3,
1022
- 'tf': 28.4,
1023
- 'r': 20.0,
1024
- },
1025
- 'UC254x254x167': {
1026
- 'h': 289.0,
1027
- 'b': 265.0,
1028
- 'tw': 19.2,
1029
- 'tf': 31.7,
1030
- 'r': 20.0,
1031
- },
1032
- 'UC305x305x97': {
1033
- 'h': 308.0,
1034
- 'b': 305.0,
1035
- 'tw': 9.9,
1036
- 'tf': 15.4,
1037
- 'r': 20.0,
1038
- },
1039
- 'UC305x305x107': {
1040
- 'h': 311.0,
1041
- 'b': 306.0,
1042
- 'tw': 10.9,
1043
- 'tf': 17.0,
1044
- 'r': 20.0,
1045
- },
1046
- }
1047
-
1048
- @classmethod
1049
- def get_polygon(cls, name: str) -> Polygon:
1050
- """Returns a shapely polygon representing a UC section."""
1051
- parameters = cls.parameters.get(name)
1052
- if parameters is None:
1053
- raise ValueError(
1054
- f"Profile '{name}' not found in UC sections. "
1055
- "Select a valid profile (available ones: "
1056
- f"{cls.profiles()})"
1057
- )
1058
- return _create_I_section(**parameters)
1059
-
1060
- @classmethod
1061
- def profiles(cls) -> list:
1062
- """Returns a list containing all available profiles."""
1063
- return list(cls.parameters.keys())
1064
-
1065
- def __init__(self, name: str) -> None:
1066
- """Creates a new UC object."""
1067
- parameters = self.parameters.get(name)
1068
- if parameters is None:
1069
- raise ValueError(
1070
- f"Profile '{name}' not found in UC sections. "
1071
- "Select a valid profile (available ones: "
1072
- f"{self.profiles()})"
1073
- )
1074
- super().__init__()
1075
- self._h = parameters.get('h')
1076
- self._b = parameters.get('b')
1077
- self._tw = parameters.get('tw')
1078
- self._tf = parameters.get('tf')
1079
- self._r = parameters.get('r')
1080
- self._polygon = _create_I_section(**parameters)
1081
-
1082
- @property
1083
- def polygon(self) -> Polygon:
1084
- """Returns shapely Polygon of section.
1085
-
1086
- Returns:
1087
- Polygon: The represention of the UC section.
1088
- """
1089
- return self._polygon
1090
-
1091
- @property
1092
- def h(self) -> float:
1093
- """Returns height of UC section.
1094
-
1095
- Returns:
1096
- float: Height h of UC section.
1097
- """
1098
- return self._h
1099
-
1100
- @property
1101
- def b(self) -> float:
1102
- """Returns width of UC section.
1103
-
1104
- Returns:
1105
- float: Width b of UC section.
1106
- """
1107
- return self._b
1108
-
1109
- @property
1110
- def tw(self) -> float:
1111
- """Returns thickness of web of UC section.
1112
-
1113
- Returns:
1114
- float: Web thickness tw of UC section.
1115
- """
1116
- return self._tw
1117
-
1118
- @property
1119
- def tf(self) -> float:
1120
- """Returns thickness of flange of UC section.
1121
-
1122
- Returns:
1123
- float: Flange thickness tw of UC section.
1124
- """
1125
- return self._tf
1126
-
1127
- @property
1128
- def r(self) -> float:
1129
- """Returns fillet radius of UC section.
1130
-
1131
- Returns:
1132
- float: Fillet radius r of UC section.
1133
- """
1134
- return self._r
1135
-
1136
-
1137
- class UBP(BaseProfile):
1138
- """Simple class for representing a UBP profile.
1139
-
1140
- Universal Bearing Pile.
1141
- """
1142
-
1143
- parameters = {
1144
- 'UBP203x203x45': {
1145
- 'h': 200.0,
1146
- 'b': 206.0,
1147
- 'tw': 9.5,
1148
- 'tf': 9.5,
1149
- 'r': 10.0,
1150
- },
1151
- 'UBP203x203x54': {
1152
- 'h': 204.0,
1153
- 'b': 208.0,
1154
- 'tw': 11.3,
1155
- 'tf': 11.4,
1156
- 'r': 10.0,
1157
- },
1158
- 'UBP254x254x63': {
1159
- 'h': 247.0,
1160
- 'b': 257.0,
1161
- 'tw': 10.6,
1162
- 'tf': 10.7,
1163
- 'r': 20.0,
1164
- },
1165
- 'UBP254x254x71': {
1166
- 'h': 250.0,
1167
- 'b': 258.0,
1168
- 'tw': 12.0,
1169
- 'tf': 12.0,
1170
- 'r': 20.0,
1171
- },
1172
- 'UBP254x254x85': {
1173
- 'h': 254.0,
1174
- 'b': 260.0,
1175
- 'tw': 14.4,
1176
- 'tf': 14.3,
1177
- 'r': 20.0,
1178
- },
1179
- 'UBP305x305x79': {
1180
- 'h': 299.0,
1181
- 'b': 306.0,
1182
- 'tw': 11.0,
1183
- 'tf': 11.1,
1184
- 'r': 20.0,
1185
- },
1186
- 'UBP305x305x88': {
1187
- 'h': 302.0,
1188
- 'b': 308.0,
1189
- 'tw': 12.4,
1190
- 'tf': 12.3,
1191
- 'r': 20.0,
1192
- },
1193
- 'UBP305x305x95': {
1194
- 'h': 304.0,
1195
- 'b': 309.0,
1196
- 'tw': 13.3,
1197
- 'tf': 13.3,
1198
- 'r': 20.0,
1199
- },
1200
- 'UBP305x305x110': {
1201
- 'h': 308.0,
1202
- 'b': 311.0,
1203
- 'tw': 15.3,
1204
- 'tf': 15.4,
1205
- 'r': 20.0,
1206
- },
1207
- 'UBP305x305x126': {
1208
- 'h': 312.0,
1209
- 'b': 313.0,
1210
- 'tw': 17.5,
1211
- 'tf': 17.6,
1212
- 'r': 20.0,
1213
- },
1214
- 'UBP305x305x149': {
1215
- 'h': 318.0,
1216
- 'b': 316.0,
1217
- 'tw': 20.6,
1218
- 'tf': 20.7,
1219
- 'r': 20.0,
1220
- },
1221
- 'UBP305x305x186': {
1222
- 'h': 328.0,
1223
- 'b': 321.0,
1224
- 'tw': 25.5,
1225
- 'tf': 25.6,
1226
- 'r': 2.0,
1227
- },
1228
- 'UBP305x305x223': {
1229
- 'h': 338.0,
1230
- 'b': 326.0,
1231
- 'tw': 30.3,
1232
- 'tf': 30.4,
1233
- 'r': 20.0,
1234
- },
1235
- 'UBP356x368x109': {
1236
- 'h': 346.0,
1237
- 'b': 371.0,
1238
- 'tw': 12.8,
1239
- 'tf': 12.9,
1240
- 'r': 20.0,
1241
- },
1242
- 'UBP356x368x133': {
1243
- 'h': 352.0,
1244
- 'b': 374.0,
1245
- 'tw': 15.6,
1246
- 'tf': 15.7,
1247
- 'r': 20.0,
1248
- },
1249
- 'UBP356x368x152': {
1250
- 'h': 356.0,
1251
- 'b': 376.0,
1252
- 'tw': 17.8,
1253
- 'tf': 17.9,
1254
- 'r': 20.0,
1255
- },
1256
- 'UBP356x368x174': {
1257
- 'h': 361.0,
1258
- 'b': 378.0,
1259
- 'tw': 20.3,
1260
- 'tf': 20.4,
1261
- 'r': 20.0,
1262
- },
1263
- }
1264
-
1265
- @classmethod
1266
- def get_polygon(cls, name: str) -> Polygon:
1267
- """Returns a shapely polygon representing a UBP section."""
1268
- parameters = cls.parameters.get(name)
1269
- if parameters is None:
1270
- raise ValueError(
1271
- f"Profile '{name}' not found in UBP sections. "
1272
- "Select a valid profile (available ones: "
1273
- f"{cls.profiles()})"
1274
- )
1275
- return _create_I_section(**parameters)
1276
-
1277
- @classmethod
1278
- def profiles(cls) -> list:
1279
- """Returns a list containing all available profiles."""
1280
- return list(cls.parameters.keys())
1281
-
1282
- def __init__(self, name: str) -> None:
1283
- """Creates a new UBP object."""
1284
- parameters = self.parameters.get(name)
1285
- if parameters is None:
1286
- raise ValueError(
1287
- f"Profile '{name}' not found in UBP sections. "
1288
- "Select a valid profile (available ones: "
1289
- f"{self.profiles()})"
1290
- )
1291
- super().__init__()
1292
- self._h = parameters.get('h')
1293
- self._b = parameters.get('b')
1294
- self._tw = parameters.get('tw')
1295
- self._tf = parameters.get('tf')
1296
- self._r = parameters.get('r')
1297
- self._polygon = _create_I_section(**parameters)
1298
-
1299
- @property
1300
- def polygon(self) -> Polygon:
1301
- """Returns shapely Polygon of section.
1302
-
1303
- Returns:
1304
- Polygon: The represention of the UBP section.
1305
- """
1306
- return self._polygon
1307
-
1308
- @property
1309
- def h(self) -> float:
1310
- """Returns height of UBP section.
1311
-
1312
- Returns:
1313
- float: Height h of UBP section.
1314
- """
1315
- return self._h
1316
-
1317
- @property
1318
- def b(self) -> float:
1319
- """Returns width of UBP section.
1320
-
1321
- Returns:
1322
- float: Width b of UBP section.
1323
- """
1324
- return self._b
1325
-
1326
- @property
1327
- def tw(self) -> float:
1328
- """Returns thickness of web of UBP section.
1329
-
1330
- Returns:
1331
- float: Web thickness tw of UBP section.
1332
- """
1333
- return self._tw
1334
-
1335
- @property
1336
- def tf(self) -> float:
1337
- """Returns thickness of flange of UBP section.
1338
-
1339
- Returns:
1340
- float: Flange thickness tw of UBP section.
1341
- """
1342
- return self._tf
1343
-
1344
- @property
1345
- def r(self) -> float:
1346
- """Returns fillet radius of UBP section.
1347
-
1348
- Returns:
1349
- float: Fillet radius r of UBP section.
1350
- """
1351
- return self._r
1352
-
1353
-
1354
- class IPN(BaseProfile):
1355
- """Simple class for representing an IPN profile.
1356
-
1357
- IPN in accordance with standard.
1358
-
1359
- 14% slope in flange.
1360
- """
1361
-
1362
- parameters = {
1363
- 'IPN80': {
1364
- 'h': 80.0,
1365
- 'b': 42.0,
1366
- 'tw': 3.9,
1367
- 'tf': 5.9,
1368
- 'r1': 3.9,
1369
- 'r2': 2.3,
1370
- 'd': 59.0,
1371
- },
1372
- 'IPN100': {
1373
- 'h': 100.0,
1374
- 'b': 50.0,
1375
- 'tw': 4.5,
1376
- 'tf': 6.8,
1377
- 'r1': 4.5,
1378
- 'r2': 2.7,
1379
- 'd': 75.7,
1380
- },
1381
- 'IPN120': {
1382
- 'h': 120.0,
1383
- 'b': 58.0,
1384
- 'tw': 5.1,
1385
- 'tf': 7.7,
1386
- 'r1': 5.1,
1387
- 'r2': 3.1,
1388
- 'd': 92.4,
1389
- },
1390
- 'IPN140': {
1391
- 'h': 140.0,
1392
- 'b': 66.0,
1393
- 'tw': 5.7,
1394
- 'tf': 8.6,
1395
- 'r1': 5.7,
1396
- 'r2': 3.4,
1397
- 'd': 109.1,
1398
- },
1399
- 'IPN160': {
1400
- 'h': 160.0,
1401
- 'b': 74.0,
1402
- 'tw': 6.3,
1403
- 'tf': 9.5,
1404
- 'r1': 6.3,
1405
- 'r2': 3.8,
1406
- 'd': 125.8,
1407
- },
1408
- 'IPN180': {
1409
- 'h': 180.0,
1410
- 'b': 82.0,
1411
- 'tw': 6.9,
1412
- 'tf': 10.4,
1413
- 'r1': 6.9,
1414
- 'r2': 4.1,
1415
- 'd': 142.4,
1416
- },
1417
- 'IPN200': {
1418
- 'h': 200.0,
1419
- 'b': 90.0,
1420
- 'tw': 7.5,
1421
- 'tf': 11.3,
1422
- 'r1': 7.5,
1423
- 'r2': 4.5,
1424
- 'd': 159.1,
1425
- },
1426
- 'IPN220': {
1427
- 'h': 220.0,
1428
- 'b': 98.0,
1429
- 'tw': 8.1,
1430
- 'tf': 12.2,
1431
- 'r1': 8.1,
1432
- 'r2': 4.9,
1433
- 'd': 175.8,
1434
- },
1435
- 'IPN240': {
1436
- 'h': 240.0,
1437
- 'b': 106.0,
1438
- 'tw': 8.7,
1439
- 'tf': 13.1,
1440
- 'r1': 8.7,
1441
- 'r2': 5.2,
1442
- 'd': 192.5,
1443
- },
1444
- 'IPN260': {
1445
- 'h': 260.0,
1446
- 'b': 113.0,
1447
- 'tw': 9.4,
1448
- 'tf': 14.1,
1449
- 'r1': 9.4,
1450
- 'r2': 5.6,
1451
- 'd': 208.9,
1452
- },
1453
- 'IPN280': {
1454
- 'h': 280.0,
1455
- 'b': 119.0,
1456
- 'tw': 10.1,
1457
- 'tf': 15.2,
1458
- 'r1': 10.1,
1459
- 'r2': 6.1,
1460
- 'd': 225.1,
1461
- },
1462
- 'IPN300': {
1463
- 'h': 300.0,
1464
- 'b': 125.0,
1465
- 'tw': 10.8,
1466
- 'tf': 16.2,
1467
- 'r1': 10.8,
1468
- 'r2': 6.5,
1469
- 'd': 241.6,
1470
- },
1471
- 'IPN320': {
1472
- 'h': 320.0,
1473
- 'b': 131.0,
1474
- 'tw': 11.5,
1475
- 'tf': 17.3,
1476
- 'r1': 11.5,
1477
- 'r2': 6.9,
1478
- 'd': 257.9,
1479
- },
1480
- 'IPN340': {
1481
- 'h': 340.0,
1482
- 'b': 137.0,
1483
- 'tw': 12.2,
1484
- 'tf': 18.3,
1485
- 'r1': 12.2,
1486
- 'r2': 7.3,
1487
- 'd': 274.3,
1488
- },
1489
- 'IPN360': {
1490
- 'h': 360.0,
1491
- 'b': 143.0,
1492
- 'tw': 13.0,
1493
- 'tf': 19.5,
1494
- 'r1': 13.0,
1495
- 'r2': 7.8,
1496
- 'd': 290.2,
1497
- },
1498
- 'IPN380': {
1499
- 'h': 380.0,
1500
- 'b': 149.0,
1501
- 'tw': 13.7,
1502
- 'tf': 20.5,
1503
- 'r1': 13.7,
1504
- 'r2': 8.2,
1505
- 'd': 306.7,
1506
- },
1507
- 'IPN400': {
1508
- 'h': 400.0,
1509
- 'b': 155.0,
1510
- 'tw': 14.4,
1511
- 'tf': 21.6,
1512
- 'r1': 14.4,
1513
- 'r2': 8.6,
1514
- 'd': 322.9,
1515
- },
1516
- 'IPN450': {
1517
- 'h': 450.0,
1518
- 'b': 170.0,
1519
- 'tw': 16.2,
1520
- 'tf': 24.3,
1521
- 'r1': 16.2,
1522
- 'r2': 9.7,
1523
- 'd': 363.6,
1524
- },
1525
- 'IPN500': {
1526
- 'h': 500.0,
1527
- 'b': 185.0,
1528
- 'tw': 18.0,
1529
- 'tf': 27.0,
1530
- 'r1': 18.0,
1531
- 'r2': 10.8,
1532
- 'd': 404.3,
1533
- },
1534
- 'IPN550': {
1535
- 'h': 550.0,
1536
- 'b': 200.0,
1537
- 'tw': 19.0,
1538
- 'tf': 30.0,
1539
- 'r1': 19.0,
1540
- 'r2': 11.9,
1541
- 'd': 445.6,
1542
- },
1543
- 'IPN600': {
1544
- 'h': 600.0,
1545
- 'b': 215.0,
1546
- 'tw': 21.6,
1547
- 'tf': 32.4,
1548
- 'r1': 21.6,
1549
- 'r2': 13.0,
1550
- 'd': 485.8,
1551
- },
1552
- }
1553
-
1554
- @classmethod
1555
- def get_polygon(cls, name: str) -> Polygon:
1556
- """Returns a shapely polygon representing an IPN section."""
1557
- if isinstance(name, (float, int)):
1558
- name = f'IPN{int(name):0d}'
1559
- parameters = cls.parameters.get(name)
1560
- if parameters is None:
1561
- raise ValueError(
1562
- f"Profile '{name}' not found in IPN sections. "
1563
- "Select a valid profile (available ones: "
1564
- f"{cls.profiles()})"
1565
- )
1566
- parameters['slope'] = 0.14
1567
- return _create_taper_I_section(
1568
- **{
1569
- key: parameters[key]
1570
- for key in parameters
1571
- if key in ['h', 'b', 'tw', 'tf', 'r1', 'r2', 'slope']
1572
- }
1573
- )
1574
-
1575
- @classmethod
1576
- def profiles(cls) -> list:
1577
- """Returns a list containing all available profiles."""
1578
- return list(cls.parameters.keys())
1579
-
1580
- def __init__(self, name: str) -> None:
1581
- """Creates a new IPN object."""
1582
- if isinstance(name, (float, int)):
1583
- name = f'IPN{int(name):0d}'
1584
- parameters = self.parameters.get(name)
1585
- if parameters is None:
1586
- raise ValueError(
1587
- f"Profile '{name}' not found in IPN sections. "
1588
- "Select a valid profile (available ones: "
1589
- f"{self.profiles()})"
1590
- )
1591
- super().__init__()
1592
- self._h = parameters.get('h')
1593
- self._b = parameters.get('b')
1594
- self._tw = parameters.get('tw')
1595
- self._tf = parameters.get('tf')
1596
- self._r1 = parameters.get('r1')
1597
- self._r2 = parameters.get('r2')
1598
- self._flange_slope = 0.14
1599
- self._polygon = _create_taper_I_section(
1600
- h=self._h,
1601
- b=self._b,
1602
- tw=self._tw,
1603
- tf=self._tf,
1604
- r1=self._r1,
1605
- r2=self._r2,
1606
- slope=self._flange_slope,
1607
- )
1608
-
1609
- @property
1610
- def polygon(self) -> Polygon:
1611
- """Returns shapely Polygon of section.
1612
-
1613
- Returns:
1614
- Polygon: The represention of the IPN section.
1615
- """
1616
- return self._polygon
1617
-
1618
- @property
1619
- def h(self) -> float:
1620
- """Returns height of IPN section.
1621
-
1622
- Returns:
1623
- float: Height h of IPN section.
1624
- """
1625
- return self._h
1626
-
1627
- @property
1628
- def b(self) -> float:
1629
- """Returns width of IPN section.
1630
-
1631
- Returns:
1632
- float: Width b of IPN section.
1633
- """
1634
- return self._b
1635
-
1636
- @property
1637
- def tw(self) -> float:
1638
- """Returns thickness of web of IPN section.
1639
-
1640
- Returns:
1641
- float: Web thickness tw of IPN section.
1642
- """
1643
- return self._tw
1644
-
1645
- @property
1646
- def tf(self) -> float:
1647
- """Returns thickness of flange of IPN section.
1648
-
1649
- Returns:
1650
- float: Flange thickness tw of IPN section.
1651
- """
1652
- return self._tf
1653
-
1654
- @property
1655
- def r1(self) -> float:
1656
- """Returns fillet radius of IPN section.
1657
-
1658
- Returns:
1659
- float: Fillet radius r1 of IPN section.
1660
- """
1661
- return self._r1
1662
-
1663
- @property
1664
- def r2(self) -> float:
1665
- """Returns fillet radius of IPN section.
1666
-
1667
- Returns:
1668
- float: Fillet radius r2 of IPN section.
1669
- """
1670
- return self._r2
1671
-
1672
-
1673
- class UPN(BaseProfile):
1674
- """Simple class for representing an UPN profile.
1675
-
1676
- European standard channels UPN 50 - 400.
1677
-
1678
- Taper flange Channels.
1679
-
1680
- 14% slope in flange.
1681
- """
1682
-
1683
- parameters = {
1684
- 'UPN50': {
1685
- 'h': 50.0,
1686
- 'b': 38.0,
1687
- 'tw': 5.0,
1688
- 'tf': 7.0,
1689
- 'r1': 7.0,
1690
- 'r2': 4.0,
1691
- 'd': 21.0,
1692
- },
1693
- 'UPN65': {
1694
- 'h': 65.0,
1695
- 'b': 42.0,
1696
- 'tw': 5.5,
1697
- 'tf': 7.5,
1698
- 'r1': 8.0,
1699
- 'r2': 4.0,
1700
- 'd': 34.0,
1701
- },
1702
- 'UPN80': {
1703
- 'h': 80.0,
1704
- 'b': 45.0,
1705
- 'tw': 6.0,
1706
- 'tf': 8.0,
1707
- 'r1': 8.0,
1708
- 'r2': 4.0,
1709
- 'd': 47.0,
1710
- },
1711
- 'UPN100': {
1712
- 'h': 100.0,
1713
- 'b': 50.0,
1714
- 'tw': 6.0,
1715
- 'tf': 8.5,
1716
- 'r1': 9.0,
1717
- 'r2': 5.0,
1718
- 'd': 64.0,
1719
- },
1720
- 'UPN120': {
1721
- 'h': 120.0,
1722
- 'b': 55.0,
1723
- 'tw': 7.0,
1724
- 'tf': 9.0,
1725
- 'r1': 9.0,
1726
- 'r2': 5.0,
1727
- 'd': 82.0,
1728
- },
1729
- 'UPN140': {
1730
- 'h': 140.0,
1731
- 'b': 60.0,
1732
- 'tw': 7.0,
1733
- 'tf': 10.0,
1734
- 'r1': 10.0,
1735
- 'r2': 5.0,
1736
- 'd': 98.0,
1737
- },
1738
- 'UPN160': {
1739
- 'h': 160.0,
1740
- 'b': 65.0,
1741
- 'tw': 7.5,
1742
- 'tf': 10.5,
1743
- 'r1': 11.0,
1744
- 'r2': 6.0,
1745
- 'd': 115.0,
1746
- },
1747
- 'UPN180': {
1748
- 'h': 180.0,
1749
- 'b': 70.0,
1750
- 'tw': 8.0,
1751
- 'tf': 11.0,
1752
- 'r1': 11.0,
1753
- 'r2': 6.0,
1754
- 'd': 133.0,
1755
- },
1756
- 'UPN200': {
1757
- 'h': 200.0,
1758
- 'b': 75.0,
1759
- 'tw': 8.5,
1760
- 'tf': 11.5,
1761
- 'r1': 12.0,
1762
- 'r2': 6.0,
1763
- 'd': 151.0,
1764
- },
1765
- 'UPN220': {
1766
- 'h': 220.0,
1767
- 'b': 80.0,
1768
- 'tw': 9.0,
1769
- 'tf': 12.5,
1770
- 'r1': 13.0,
1771
- 'r2': 7.0,
1772
- 'd': 167.0,
1773
- },
1774
- 'UPN240': {
1775
- 'h': 240.0,
1776
- 'b': 85.0,
1777
- 'tw': 9.5,
1778
- 'tf': 13.0,
1779
- 'r1': 13.0,
1780
- 'r2': 7.0,
1781
- 'd': 184.0,
1782
- },
1783
- 'UPN260': {
1784
- 'h': 260.0,
1785
- 'b': 90.0,
1786
- 'tw': 10.0,
1787
- 'tf': 14.0,
1788
- 'r1': 14.0,
1789
- 'r2': 7.0,
1790
- 'd': 200.0,
1791
- },
1792
- 'UPN280': {
1793
- 'h': 280.0,
1794
- 'b': 95.0,
1795
- 'tw': 10.0,
1796
- 'tf': 15.0,
1797
- 'r1': 15.0,
1798
- 'r2': 8.0,
1799
- 'd': 216.0,
1800
- },
1801
- 'UPN300': {
1802
- 'h': 300.0,
1803
- 'b': 100.0,
1804
- 'tw': 10.0,
1805
- 'tf': 16.0,
1806
- 'r1': 16.0,
1807
- 'r2': 8.0,
1808
- 'd': 232.0,
1809
- },
1810
- 'UPN320': {
1811
- 'h': 320.0,
1812
- 'b': 100.0,
1813
- 'tw': 14.0,
1814
- 'tf': 17.5,
1815
- 'r1': 18.0,
1816
- 'r2': 9.0,
1817
- 'd': 246.0,
1818
- },
1819
- 'UPN350': {
1820
- 'h': 350.0,
1821
- 'b': 100.0,
1822
- 'tw': 14.0,
1823
- 'tf': 16.0,
1824
- 'r1': 16.0,
1825
- 'r2': 8.0,
1826
- 'd': 282.0,
1827
- },
1828
- 'UPN380': {
1829
- 'h': 380.0,
1830
- 'b': 102.0,
1831
- 'tw': 13.5,
1832
- 'tf': 16.0,
1833
- 'r1': 16.0,
1834
- 'r2': 8.0,
1835
- 'd': 313.0,
1836
- },
1837
- 'UPN400': {
1838
- 'h': 400.0,
1839
- 'b': 110.0,
1840
- 'tw': 14.0,
1841
- 'tf': 18.0,
1842
- 'r1': 18.0,
1843
- 'r2': 9.0,
1844
- 'd': 324.0,
1845
- },
1846
- }
1847
-
1848
- @classmethod
1849
- def get_polygon(cls, name: str) -> Polygon:
1850
- """Returns a shapely polygon representing an UPN section."""
1851
- if isinstance(name, (float, int)):
1852
- name = f'UPN{int(name):0d}'
1853
- parameters = cls.parameters.get(name)
1854
- if parameters is None:
1855
- raise ValueError(
1856
- f"Profile '{name}' not found in UPN sections. "
1857
- "Select a valid profile (available ones: "
1858
- f"{cls.profiles()})"
1859
- )
1860
- if parameters['h'] <= 300:
1861
- parameters['slope'] = 0.08
1862
- parameters['u'] = parameters['b'] / 2.0
1863
- else:
1864
- parameters['slope'] = 0.05
1865
- parameters['u'] = (parameters['b'] - parameters['tw']) / 2.0
1866
- return _create_taper_U_section(
1867
- **{
1868
- key: parameters[key]
1869
- for key in parameters
1870
- if key in ['h', 'b', 'tw', 'tf', 'r1', 'r2', 'slope', 'u']
1871
- }
1872
- )
1873
-
1874
- @classmethod
1875
- def profiles(cls) -> list:
1876
- """Returns a list containing all available profiles."""
1877
- return list(cls.parameters.keys())
1878
-
1879
- def __init__(self, name: str) -> None:
1880
- """Creates a new UPN object."""
1881
- if isinstance(name, (float, int)):
1882
- name = f'UPN{int(name):0d}'
1883
- parameters = self.parameters.get(name)
1884
- if parameters is None:
1885
- raise ValueError(
1886
- f"Profile '{name}' not found in UPN sections. "
1887
- "Select a valid profile (available ones: "
1888
- f"{self.profiles()})"
1889
- )
1890
- super().__init__()
1891
- self._h = parameters.get('h')
1892
- self._b = parameters.get('b')
1893
- self._tw = parameters.get('tw')
1894
- self._tf = parameters.get('tf')
1895
- self._r1 = parameters.get('r1')
1896
- self._r2 = parameters.get('r2')
1897
- if self._h <= 300:
1898
- self._flange_slope = 0.08
1899
- self._u = self._b / 2.0
1900
- else:
1901
- self._flange_slope = 0.05
1902
- self._u = (self._b - self._tw) / 2.0
1903
- self._polygon = _create_taper_U_section(
1904
- h=self._h,
1905
- b=self._b,
1906
- tw=self._tw,
1907
- tf=self._tf,
1908
- r1=self._r1,
1909
- r2=self._r2,
1910
- slope=self._flange_slope,
1911
- u=self._u,
1912
- )
1913
-
1914
- @property
1915
- def polygon(self) -> Polygon:
1916
- """Returns shapely Polygon of section.
1917
-
1918
- Returns:
1919
- Polygon: The represention of the UPN section.
1920
- """
1921
- return self._polygon
1922
-
1923
- @property
1924
- def h(self) -> float:
1925
- """Returns height of UPN section.
1926
-
1927
- Returns:
1928
- float: Height h of UPN section.
1929
- """
1930
- return self._h
1931
-
1932
- @property
1933
- def b(self) -> float:
1934
- """Returns width of UPN section.
1935
-
1936
- Returns:
1937
- float: Width b of UPN section.
1938
- """
1939
- return self._b
1940
-
1941
- @property
1942
- def tw(self) -> float:
1943
- """Returns thickness of web of UPN section.
1944
-
1945
- Returns:
1946
- float: Web thickness tw of UPN section.
1947
- """
1948
- return self._tw
1949
-
1950
- @property
1951
- def tf(self) -> float:
1952
- """Returns thickness of flange of UPN section.
1953
-
1954
- Returns:
1955
- float: Flange thickness tw of UPN section.
1956
- """
1957
- return self._tf
1958
-
1959
- @property
1960
- def r1(self) -> float:
1961
- """Returns fillet radius of UPN section.
1962
-
1963
- Returns:
1964
- float: Fillet radius r1 of UPN section.
1965
- """
1966
- return self._r1
1967
-
1968
- @property
1969
- def r2(self) -> float:
1970
- """Returns fillet radius of UPN section.
1971
-
1972
- Returns:
1973
- float: Fillet radius r2 of UPN section.
1974
- """
1975
- return self._r2
1976
-
1977
-
1978
- def _create_I_section(h: float, b: float, tw: float, tf: float, r: float):
1979
- """Returns a polygon for a I section."""
1980
- # top flange
1981
- top_flange = Polygon(
1982
- [
1983
- (-b / 2, -h / 2),
1984
- (b / 2, -h / 2),
1985
- (b / 2, -h / 2 + tf),
1986
- (-b / 2, -h / 2 + tf),
1987
- ]
1988
- )
1989
- # bottom flange
1990
- bottom_flange = translate(top_flange, xoff=0, yoff=h - tf)
1991
- web = Polygon(
1992
- [
1993
- (-tw / 2, -h / 2 + tf),
1994
- (tw / 2, -h / 2 + tf),
1995
- (tw / 2, h / 2 - tf),
1996
- (-tw / 2, h / 2 - tf),
1997
- ]
1998
- )
1999
- # fillets
2000
- p = Point([tw / 2 + r, -h / 2 + tf + r]).buffer(r)
2001
- s = Polygon(
2002
- [
2003
- (tw / 2, -h / 2 + tf),
2004
- (tw / 2 + r, -h / 2 + tf),
2005
- (tw / 2 + r, -h / 2 + tf + r),
2006
- (tw / 2, -h / 2 + tf + r),
2007
- ]
2008
- )
2009
- fillet = s.difference(p)
2010
- p = Point([-tw / 2 - r, -h / 2 + tf + r]).buffer(r)
2011
- s = Polygon(
2012
- [
2013
- (-tw / 2 - r, -h / 2 + tf),
2014
- (-tw / 2, -h / 2 + tf),
2015
- (-tw / 2, -h / 2 + tf + r),
2016
- (-tw / 2 - r, -h / 2 + tf + r),
2017
- ]
2018
- )
2019
- fillet = s.difference(p).union(fillet)
2020
- fillet = translate(
2021
- scale(fillet, 1, -1), xoff=0, yoff=h - 2 * tf - r
2022
- ).union(fillet)
2023
- # Create the geometry
2024
- geometries = [
2025
- set_precision(geometry, grid_size=1e-13)
2026
- for geometry in [fillet, top_flange, bottom_flange, web]
2027
- ]
2028
- return orient(unary_union(geometries), 1)
2029
-
2030
-
2031
- def _create_taper_I_section(
2032
- h: float,
2033
- b: float,
2034
- tw: float,
2035
- tf: float,
2036
- r1: float,
2037
- r2: float,
2038
- slope: float,
2039
- ) -> Polygon:
2040
- """Returns a shapely polygon representing a Taper Flange I Section."""
2041
- # Create first part of line
2042
- ls = [
2043
- set_precision(
2044
- LineString([[0, -h / 2], [b / 2, -h / 2]]), grid_size=1e-13
2045
- )
2046
- ]
2047
- # Create first fillet
2048
- xy = np.array(
2049
- [
2050
- [b / 2, -h / 2],
2051
- [b / 2, -h / 2 + tf - (b / 4 * slope)],
2052
- [b / 4, -h / 2 + tf],
2053
- ]
2054
- )
2055
- ls.append(
2056
- set_precision(
2057
- LineString(xy).offset_curve(r2).offset_curve(-r2), grid_size=1e-13
2058
- )
2059
- )
2060
- # Create second fillet
2061
- xy = np.array(
2062
- [
2063
- [b / 4, -h / 2 + tf],
2064
- [tw / 2, -h / 2 + tf + (b / 4 - tw / 2) * slope],
2065
- [tw / 2, 0],
2066
- ]
2067
- )
2068
- ls.append(
2069
- set_precision(
2070
- LineString(xy).offset_curve(-r1).offset_curve(r1), grid_size=1e-13
2071
- )
2072
- )
2073
-
2074
- # Merge filleted
2075
- merged_ls = linemerge(ls)
2076
-
2077
- # mirror the parts
2078
- merged_ls = linemerge(
2079
- [
2080
- merged_ls,
2081
- translate(scale(merged_ls, -1, 1), -b / 2, 0),
2082
- ]
2083
- )
2084
- merged_ls = linemerge(
2085
- [
2086
- merged_ls,
2087
- translate(scale(merged_ls, 1, -1), 0, h / 2),
2088
- ]
2089
- )
2090
-
2091
- # Create a polygon
2092
- poly = polygonize([merged_ls])
2093
-
2094
- # Return the first and only polygon of this collection
2095
- return orient(get_geometry(poly, 0), 1)
2096
-
2097
-
2098
- def _create_taper_U_section(
2099
- h: float,
2100
- b: float,
2101
- tw: float,
2102
- tf: float,
2103
- r1: float,
2104
- r2: float,
2105
- slope: float,
2106
- u: float,
2107
- ) -> Polygon:
2108
- """Returns a shapely polygon representing a Taper Flange U Section."""
2109
- # Create first part of line
2110
- ls = [
2111
- set_precision(
2112
- LineString([[0, h / 2], [0, 0], [b, 0]]), grid_size=1e-13
2113
- )
2114
- ]
2115
- # Create first fillet
2116
- xy = np.array([[b, 0], [b, tf - slope * u], [b - u, tf]])
2117
- ls.append(
2118
- set_precision(
2119
- LineString(xy).offset_curve(r2).offset_curve(-r2), grid_size=1e-13
2120
- )
2121
- )
2122
- # Create second fillet
2123
- xy = np.array(
2124
- [
2125
- [b - u, tf],
2126
- [tw, tf + slope * (b - u - tw)],
2127
- [tw, h / 2],
2128
- ]
2129
- )
2130
- ls.append(
2131
- set_precision(
2132
- LineString(xy).offset_curve(-r1).offset_curve(r1), grid_size=1e-13
2133
- )
2134
- )
2135
-
2136
- # Merge filleted
2137
- merged_ls = linemerge(ls)
2138
-
2139
- # mirror the parts
2140
- merged_ls = linemerge(
2141
- [
2142
- merged_ls,
2143
- translate(scale(merged_ls, 1, -1), 0, h / 2),
2144
- ]
2145
- )
2146
-
2147
- # Create a polygon
2148
- poly = polygonize([merged_ls])
2149
-
2150
- # Get the first and only polygon of this collection
2151
- poly = get_geometry(poly, 0)
2152
- # Translate it to the centroid when returning
2153
- return orient(
2154
- translate(poly, xoff=-poly.centroid.x, yoff=-poly.centroid.y), 1
2155
- )