RCAIDE-GUI 1.0.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.
Files changed (170) hide show
  1. common_widgets/__init__.py +6 -0
  2. common_widgets/animated_toggle.py +141 -0
  3. common_widgets/color.py +17 -0
  4. common_widgets/data_entry_widget.py +337 -0
  5. common_widgets/image_widget.py +21 -0
  6. common_widgets/unit_picker_widget.py +48 -0
  7. main.py +168 -0
  8. rcaide_gui-1.0.0.dist-info/METADATA +96 -0
  9. rcaide_gui-1.0.0.dist-info/RECORD +170 -0
  10. rcaide_gui-1.0.0.dist-info/WHEEL +5 -0
  11. rcaide_gui-1.0.0.dist-info/entry_points.txt +2 -0
  12. rcaide_gui-1.0.0.dist-info/top_level.txt +5 -0
  13. rcaide_io.py +818 -0
  14. tabs/__init__.py +10 -0
  15. tabs/aircraft_configs/__init__.py +3 -0
  16. tabs/aircraft_configs/aircraft_configs.py +301 -0
  17. tabs/analysis/__init__.py +4 -0
  18. tabs/analysis/analysis.py +92 -0
  19. tabs/analysis/widgets/__init__.py +13 -0
  20. tabs/analysis/widgets/aeroacoustics_widget.py +158 -0
  21. tabs/analysis/widgets/aerodynamics_widget.py +108 -0
  22. tabs/analysis/widgets/analysis_data_widget.py +29 -0
  23. tabs/analysis/widgets/atmosphere_widget.py +49 -0
  24. tabs/analysis/widgets/costs_widget.py +35 -0
  25. tabs/analysis/widgets/energy_widget.py +32 -0
  26. tabs/analysis/widgets/geometry_widget.py +55 -0
  27. tabs/analysis/widgets/planets_widget.py +34 -0
  28. tabs/analysis/widgets/propulsion_widget.py +53 -0
  29. tabs/analysis/widgets/stability_widget.py +34 -0
  30. tabs/analysis/widgets/weights_widget.py +94 -0
  31. tabs/geometry/__init__.py +6 -0
  32. tabs/geometry/aircraft_configs.py +232 -0
  33. tabs/geometry/frames/__init__.py +15 -0
  34. tabs/geometry/frames/booms/__init__.py +5 -0
  35. tabs/geometry/frames/booms/boom_frame.py +238 -0
  36. tabs/geometry/frames/cargo_bays/__init__.py +5 -0
  37. tabs/geometry/frames/cargo_bays/cargo_bay_frame.py +159 -0
  38. tabs/geometry/frames/default_frame.py +23 -0
  39. tabs/geometry/frames/energy_network/__init__.py +2 -0
  40. tabs/geometry/frames/energy_network/turbofan_network/__init__.py +3 -0
  41. tabs/geometry/frames/energy_network/turbofan_network/frames/__init__.py +1 -0
  42. tabs/geometry/frames/energy_network/turbofan_network/widgets/__init__.py +1 -0
  43. tabs/geometry/frames/fuselages/__init__.py +5 -0
  44. tabs/geometry/frames/fuselages/fuselage_frame.py +294 -0
  45. tabs/geometry/frames/geometry_frame.py +91 -0
  46. tabs/geometry/frames/landing_gears/__init__.py +5 -0
  47. tabs/geometry/frames/landing_gears/landing_gear_frame.py +189 -0
  48. tabs/geometry/frames/nacelles/__init__.py +1 -0
  49. tabs/geometry/frames/powertrain/__init__.py +6 -0
  50. tabs/geometry/frames/powertrain/converters/__init__.py +5 -0
  51. tabs/geometry/frames/powertrain/converters/converter_frame.py +137 -0
  52. tabs/geometry/frames/powertrain/distributors/__init__.py +5 -0
  53. tabs/geometry/frames/powertrain/distributors/distributor_frame.py +143 -0
  54. tabs/geometry/frames/powertrain/nacelles/__init__.py +5 -0
  55. tabs/geometry/frames/powertrain/nacelles/nacelle_frame.py +283 -0
  56. tabs/geometry/frames/powertrain/powertrain_frame.py +259 -0
  57. tabs/geometry/frames/powertrain/propulsors/__init__.py +5 -0
  58. tabs/geometry/frames/powertrain/propulsors/propulsor_frame.py +146 -0
  59. tabs/geometry/frames/powertrain/sources/__init__.py +6 -0
  60. tabs/geometry/frames/powertrain/sources/energy_source_frame.py +147 -0
  61. tabs/geometry/frames/vehicle_frame.py +171 -0
  62. tabs/geometry/frames/wings/__init__.py +5 -0
  63. tabs/geometry/frames/wings/wings_frame.py +457 -0
  64. tabs/geometry/geometry.py +513 -0
  65. tabs/geometry/widgets/__init__.py +12 -0
  66. tabs/geometry/widgets/booms/__init__.py +6 -0
  67. tabs/geometry/widgets/booms/boom_section_widget.py +109 -0
  68. tabs/geometry/widgets/cargo_bays/__init__.py +1 -0
  69. tabs/geometry/widgets/fuselages/__init__.py +8 -0
  70. tabs/geometry/widgets/fuselages/cabin_class_widget.py +188 -0
  71. tabs/geometry/widgets/fuselages/cabin_widget.py +217 -0
  72. tabs/geometry/widgets/fuselages/fuselage_section_widget.py +190 -0
  73. tabs/geometry/widgets/geometry_data_widget.py +25 -0
  74. tabs/geometry/widgets/landing_gears/__init__.py +6 -0
  75. tabs/geometry/widgets/nacelles/__init__.py +1 -0
  76. tabs/geometry/widgets/powertrain/__init__.py +9 -0
  77. tabs/geometry/widgets/powertrain/converters/__init__.py +5 -0
  78. tabs/geometry/widgets/powertrain/converters/turboelectric_generator_widget.py +74 -0
  79. tabs/geometry/widgets/powertrain/distributors/__init__.py +5 -0
  80. tabs/geometry/widgets/powertrain/distributors/fuel_line_widget.py +81 -0
  81. tabs/geometry/widgets/powertrain/modulators/__init__.py +5 -0
  82. tabs/geometry/widgets/powertrain/modulators/esc_widget.py +58 -0
  83. tabs/geometry/widgets/powertrain/nacelles/__init__.py +5 -0
  84. tabs/geometry/widgets/powertrain/nacelles/nacelle_section_widget.py +115 -0
  85. tabs/geometry/widgets/powertrain/powertrain_connector_widget.py +136 -0
  86. tabs/geometry/widgets/powertrain/powertrain_widget.py +206 -0
  87. tabs/geometry/widgets/powertrain/propulsors/__init__.py +5 -0
  88. tabs/geometry/widgets/powertrain/propulsors/turbofan_widget.py +462 -0
  89. tabs/geometry/widgets/powertrain/sources/__init__.py +6 -0
  90. tabs/geometry/widgets/powertrain/sources/fuel_tank_widget.py +103 -0
  91. tabs/geometry/widgets/powertrain/sources/source_selector_widget.py +35 -0
  92. tabs/geometry/widgets/wings/__init__.py +7 -0
  93. tabs/geometry/widgets/wings/wing_cs_widget.py +198 -0
  94. tabs/geometry/widgets/wings/wing_section_widget.py +298 -0
  95. tabs/home/__init__.py +3 -0
  96. tabs/home/home.py +585 -0
  97. tabs/mission/__init__.py +4 -0
  98. tabs/mission/mission.py +1124 -0
  99. tabs/mission/widgets/__init__.py +3 -0
  100. tabs/mission/widgets/flight_controls_widget.py +186 -0
  101. tabs/mission/widgets/mission_analysis_widget.py +166 -0
  102. tabs/mission/widgets/mission_segment_helper.py +358 -0
  103. tabs/mission/widgets/mission_segment_widget.py +358 -0
  104. tabs/solve/__init__.py +4 -0
  105. tabs/solve/plots/__init__.py +12 -0
  106. tabs/solve/plots/aeroacoustics/__init__.py +6 -0
  107. tabs/solve/plots/aeroacoustics/plot_2D_noise_contour.py +184 -0
  108. tabs/solve/plots/aeroacoustics/plot_3D_noise_contour.py +219 -0
  109. tabs/solve/plots/aeroacoustics/plot_noise_certification_contour.py +115 -0
  110. tabs/solve/plots/aeroacoustics/plot_noise_level.py +118 -0
  111. tabs/solve/plots/aerodynamics/__init__.py +10 -0
  112. tabs/solve/plots/aerodynamics/plot_aerodynamic_coefficients.py +156 -0
  113. tabs/solve/plots/aerodynamics/plot_aerodynamic_forces.py +155 -0
  114. tabs/solve/plots/aerodynamics/plot_aircraft_aerodynamics.py +136 -0
  115. tabs/solve/plots/aerodynamics/plot_drag_components.py +157 -0
  116. tabs/solve/plots/aerodynamics/plot_lift_distribution.py +107 -0
  117. tabs/solve/plots/aerodynamics/plot_rotor_conditions.py +255 -0
  118. tabs/solve/plots/aerodynamics/plot_rotor_disc_performance.py +144 -0
  119. tabs/solve/plots/aerodynamics/plot_rotor_performance.py +124 -0
  120. tabs/solve/plots/common/__init__.py +4 -0
  121. tabs/solve/plots/common/plot_style.py +71 -0
  122. tabs/solve/plots/common/set_axes.py +55 -0
  123. tabs/solve/plots/create_plot_widgets.py +34 -0
  124. tabs/solve/plots/emissions/__init__.py +3 -0
  125. tabs/solve/plots/emissions/plot_emissions.py +167 -0
  126. tabs/solve/plots/energy/__init__.py +12 -0
  127. tabs/solve/plots/energy/plot_altitude_sfc_weight.py +134 -0
  128. tabs/solve/plots/energy/plot_battery_cell_conditions.py +154 -0
  129. tabs/solve/plots/energy/plot_battery_degradation.py +157 -0
  130. tabs/solve/plots/energy/plot_battery_module_C_rates.py +139 -0
  131. tabs/solve/plots/energy/plot_battery_module_conditions.py +157 -0
  132. tabs/solve/plots/energy/plot_battery_pack_conditions.py +164 -0
  133. tabs/solve/plots/energy/plot_battery_ragone_diagram.py +97 -0
  134. tabs/solve/plots/energy/plot_battery_temperature.py +136 -0
  135. tabs/solve/plots/energy/plot_electric_propulsor_efficiencies.py +136 -0
  136. tabs/solve/plots/energy/plot_propulsor_throttles.py +119 -0
  137. tabs/solve/plots/mission/__init__.py +5 -0
  138. tabs/solve/plots/mission/plot_aircraft_velocities.py +145 -0
  139. tabs/solve/plots/mission/plot_flight_conditions.py +236 -0
  140. tabs/solve/plots/mission/plot_flight_trajectory.py +172 -0
  141. tabs/solve/plots/stability/__init__.py +5 -0
  142. tabs/solve/plots/stability/plot_flight_forces_and_moments.py +163 -0
  143. tabs/solve/plots/stability/plot_lateral_stability.py +151 -0
  144. tabs/solve/plots/stability/plot_longitudinal_stability.py +173 -0
  145. tabs/solve/plots/thermal_management/__init__.py +7 -0
  146. tabs/solve/plots/thermal_management/plot_air_cooled_conditions.py +152 -0
  147. tabs/solve/plots/thermal_management/plot_cross_flow_heat_exchanger_conditions.py +185 -0
  148. tabs/solve/plots/thermal_management/plot_reservoir_conditions.py +141 -0
  149. tabs/solve/plots/thermal_management/plot_thermal_management_performance.py +105 -0
  150. tabs/solve/plots/thermal_management/plot_wavy_channel_conditions.py +161 -0
  151. tabs/solve/plots/weights/__init__.py +4 -0
  152. tabs/solve/plots/weights/plot_load_diagram.py +163 -0
  153. tabs/solve/plots/weights/plot_weight_breakdown.py +164 -0
  154. tabs/solve/solve.py +1498 -0
  155. tabs/style_sheet.py +114 -0
  156. tabs/tab_widget.py +14 -0
  157. tabs/visualize_geometry/__init__.py +4 -0
  158. tabs/visualize_geometry/core_3d_viewer.py +253 -0
  159. tabs/visualize_geometry/features/__init__.py +10 -0
  160. tabs/visualize_geometry/features/axes_gizmo.py +173 -0
  161. tabs/visualize_geometry/features/background.py +161 -0
  162. tabs/visualize_geometry/features/blueprint.py +685 -0
  163. tabs/visualize_geometry/features/camera.py +364 -0
  164. tabs/visualize_geometry/features/drag_aircraft.py +219 -0
  165. tabs/visualize_geometry/features/grid.py +194 -0
  166. tabs/visualize_geometry/features/measurement.py +367 -0
  167. tabs/visualize_geometry/features/screenshot.py +91 -0
  168. tabs/visualize_geometry/geometry_helper_functions.py +3 -0
  169. tabs/visualize_geometry/visualize_geometry.py +731 -0
  170. utilities.py +257 -0
@@ -0,0 +1,137 @@
1
+ # RCAIDE_GUI/tabs/geometry/frames/powertrain/converters/converter_frame.py
2
+ #
3
+ # Created: Dec 2025, M. Clarke
4
+
5
+ # ----------------------------------------------------------------------------------------------------------------------
6
+ # IMPORT
7
+ # ----------------------------------------------------------------------------------------------------------------------
8
+ from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QFrame, \
9
+ QSizePolicy, QSpacerItem
10
+
11
+ from tabs.geometry.widgets.powertrain.converters import TurboelectricGeneratorWidget
12
+ from common_widgets import DataEntryWidget
13
+
14
+ class ConverterFrame(QWidget):
15
+ def __init__(self):
16
+ super(ConverterFrame, self).__init__()
17
+
18
+ self.save_function = None
19
+ self.data_entry_widget: DataEntryWidget | None = None
20
+
21
+ # List to store data values source_ sections
22
+ self.converter_sections_layout = QVBoxLayout()
23
+
24
+ # Create a horizontal layout for the label and buttons
25
+ header_layout = QVBoxLayout()
26
+ # label = QLabel("<u><b>source Frame</b></u>")
27
+
28
+ layout = self.create_scroll_layout()
29
+
30
+ # header_layout.addWidget(label)
31
+
32
+ # Add source_ Section Button
33
+ add_turboelectric_generator_button = QPushButton("Add Turboelectric Generator", self)
34
+ add_turboelectric_generator_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
35
+ add_turboelectric_generator_button.setMaximumWidth(200)
36
+ add_turboelectric_generator_button.clicked.connect(self.add_turboelectric_generator)
37
+ header_layout.addWidget(add_turboelectric_generator_button)
38
+
39
+ layout.addLayout(header_layout)
40
+
41
+ # Create a horizontal line
42
+ line_bar = QFrame()
43
+ line_bar.setFrameShape(QFrame.Shape.HLine)
44
+ line_bar.setFrameShadow(QFrame.Shadow.Sunken)
45
+ line_bar.setStyleSheet("background-color: light grey;")
46
+
47
+ # Add the line bar to the main layout
48
+ layout.addWidget(line_bar)
49
+
50
+ # Add the layout for additional source_ sections to the main layout
51
+ layout.addLayout(self.converter_sections_layout)
52
+
53
+ # Create a QHBoxLayout to contain the buttons
54
+ button_layout = QHBoxLayout()
55
+
56
+ # Add the button layout to the main layout
57
+ layout.addLayout(button_layout)
58
+
59
+ # Adds scroll function
60
+ layout.addItem(QSpacerItem(
61
+ 20, 40, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding))
62
+
63
+ def get_data_values(self):
64
+ data = []
65
+ sources = []
66
+ for index in range(self.converter_sections_layout.count()):
67
+ item = self.converter_sections_layout.itemAt(index)
68
+ assert item is not None
69
+ widget = item.widget()
70
+ assert widget is not None and isinstance(widget, TurboelectricGeneratorWidget)
71
+
72
+ source_data, fuel_tank = widget.get_data_values()
73
+ data.append(source_data)
74
+ sources.append(fuel_tank)
75
+
76
+ return data, sources
77
+
78
+ def load_data(self, data):
79
+ while self.converter_sections_layout.count():
80
+ widget_item = self.converter_sections_layout.itemAt(0)
81
+ assert widget_item is not None
82
+ widget = widget_item.widget()
83
+ assert widget is not None
84
+
85
+ self.converter_sections_layout.removeWidget(widget)
86
+ widget.deleteLater()
87
+
88
+ for section_data in data:
89
+ self.converter_sections_layout.addWidget(TurboelectricGeneratorWidget(
90
+ self.converter_sections_layout.count(), self.on_delete_button_pressed, section_data))
91
+
92
+ def delete_data(self):
93
+ # TODO Implement proper deletion of data
94
+ pass
95
+
96
+ def add_turboelectric_generator(self):
97
+ self.converter_sections_layout.addWidget(
98
+ TurboelectricGeneratorWidget(self.converter_sections_layout.count(), self.on_delete_button_pressed))
99
+
100
+ def on_delete_button_pressed(self, index):
101
+ distributor = self.converter_sections_layout.itemAt(index)
102
+ if distributor is None:
103
+ return
104
+
105
+ widget = distributor.widget()
106
+ if widget is None:
107
+ return
108
+
109
+ widget.deleteLater()
110
+ self.converter_sections_layout.removeWidget(widget)
111
+ self.converter_sections_layout.update()
112
+
113
+ for i in range(index, self.converter_sections_layout.count()):
114
+ distributor = self.converter_sections_layout.itemAt(i)
115
+ if distributor is None:
116
+ continue
117
+
118
+ widget = distributor.widget()
119
+ if widget is None or not isinstance(widget, TurboelectricGeneratorWidget):
120
+ continue
121
+
122
+ widget.index = i
123
+
124
+ def set_save_function(self, function):
125
+ self.save_function = function
126
+
127
+ def create_scroll_layout(self):
128
+ # Create a widget to contain the layout
129
+ scroll_content = QWidget()
130
+
131
+ # Set the main layout inside the scroll content
132
+ layout = QVBoxLayout(scroll_content)
133
+
134
+ # Set the main layout of the widget
135
+ self.setLayout(layout)
136
+
137
+ return layout
@@ -0,0 +1,5 @@
1
+ # RCAIDE_GUI/tabs/geometry/frames/powertrain/distributors/__init__.py
2
+ # ----------------------------------------------------------------------------------------------------------------------
3
+ # IMPORT
4
+ # ----------------------------------------------------------------------------------------------------------------------
5
+ from tabs.geometry.frames.powertrain.distributors.distributor_frame import DistributorFrame
@@ -0,0 +1,143 @@
1
+ # RCAIDE_GUI/tabs/geometry/frames/powertrain/distributor_frame.py
2
+ #
3
+ # Created: Dec 2025, M. Clarke
4
+
5
+ # ----------------------------------------------------------------------------------------------------------------------
6
+ # IMPORT
7
+ # ----------------------------------------------------------------------------------------------------------------------
8
+ # RCAIDE imports
9
+ import RCAIDE
10
+
11
+ # PyQT imports
12
+ from PyQt6.QtCore import Qt
13
+ from PyQt6.QtWidgets import QWidget, QPushButton, QLineEdit, QSizePolicy, QVBoxLayout, \
14
+ QHBoxLayout, QLabel, QFrame, QScrollArea, QSpacerItem, QComboBox
15
+
16
+ from tabs.geometry.widgets.powertrain.distributors import FuelLineWidget
17
+ from utilities import set_data, show_popup, create_line_bar, Units, create_scroll_area, clear_layout
18
+ from common_widgets import DataEntryWidget
19
+
20
+
21
+ # ----------------------------------------------------------------------------------------------------------------------
22
+ # Distributor Frame
23
+ # ----------------------------------------------------------------------------------------------------------------------
24
+ class DistributorFrame(QWidget):
25
+ def __init__(self):
26
+ super(DistributorFrame, self).__init__()
27
+
28
+ self.save_function = None
29
+ self.data_entry_widget: DataEntryWidget | None = None
30
+
31
+ # List to store data values distributor_ sections
32
+ self.distributor_sections_layout = QVBoxLayout()
33
+
34
+ # Create a horizontal layout for the label and buttons`
35
+ header_layout = QVBoxLayout()
36
+
37
+ layout = self.create_scroll_layout()
38
+
39
+ # Add distributor_ Section Button
40
+ add_fuel_line_button = QPushButton("Add Fuel Line", self)
41
+ add_fuel_line_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
42
+ add_fuel_line_button.setMaximumWidth(200)
43
+ add_fuel_line_button.clicked.connect(self.add_fuel_line)
44
+ header_layout.addWidget(add_fuel_line_button)
45
+ layout.addLayout(header_layout)
46
+
47
+ # Create a horizontal line
48
+ line_bar = QFrame()
49
+ line_bar.setFrameShape(QFrame.Shape.HLine)
50
+ line_bar.setFrameShadow(QFrame.Shadow.Sunken)
51
+ line_bar.setStyleSheet("background-color: light grey;")
52
+
53
+ # Add the line bar to the main layout
54
+ layout.addWidget(line_bar)
55
+
56
+ # Add the layout for additional distributor_ sections to the main layout
57
+ layout.addLayout(self.distributor_sections_layout)
58
+
59
+ # Create a QHBoxLayout to contain the buttons
60
+ button_layout = QHBoxLayout()
61
+
62
+ # Add the button layout to the main layout
63
+ layout.addLayout(button_layout)
64
+
65
+ # Adds scroll function
66
+ layout.addItem(QSpacerItem(
67
+ 20, 40, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding))
68
+
69
+ def get_data_values(self):
70
+ data = []
71
+ distributors = []
72
+ for index in range(self.distributor_sections_layout.count()):
73
+ item = self.distributor_sections_layout.itemAt(index)
74
+ assert item is not None
75
+ widget = item.widget()
76
+ assert widget is not None and isinstance(widget, FuelLineWidget)
77
+
78
+ distributor_data, distributor = widget.get_data_values()
79
+ data.append(distributor_data)
80
+ distributors.append(distributor)
81
+
82
+ return data, distributors
83
+
84
+ def load_data(self, data):
85
+ while self.distributor_sections_layout.count():
86
+ widget_item = self.distributor_sections_layout.itemAt(0)
87
+ assert widget_item is not None
88
+ widget = widget_item.widget()
89
+ assert widget is not None
90
+
91
+ self.distributor_sections_layout.removeWidget(widget)
92
+ widget.deleteLater()
93
+
94
+ for section_data in data:
95
+ self.distributor_sections_layout.addWidget(FuelLineWidget(
96
+ self.distributor_sections_layout.count(), self.on_delete_button_pressed, section_data))
97
+
98
+ def delete_data(self):
99
+ # TODO Implement proper deletion of data
100
+ pass
101
+
102
+ def add_fuel_line(self):
103
+ self.distributor_sections_layout.addWidget(
104
+ FuelLineWidget(self.distributor_sections_layout.count(), self.on_delete_button_pressed))
105
+
106
+ def on_delete_button_pressed(self, index):
107
+ distributor = self.distributor_sections_layout.itemAt(index)
108
+ if distributor is None:
109
+ return
110
+
111
+ widget = distributor.widget()
112
+ if widget is None:
113
+ return
114
+
115
+ widget.deleteLater()
116
+ self.distributor_sections_layout.removeWidget(widget)
117
+ self.distributor_sections_layout.update()
118
+
119
+ for i in range(index, self.distributor_sections_layout.count()):
120
+ distributor = self.distributor_sections_layout.itemAt(i)
121
+ if distributor is None:
122
+ continue
123
+
124
+ widget = distributor.widget()
125
+ if widget is None or not isinstance(widget, FuelLineWidget):
126
+ continue
127
+
128
+ widget.index = i
129
+
130
+ def set_save_function(self, function):
131
+ self.save_function = function
132
+
133
+ def create_scroll_layout(self):
134
+ # Create a widget to contain the layout
135
+ scroll_content = QWidget()
136
+
137
+ # Set the main layout inside the scroll content
138
+ layout = QVBoxLayout(scroll_content)
139
+
140
+ # Set the main layout of the widget
141
+ self.setLayout(layout)
142
+
143
+ return layout
@@ -0,0 +1,5 @@
1
+ # RCAIDE_GUI/tabs/geometry/frames/powertrain/nacelles/__init__.py
2
+ # ----------------------------------------------------------------------------------------------------------------------
3
+ # IMPORT
4
+ # ----------------------------------------------------------------------------------------------------------------------
5
+ from tabs.geometry.frames.powertrain.nacelles.nacelle_frame import NacelleFrame
@@ -0,0 +1,283 @@
1
+ # RCAIDE_GUI/tabs/geometry/frames/powertrain/nacelles/nacelle_frame.py
2
+ #
3
+ # Created: Dec 2025, M. Clarke
4
+
5
+ # NOTE: This file is no longer used - nacelles are now integrated into the powertrain. See turbofan_widget.py.
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ # # RCAIDE_GUI/tabs/geometry/frames/nacelles/nacelle_frame.py
14
+ # #
15
+ # # Created: Dec 2025, M. Clarke
16
+
17
+ # # ----------------------------------------------------------------------------------------------------------------------
18
+ # # IMPORT
19
+ # # ----------------------------------------------------------------------------------------------------------------------
20
+ # # RCAIDE imports
21
+ # import RCAIDE
22
+
23
+ # # PyQT imports
24
+ # from PyQt6.QtCore import Qt
25
+ # from PyQt6.QtWidgets import QWidget, QPushButton, QLineEdit, QSizePolicy, QVBoxLayout,\
26
+ # QHBoxLayout, QLabel, QFrame, QScrollArea, QSpacerItem, QComboBox
27
+
28
+ # # RCAIDE GUI imports
29
+ # from tabs.geometry.frames import GeometryFrame
30
+ # from tabs.geometry.widgets.nacelles.nacelle_section_widget import NacelleSectionWidget
31
+ # from utilities import set_data, show_popup, create_line_bar, Units, create_scroll_area, clear_layout
32
+ # from common_widgets import DataEntryWidget
33
+
34
+ # # python imports
35
+ # from turtle import clear
36
+
37
+ # # ----------------------------------------------------------------------------------------------------------------------
38
+ # # Nacelle Frame
39
+ # # ----------------------------------------------------------------------------------------------------------------------
40
+ # class NacelleFrame(GeometryFrame):
41
+ # def __init__(self):
42
+ # """Create a frame for entering nacelle data."""
43
+ # super(NacelleFrame, self).__init__()
44
+
45
+ # create_scroll_area(self)
46
+ # assert self.main_layout is not None and isinstance(
47
+ # self.main_layout, QVBoxLayout)
48
+ # self.main_layout.addWidget(QLabel("<b>Nacelles</b>"))
49
+ # self.main_layout.addWidget(create_line_bar())
50
+
51
+ # self.add_name_layout()
52
+ # self.add_nacelle_type()
53
+
54
+ # # List of data labels
55
+ # self.data_units_labels = [
56
+ # ("Length", Units.Length, "length"),
57
+ # ("Inlet Diameter", Units.Length, "inlet_diameter"),
58
+ # ("Diameter", Units.Length, "diameter"),
59
+ # ("Origin", Units.Position, "origin"),
60
+ # ("Wetted Area", Units.Area, "areas.wetted"),
61
+ # ("Flow Through", Units.Boolean, "flow_through"),
62
+ # ]
63
+
64
+ # # Add the data entry widget to the main layout
65
+ # self.data_entry_widget: DataEntryWidget = DataEntryWidget(
66
+ # self.data_units_labels)
67
+ # self.main_layout.addWidget(self.data_entry_widget)
68
+ # self.main_layout.addWidget(create_line_bar())
69
+
70
+ # # Add the secctions layout to the main layout
71
+ # self.nacelle_sections_layout = QVBoxLayout()
72
+ # self.main_layout.addLayout(self.nacelle_sections_layout)
73
+
74
+ # self.add_buttons_layout()
75
+
76
+ # # Adds scroll function
77
+ # self.main_layout.addItem(QSpacerItem(
78
+ # 20, 40, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding))
79
+
80
+ # def add_name_layout(self):
81
+ # assert self.main_layout is not None
82
+ # name_layout = QHBoxLayout()
83
+ # spacer_left = QSpacerItem(
84
+ # 50, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
85
+ # spacer_right = QSpacerItem(
86
+ # 200, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
87
+ # self.name_line_edit: QLineEdit = QLineEdit(self)
88
+ # name_layout.addItem(spacer_left)
89
+ # name_layout.addWidget(QLabel("Name: "))
90
+ # name_layout.addWidget(self.name_line_edit)
91
+ # name_layout.addItem(spacer_right)
92
+ # self.main_layout.addLayout(name_layout)
93
+
94
+ # def add_nacelle_type(self):
95
+ # nacelle_type_label = QLabel("Nacelle Type: ")
96
+ # nacelle_type_layout = QHBoxLayout()
97
+ # spacer_left = QSpacerItem(
98
+ # 50, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
99
+ # spacer_right = QSpacerItem(
100
+ # 200, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
101
+ # nacelle_type_layout.addItem(spacer_left)
102
+ # nacelle_type_layout.addWidget(nacelle_type_label)
103
+ # self.nacelle_combo = QComboBox()
104
+ # self.nacelle_combo.addItems(["Select Nacelle Type","Generic Nacelle", "Body of Revolution", "Stack Nacelle"])
105
+ # self.nacelle_combo.setFixedWidth(600)
106
+ # nacelle_type_layout.addWidget(self.nacelle_combo, alignment=Qt.AlignmentFlag.AlignCenter)
107
+ # nacelle_type_layout.addItem(spacer_right)
108
+
109
+ # assert self.main_layout is not None
110
+ # self.main_layout.addLayout(nacelle_type_layout)
111
+
112
+ # # noinspection PyUnresolvedReferences
113
+ # def add_buttons_layout(self):
114
+ # """Add the save, delete, and new buttons to the layout."""
115
+ # assert self.main_layout is not None
116
+
117
+ # new_section_button = QPushButton("New Nacelle Section", self)
118
+ # new_section_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
119
+ # save_button = QPushButton("Save Data", self)
120
+ # save_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
121
+ # delete_button = QPushButton("Delete Data", self)
122
+ # delete_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
123
+ # new_button = QPushButton("New Nacelle Structure", self)
124
+ # new_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
125
+
126
+ # new_section_button.clicked.connect(self.add_nacelle_section)
127
+ # save_button.clicked.connect(self.save_data)
128
+ # delete_button.clicked.connect(self.delete_data)
129
+ # new_button.clicked.connect(self.create_new_structure)
130
+
131
+ # buttons_layout = QHBoxLayout()
132
+ # buttons_layout.addWidget(new_section_button)
133
+ # buttons_layout.addWidget(save_button)
134
+ # buttons_layout.addWidget(delete_button)
135
+ # buttons_layout.addWidget(new_button)
136
+ # self.main_layout.addLayout(buttons_layout)
137
+
138
+ # # noinspection DuplicatedCode
139
+ # def save_data(self):
140
+ # """Call the save function and pass the entered data to it."""
141
+ # entered_data, v_comp = self.get_data_values()
142
+ # if self.save_function:
143
+ # if self.index >= 0:
144
+ # self.index = self.save_function(
145
+ # tab_index=self.tab_index, index=self.index, data=entered_data)
146
+ # return
147
+ # else:
148
+ # self.index = self.save_function(
149
+ # tab_index=self.tab_index, vehicle_component=v_comp, data=entered_data, new=True)
150
+
151
+ # show_popup("Data Saved!", self)
152
+
153
+ # def add_nacelle_section(self):
154
+ # self.nacelle_sections_layout.addWidget(NacelleSectionWidget(
155
+ # self.nacelle_sections_layout.count(), self.delete_nacelle_section))
156
+
157
+ # def delete_nacelle_section(self, index):
158
+ # item = self.nacelle_sections_layout.itemAt(index)
159
+ # if item is None:
160
+ # return
161
+
162
+ # widget = item.widget()
163
+ # if widget is None or not isinstance(widget, NacelleSectionWidget):
164
+ # return
165
+
166
+ # widget.deleteLater()
167
+ # self.nacelle_sections_layout.removeWidget(widget)
168
+ # self.nacelle_sections_layout.update()
169
+
170
+ # for i in range(index, self.nacelle_sections_layout.count()):
171
+ # item = self.nacelle_sections_layout.itemAt(i)
172
+ # if item is None:
173
+ # continue
174
+
175
+ # widget = item.widget()
176
+ # if widget is not None and isinstance(widget, NacelleSectionWidget):
177
+ # widget.index = i
178
+
179
+ # # TODO: Implement proper deletion of data
180
+ # def delete_data(self):
181
+ # pass
182
+
183
+ # def create_new_structure(self):
184
+ # """Create a new nacelle structure."""
185
+ # # Clear the main data values
186
+ # self.data_entry_widget.clear_values()
187
+ # self.name_line_edit.clear()
188
+
189
+ # # Clear the nacelle sections
190
+ # for i in range(self.nacelle_sections_layout.count()):
191
+ # item = self.nacelle_sections_layout.itemAt(i)
192
+ # if item is None:
193
+ # continue
194
+
195
+ # widget = item.widget()
196
+ # if widget is not None and isinstance(widget, NacelleSectionWidget):
197
+ # widget.deleteLater()
198
+
199
+ # self.nacelle_sections_layout.update()
200
+ # self.index = -1
201
+
202
+ # def create_rcaide_structure(self):
203
+ # """Create a nacelle structure from the given data."""
204
+ # data = self.data_entry_widget.get_values_si()
205
+ # data["name"] = self.name_line_edit.text()
206
+
207
+ # # TODO: what is this line
208
+ # # self.nacelle_combo.addItems(["Select Nacelle Type","Generic Nacelle", "Body of Revolution", "Stack Nacelle"])
209
+ # # selected_nacelle_type = self.nacelle_combo.currentText()
210
+ # # nacelle = RCAIDE.Library.Components.Nacelles.Nacelle() #set to default
211
+ # # if selected_nacelle_type == "Generic Nacelle":
212
+ # # nacelle = RCAIDE.Library.Components.Nacelles.Nacelle()
213
+ # # if selected_nacelle_type == "Body of Revolution":
214
+ # nacelle = RCAIDE.Library.Components.Nacelles.Body_of_Revolution_Nacelle()
215
+ # # if selected_nacelle_type == "Stack Nacelle":
216
+ # # nacelle = RCAIDE.Library.Components.Nacelles.Stack_Nacelle()
217
+
218
+ # # assign nacelle name
219
+ # nacelle.tag = data["name"]
220
+
221
+ # # assign nacelle properties
222
+ # for data_unit_label in self.data_units_labels:
223
+ # user_label = data_unit_label[0]
224
+ # rcaide_label = data_unit_label[-1]
225
+ # set_data(nacelle, rcaide_label, data[user_label][0])
226
+
227
+ # nacelle_airfoil = RCAIDE.Library.Components.Airfoils.NACA_4_Series_Airfoil()
228
+ # nacelle_airfoil.NACA_4_Series_code = '2410' # UPDATE
229
+ # nacelle.append_airfoil(nacelle_airfoil)
230
+
231
+ # for i in range(self.nacelle_sections_layout.count()):
232
+ # item = self.nacelle_sections_layout.itemAt(i)
233
+ # if item is None:
234
+ # continue
235
+
236
+ # widget = item.widget()
237
+ # if widget is not None and isinstance(widget, NacelleSectionWidget):
238
+ # _, segment = widget.get_data_values()
239
+ # nacelle.append_segment(segment)
240
+
241
+ # return nacelle
242
+
243
+ # def get_data_values(self):
244
+ # """Retrieve the entered data values from the text fields."""
245
+ # data = self.data_entry_widget.get_values()
246
+ # data_si = self.data_entry_widget.get_values_si()
247
+ # data_si["name"] = self.name_line_edit.text()
248
+
249
+ # nacelle = self.create_rcaide_structure()
250
+
251
+ # data["sections"] = []
252
+ # for i in range(self.nacelle_sections_layout.count()):
253
+ # item = self.nacelle_sections_layout.itemAt(i)
254
+ # if item is None:
255
+ # continue
256
+
257
+ # widget = item.widget()
258
+ # if widget is not None and isinstance(widget, NacelleSectionWidget):
259
+ # segment_data, segment = widget.get_data_values()
260
+ # data["sections"].append(segment_data)
261
+ # nacelle.append_segment(segment)
262
+
263
+ # data["name"] = self.name_line_edit.text()
264
+ # return data, nacelle
265
+
266
+ # def load_data(self, data, index):
267
+ # """Load the data into the widgets.
268
+
269
+ # Args:
270
+ # data: The data to be loaded into the widgets.
271
+ # index: The index of the data in the list.
272
+ # """
273
+ # self.data_entry_widget.load_data(data)
274
+ # while self.nacelle_sections_layout.count():
275
+ # item = self.nacelle_sections_layout.takeAt(0)
276
+ # assert item is not None
277
+ # widget = item.widget()
278
+ # if widget is not None:
279
+ # widget.deleteLater()
280
+
281
+ # clear_layout(self.nacelle_sections_layout)
282
+ # self.name_line_edit.setText(data["name"])
283
+ # self.index = index