civil-tools-v 0.0.1__py3-none-any.whl → 0.0.2__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.
Files changed (45) hide show
  1. CivilTools/Const/CAD.py +2 -0
  2. CivilTools/Const/Concrete.py +144 -0
  3. CivilTools/Const/Steel.py +21 -0
  4. CivilTools/Const/__init__.py +3 -0
  5. CivilTools/DXFGenerator/BasicDXF.py +238 -1
  6. CivilTools/DXFGenerator/DetailDXF.py +324 -0
  7. CivilTools/DXFGenerator/DrawingAttribs.py +45 -0
  8. CivilTools/DXFGenerator/LayerManager.py +37 -0
  9. CivilTools/DXFGenerator/__init__.py +3 -0
  10. CivilTools/FigureGenerator/BasicPNGPlotter.py +28 -25
  11. CivilTools/FigureGenerator/BasicPltPlotter.py +56 -1
  12. CivilTools/FigureGenerator/StairCalculationSheetPNGPlotter.py +2 -8
  13. CivilTools/ReportGenerator/BasicGenerator.py +109 -83
  14. CivilTools/ReportGenerator/DocParagraph.py +3 -5
  15. CivilTools/ReportGenerator/DocPicture.py +7 -8
  16. CivilTools/ReportGenerator/DocTable.py +11 -11
  17. CivilTools/ReportGenerator/SeismicReport.py +302 -143
  18. CivilTools/ReportGenerator/SeismicReportTemplate.py +523 -202
  19. CivilTools/ReportGenerator/StairCalculationReport.py +249 -185
  20. CivilTools/ReportGenerator/UtilFunctions.py +108 -104
  21. CivilTools/ReportGenerator/__init__.py +2 -2
  22. CivilTools/YDBLoader/BuildingDefine/Beam/Beam.py +12 -15
  23. CivilTools/YDBLoader/BuildingDefine/Column/Column.py +5 -5
  24. CivilTools/YDBLoader/BuildingDefine/ComponentType.py +1 -1
  25. CivilTools/YDBLoader/BuildingDefine/Geometry/Grid.py +8 -12
  26. CivilTools/YDBLoader/BuildingDefine/Geometry/Joint.py +11 -10
  27. CivilTools/YDBLoader/BuildingDefine/Geometry/StandFloor.py +1 -1
  28. CivilTools/YDBLoader/BuildingDefine/GlobalResult/BasicResult.py +29 -20
  29. CivilTools/YDBLoader/BuildingDefine/GlobalResult/SeismicResult.py +149 -54
  30. CivilTools/YDBLoader/BuildingDefine/Section/Section.py +26 -31
  31. CivilTools/YDBLoader/BuildingDefine/Section/ShapeEnum.py +9 -9
  32. CivilTools/YDBLoader/BuildingDefine/Slab/Slab.py +1 -1
  33. CivilTools/YDBLoader/BuildingDefine/StairPart/LoadDefine.py +16 -10
  34. CivilTools/YDBLoader/BuildingDefine/StairPart/StairComponent.py +41 -37
  35. CivilTools/YDBLoader/BuildingDefine/StairPart/StairPart.py +133 -78
  36. CivilTools/YDBLoader/SQLiteConnector/Connector.py +16 -8
  37. CivilTools/YDBLoader/SQLiteConnector/RowDataFactory.py +19 -17
  38. CivilTools/YDBLoader/SQLiteConnector/YDBTableName.py +31 -20
  39. CivilTools/YDBLoader/YDBLoader.py +129 -110
  40. {civil_tools_v-0.0.1.dist-info → civil_tools_v-0.0.2.dist-info}/METADATA +88 -5
  41. civil_tools_v-0.0.2.dist-info/RECORD +57 -0
  42. {civil_tools_v-0.0.1.dist-info → civil_tools_v-0.0.2.dist-info}/WHEEL +1 -1
  43. civil_tools_v-0.0.1.dist-info/RECORD +0 -50
  44. {civil_tools_v-0.0.1.dist-info → civil_tools_v-0.0.2.dist-info}/LICENSE +0 -0
  45. {civil_tools_v-0.0.1.dist-info → civil_tools_v-0.0.2.dist-info}/top_level.txt +0 -0
@@ -3,78 +3,174 @@ import abc
3
3
  from typing import List
4
4
  import matplotlib.pyplot as plt
5
5
 
6
+
6
7
  class SinglePeriod:
7
- """单个周期
8
- """
8
+ """单个周期"""
9
+
9
10
  def __init__(
10
- self,index:int,
11
- time:float,
12
- angle:float = 0,
13
- coeff_x:float = 1,
14
- coeff_y:float = 0,
15
- coeff_z:float = 0,
16
- mass_particpate_x:float = 0,
17
- mass_particpate_y:float = 0,
18
- mass_particpate_z:float = 0,
11
+ self,
12
+ index: int,
13
+ time: float,
14
+ angle: float = 0,
15
+ coeff_x: float = 1,
16
+ coeff_y: float = 0,
17
+ coeff_z: float = 0,
18
+ mass_particpate_x: float = 0,
19
+ mass_particpate_y: float = 0,
20
+ mass_particpate_z: float = 0,
19
21
  ):
20
22
  self.index = index
21
23
  self.time = time
22
24
  self.angle = angle
23
- assert abs(coeff_x
24
- + coeff_y
25
- + coeff_z-1)<0.01 ,"The sum of three participite coeff should == 1"
25
+ assert (
26
+ abs(coeff_x + coeff_y + coeff_z - 1) < 0.01
27
+ ), "The sum of three participite coeff should == 1"
26
28
  self.coeff_x = coeff_x
27
29
  self.coeff_y = coeff_y
28
30
  self.coeff_z = coeff_z
31
+ if coeff_x >= coeff_y and coeff_x >= coeff_z:
32
+ self.direction = "X"
33
+ elif coeff_y >= coeff_x and coeff_y >= coeff_z:
34
+ self.direction = "Y"
35
+ else:
36
+ self.direction = "Z"
29
37
  self.mass_participate_x = mass_particpate_x
30
38
  self.mass_participate_y = mass_particpate_y
31
39
  self.mass_participate_z = mass_particpate_z
32
-
40
+
41
+ @property
42
+ def time_str(self):
43
+ return f"{self.time:.4f}"
44
+
45
+ @property
46
+ def movement_coeff(self):
47
+ return (
48
+ f"{self.coeff_x + self.coeff_y:.2f} ({self.coeff_x:.2f}+{self.coeff_y:.2f})"
49
+ )
50
+
51
+ @property
52
+ def rotation_coeff(self):
53
+ return f"{self.coeff_z:.2f}"
54
+
55
+ def get_mass_participate_x(self, last):
56
+ return f"{self.mass_participate_x*100:.1f} ({(self.mass_participate_x + last)*100:.1f})"
57
+
58
+ def get_mass_participate_y(self, last):
59
+ return f"{self.mass_participate_y*100:.1f} ({(self.mass_participate_y + last)*100:.1f})"
60
+
33
61
  def __str__(self):
34
- return f"T{self.index}:\t{self.time:.4f}s\t[X:{self.coeff_x*100:.1f}%;\tY:{self.coeff_y*100:.1f}%;\tZ:{self.coeff_z*100:.1f}%]"
35
-
62
+ return f"T{self.index}:\t{self.time:.4f}s\t[X:{self.coeff_x*100:.1f}%;\tY:{self.coeff_y*100:.1f}%;\tZ:{self.coeff_z*100:.1f}%]"
63
+
36
64
  def __repr__(self):
37
- return str(self)
65
+ return str(self)
66
+
38
67
 
39
68
  class Period:
40
- def __init__(self,periods:List[SinglePeriod] , model_type = None):
69
+ def __init__(self, periods: List[SinglePeriod], model_type=None):
70
+ if len(periods) < 3:
71
+ raise ValueError("At least three periods is needed.")
41
72
  self.periods = periods
42
-
73
+
43
74
  def __str__(self):
44
- if len(self.periods)<=10:
75
+ if len(self.periods) <= 10:
45
76
  return "\n".join([str(period) for period in self.periods])
46
77
  else:
47
78
  result = "\n".join([str(period) for period in self.periods[:9]])
48
79
  result += "\n....\n"
49
80
  result += str(self.periods[-1])
50
81
  return result
51
-
82
+
52
83
  def __repr__(self):
53
84
  return self.__str__()
54
-
85
+
86
+ @classmethod
87
+ def mock_data(
88
+ cls, order: str = "xyz", num: int = 40, mass_participate: float = 0.95
89
+ ):
90
+ single_period_list = []
91
+ single_period_list.append(
92
+ SinglePeriod(
93
+ 1,
94
+ 2.5,
95
+ 0,
96
+ order[0] == "x",
97
+ order[0] == "y",
98
+ order[0] == "z",
99
+ 0.1,
100
+ 0.1,
101
+ 0.1,
102
+ )
103
+ )
104
+ single_period_list.append(
105
+ SinglePeriod(
106
+ 2,
107
+ 2.0,
108
+ 0,
109
+ order[1] == "x",
110
+ order[1] == "y",
111
+ order[1] == "z",
112
+ 0.2,
113
+ 0.2,
114
+ 0.2,
115
+ )
116
+ )
117
+ single_period_list.append(
118
+ SinglePeriod(
119
+ 3,
120
+ 1.5,
121
+ 0,
122
+ order[2] == "x",
123
+ order[2] == "y",
124
+ order[2] == "z",
125
+ 0.3,
126
+ 0.3,
127
+ 0.3,
128
+ )
129
+ )
130
+
131
+ for i in range(num - 3):
132
+ single_period_list.append(
133
+ SinglePeriod(
134
+ i + 4,
135
+ 0.5 - 0.01 * i,
136
+ 0,
137
+ 1,
138
+ 0,
139
+ 0,
140
+ mass_participate,
141
+ mass_participate,
142
+ mass_participate,
143
+ )
144
+ )
145
+ return Period(single_period_list)
146
+
147
+
55
148
  class ValuePeer:
56
- def __init__(self, x:float, y:float):
149
+ def __init__(self, x: float, y: float):
57
150
  self.x = x
58
151
  self.y = y
152
+
59
153
  def __str__(self):
60
- if self.x >500:
154
+ if self.x > 500:
61
155
  return f"X:{self.x:.1f}\tY:{self.y:.1f}"
62
- elif self.x >5:
156
+ elif self.x > 5:
63
157
  return f"X:{self.x:.2f}\tY:{self.y:.2f}"
64
158
  else:
65
159
  return f"X:{self.x:.3f}\tY:{self.y:.3f}"
66
-
160
+
161
+
67
162
  class FloorSeismicResult:
68
- def __init__(self,
69
- floor_num: int,
70
- tower_num: int,
71
- force:ValuePeer = None,
72
- shear:ValuePeer = None,
73
- moment:ValuePeer = None,
74
- disp:ValuePeer = None,
75
- stiffness:ValuePeer = None,
76
- shear_capacity:ValuePeer = None,
77
- ):
163
+ def __init__(
164
+ self,
165
+ floor_num: int,
166
+ tower_num: int,
167
+ force: ValuePeer = None,
168
+ shear: ValuePeer = None,
169
+ moment: ValuePeer = None,
170
+ disp: ValuePeer = None,
171
+ stiffness: ValuePeer = None,
172
+ shear_capacity: ValuePeer = None,
173
+ ):
78
174
  self.floor_num = floor_num
79
175
  self.tower_num = tower_num
80
176
  self.force = force
@@ -83,46 +179,45 @@ class FloorSeismicResult:
83
179
  self.disp = disp
84
180
  self.stiffness = stiffness
85
181
  self.shear_capacity = shear_capacity
86
-
182
+
87
183
  def __str__(self):
88
184
  return f"Flr.{self.floor_num}:Fx={self.force.x};Fy={self.force.y}"
89
185
 
90
186
  def __repr__(self):
91
187
  return self.__str__()
92
188
 
189
+
93
190
  class SeismicResult:
94
- def __init__(self,
95
- floor_result : List[FloorSeismicResult]
96
- ):
191
+ def __init__(self, floor_result: List[FloorSeismicResult]):
97
192
  self.floor_result = floor_result
98
-
193
+
99
194
  @property
100
195
  def seismic_shear_x(self):
101
196
  return [i.shear.x for i in self.floor_result]
102
-
197
+
103
198
  @property
104
199
  def floor_index(self):
105
- return [i+1 for i in range(len(self.floor_result))]
106
-
200
+ return [i + 1 for i in range(len(self.floor_result))]
201
+
107
202
  def plot_shear(self):
108
- fig,ax = plt.subplots(figsize=(2,5))
109
- ax.plot(self.seismic_shear_x,self.floor_index)
110
- return fig,ax
111
-
203
+ fig, ax = plt.subplots(figsize=(2, 5))
204
+ ax.plot(self.seismic_shear_x, self.floor_index)
205
+ return fig, ax
206
+
112
207
  def __str__(self):
113
208
  result = f"Total floor: {len(self.floor_result)}\n"
114
209
  for temp_result in self.floor_result:
115
210
  result += str(temp_result)
116
211
  result += "\n"
117
212
  return result
118
-
213
+
119
214
  def __repr__(self):
120
215
  return self.__str__()
121
-
122
-
216
+
217
+
123
218
  if __name__ == "__main__":
124
219
  p_list = []
125
220
  for i in range(112):
126
- p_list.append(SinglePeriod(i+1,i*0.1+0.1,0,1-i*0.1,i*0.1,0))
221
+ p_list.append(SinglePeriod(i + 1, i * 0.1 + 0.1, 0, 1 - i * 0.1, i * 0.1, 0))
127
222
  P = Period(p_list)
128
- print(str(P))
223
+ print(str(P))
@@ -1,49 +1,44 @@
1
1
  from .ShapeEnum import ShapeEnum
2
2
  from typing import List
3
3
 
4
+
4
5
  class Section:
5
- def __init__(self,
6
- id:int,
7
- k:ShapeEnum,
8
- vals:List[float],
9
- mat:int = 1
10
- ):
6
+ def __init__(self, id: int, k: ShapeEnum, vals: List[float], mat: int = 1):
11
7
  self.id = id
12
8
  self.k = k
13
9
  self.mat = mat
14
10
  value_number = len(vals)
15
- self.b = vals[0] if value_number>=1 else None
16
- self.h = vals[1] if value_number>=2 else None
17
- self.u = vals[2] if value_number>=3 else None
18
- self.t = vals[3] if value_number>=4 else None
19
- self.d = vals[4] if value_number>=5 else None
20
- self.f = vals[5] if value_number>=6 else None
21
-
11
+ self.b = vals[0] if value_number >= 1 else None
12
+ self.h = vals[1] if value_number >= 2 else None
13
+ self.u = vals[2] if value_number >= 3 else None
14
+ self.t = vals[3] if value_number >= 4 else None
15
+ self.d = vals[4] if value_number >= 5 else None
16
+ self.f = vals[5] if value_number >= 6 else None
22
17
 
23
18
  def __str__(self):
24
- '''todo:这里需要完善str方法'''
19
+ """todo:这里需要完善str方法"""
25
20
  display_function = {
26
- ShapeEnum.Rect : lambda : f"Rect-{self.b}mmx{self.h}mm",
27
- ShapeEnum.HShape : lambda : f"{self.b}",
28
- ShapeEnum.Circle : lambda : f"Circle-Diameter:{self.b}mm",
29
- ShapeEnum.RegularPolygon : lambda : f"{self.b}",
30
- ShapeEnum.Groove : lambda : f"{self.b}",
31
- ShapeEnum.Cross : lambda : f"{self.b}",
32
- ShapeEnum.Box : lambda : f"{self.b}",
33
- ShapeEnum.CircleTube : lambda : f"{self.b}",
34
- ShapeEnum.CircleCFT : lambda : f"{self.b}",
35
- ShapeEnum.HSRC : lambda : f"{self.b}",
36
- ShapeEnum.BoxSRC : lambda : f"{self.b}",
37
- ShapeEnum.CrossSRC : lambda : f"{self.b}",
38
-
39
- ShapeEnum.UnKnown : lambda : f"Unknown:{self.b}"
21
+ ShapeEnum.Rect: lambda: f"Rect-{self.b}mmx{self.h}mm",
22
+ ShapeEnum.HShape: lambda: f"{self.b}",
23
+ ShapeEnum.Circle: lambda: f"Circle-Diameter:{self.b}mm",
24
+ ShapeEnum.RegularPolygon: lambda: f"{self.b}",
25
+ ShapeEnum.Groove: lambda: f"{self.b}",
26
+ ShapeEnum.Cross: lambda: f"{self.b}",
27
+ ShapeEnum.Box: lambda: f"{self.b}",
28
+ ShapeEnum.CircleTube: lambda: f"{self.b}",
29
+ ShapeEnum.CircleCFT: lambda: f"{self.b}",
30
+ ShapeEnum.HSRC: lambda: f"{self.b}",
31
+ ShapeEnum.BoxSRC: lambda: f"{self.b}",
32
+ ShapeEnum.CrossSRC: lambda: f"{self.b}",
33
+ ShapeEnum.UnKnown: lambda: f"Unknown:{self.b}",
40
34
  }
41
35
  return display_function[self.k]()
42
-
36
+
43
37
  def __repr__(self):
44
38
  return self.__str__()
45
39
 
40
+
46
41
  if __name__ == "__main__":
47
- s = Section(1,ShapeEnum.Circle,[20,32])
42
+ s = Section(1, ShapeEnum.Circle, [20, 32])
48
43
 
49
- print(s)
44
+ print(s)
@@ -1,5 +1,7 @@
1
1
  from enum import Enum
2
2
  import warnings
3
+
4
+
3
5
  class ShapeEnum(Enum):
4
6
  # 矩形
5
7
  Rect = 1
@@ -25,18 +27,16 @@ class ShapeEnum(Enum):
25
27
  BoxSRC = 14
26
28
  # 十字劲
27
29
  CrossSRC = 15
28
-
30
+
29
31
  # 未知截面均归于这个类别
30
32
  UnKnown = 999
31
-
33
+
32
34
  @classmethod
33
- def ConvertToShapeEnum(cls,index:int):
34
- try:
35
+ def ConvertToShapeEnum(cls, index: int):
36
+ try:
35
37
  return (ShapeEnum)(index)
36
38
  except ValueError:
37
- warnings.warn(f"Shape kind ${index} is not supported yet. It will be converted to UnKnown.")
39
+ warnings.warn(
40
+ f"Shape kind ${index} is not supported yet. It will be converted to UnKnown."
41
+ )
38
42
  return ShapeEnum.UnKnown
39
-
40
-
41
-
42
-
@@ -1,2 +1,2 @@
1
1
  class Slab:
2
- pass
2
+ pass
@@ -1,5 +1,6 @@
1
1
  from enum import Enum
2
2
 
3
+
3
4
  class LoadParams:
4
5
  def __init__(self):
5
6
  self.append_dead_load = 1
@@ -8,31 +9,36 @@ class LoadParams:
8
9
  self.live_load_coef = 1.5
9
10
  self.live_load_adjust_coef = 1
10
11
  self.live_load_permenent_coef = 0.5
11
-
12
+
13
+
12
14
  class LoadType(Enum):
13
15
  Dead = 1
14
16
  Live = 2
15
-
17
+
18
+
16
19
  class LoadCalulateType(Enum):
17
20
  qk = 1
18
21
  q = 2
19
22
  qe = 3
20
-
23
+
24
+
21
25
  class StairLoad:
22
- def __init__(self, dead, live, load_params:LoadParams):
26
+ def __init__(self, dead, live, load_params: LoadParams):
23
27
  self.dead = dead
24
28
  self.live = live
25
29
  self.load_params = load_params
26
-
30
+
27
31
  @property
28
32
  def qk(self):
29
33
  return self.dead + self.live
30
-
34
+
31
35
  @property
32
36
  def q(self):
33
- return self.load_params.dead_load_coef* self.dead +self.load_params.live_load_coef* self.live
34
-
37
+ return (
38
+ self.load_params.dead_load_coef * self.dead
39
+ + self.load_params.live_load_coef * self.live
40
+ )
41
+
35
42
  @property
36
43
  def qe(self):
37
- return self.dead + self.load_params.live_load_permenent_coef* self.live
38
-
44
+ return self.dead + self.load_params.live_load_permenent_coef * self.live
@@ -1,40 +1,47 @@
1
1
  import math
2
2
  import numpy as np
3
3
 
4
+
4
5
  class Component:
5
-
6
+
6
7
  def init_attr(self):
7
8
  self.E = 30000
8
9
  self.B = 1000
9
10
  self.H = 150
10
11
  self.vertical_q = 10
11
- self.length = math.sqrt((self.end_point[1] - self.start_point[1])**2 + (self.end_point[0] - self.start_point[0])**2)
12
+ self.length = math.sqrt(
13
+ (self.end_point[1] - self.start_point[1]) ** 2
14
+ + (self.end_point[0] - self.start_point[0]) ** 2
15
+ )
12
16
  if self.start_point[0] == self.end_point[0]:
13
17
  self.alpha = 0
14
18
  else:
15
- self.alpha = math.atan((self.end_point[1] - self.start_point[1]) / (self.end_point[0] - self.start_point[0]))
16
-
17
- def __init__(self,p1,p2) -> None:
19
+ self.alpha = math.atan(
20
+ (self.end_point[1] - self.start_point[1])
21
+ / (self.end_point[0] - self.start_point[0])
22
+ )
23
+
24
+ def __init__(self, p1, p2) -> None:
18
25
  self.start_point = p1
19
26
  self.end_point = p2
20
27
  self.section_kind = "Rectangle"
21
28
  self.init_attr()
22
-
23
- def set_comp_attr(self,e,b,h):
29
+
30
+ def set_comp_attr(self, e, b, h):
24
31
  self.E = e
25
32
  self.B = b
26
33
  self.H = h
27
-
34
+
28
35
  def set_vertical_q(self, q):
29
36
  self.vertical_q = q
30
-
37
+
31
38
  def create_k(self):
32
39
  self.calculate_section_attr()
33
- K = np.zeros((6,6))
34
-
40
+ K = np.zeros((6, 6))
41
+
35
42
  l = self.length
36
- i = self.E *self.I / l
37
- B = self.E *self.area / l
43
+ i = self.E * self.I / l
44
+ B = self.E * self.area / l
38
45
  c_x = math.cos(self.alpha)
39
46
  c_y = math.sin(self.alpha)
40
47
  a1 = B * c_x * c_x + 12 * i / l / l * c_y * c_y
@@ -56,40 +63,37 @@ class Component:
56
63
  K[2, 2] = K[5, 5] = a6
57
64
  K[2, 5] = K[5, 2] = a6 / 2
58
65
  return K
59
-
66
+
60
67
  def create_f(self):
61
- F = np.zeros((6,1))
68
+ F = np.zeros((6, 1))
62
69
  # 这里只针对竖向荷载
63
70
  length = abs(self.end_point[0] - self.start_point[0])
64
-
65
- F[1,0] = -self.vertical_q * length / 2
66
- F[2,0] = -self.vertical_q * length ** 2 / 12
67
- F[4,0] = -self.vertical_q * length / 2
68
- F[5,0] = self.vertical_q * length ** 2 / 12
71
+
72
+ F[1, 0] = -self.vertical_q * length / 2
73
+ F[2, 0] = -self.vertical_q * length**2 / 12
74
+ F[4, 0] = -self.vertical_q * length / 2
75
+ F[5, 0] = self.vertical_q * length**2 / 12
69
76
  return F
70
-
77
+
71
78
  def calculate_section_attr(self):
72
79
  if self.section_kind == "Rectangle":
73
- self.I = self.B * self.H **3 / 12
80
+ self.I = self.B * self.H**3 / 12
74
81
  self.area = self.B * self.H
75
-
76
-
77
- def set_f(self,f_1_x,f_1_y,f_2_x,f_2_y):
78
- self.f_1_x = f_1_x/1e3
79
- self.f_1_y = f_1_y/1e3
80
- self.f_2_x = f_2_x/1e3
81
- self.f_2_y = f_2_y/1e3
82
-
82
+
83
+ def set_f(self, f_1_x, f_1_y, f_2_x, f_2_y):
84
+ self.f_1_x = f_1_x / 1e3
85
+ self.f_1_y = f_1_y / 1e3
86
+ self.f_2_x = f_2_x / 1e3
87
+ self.f_2_y = f_2_y / 1e3
88
+
83
89
  def set_m(self, m_1, m_2):
84
- self.m_1 = m_1/1e6
85
- self.m_2 = m_2/1e6
86
-
90
+ self.m_1 = m_1 / 1e6
91
+ self.m_2 = m_2 / 1e6
87
92
 
88
93
  @property
89
94
  def v1(self):
90
- return self.f_1_y*np.cos(self.alpha) - self.f_1_x*np.sin(self.alpha)
91
-
95
+ return self.f_1_y * np.cos(self.alpha) - self.f_1_x * np.sin(self.alpha)
96
+
92
97
  @property
93
98
  def v2(self):
94
- return -self.f_2_y*np.cos(self.alpha) + self.f_2_x*np.sin(self.alpha)
95
-
99
+ return -self.f_2_y * np.cos(self.alpha) + self.f_2_x * np.sin(self.alpha)