import argparse from matplotlib import pyplot as plt from math import floor class ProfileHeights: bobbin_train_segment_types = {165: 0.38, 210: 0.248, 225: 0.354648} # Key = Spulenzug-Typ - Value = Gewicht def __init__(self, cross_section_type, datum, width, thickness, ap_positions=None, beam_length=2000, min_ap_distance=200, yield_strength=235, segment_type=165, bobbin_mass=4, column_distance=3.6, ): self.cross_section_type = cross_section_type self.datum = datum self.width = width self.thickness = thickness self.ap_positions = ap_positions self.beam_length = beam_length self.min_ap_distance = min_ap_distance self.yield_strength = yield_strength self.segment_type = segment_type self.bobbin_mass = bobbin_mass self.column_distance = column_distance def ap_position_check(self): # Überprüft, ob alle AP's den zulässigen Mindestabstand zueinander einhalten if not [abs(new_pos - old_pos) < self.min_ap_distance for old_pos, new_pos in zip(self.ap_positions, self.ap_positions[1:])]: raise ValueError(f"Abstände zwischen ") else: return True def ap_amount(self): return floor(self.beam_length / self.min_ap_distance) def individual_ap_positions(self): # Funktion gibt Einzelabstände der AP-Profile zur Säule zurück # Fall 1: Es wurden keine Einzelabstände zur Säule definiert. Abstand zwischen AP's = zulässiger Mindestabstand # Fall 2: Es wurden individuelle AP-Abstände definiert. if self.ap_positions is None: return [ap_count * self.min_ap_distance for ap_count in range(1, self.ap_amount() + 1)] elif self.ap_position_check(): return self.ap_positions def force_per_ap_meter(self): if self.bobbin_mass > 4: raise ValueError(f"Gewicht der Spulen darf max. 4 kg betragen!") else: column_rows = 2 location_factor = 9.81 # m/s^2 ap_weight_per_meter = 1.88 total_bobbin_mass = self.bobbin_mass * (1000 / self.segment_type) mass = total_bobbin_mass + 2 * self.bobbin_train_segment_types[self.segment_type] + ap_weight_per_meter return mass * location_factor * self.column_distance / column_rows def ref_moment_of_resistance(self, current_beam_length, ap_column_distances, force_per_rail): # Funktion berechnet Widerstandsmoment für die aktuelle Trägerlänge total_column_distance = 0 for ap_column_distance in ap_column_distances: if current_beam_length >= ap_column_distance: total_column_distance += ap_column_distance else: break safety_factor = 1.7 bend_moment = force_per_rail * total_column_distance allowed_bend_stress = (self.yield_strength * 1.2) / safety_factor return bend_moment / allowed_bend_stress def recalculated_moment_of_resistance(self, height): # Berechnet das Widerstandsmoment mit der derzeitigen Profilhöhe für verschiedene Querschnitts-Arten inner_width = self.width - 2 * self.thickness inner_height = height - 2 * self.thickness bar_width = self.width - self.thickness # 1. Widerstandsmoment-Berechnung für idealisiertes rechteckiges Hohlprofil: if self.cross_section_type == "hohlprofil": return (self.width * height ** 3 - inner_width * inner_height ** 3) / (6 * height) # 2. Widerstandsmoment-Berechnung für idealisiertes IPE-Profil / C-Profil: elif self.cross_section_type in ["c", "ipe"]: return (self.width * height ** 3 - bar_width * inner_height ** 3) / (6 * height) def datum_reference(self): # Legt fest, ob die notwendige Profilhöhe im Plot in Abhängigkeit von jedem Millimeter der Gesamtlänge [l] # des Trägers oder der Trägerlänge an der Stelle jedes AP-Profils [n] dargestellt werden soll. if self.datum == "l": return list(range(self.min_ap_distance, self.beam_length + 1)) elif self.datum == "n": return self.individual_ap_positions() def height_calculation(self): start_height = 2 * self.thickness beam_lengths = self.datum_reference() ap_column_distance = self.individual_ap_positions() force_per_ap_meter = self.force_per_ap_meter() heights = [] lengths = [] moment_of_resistances = [] recalculated_moment_of_resistance = 0 for count, beam_length in enumerate(beam_lengths): reference_moment_of_resistance = self.ref_moment_of_resistance(beam_length, ap_column_distance, force_per_ap_meter) while recalculated_moment_of_resistance < reference_moment_of_resistance: recalculated_moment_of_resistance = self.recalculated_moment_of_resistance(start_height) start_height += 0.01 moment_of_resistances.append(reference_moment_of_resistance) heights.append(start_height) lengths.append(beam_length) return heights, lengths a = ProfileHeights(cross_section_type="hohlprofil", datum="l", width=50, thickness=2.5) ya_heights, xa_lengths = a.height_calculation() plt.plot(xa_lengths, ya_heights) plt.xlabel("Länge des Trägers in mm") plt.ylabel("Benötigte Querschnittshöhe des Trägers in mm") plt.grid(True) plt.show()