def __init__(self, master, name: str, beams, polynomials, polyID): self.master = master self.master.geometry(f"1360x768") self.master.title(name) self.canvas = Canvas(self.master, width = 1360, height = 768) self.canvas.pack(fill = BOTH, expand = True, side = TOP) for (i, beam) in enumerate(beams): if polynomials[i] != None: start = Point(beam[1].x, beam[1].y) end = Point(beam[3].x, beam[3].y) self.canvas.create_line((start, end), smooth = True, width = 5, fill="#404040") stressFunctions = polynomials[i] length = beam[0].length angle = beam[2] tipX = start.x tipY = start.y scale = -0.03 if polyID == 2 else 0.3 for j in range(0, 100): fun = stressFunctions(polyID, j * length / 100) self.canvas.create_line(tipX, tipY, tipX + 20 * fun * scale * pcos(90 + angle), tipY - 20 * fun * scale * psin(90 + angle)) tipX += 1 / 10 * length * pcos(angle) tipY -= 1 / 10 * length * psin(angle)
def insertForce(self): force_angle = float(self.angleContent.get()) - self.beamAngle if len(self.angleContent.get()) != 0 else 0 length = float(self.lengthContent.get()) if len(self.lengthContent.get()) != 0 else 1 pos = float(self.positionContent.get()) if len(self.positionContent.get()) != 0 else 0 scale = 1 if 0 <= length < 10 else 0.1 if 10 <= length < 100 else 0.01 if 100 <= length < 1000 else 0.001 tipX : float = self.master_force.x + (pos * pcos(self.beamAngle) * 10) tipY : float = self.master_force.y - (pos * psin(self.beamAngle) * 10) self.master_window.system.beams[self.beamID - 1][0].concentratedList.append((Concentrated(length), pos, force_angle + self.beamAngle)) self.master_window.drawing_area.delete(self.master_window.forcePreview) self.master_window.drawing_area.delete(self.master_window.labelPreview) force = self.master_window.drawing_area.create_line(tipX - 20 * length * scale * pcos(force_angle), tipY - 20 * length * scale * psin(force_angle), tipX, tipY, arrow = LAST, width = 4.0, activefill = "blue", smooth = True) label = self.master_window.drawing_area.create_text(tipX + 10 - 40 * pcos(force_angle) if force_angle <= 180 else tipX, tipY - 20 - 40 * psin(force_angle) if force_angle < 180 else tipY - 20, font = "Helvetica", text = f"{length} kN", anchor = W) self.master_window.actions.append(Action(related = (force, label, self.beamID), type = ActionType.ADD_CONCENTRATED)) self.master_window.inserting = False self.master.destroy()
def updateMoment(self): magnitude = float(self.magnitudeContent.get()) if len(self.magnitudeContent.get()) != 0 else 1 tipX : float = ((self.master_force.x + self.beamEnd.x) // 2) - 40 * pcos(self.beamAngle) tipY : float = ((self.master_force.y + self.beamEnd.y) // 2) textAngle = self.beamAngle if 0 <= self.beamAngle < 90 else self.beamAngle - 180 if self.beamAngle > 90 else 360 + self.beamAngle if - 90 < self.beamAngle < 0 else self.beamAngle + 180 self.master_window.drawing_area.delete(self.master_window.forcePreview) self.momentAsset = ImageTk.PhotoImage(Image.open("assets/arrow1.png").rotate(self.beamAngle)) if magnitude > 0 else ImageTk.PhotoImage(Image.open("assets/arrow2.png").rotate(self.beamAngle)) self.master_window.forcePreview = self.master_window.drawing_area.create_image(tipX, tipY, image = self.momentAsset) self.master_window.drawing_area.delete(self.master_window.labelPreview) self.master_window.labelPreview = self.master_window.drawing_area.create_text(tipX + 40, tipY - 40, font = "Helvetica", text = f"{magnitude} kNm", angle = textAngle)
def angledComponents(self, angle: float) -> Tuple[Distributed, Distributed]: basePolynomial: Polynomial = Polynomial( self.distribution.coefficients.copy()) if self.distribution.degree < 1: basePolynomial.coefficients.append(pcot(angle)) basePolynomial.degree = 1 else: basePolynomial.coefficients[1] += pcot(angle) return (Distributed(self.length / psin(angle), pcos(angle) * basePolynomial), Distributed(self.length / psin(angle), psin(angle) * basePolynomial))
def __init__(self, name: str, angle: float = 0): # this member is the reaction vector from the support # its values are used for solving the system self.reaction: Vector3 = Vector3(0, 0, 0) if SupportType[name].value[0] > 1: self.reaction.x = 1 self.reaction.y = 1 else: self.reaction.x = pcos(angle) self.reaction.y = psin(angle) if SupportType[name].value[1] == 1: self.reaction.z = 1
def updateForce(self): force_angle = float(self.angleContent.get()) - self.beamAngle if len(self.angleContent.get()) != 0 else 0 length = float(self.lengthContent.get()) if len(self.lengthContent.get()) != 0 else 1 pos = float(self.positionContent.get()) if len(self.positionContent.get()) != 0 else 0 scale = 1 if 0 <= length < 10 else 0.1 if 10 <= length < 100 else 0.01 if 100 <= length < 1000 else 0.001 tipX : float = self.master_force.x + (pos * pcos(self.beamAngle) * 10) tipY : float = self.master_force.y - (pos * psin(self.beamAngle) * 10) self.master_window.drawing_area.delete(self.master_window.forcePreview) self.master_window.forcePreview = self.master_window.drawing_area.create_line(tipX - 20 * length * scale * pcos(force_angle), tipY - 20 * length * scale * psin(force_angle), tipX, tipY, arrow = LAST, width = 4.0, activefill = "blue", smooth = True) self.master_window.drawing_area.delete(self.master_window.labelPreview) self.master_window.labelPreview = self.master_window.drawing_area.create_text(tipX + 10 - 40 * pcos(force_angle) if force_angle <= 180 else tipX, tipY - 20 - 40 * psin(force_angle) if force_angle < 180 else tipY - 20, font = "Helvetica", text = f"{length} kN", anchor = W)
def insertMoment(self): magnitude = float(self.magnitudeContent.get()) if len(self.magnitudeContent.get()) != 0 else 1 tipX : float = ((self.master_force.x + self.beamEnd.x) // 2) - 40 * pcos(self.beamAngle) tipY : float = ((self.master_force.y + self.beamEnd.y) // 2) self.master_window.system.beams[self.beamID - 1][0].moment = Moment(magnitude) self.master_window.drawing_area.delete(self.master_window.forcePreview) self.master_window.drawing_area.delete(self.master_window.labelPreview) textAngle = self.beamAngle if 0 <= self.beamAngle < 90 else self.beamAngle - 180 if self.beamAngle > 90 else 360 + self.beamAngle if - 90 < self.beamAngle < 0 else self.beamAngle + 180 momentAsset = ImageTk.PhotoImage(Image.open("assets/arrow1.png").rotate(self.beamAngle)) if magnitude > 0 else ImageTk.PhotoImage(Image.open("assets/arrow2.png").rotate(self.beamAngle)) moment = self.master_window.drawing_area.create_image(tipX, tipY, image = momentAsset) label = self.master_window.drawing_area.create_text(tipX + 40, tipY - 40, font = "Helvetica", text = f"{magnitude} kNm", angle = textAngle) self.master_window.actions.append(Action(related = (moment, label, self.beamID, momentAsset), type = ActionType.ADD_MOMENT)) self.master_window.inserting = False self.master.destroy()
def drawBeam(self, start : Point, end : Point, beamAngle : float, size : float, event = None) -> Tuple[object, object]: if self.beamPreview != None: event.widget.delete(self.beamPreview) if self.arcPreview != None: event.widget.delete(self.arcPreview) if self.labelPreview != None: event.widget.delete(self.labelPreview) if self.anglePreview != None: event.widget.delete(self.anglePreview) beam = event.widget.create_line((start, end), smooth = True, width = 5, fill="#404040") textAngle = beamAngle if 0 <= beamAngle < 90 else beamAngle - 180 if beamAngle > 90 else 360 + beamAngle if - 90 < beamAngle < 0 else beamAngle + 180 length = event.widget.create_text((start.x + end.x) / 2 - 20 * psin(beamAngle), (start.y + end.y) / 2 - 20 * pcos(beamAngle), font = "Helvetica", text = "{0:1.1f} m".format(size), angle = textAngle) return (beam, length)
def insertDistributed(self): force_angle = float(self.angleContent.get()) - self.beamAngle if len(self.angleContent.get()) != 0 else 0 radioOption = self.radioContent.get() start_pos = float(self.startPosContent.get()) if len(self.startPosContent.get()) != 0 else 0 end_pos = float(self.endPosContent.get()) if len(self.endPosContent.get()) != 0 else 5 if radioOption == 0: uniformLoad = int(self.distributedParameters[0].get()) if len(self.distributedParameters[0].get()) != 0 else 1 scale = 1 if 0 <= uniformLoad <= 10 else 0.1 if 10 < uniformLoad < 100 else 0.01 if 100 <= uniformLoad < 1000 else 0.001 if len(self.master_window.forcePreview) != 0: for force in self.master_window.forcePreview: self.master_window.drawing_area.delete(force) self.master_window.forcePreview.clear() self.master_window.drawing_area.delete(self.master_window.labelPreview) tipX : float = self.master_force.x + (start_pos * pcos(self.beamAngle) * 10) tipY : float = self.master_force.y - (start_pos * psin(self.beamAngle) * 10) tipX0 : float = tipX tipY0 : float = tipY forces = list() for i in range(11): forces.append(self.master_window.drawing_area.create_line(tipX - 20 * uniformLoad * scale * pcos(force_angle), tipY - 20 * uniformLoad * scale * psin(force_angle), tipX, tipY, arrow = LAST, width = 4.0, activefill = "blue", smooth = True)) tipX = tipX + (end_pos - start_pos) * pcos(self.beamAngle) tipY = tipY - (end_pos - start_pos) * psin(self.beamAngle) label = self.master_window.drawing_area.create_text((tipX + tipX0) / 2 - 40 * pcos(force_angle) if force_angle <= 180 else (tipX + tipX0) / 2, (tipY + tipY0) // 2 - 30 * (uniformLoad), font = "Helvetica", text = f"{uniformLoad} kN/m") self.master_window.system.beams[self.beamID - 1][0].distributedList.append((Distributed(end_pos - start_pos, Polynomial([uniformLoad])), start_pos, force_angle + self.beamAngle)) self.master_window.actions.append(Action(related = (forces, label, self.beamID, False, 0), type = ActionType.ADD_DISTRIBUTED)) if radioOption == 1: startLoad = int(self.distributedParameters[0].get()) if len(self.distributedParameters[0].get()) != 0 else 0 endLoad = int(self.distributedParameters[1].get()) if len(self.distributedParameters[1].get()) != 0 else 1 scale = 1 if len(self.master_window.forcePreview) != 0: for force in self.master_window.forcePreview: self.master_window.drawing_area.delete(force) self.master_window.forcePreview.clear() self.master_window.drawing_area.delete(self.master_window.labelPreview) if self.master_window.startLabelPreview != None and self.master_window.startLabelPreview != 0: self.master_window.drawing_area.delete(self.master_window.startLabelPreview) tipX : float = self.master_force.x + (start_pos * pcos(self.beamAngle) * 10) tipY : float = self.master_force.y - (start_pos * psin(self.beamAngle) * 10) load : int = startLoad tipX0 : float = tipX tipY0 : float = tipY forces = list() for i in range(11): forces.append(self.master_window.drawing_area.create_line(tipX - 20 * load * scale * pcos(force_angle), tipY - 20 * load * scale * psin(force_angle), tipX, tipY, arrow = LAST, width = 2.0, activefill = "blue", smooth = True)) tipX = tipX + (end_pos - start_pos) * pcos(self.beamAngle) tipY = tipY - (end_pos - start_pos) * psin(self.beamAngle) load = load + (endLoad - startLoad) / 10 startLabel = 0 if startLoad != 0: startLabel = self.master_window.drawing_area.create_text(tipX0, tipY0 - 5 - 25 * startLoad, font = "Helvetica", text = f"{startLoad} kN/m") label = self.master_window.drawing_area.create_text(tipX, tipY - 5 - 25 * endLoad, font = "Helvetica", text = f"{endLoad} kN/m") self.master_window.system.beams[self.beamID - 1][0].distributedList.append((Distributed(end_pos - start_pos, Polynomial([startLoad, (endLoad - startLoad) / (end_pos - start_pos)])), start_pos, force_angle + self.beamAngle)) self.master_window.actions.append(Action(related = (forces, label, self.beamID, startLoad != 0, startLabel), type = ActionType.ADD_DISTRIBUTED)) for force in self.master_window.forcePreview: self.master_window.drawing_area.delete(force) self.master_window.forcePreview.clear() self.master_window.drawing_area.delete(self.master_window.labelPreview) self.master_window.inserting = False self.master.destroy()
def updateDistributed(self): force_angle = float(self.angleContent.get()) - self.beamAngle if len(self.angleContent.get()) != 0 else 0 radioOption = self.radioContent.get() start_pos = float(self.startPosContent.get()) if len(self.startPosContent.get()) != 0 else 0 end_pos = float(self.endPosContent.get()) if len(self.endPosContent.get()) != 0 else 5 if self.lastRadio != radioOption: self.distributedParameters.clear() for entry in self.distributedEntries: entry.grid_remove() for label in self.distributedLabels: label.grid_remove() self.distributedEntries.clear() self.distributedLabels.clear() if radioOption == 0: uniformLoad = StringVar() uniformLoad.set("1") uniformLoad.trace("w", lambda a, b, c: self.updateDistributed()) self.distributedParameters.append(uniformLoad) loadEntry = Entry(self.frame, textvariable = uniformLoad, width = 4) loadEntry.grid(row = 4, column = 0) entryLabel = Label(self.frame, font = "Helvetica", text = "kN/m") entryLabel.grid(row = 4, column = 1) self.distributedEntries.append(loadEntry) self.distributedLabels.append(entryLabel) elif radioOption == 1: startLoad = StringVar() startLoad.set("0") startLoad.trace("w", lambda a, b, c: self.updateDistributed()) endLoad = StringVar() endLoad.set("1") endLoad.trace("w", lambda a, b, c: self.updateDistributed()) self.distributedParameters.append(startLoad) self.distributedParameters.append(endLoad) startLabel = Label(self.frame, font = "Helvetica", text = "De") startLabel.grid(row = 4, column = 0) startEntry = Entry(self.frame, textvariable = startLoad, width = 4) startEntry.grid(row = 4, column = 1) endLabel = Label(self.frame, font = "Helvetica", text = "até") endLabel.grid(row = 4, column = 2) endEntry = Entry(self.frame, textvariable = endLoad, width = 4) endEntry.grid(row = 4, column = 3, padx = 0) self.distributedEntries.append(startEntry) self.distributedEntries.append(endEntry) self.distributedLabels.append(startLabel) self.distributedLabels.append(endLabel) if radioOption == 0: uniformLoad = int(self.distributedParameters[0].get()) if len(self.distributedParameters[0].get()) != 0 else 1 scale = 1 if 0 <= uniformLoad <= 10 else 0.1 if 10 < uniformLoad < 100 else 0.01 if 100 <= uniformLoad < 1000 else 0.001 if len(self.master_window.forcePreview) != 0: for force in self.master_window.forcePreview: self.master_window.drawing_area.delete(force) self.master_window.forcePreview.clear() self.master_window.drawing_area.delete(self.master_window.labelPreview) tipX : float = self.master_force.x + (start_pos * pcos(self.beamAngle) * 10) tipY : float = self.master_force.y - (start_pos * psin(self.beamAngle) * 10) tipX0 : float = tipX tipY0 : float = tipY for i in range(11): self.master_window.forcePreview.append(self.master_window.drawing_area.create_line(tipX - 20 * uniformLoad * scale * pcos(force_angle), tipY - 20 * uniformLoad * scale * psin(force_angle), tipX, tipY, arrow = LAST, width = 4.0, activefill = "blue", smooth = True)) tipX = tipX + (end_pos - start_pos) * pcos(self.beamAngle) tipY = tipY - (end_pos - start_pos) * psin(self.beamAngle) self.master_window.labelPreview = self.master_window.drawing_area.create_text((tipX + tipX0) / 2 - 40 * pcos(force_angle) if force_angle <= 180 else (tipX + tipX0) / 2, (tipY + tipY0) // 2 - 30 * (uniformLoad), font = "Helvetica", text = f"{uniformLoad} kN/m") self.lastRadio = 0 if radioOption == 1: startLoad = int(self.distributedParameters[0].get()) if len(self.distributedParameters[0].get()) != 0 else 0 endLoad = int(self.distributedParameters[1].get()) if len(self.distributedParameters[1].get()) != 0 else 1 scale = 1 if self.master_window.startLabelPreview != None and self.master_window.startLabelPreview != 0: self.master_window.drawing_area.delete(self.master_window.startLabelPreview) if len(self.master_window.forcePreview) != 0: for force in self.master_window.forcePreview: self.master_window.drawing_area.delete(force) self.master_window.forcePreview.clear() self.master_window.drawing_area.delete(self.master_window.labelPreview) tipX : float = self.master_force.x + (start_pos * pcos(self.beamAngle) * 10) tipY : float = self.master_force.y - (start_pos * psin(self.beamAngle) * 10) load : int = startLoad tipX0 : float = tipX tipY0 : float = tipY for i in range(11): self.master_window.forcePreview.append(self.master_window.drawing_area.create_line(tipX - 20 * load * scale * pcos(force_angle), tipY - 20 * load * scale * psin(force_angle), tipX, tipY, arrow = LAST, width = 2.0, activefill = "blue", smooth = True)) tipX = tipX + (end_pos - start_pos) * pcos(self.beamAngle) tipY = tipY - (end_pos - start_pos) * psin(self.beamAngle) load = load + (endLoad - startLoad) / 10 if startLoad != 0: self.master_window.startLabelPreview = self.master_window.drawing_area.create_text(tipX0, tipY0 - 5 - 25 * startLoad, font = "Helvetica", text = f"{startLoad} kN/m") self.master_window.labelPreview = self.master_window.drawing_area.create_text(tipX, tipY - 5 - 25 * endLoad, font = "Helvetica", text = f"{endLoad} kN/m") self.lastRadio = 1
def drawBeamPreview(self, start : Point, end : Point, beamAngle : float, size: float, event = None): if self.beamPreview != None: event.widget.delete(self.beamPreview) if self.arcPreview != None: event.widget.delete(self.arcPreview) if self.labelPreview != None: event.widget.delete(self.labelPreview) if self.anglePreview != None: event.widget.delete(self.anglePreview) self.beamPreview = event.widget.create_line((start, end), smooth = True, dash = (10, 10)) self.arcPreview = event.widget.create_arc(start.x - 20, start.y - 20, start.x + 20, start.y + 20, start = 0, extent = beamAngle) self.anglePreview = event.widget.create_text(start.x + 40, start.y + (20 * sign(beamAngle)) if beamAngle != 0 else start.y + 20, font = "Helvetica", text = "{0:.1f}º".format(beamAngle)) textAngle = beamAngle if 0 <= beamAngle < 90 else beamAngle - 180 if beamAngle > 90 else 360 + beamAngle if - 90 < beamAngle < 0 else beamAngle + 180 self.labelPreview = event.widget.create_text((start.x + end.x) / 2 - 20 * psin(beamAngle), (start.y + end.y) / 2 - 20 * pcos(beamAngle), font = "Helvetica", text = "{0:1.1f} m".format(size), angle = textAngle)
def pointPos(self, startPos: Vector3, point: float, angle: float) -> Vector3: if point > self.length or point < 0: raise Exception('Point is outside the beam!') return startPos + Vector3(point*pcos(angle), point*psin(angle), 0)
def forceVector(self, angle: float) -> Vector3: return Vector3(self.magnitude * pcos(angle), -self.magnitude * psin(angle), 0)