are already set)
+ values_to_display = {
+ 'Plate Length': self.plate_length,
+ 'Plate Width': self.plate_width,
+
+ }
+
+
+ for key in keys_to_display:
+ if key in values_to_display:
+ label = QLabel(f"{key}: {values_to_display[key]}")
+ left_layout.addWidget(label)
+ # Step 4: Graphics view and scene
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Background and test shape (optional)
+ self.scene.setBackgroundBrush(Qt.white)
+
+ # Step 5: Add to main layout
+ main_layout.addWidget(self.view, stretch=2)
+ main_layout.addWidget(left_panel, stretch=1)
+
+ self.fontsize=10
+ self.arrowsize=10
+
+ if self.plate_length>1200 or self.plate_width>1200:
+ self.fontsize=5
+ self.arrowsize=5
+ elif self.plate_length>600 or self.plate_width>600:
+ self.fontsize=10
+ self.arrowsize=10
+ self.createDrawing()
+ if self.plate_length>1200 or self.plate_width>1200:
+ self.view.resetTransform()
+ self.view.scale(0.4, 0.4)
+ elif self.plate_length>600 or self.plate_width>600:
+ self.view.resetTransform()
+ self.view.scale(0.75, 0.75)
+
+ # Step 6: Call parameter extraction and drawing
+
+
+ def createDrawing(self):
+ try:
+ plate_length = float(self.plate_length)
+ plate_width = float(self.plate_width)
+ except (TypeError, ValueError):
+ print("Invalid plate dimensions")
+ return
+ rect = QRectF(0, 0, plate_length, plate_width)
+ # Create a rectangle item
+ rect_item = QGraphicsRectItem(rect)
+
+ # Set pen and brush (black border, transparent fill)
+ pen = QPen(Qt.black)
+ pen.setWidth(2)
+ rect_item.setPen(pen)
+ rect_item.setBrush(QBrush(Qt.NoBrush))
+
+ # Add rectangle to the scene
+ self.scene.addItem(rect_item)
+ # Extract parameters
+ outline_pen = QPen(Qt.black)
+ outline_pen.setWidth(2)
+
+ # === Draw Base Plate Rectangle ===
+ rect_item = QGraphicsRectItem(QRectF(0, 0, plate_length, plate_width))
+ rect_item.setPen(outline_pen)
+ rect_item.setBrush(QBrush(Qt.white))
+ self.scene.addItem(rect_item)
+
+ dimension_pen = QPen(Qt.black, 1.5)
+ weld_fill = QBrush(Qt.blue)
+ if self.web==True:
+ self.scene.addRect(0, (plate_width-self.plate_thickness)/2 , plate_length, self.plate_thickness, dimension_pen, weld_fill)
+ elif self.web==False:
+ self.scene.addRect((plate_length-self.plate_thickness)/2, 0 , self.plate_thickness, plate_width, dimension_pen, weld_fill)
+ # === Center of the base plate ===
+ center_x = plate_length / 2
+ center_y = plate_width / 2
+ self.addHorizontalDimension(
+ 0, -30, # x1 at left edge, y above plate
+ self.plate_length, -30, # x2 at right edge, same y
+ f"{self.plate_length} mm", pen
+ )
+
+ # Vertical dimension for plate width (to the left of the plate)
+ self.addVerticalDimension(
+ self.plate_length+30, 0, # x left of plate, y1 at top
+ self.plate_length+30, self.plate_width, # x2 same, y2 at bottom
+ f"{self.plate_width} mm", pen
+ )
+ weld_size=self.weld_size
+ weld_gap=self.weld_gap
+ red_brush = QBrush(Qt.red)
+
+ # === Top weld outside plate ===
+ top_weld = QGraphicsRectItem(QRectF(0, -weld_size, plate_length, weld_size))
+ top_weld.setBrush(red_brush)
+ self.scene.addItem(top_weld)
+
+ # === Bottom weld outside plate ===
+ bottom_weld = QGraphicsRectItem(QRectF(0, plate_width, plate_length, weld_size))
+ bottom_weld.setBrush(red_brush)
+ self.scene.addItem(bottom_weld)
+
+ # === Vertical welds (left and right), split due to weld_gap ===
+ half_gap = weld_gap / 2
+ half_height = (plate_width - weld_gap) / 2
+
+ # Left side, top weld (outside)
+ left_top = QGraphicsRectItem(QRectF(-weld_size, 0, weld_size, half_height))
+ left_top.setBrush(red_brush)
+ self.scene.addItem(left_top)
+
+ # Left side, bottom weld (outside)
+ left_bottom = QGraphicsRectItem(QRectF(-weld_size, plate_width - half_height, weld_size, half_height))
+ left_bottom.setBrush(red_brush)
+ self.scene.addItem(left_bottom)
+
+ # Right side, top weld (outside)
+ right_top = QGraphicsRectItem(QRectF(plate_length, 0, weld_size, half_height))
+ right_top.setBrush(red_brush)
+ self.scene.addItem(right_top)
+
+ # Right side, bottom weld (outside)
+ right_bottom = QGraphicsRectItem(QRectF(plate_length, plate_width - half_height, weld_size, half_height))
+ right_bottom.setBrush(red_brush)
+ self.scene.addItem(right_bottom)
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = self.arrowsize
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(self.fontsize)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = self.arrowsize
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(self.fontsize)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
diff --git a/src/osdag/gui/b2cendplateSketch.py b/src/osdag/gui/b2cendplateSketch.py
new file mode 100644
index 000000000..140623855
--- /dev/null
+++ b/src/osdag/gui/b2cendplateSketch.py
@@ -0,0 +1,702 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+class B2BEndPlateSketch(QMainWindow):
+ def __init__(self, connection_obj,main, rows=3, cols=2):
+ super().__init__()
+ self.connection = connection_obj
+ data=main.output_values(main,True)
+ self.web_thick=main.beam_tw
+ self.endplatetype=main.endplate_type
+ self.flange_thick=main.beam_tf
+ self.middle_bolts=main.bolt_row_web
+ self.stiffener_length = main.stiffener_height
+ self.stiffener_thickness=main.stiffener_thickness
+ self.stiffener_width=main.stiffener_length
+ self.rows_inside_D_max = main.rows_inside_D_max
+ self.rows_outside_D_max = main.rows_outside_D_max
+ self.detail_dict = {
+ entry[1]: entry[3]
+ for entry in data
+ }
+ for i in self.detail_dict:
+ print(f' {i} : {self.detail_dict[i]}')
+ self.beam_width=main.beam_D
+ print(f'Beam Width : {main.beam_bf} , Beam Depth : {main.beam_D}')
+ print(self.stiffener_width,self.stiffener_length)
+ self.initUI()
+
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ print(f'End Plate Type : {self.endplatetype}')
+ print(f'middle bolts : {self.middle_bolts}')
+ print(f'stiffener length : {self.stiffener_length}')
+
+ self.setGeometry(100, 100, 1200, 500)
+ print(f'web thickness : {self.web_thick}, flange thickness : {self.flange_thick} ')
+ # Step 1: Create a central widget
+ central_widget = QWidget()
+ self.setCentralWidget(central_widget)
+
+ # Step 2: Create main layout
+ main_layout = QHBoxLayout()
+ central_widget.setLayout(main_layout)
+
+ # Step 3: Left panel for selected labels only
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+ left_panel.setLayout(left_layout)
+
+ # Only display selected keys
+ keys_to_display = [
+
+ ]
+
+ # Add labels
+ for key in keys_to_display:
+ if key in self.detail_dict:
+ value = self.detail_dict[key]
+ label = QLabel(f"{key}: {value}")
+ left_layout.addWidget(label)
+
+ # Step 4: Graphics view and scene
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Background and test shape (optional)
+ self.scene.setBackgroundBrush(Qt.white)
+
+ # Step 5: Add to main layout
+ main_layout.addWidget(left_panel, stretch=1)
+ main_layout.addWidget(self.view, stretch=3)
+
+ # Step 6: Call parameter extraction and drawing
+ self.get_parameters()
+ def get_parameters(self):
+ print('setting parameters')
+ self.rows=self.detail_dict['No. of Rows']
+ self.cols=self.detail_dict['No. of Columns']
+ print(f'rows : {self.rows} , cols : {self.cols}')
+ self.pitch=self.detail_dict['Pitch Distance (mm)']
+ self.CrossGauge=self.detail_dict['Cross-centre Gauge (mm)']
+ value = self.detail_dict['Gauge Distance (mm)']
+ self.Gauge = float(value) if str(value).isdigit() else self.CrossGauge
+ self.End=self.detail_dict['End Distance (mm)']
+ self.Edge=self.detail_dict['Edge Distance (mm)']
+ self.height=self.detail_dict['Height (mm)']
+ self.width=self.detail_dict['Width (mm)']
+ self.hole_diameter=self.detail_dict['Diameter (mm)']
+ self.plate_thickness=self.detail_dict['Thickness (mm)']
+ if self.endplatetype.startswith('Flushed'):
+ self.createDrawingFlushedReversible()
+ elif self.endplatetype.startswith('Extended One'):
+ self.createDrawingExtendedOneWay()
+ else:
+ self.createDrawingExtendedTwoWay()
+ def createDrawingFlushedReversible(self):
+ from PyQt5.QtCore import Qt
+ from PyQt5.QtGui import QPen, QColor, QBrush,QPolygonF
+ from PyQt5.QtWidgets import QGraphicsRectItem,QGraphicsPolygonItem
+ # === Input Parameters ===
+ plate_height = self.height
+ stiffener_height = self.stiffener_length
+ stiffener_width=self.stiffener_width
+ stiffener_thickness=self.stiffener_thickness
+ plate_thickness=self.plate_thickness
+ print('stiff thicknes:',stiffener_thickness , 'stiff width : ',stiffener_width)
+ h_gap = 12.5
+ flange_thick=self.flange_thick
+ beam_width=self.beam_width
+ total_plate_width = 2 * plate_thickness
+ view_width,view_height=800,800
+ start_x = (view_width - total_plate_width) / 2
+ start_y = (view_height - plate_height) / 2
+
+ # Draw first plate
+ total_plate_width = 2 * plate_thickness
+ start_x = (view_width - total_plate_width) / 2
+ start_y = (view_height - plate_height) / 2
+
+ # === Pen (blue border, no fill) ===
+ blue_pen = QPen(QColor("blue"))
+ blue_pen.setWidth(2)
+ blackpen=QPen(QColor("black"))
+ # === Draw Rectangles ===
+ self.scene.addRect(start_x, start_y, plate_thickness, plate_height, blue_pen)
+ dim_y = start_y + plate_height + 20 # 20 px below
+ self.addHorizontalDimension(start_x, dim_y, start_x + plate_thickness, dim_y, str(plate_thickness), blackpen)
+ self.addHorizontalDimension(start_x, dim_y, start_x -beam_width, dim_y, str(beam_width), blackpen)
+ self.addVerticalDimension(start_x-beam_width-20,start_y,start_x-beam_width-20,start_y+plate_height , str(plate_height),blackpen)
+ self.scene.addRect(start_x + plate_thickness, start_y, plate_thickness, plate_height, blue_pen, )
+ red_brush = QBrush(QColor("red"))
+ red_pen = QPen(Qt.NoPen) # No border for stiffeners
+
+ stiffener_width = stiffener_thickness / 2
+
+ beam_y = start_y + 12.5
+ beam_height = plate_height - 2 *12.5
+ pen = QPen(QColor("orange"))
+ # Left beam rectangle (left of left plate)
+ self.scene.addRect(
+ start_x - beam_width,
+ beam_y,
+ beam_width,
+ beam_height,
+ pen,
+ QBrush(Qt.NoBrush)
+ )
+
+ # Right beam rectangle (right of right plate)
+ self.scene.addRect(
+ start_x + 2 * plate_thickness,
+ beam_y,
+ beam_width,
+ beam_height,
+ pen,
+ QBrush(Qt.NoBrush)
+ )
+
+ stiffener_width=self.stiffener_width
+ # X coordinates
+ x_left_start = start_x
+ x_left_end = start_x-beam_width
+
+ x_right_end = start_x+2*plate_thickness
+ x_right_start = x_right_end +beam_width
+
+ # Y positions
+ y_top = start_y+ flange_thick + 12.5
+ y_bottom = (start_y+plate_height) - 12.5 - flange_thick
+
+ # Left-top horizontal line
+ self.scene.addLine(x_left_start, y_top, x_left_end, y_top, pen)
+
+ # Left-bottom horizontal line
+ self.scene.addLine(x_left_start, y_bottom, x_left_end, y_bottom, pen)
+
+ # Right-top horizontal line
+ self.scene.addLine(x_right_start, y_top, x_right_end, y_top, pen)
+
+ # Right-bottom horizontal line
+ self.scene.addLine(x_right_start, y_bottom, x_right_end, y_bottom, pen)
+ self.view.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio)
+ pen = QPen(QColor("black"))
+ pen.setWidth(2)
+ offset_len = 25 # 25mm offset for both lines
+
+# Coordinates for the top-left corner of the left plate
+ pen = QPen(Qt.black, 2)
+ pen2=QPen(Qt.black, 1)
+ brush = QBrush(Qt.NoBrush)
+ half_thick = stiffener_thickness / 2.0
+
+ self.scene.addRect(
+ start_x - stiffener_thickness,
+ start_y+12.5,
+ stiffener_thickness,
+ plate_height - 2*12.5,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x +2*plate_thickness,
+ start_y+12.5,
+ stiffener_thickness,
+ plate_height - 2*12.5,
+ red_pen,
+ red_brush
+ )
+
+ def createDrawingExtendedOneWay(self):
+ from PyQt5.QtCore import Qt
+ from PyQt5.QtGui import QPen, QColor, QBrush,QPolygonF
+ from PyQt5.QtWidgets import QGraphicsRectItem,QGraphicsPolygonItem
+ # === Input Parameters ===
+ plate_height = self.height
+ stiffener_height = self.stiffener_length
+ stiffener_width=self.stiffener_width
+ stiffener_thickness=self.stiffener_thickness
+ plate_thickness=self.plate_thickness
+ print('stiff thicknes:',stiffener_thickness , 'stiff width : ',stiffener_width)
+ h_gap = 12.5
+ flange_thick=self.flange_thick
+ beam_width=self.beam_width
+ total_plate_width = 2 * plate_thickness
+ view_width,view_height=800,800
+ start_x = (view_width - total_plate_width) / 2
+ start_y = (view_height - plate_height) / 2
+ blackpen=QPen(QColor("black"))
+ # Draw first plate
+ total_plate_width = 2 * plate_thickness
+ start_x = (view_width - total_plate_width) / 2
+ start_y = (view_height - plate_height) / 2
+
+ # === Pen (blue border, no fill) ===
+ blue_pen = QPen(QColor("blue"))
+ blue_pen.setWidth(2)
+
+ # === Draw Rectangles ===
+ self.scene.addRect(start_x, start_y, plate_thickness, plate_height, blue_pen)
+ self.scene.addRect(start_x + plate_thickness, start_y, plate_thickness, plate_height, blue_pen, )
+ red_brush = QBrush(QColor("red"))
+ red_pen = QPen(Qt.NoPen) # No border for stiffeners
+ dim_y = start_y + plate_height + 20 # 20 px below
+ self.addHorizontalDimension(start_x, dim_y, start_x + plate_thickness, dim_y, str(plate_thickness), blackpen)
+ self.addHorizontalDimension(start_x, dim_y, start_x -beam_width, dim_y, str(beam_width), blackpen)
+ self.addVerticalDimension(start_x-beam_width-20,start_y,start_x-beam_width-20,start_y+plate_height , str(plate_height),blackpen)
+
+ stiffener_width = stiffener_thickness / 2
+
+ # Top stiffener (left of left plate)
+ self.scene.addRect(
+ start_x - stiffener_width,
+ start_y,
+ stiffener_width,
+ stiffener_height,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x - 2*stiffener_width,
+ start_y+stiffener_height,
+ 2*stiffener_width,
+ plate_height-stiffener_height,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x + 2 * plate_thickness,
+ start_y+stiffener_height,
+ 2*stiffener_width,
+ plate_height-stiffener_height,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x + 2 * plate_thickness, # Right side of right plate
+ start_y,
+ stiffener_width,
+ stiffener_height,
+ red_pen,
+ red_brush
+ )
+
+ beam_y = start_y + stiffener_height
+ beam_height = plate_height -stiffener_height-12.5
+ pen = QPen(QColor("orange"))
+ # Left beam rectangle (left of left plate)
+ self.scene.addRect(
+ start_x - beam_width,
+ beam_y,
+ beam_width,
+ beam_height,
+ pen,
+ QBrush(Qt.NoBrush)
+ )
+
+ # Right beam rectangle (right of right plate)
+ self.scene.addRect(
+ start_x + 2 * plate_thickness,
+ beam_y,
+ beam_width,
+ beam_height,
+ pen,
+ QBrush(Qt.NoBrush)
+ )
+
+ stiffener_width=self.stiffener_width
+ # X coordinates
+ x_left_start = start_x
+ x_left_end = start_x-beam_width
+
+ x_right_end = start_x+2*plate_thickness
+ x_right_start = x_right_end +beam_width
+
+ # Y positions
+ y_top = start_y+stiffener_height + flange_thick
+ y_bottom = (start_y+plate_height) - flange_thick-12.5
+
+ # Left-top horizontal line
+ self.scene.addLine(x_left_start, y_top, x_left_end, y_top, pen)
+
+ # Left-bottom horizontal line
+ self.scene.addLine(x_left_start, y_bottom, x_left_end, y_bottom, pen)
+
+ # Right-top horizontal line
+ self.scene.addLine(x_right_start, y_top, x_right_end, y_top, pen)
+
+ # Right-bottom horizontal line
+ self.scene.addLine(x_right_start, y_bottom, x_right_end, y_bottom, pen)
+ self.view.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio)
+ pen = QPen(QColor("black"))
+ pen.setWidth(2)
+ offset_len = 25 # 25mm offset for both lines
+
+# Coordinates for the top-left corner of the left plate
+ pen = QPen(Qt.black, 2)
+ pen2=QPen(Qt.black, 1)
+ brush = QBrush(Qt.NoBrush)
+ half_thick = stiffener_thickness / 2.0
+ # === TOP LEFT ===
+ x1, y1 = start_x, start_y
+ x2, y2 = start_x - offset_len, start_y
+ x3, y3 = start_x - stiffener_width, start_y + stiffener_height - offset_len
+ x4, y4 = start_x - stiffener_width, start_y + stiffener_height
+ x5, y5 = start_x, start_y + stiffener_height
+ points_tl = [QPointF(x1, y1), QPointF(x2, y2), QPointF(x3, y3), QPointF(x4, y4), QPointF(x5, y5)]
+ polygon_tl = QGraphicsPolygonItem(QPolygonF(points_tl))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(brush)
+ self.scene.addItem(polygon_tl)
+ # Red cap
+ x6, y6 = x5, y5 - half_thick
+ x7, y7 = x4, y4 - half_thick
+ polygon_tl = QGraphicsPolygonItem(QPolygonF([QPointF(x4, y4), QPointF(x5, y5), QPointF(x6, y6), QPointF(x7, y7)]))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(red_brush)
+ self.scene.addItem(polygon_tl)
+
+ # Red cap
+
+ # === TOP RIGHT ===
+ x1, y1 = start_x + 2 * plate_thickness, start_y
+ x2, y2 = x1 + offset_len, start_y
+ x3, y3 = x1 + stiffener_width, start_y + stiffener_height - offset_len
+ x4, y4 = x1 + stiffener_width, start_y + stiffener_height
+ x5, y5 = x1, start_y + stiffener_height
+ points_tr = [QPointF(x1, y1), QPointF(x2, y2), QPointF(x3, y3), QPointF(x4, y4), QPointF(x5, y5)]
+ polygon_tr = QGraphicsPolygonItem(QPolygonF(points_tr))
+ polygon_tr.setPen(pen)
+ polygon_tr.setBrush(brush)
+ self.scene.addItem(polygon_tr)
+ # Red cap
+ x6, y6 = x5, y5 - half_thick
+ x7, y7 = x4, y4 - half_thick
+ polygon_tl = QGraphicsPolygonItem(QPolygonF([QPointF(x4, y4), QPointF(x5, y5), QPointF(x6, y6), QPointF(x7, y7)]))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(red_brush)
+ self.scene.addItem(polygon_tl)
+
+ # Red cap
+
+ self.addHorizontalDimension(start_x,start_y-40,start_x-stiffener_width,start_y-40,str(stiffener_width),blackpen)
+ xpos=start_x +2*plate_thickness +stiffener_width+20
+ self.addVerticalDimension(xpos,start_y,xpos,start_y+stiffener_height,str(stiffener_height),blackpen)
+ # self.addInternalGapsExtendedOneWay()
+ # self.addDimensionsExtendedOneWay(edge,self.Gauge,self.CrossGauge,self.cols)
+
+ def createDrawingExtendedTwoWay(self):
+ from PyQt5.QtCore import Qt
+ from PyQt5.QtGui import QPen, QColor, QBrush,QPolygonF
+ from PyQt5.QtWidgets import QGraphicsRectItem,QGraphicsPolygonItem
+ # === Input Parameters ===
+ plate_height = self.height
+ stiffener_height = self.stiffener_length
+ stiffener_width=self.stiffener_width
+ stiffener_thickness=self.stiffener_thickness
+ plate_thickness=self.plate_thickness
+ print('stiff thicknes:',stiffener_thickness , 'stiff width : ',stiffener_width)
+ h_gap = 12.5
+ flange_thick=self.flange_thick
+ beam_width=self.beam_width
+ total_plate_width = 2 * plate_thickness
+ view_width,view_height=800,800
+ start_x = (view_width - total_plate_width) / 2
+ start_y = (view_height - plate_height) / 2
+
+ # Draw first plate
+ total_plate_width = 2 * plate_thickness
+ start_x = (view_width - total_plate_width) / 2
+ start_y = (view_height - plate_height) / 2
+
+ # === Pen (blue border, no fill) ===
+ blue_pen = QPen(QColor("blue"))
+ blue_pen.setWidth(2)
+ blackpen=QPen(QColor("black"))
+ # === Draw Rectangles ===
+ self.scene.addRect(start_x, start_y, plate_thickness, plate_height, blue_pen)
+ self.scene.addRect(start_x + plate_thickness, start_y, plate_thickness, plate_height, blue_pen, )
+ red_brush = QBrush(QColor("red"))
+ red_pen = QPen(Qt.NoPen) # No border for stiffeners
+ dim_y = start_y + plate_height + 20 # 20 px below
+ self.addHorizontalDimension(start_x, dim_y, start_x + plate_thickness, dim_y, str(plate_thickness), blackpen)
+ self.addHorizontalDimension(start_x, dim_y, start_x -beam_width, dim_y, str(beam_width), blackpen)
+ self.addVerticalDimension(start_x-beam_width-20,start_y,start_x-beam_width-20,start_y+plate_height , str(plate_height),blackpen)
+
+ stiffener_width = stiffener_thickness / 2
+
+ # Top stiffener (left of left plate)
+ self.scene.addRect(
+ start_x - stiffener_width,
+ start_y,
+ stiffener_width,
+ stiffener_height,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x - 2*stiffener_width,
+ start_y+stiffener_height,
+ stiffener_width*2,
+ plate_height-2*stiffener_height,
+ red_pen,
+ red_brush
+ )
+
+ # Bottom stiffener (left of left plate)
+ self.scene.addRect(
+ start_x - stiffener_width,
+ start_y + plate_height - stiffener_height,
+ stiffener_width,
+ stiffener_height,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x + 2 * plate_thickness, # Right side of right plate
+ start_y,
+ stiffener_width,
+ stiffener_height,
+ red_pen,
+ red_brush
+ )
+ self.scene.addRect(
+ start_x + 2 * plate_thickness, # Right side of right plate
+ start_y+stiffener_height,
+ stiffener_width*2,
+ plate_height-2*stiffener_height,
+ red_pen,
+ red_brush
+ )
+
+ self.scene.addRect(
+ start_x + 2 * plate_thickness, # Right side of right plate
+ start_y + plate_height - stiffener_height,
+ stiffener_width,
+ stiffener_height,
+ red_pen,
+ red_brush
+ )
+ beam_y = start_y + stiffener_height
+ beam_height = plate_height - 2 * stiffener_height
+ pen = QPen(QColor("orange"))
+ # Left beam rectangle (left of left plate)
+ self.scene.addRect(
+ start_x - beam_width,
+ beam_y,
+ beam_width,
+ beam_height,
+ pen,
+ QBrush(Qt.NoBrush)
+ )
+
+ # Right beam rectangle (right of right plate)
+ self.scene.addRect(
+ start_x + 2 * plate_thickness,
+ beam_y,
+ beam_width,
+ beam_height,
+ pen,
+ QBrush(Qt.NoBrush)
+ )
+
+ stiffener_width=self.stiffener_width
+ # X coordinates
+ x_left_start = start_x
+ x_left_end = start_x-beam_width
+
+ x_right_end = start_x+2*plate_thickness
+ x_right_start = x_right_end +beam_width
+
+ # Y positions
+ y_top = start_y+stiffener_height + flange_thick
+ y_bottom = (start_y+plate_height) - stiffener_height - flange_thick
+
+ # Left-top horizontal line
+ self.scene.addLine(x_left_start, y_top, x_left_end, y_top, pen)
+
+ # Left-bottom horizontal line
+ self.scene.addLine(x_left_start, y_bottom, x_left_end, y_bottom, pen)
+
+ # Right-top horizontal line
+ self.scene.addLine(x_right_start, y_top, x_right_end, y_top, pen)
+
+ # Right-bottom horizontal line
+ self.scene.addLine(x_right_start, y_bottom, x_right_end, y_bottom, pen)
+ self.view.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio)
+ pen = QPen(QColor("black"))
+ pen.setWidth(2)
+ offset_len = 25 # 25mm offset for both lines
+
+# Coordinates for the top-left corner of the left plate
+ pen = QPen(Qt.black, 2)
+ pen2=QPen(Qt.black, 1)
+ brush = QBrush(Qt.NoBrush)
+ half_thick = stiffener_thickness / 2.0
+ # === TOP LEFT ===
+ x1, y1 = start_x, start_y
+ x2, y2 = start_x - offset_len, start_y
+ x3, y3 = start_x - stiffener_width, start_y + stiffener_height - offset_len
+ x4, y4 = start_x - stiffener_width, start_y + stiffener_height
+ x5, y5 = start_x, start_y + stiffener_height
+ points_tl = [QPointF(x1, y1), QPointF(x2, y2), QPointF(x3, y3), QPointF(x4, y4), QPointF(x5, y5)]
+ polygon_tl = QGraphicsPolygonItem(QPolygonF(points_tl))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(brush)
+ self.scene.addItem(polygon_tl)
+ # Red cap
+ x6, y6 = x5, y5 - half_thick
+ x7, y7 = x4, y4 - half_thick
+ polygon_tl = QGraphicsPolygonItem(QPolygonF([QPointF(x4, y4), QPointF(x5, y5), QPointF(x6, y6), QPointF(x7, y7)]))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(red_brush)
+ self.scene.addItem(polygon_tl)
+ # === BOTTOM LEFT ===
+ x1, y1 = start_x, start_y + plate_height
+ x2, y2 = start_x - offset_len, start_y + plate_height
+ x3, y3 = start_x - stiffener_width, start_y + plate_height - stiffener_height + offset_len
+ x4, y4 = start_x - stiffener_width, start_y + plate_height - stiffener_height
+ x5, y5 = start_x, start_y + plate_height - stiffener_height
+ points_bl = [QPointF(x1, y1), QPointF(x2, y2), QPointF(x3, y3), QPointF(x4, y4), QPointF(x5, y5)]
+ polygon_bl = QGraphicsPolygonItem(QPolygonF(points_bl))
+ polygon_bl.setPen(pen)
+ polygon_bl.setBrush(brush)
+ self.scene.addItem(polygon_bl)
+ # Red cap
+ x6, y6 = x5, y5 + half_thick
+ x7, y7 = x4, y4 + half_thick
+ polygon_tl = QGraphicsPolygonItem(QPolygonF([QPointF(x4, y4), QPointF(x5, y5), QPointF(x6, y6), QPointF(x7, y7)]))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(red_brush)
+ self.scene.addItem(polygon_tl)
+ # === TOP RIGHT ===
+ x1, y1 = start_x + 2 * plate_thickness, start_y
+ x2, y2 = x1 + offset_len, start_y
+ x3, y3 = x1 + stiffener_width, start_y + stiffener_height - offset_len
+ x4, y4 = x1 + stiffener_width, start_y + stiffener_height
+ x5, y5 = x1, start_y + stiffener_height
+ points_tr = [QPointF(x1, y1), QPointF(x2, y2), QPointF(x3, y3), QPointF(x4, y4), QPointF(x5, y5)]
+ polygon_tr = QGraphicsPolygonItem(QPolygonF(points_tr))
+ polygon_tr.setPen(pen)
+ polygon_tr.setBrush(brush)
+ self.scene.addItem(polygon_tr)
+ # Red cap
+ x6, y6 = x5, y5 - half_thick
+ x7, y7 = x4, y4 - half_thick
+ polygon_tl = QGraphicsPolygonItem(QPolygonF([QPointF(x4, y4), QPointF(x5, y5), QPointF(x6, y6), QPointF(x7, y7)]))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(red_brush)
+ self.scene.addItem(polygon_tl)
+ # === BOTTOM RIGHT ===
+ x1, y1 = start_x + 2 * plate_thickness, start_y + plate_height
+ x2, y2 = x1 + offset_len, y1
+ x3, y3 = x1 + stiffener_width, start_y + plate_height - stiffener_height + offset_len
+ x4, y4 = x1 + stiffener_width, start_y + plate_height - stiffener_height
+ x5, y5 = x1, start_y + plate_height - stiffener_height
+ points_br = [QPointF(x1, y1), QPointF(x2, y2), QPointF(x3, y3), QPointF(x4, y4), QPointF(x5, y5)]
+ polygon_br = QGraphicsPolygonItem(QPolygonF(points_br))
+ polygon_br.setPen(pen)
+ polygon_br.setBrush(brush)
+ self.scene.addItem(polygon_br)
+ # Red cap
+ x6, y6 = x5, y5 + half_thick
+ x7, y7 = x4, y4 + half_thick
+ polygon_tl = QGraphicsPolygonItem(QPolygonF([QPointF(x4, y4), QPointF(x5, y5), QPointF(x6, y6), QPointF(x7, y7)]))
+ polygon_tl.setPen(pen)
+ polygon_tl.setBrush(red_brush)
+ self.scene.addItem(polygon_tl)
+ self.addHorizontalDimension(start_x,start_y-40,start_x-stiffener_width,start_y-40,str(stiffener_width),blackpen)
+ xpos=start_x +2*plate_thickness +stiffener_width+20
+ self.addVerticalDimension(xpos,start_y,xpos,start_y+stiffener_height,str(stiffener_height),blackpen)
+
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(10)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(10)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
\ No newline at end of file
diff --git a/src/osdag/gui/baseplatedetailing.py b/src/osdag/gui/baseplatedetailing.py
new file mode 100644
index 000000000..48c949353
--- /dev/null
+++ b/src/osdag/gui/baseplatedetailing.py
@@ -0,0 +1,611 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene,QGraphicsRectItem)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont,QColor
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+class BasePlateDetailing(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+ self.connection = connection_obj
+ data=main.output_values(main,True)
+ print(type(main))
+
+ bp_width_provided=main.bp_width_provided
+ column_bf=main.column_bf
+ effective_length_flange=self.connection.effective_length_flange
+ plate_thk_provided=main.plate_thk_provided
+ column_tw=main.column_tw
+ columnflange_tf=main.column_tf
+ effective_length_web=self.connection.effective_length_web
+ plate_thk_provided=main.plate_thk_provided
+ column_D=main.column_D
+ print(f'Connectivity : {main.connectivity}\n\n')
+ # print(data)
+ print(f"""
+ bp_width_provided: {bp_width_provided}
+ column_bf: {column_bf}
+ effective_length_flange: {effective_length_flange}
+ plate_thk_provided: {plate_thk_provided}
+ column_tw: {column_tw}\\column thickness
+ effective_length_web: {effective_length_web}
+ column_D:{column_D}
+ col thickness : {columnflange_tf}
+ """)
+ # for i in data:
+ # print(i)
+ self.column_len=column_D
+ self.column_width=column_bf
+ self.web_thickness=column_tw
+ self.column_thickness=columnflange_tf
+ self.detail_dict = {
+ f'{entry[1]} + {entry[0]}': entry[3]
+ for entry in data
+ }
+ for i in self.detail_dict.keys():
+ print(i)
+ self.no_outsidebolts=self.detail_dict['No. of Anchors + Anchor Bolt.No of Anchor Bolts']
+ self.dia_outside_bolt=self.detail_dict['Diameter (mm) + Anchor Bolt.Diameter']
+ self.no_insidebolts=self.detail_dict['No. of Anchors + Anchor Bolt.No of Anchor Bolts_Uplift']
+ self.dia_inside_bolt=self.detail_dict['Diameter (mm) + Anchor Bolt.Diameter_Uplift']
+ self.plate_length=self.detail_dict['Length (mm) + Baseplate.Length']
+ self.plate_width=self.detail_dict['Width (mm) + Baseplate.Width']
+ self.Endout=self.detail_dict['End Distance (mm) + Detailing.EndDistanceOut']
+ self.Edgeout=self.detail_dict['Edge Distance (mm) + Detailing.EdgeDistanceOut']
+ self.pitchout=self.detail_dict['Pitch Distance (mm) + Detailing.PitchDistanceOut']
+ self.Gaugeout=self.detail_dict['Gauge Distance (mm) + Detailing.GaugeDistanceOut']
+ self.Endin=self.detail_dict['End Distance (mm) + Detailing.EndDistanceIn']
+ self.Edgein=self.detail_dict['Edge Distance (mm) + Detailing.EdgeDistanceIn']
+ self.pitchin=self.detail_dict['Pitch Distance (mm) + Detailing.PitchDistanceIn']
+ self.Gaugein=self.detail_dict['Gauge Distance (mm) + Detailing.GaugeDistanceIn']
+
+ stiffacrossdata=main.stiffener_across_web_details(main,True)
+
+ stiffalongdata=main.stiffener_along_web_details(main,True)
+
+ stiffflangedata=main.stiffener_flange_details(main,True)
+ self.stiff_across_length=stiffacrossdata[0][3]
+ self.stiff_across_thickness=stiffacrossdata[2][3]
+ self.stiff_along_length=stiffalongdata[0][3]
+ self.stiff_along_thickness=stiffalongdata[2][3]
+ self.stiff_flange_length=stiffflangedata[0][3]
+ self.stiff_flange_thickness=stiffflangedata[2][3]
+
+ self.rows = rows
+ self.cols = cols
+ self.initUI()
+
+ def initUI(self):
+ if self.stiff_along_length!='N/A':
+ self.column_len=(self.plate_length-2*self.column_thickness-2*self.stiff_along_length)
+ self.setWindowTitle('Bolt Pattern Generator')
+ print(f"""
+ Base Plate & Bolt Details:
+ --------------------------
+ No. of Outside Bolts : {self.no_outsidebolts}
+ Diameter Outside Bolt: {self.dia_outside_bolt}
+ No. of Inside Bolts : {self.no_insidebolts}
+ Diameter Inside Bolt : {self.dia_inside_bolt}
+ Base Plate Length : {self.plate_length}
+ Base Plate Width : {self.plate_width}
+ End Distance : {self.Endout}
+ Edge Distance : {self.Edgeout}
+
+ Stiffener Plate Dimensions:
+ ---------------------------
+ Across Web - Length: {self.stiff_across_length}, Thickness: {self.stiff_across_thickness}
+ Along Web - Length: {self.stiff_along_length}, Thickness: {self.stiff_along_thickness}
+ Flange - Length: {self.stiff_flange_length}, Thickness: {self.stiff_flange_thickness}
+ """)
+ self.setGeometry(100, 100, 800, 500)
+ # Step 1: Create a central widget
+ central_widget = QWidget()
+ self.setCentralWidget(central_widget)
+
+ # Step 2: Create main layout
+ main_layout = QHBoxLayout()
+ central_widget.setLayout(main_layout)
+
+ # Step 3: Left panel for selected labels only
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+ left_panel.setLayout(left_layout)
+
+ # Only display selected keys
+ keys_to_display = [
+
+ ]
+
+ # Add labels
+
+ # Step 4: Graphics view and scene
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Background and test shape (optional)
+ self.scene.setBackgroundBrush(Qt.white)
+
+ # Step 5: Add to main layout
+ main_layout.addWidget(self.view, stretch=2)
+
+ # Step 6: Call parameter extraction and drawing
+ # self.get_parameters()
+ self.createDrawing()
+ if self.plate_length>700:
+ self.view.resetTransform()
+ self.view.scale(0.5, 0.5)
+ def createDrawing(self):
+ from PyQt5.QtGui import QColor
+ try:
+ plate_length = float(self.plate_length)
+ plate_width = float(self.plate_width)
+ except (TypeError, ValueError):
+ print("Invalid plate dimensions")
+ return
+ rect = QRectF(0, 0, plate_length, plate_width)
+ column_len=self.column_len
+ column_width=self.column_width
+ flange_thickness=self.column_thickness
+ web_thickness=self.web_thickness
+ # Create a rectangle item
+ rect_item = QGraphicsRectItem(rect)
+
+ # Set pen and brush (black border, transparent fill)
+ pen = QPen(Qt.black)
+ pen.setWidth(2)
+ rect_item.setPen(pen)
+ rect_item.setBrush(QBrush(Qt.NoBrush))
+
+ # Add rectangle to the scene
+ self.scene.addItem(rect_item)
+ # Extract parameters
+
+ outline_pen=QPen(Qt.black)
+ # === Draw Base Plate Rectangle ===
+ rect_item = QGraphicsRectItem(QRectF(0, 0, plate_length, plate_width))
+ rect_item.setPen(outline_pen)
+ rect_item.setBrush(QBrush(Qt.white))
+ self.scene.addItem(rect_item)
+ outline_pen = QPen(QColor("orange"))
+ # === Center of the base plate ===
+ center_x = plate_length / 2
+ center_y = plate_width / 2
+ web_top_y=center_y-web_thickness/2
+ web_bot_y=center_y+web_thickness/2
+ web_left_x=center_x-column_len/2
+ web_right_x=center_x+column_len/2
+ self.scene.addLine(web_left_x,web_top_y,web_right_x,web_top_y,outline_pen)
+ self.scene.addLine(web_left_x,web_bot_y,web_right_x,web_bot_y,outline_pen)
+ #LEFT FLANGE
+ left_x=web_left_x-flange_thickness
+ right_x=web_left_x
+ top_y=center_y-column_width/2
+ bot_y=center_y+column_width/2
+ junctiontop_y=web_top_y
+ junctionbot_y=web_bot_y
+ #1
+ self.scene.addLine(left_x,bot_y,left_x,top_y,outline_pen)
+ self.scene.addLine(left_x,top_y,right_x,top_y,outline_pen)
+ self.scene.addLine(right_x,top_y,right_x,junctiontop_y,outline_pen)
+ self.scene.addLine(right_x,junctionbot_y,right_x,bot_y,outline_pen)
+ self.scene.addLine(right_x,bot_y,left_x,bot_y,outline_pen)
+ # === RIGHT FLANGE ===
+ left_x = web_right_x # Inner edge (adjacent to web)
+ right_x = web_right_x + flange_thickness # Outer edge of flange
+ top_y = center_y - column_width / 2
+ bot_y = center_y + column_width / 2
+ junctiontop_y = web_top_y
+ junctionbot_y = web_bot_y
+
+ # 1. Right vertical line
+ self.scene.addLine(right_x, bot_y, right_x, top_y, outline_pen)
+
+ # 2. Top horizontal line
+ self.scene.addLine(right_x, top_y, left_x, top_y, outline_pen)
+
+ # 3. Left vertical line (top segment above web)
+ self.scene.addLine(left_x, top_y, left_x, junctiontop_y, outline_pen)
+
+ # 4. Left vertical line (bottom segment below web)
+ self.scene.addLine(left_x, junctionbot_y, left_x, bot_y, outline_pen)
+
+ # 5. Bottom horizontal line
+ self.scene.addLine(left_x, bot_y, right_x, bot_y, outline_pen)
+ red_brush = QBrush(Qt.red)
+ outline_pen = QPen(Qt.blue)
+ outline_pen.setWidth(2)
+ if isinstance(self.stiff_flange_length, (int, float)):
+ print('her')
+ stiff_thk = self.stiff_flange_thickness
+ offset = (stiff_thk - flange_thickness) / 2
+
+ # === Left Flange Stiffeners ===
+ # Top stiffener (left)
+ left_x=web_left_x-flange_thickness
+ stiffener_left_top = QRectF(
+ left_x - offset, # shift outward from flange face
+ 0, # top of plate
+ stiff_thk,
+ top_y # height to top of flange
+ )
+ self.scene.addRect(stiffener_left_top, outline_pen, red_brush)
+
+ # Bottom stiffener (left)
+ stiffener_left_bottom = QRectF(
+ left_x - offset,
+ bot_y, # just below bottom of flange
+ stiff_thk,
+ plate_width - bot_y # height from flange to bottom of plate
+ )
+ self.scene.addRect(stiffener_left_bottom, outline_pen, red_brush)
+ left_x=web_left_x-flange_thickness
+ # === Right Flange Stiffeners ===
+ # Top stiffener (right)
+ stiffener_right_top = QRectF(
+ right_x - flange_thickness - offset,
+ 0,
+ stiff_thk,
+ top_y
+ )
+ self.scene.addRect(stiffener_right_top, outline_pen, red_brush)
+
+ # Bottom stiffener (right)
+ stiffener_right_bottom = QRectF(
+ right_x - flange_thickness - offset,
+ bot_y,
+ stiff_thk,
+ plate_width - bot_y
+ )
+ self.scene.addRect(stiffener_right_bottom, outline_pen, red_brush)
+ if isinstance(self.stiff_along_thickness, (int, float)):
+ # Web center X range
+ web_center_left = plate_length/2 - column_len/2 - flange_thickness
+ web_center_right = center_x + column_len/2+flange_thickness
+ offset=(web_thickness-self.stiff_along_thickness)/2
+ # Left web stiffener: from left edge to web start
+ stiffener_web_left = QRectF(
+ 0, # x-position (starts from left edge of plate)
+ plate_width / 2 - self.stiff_along_thickness/2+offset , # y-position (top edge of stiffener)
+ web_center_left , # width (same as before, up to web)
+ self.stiff_along_thickness # height (from y-position down)
+ )
+ self.scene.addRect(stiffener_web_left, outline_pen, red_brush)
+
+ # Right web stiffener: from web end to right edge
+ stiffener_web_right = QRectF(
+ web_center_right, # x-position (starts from web outward)
+ plate_width / 2 - self.stiff_along_thickness / 2 + offset, # centered vertically
+ plate_length - web_center_right, # width from web to right edge
+ self.stiff_along_thickness
+ )
+ self.scene.addRect(stiffener_web_right, outline_pen, red_brush)
+
+ if isinstance(self.stiff_across_thickness, (int, float)):
+ web_center_left=center_x-self.stiff_across_thickness/2
+ web_center_right=center_x+self.stiff_across_thickness/2
+ stiffener_web_top = QRectF(
+ web_center_left, # x
+ center_y - self.stiff_across_length-web_thickness/2, # y
+ self.stiff_across_thickness, # width = right - left
+ self.stiff_across_length # height from top to web
+ )
+ stiffener_web_bot = QRectF(
+ web_center_left, # x-start
+ center_y + self.web_thickness/2, # y-start (just below web)
+ self.stiff_across_thickness, # width
+ self.stiff_across_length # height to bottom of plate
+ )
+ self.scene.addRect(stiffener_web_top, outline_pen, red_brush)
+ self.scene.addRect(stiffener_web_bot, outline_pen, red_brush)
+ bolts=self.no_outsidebolts
+ hole_dia=self.dia_outside_bolt
+ radius=hole_dia/2
+ #2 rows
+ #FINDING EFFECTIVE Edge distance
+ edge=self.Edgeout
+ end=self.Endout
+ Gauge=0
+ if self.Gaugeout!='N/A':
+ Gauge=self.Gaugeout
+ if self.pitchout!='N/A':
+ pitch=self.pitchout
+ print(bolts/4,edge,hole_dia)
+ if bolts/4 ==1:
+ edge = (plate_length-column_len-2*flange_thickness)/4
+ else:
+ edge=((plate_length-column_len)/2 - flange_thickness - Gauge)/2
+ print(edge)
+
+ gold_brush = QBrush(QColor("gold"))
+ black_pen = QPen(Qt.black)
+ black_pen.setWidth(2)
+ for col in range(int(bolts/4)):
+ x = edge + col * Gauge # horizontal position
+
+ # Top row bolt
+ y_top = end
+ self.scene.addEllipse(x - radius, y_top - radius, 2 * radius, 2 * radius, outline_pen)
+
+ # Bottom bolt
+ y_bot = plate_width - end
+ self.scene.addEllipse(x - radius, y_bot - radius, 2 * radius, 2 * radius, outline_pen)
+ for col in range(int(bolts/4)):
+ x = plate_length - edge - col * Gauge
+ y_top = end
+ y_bot = plate_width - end
+
+ self.scene.addEllipse(x - radius, y_top - radius, 2 * radius, 2 * radius, outline_pen)
+ self.scene.addEllipse(x - radius, y_bot - radius, 2 * radius, 2 * radius, outline_pen)
+
+ bolts=self.no_insidebolts
+ self.Edgeout=edge
+ if bolts!=0 and bolts!='N/A' :
+ hole_dia=self.dia_inside_bolt
+ radius=hole_dia/2
+ #2 rows
+ #FINDING EFFECTIVE Edge distance
+ edge=self.Edgein
+ end=self.Endin
+ if self.Gaugein!='N/A':
+ Gauge=self.Gaugein
+ if self.pitchin!='N/A':
+ pitch=self.pitchin
+
+
+ if bolts==4 and self.stiff_across_thickness!='N/A':
+ x_mid_left=center_x-self.stiff_across_thickness/2
+ x_mid_right=center_x+self.stiff_across_thickness/2
+ y_mid_top=center_y-web_thickness/2
+ y_mid_bot=center_y+web_thickness/2
+ #4 bolts :
+ x1 = x_mid_left - edge
+ y1 = y_mid_top - end
+ self.scene.addEllipse(x1 - radius, y1 - radius, 2 * radius, 2 * radius, outline_pen)
+
+ # Bottom-left bolt
+ y2 = y_mid_bot + end
+ self.scene.addEllipse(x1 - radius, y2 - radius, 2 * radius, 2 * radius, outline_pen)
+
+ # Top-right bolt
+ x2 = x_mid_right + edge
+ y3 = y_mid_top - end
+ self.scene.addEllipse(x2 - radius, y3 - radius, 2 * radius, 2 * radius, outline_pen)
+
+ # Bottom-right bolt
+ y4 = y_mid_bot + end
+ self.scene.addEllipse(x2 - radius, y4 - radius, 2 * radius, 2 * radius, outline_pen)
+ elif self.stiff_across_thickness=='N/A' and bolts==2 :
+ x1=center_x
+ y1=center_y-end
+ self.scene.addEllipse(x1 - radius, y1 - radius, 2 * radius, 2 * radius, outline_pen)
+ y1=center_y+end
+ self.scene.addEllipse(x1 - radius, y1 - radius, 2 * radius, 2 * radius, outline_pen)
+ self.addDimensions(black_pen)
+ def addDimensions(self, pen):
+ num_bolts = self.no_outsidebolts
+ edge_x = float(self.Edgeout)
+ end_y = float(self.Endout)
+ plate_length = float(self.plate_length)
+ plate_width = float(self.plate_width)
+
+ gauge = 0
+ if self.Gaugeout != 'N/A':
+ gauge = float(self.Gaugeout)
+
+ # Top side bolts
+ bolt1_x = edge_x
+ bolt1_y = end_y
+ bolt2_x = bolt1_x + gauge
+ bolt2_y = bolt1_y
+
+ # 1. Top - Edge to bolt 1
+ self.addHorizontalDimension(0, bolt1_y + 30, bolt1_x, bolt1_y + 30, f"{round(edge_x)} mm", pen)
+ # 2. Top - Gauge
+ if num_bolts // 4 == 2:
+ self.addHorizontalDimension(bolt1_x, bolt1_y - 20, bolt2_x, bolt2_y - 20, f"{round(gauge)} mm", pen)
+ # 3. Top - Bolt 2 to edge
+ self.addHorizontalDimension(bolt2_x, bolt2_y + 30, bolt2_x + edge_x, bolt2_y + 30, f"{round(edge_x)} mm", pen)
+ # 4. Top - Vertical from plate top to bolts
+ self.addVerticalDimension(bolt1_x + 30, 0, bolt1_x + 30, bolt1_y, f"{round(end_y)} mm", pen)
+
+ # Bottom side bolts
+ bolt1_y_bot = plate_width - end_y
+ bolt2_y_bot = bolt1_y_bot
+ self.addHorizontalDimension(0, bolt1_y_bot + 30, bolt1_x, bolt1_y_bot + 30, f"{round(edge_x)} mm", pen)
+ if num_bolts // 4 == 2:
+ self.addHorizontalDimension(bolt1_x, bolt1_y_bot + 20, bolt2_x, bolt2_y_bot + 20, f"{round(gauge)} mm", pen)
+ self.addHorizontalDimension(bolt2_x, bolt2_y_bot + 30, bolt2_x + edge_x, bolt2_y_bot + 30, f"{round(edge_x)} mm", pen)
+ self.addVerticalDimension(bolt1_x + 30, bolt1_y_bot, bolt1_x + 30, plate_width, f"{round(end_y)} mm", pen)
+
+ # Left side bolts
+ bolt2_x_right = plate_length - edge_x
+ bolt1_x_right = bolt2_x_right - gauge
+ bolt_y_right = end_y
+
+ # === 1. Right Edge to Bolt 2
+ self.addHorizontalDimension(
+ bolt2_x_right, bolt_y_right + 30, plate_length, bolt_y_right + 30,
+ f"{round(edge_x)} mm", pen
+ )
+
+ # === 2. Gauge (Bolt 1 to Bolt 2)
+ if num_bolts // 4 == 2:
+ self.addHorizontalDimension(
+ bolt1_x_right, bolt_y_right - 20, bolt2_x_right, bolt_y_right - 20,
+ f"{round(gauge)} mm", pen
+ )
+
+ # === 3. Left Edge to Bolt 1 (mirrored)
+ self.addHorizontalDimension(
+ bolt1_x_right - edge_x, bolt_y_right + 30, bolt1_x_right, bolt_y_right + 30,
+ f"{round(edge_x)} mm", pen
+ )
+
+ # === 4. Vertical (top edge to bolts)
+ self.addVerticalDimension(
+ bolt2_x_right + 30, 0, bolt2_x_right + 30, bolt_y_right,
+ f"{round(end_y)} mm", pen
+ )
+ # === Bottom-right corner bolts (horizontal gauge line between bolts)
+ bolt2_x_br = plate_length - edge_x
+ bolt1_x_br = bolt2_x_br - gauge
+ bolt_y_br = plate_width - end_y
+
+ # 1. Vertical from bottom edge to bolt row
+ self.addVerticalDimension(
+ bolt2_x_br + 30, bolt_y_br, bolt2_x_br + 30, plate_width,
+ f"{round(end_y)} mm", pen
+ )
+ # 2. Gauge (horizontal between bolts)
+ if num_bolts // 4 == 2:
+ self.addHorizontalDimension(
+ bolt1_x_br, bolt_y_br + 20, bolt2_x_br, bolt_y_br + 20,
+ f"{round(gauge)} mm", pen
+ )
+
+ # 3. Edge distance from left of bolt 1 (mirror)
+ self.addHorizontalDimension(
+ bolt1_x_br - edge_x, bolt_y_br + 30, bolt1_x_br, bolt_y_br + 30,
+ f"{round(edge_x)} mm", pen
+ )
+
+ # 4. Edge distance from bolt 2 to plate edge
+ self.addHorizontalDimension(
+ bolt2_x_br, bolt_y_br + 30, plate_length, bolt_y_br + 30,
+ f"{round(edge_x)} mm", pen
+ )
+ center_x=plate_length/2
+ center_y=plate_width/2
+ web_thickness=self.web_thickness
+ flange_thickness = self.column_thickness
+ column_len=self.column_len
+ column_width=self.column_width
+ if self.stiff_along_thickness != 'N/A':
+ #x = 0 to x= center_x -column_len/2 - flange_thickness (horizontal line) , y = center_y - self.stiff_along_thickness/2
+ x1 = 0
+ x2 = center_x - column_len / 2 - flange_thickness
+ y = center_y - self.stiff_along_thickness / 2
+
+ self.addHorizontalDimension(x1, y-30, x2, y-30, f"{round(x2 - x1)} mm", pen)
+ if self.stiff_across_thickness != 'N/A':
+ x=center_x-self.stiff_across_thickness/2
+ y2=center_y-web_thickness/2
+ y1=y2-self.stiff_across_length
+ self.addVerticalDimension(x+60,y1,x+60,y2,f"{round(y2-y1)}mm" , pen)
+ if self.stiff_flange_thickness!='N/A':
+ x=center_x-column_len/2 + 20
+ y1=0
+ y2=center_y -column_width/2
+ self.addVerticalDimension(x,y1,x,y2,f"{round(y2-y1)}mm" , pen)
+ num_bolts = self.no_insidebolts
+ if num_bolts!='N/A' and num_bolts!=0:
+ edge_x = float(self.Edgein)
+ end_y = float(self.Endin)
+ if self.stiff_across_thickness!='N/A' and num_bolts==4:
+ #1
+ x1=center_x-edge_x-self.stiff_across_thickness/2
+ x2=x1+edge_x
+ y1=center_y-end_y-web_thickness/2
+ y2=y1+end_y
+ self.addHorizontalDimension(x1, y1-30, x2, y1-30, f"{round(edge_x)} mm", pen)
+ self.addVerticalDimension(x1-30,y1,x1-30,y2,f"{round(end_y)}",pen)
+ elif num_bolts==2:
+ x1=center_x
+ y1=center_y-end_y-web_thickness/2
+ y2=y1+end_y
+ self.addVerticalDimension(x1-30,y1,x1-30,y2,f"{round(end_y)} mm",pen)
+ x1=0
+ x2=plate_length
+ y1=0
+ self.addHorizontalDimension(x1, y1-40, x2, y1-40, f"{round(x2)} mm", pen)
+ x1=plate_length
+ y1=0
+ y2=plate_width
+ self.addVerticalDimension(x1+20,y1,x1+20,y2,f"{round(y2)} mm",pen)
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(10)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(10)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
diff --git a/src/osdag/gui/baseplatedetailinghollow.py b/src/osdag/gui/baseplatedetailinghollow.py
new file mode 100644
index 000000000..eb886090a
--- /dev/null
+++ b/src/osdag/gui/baseplatedetailinghollow.py
@@ -0,0 +1,452 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene,QGraphicsRectItem)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont , QColor
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+class BasePlateDetailingHollow(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+ self.connection = connection_obj
+ data=main.output_values(main,True)
+ print(type(main))
+
+ bp_width_provided=main.bp_width_provided
+ column_bf=main.column_bf
+ effective_length_flange=self.connection.effective_length_flange
+ plate_thk_provided=main.plate_thk_provided
+ column_tw=main.column_tw
+ columnflange_tf=main.column_tf
+ effective_length_web=self.connection.effective_length_web
+ plate_thk_provided=main.plate_thk_provided
+ column_D=main.column_D
+ print(f'Connectivity : {main.connectivity}\n\n')
+ # print(data)
+ print(f"""
+ bp_width_provided: {bp_width_provided}
+ column_bf: {column_bf}
+ effective_length_flange: {effective_length_flange}
+ plate_thk_provided: {plate_thk_provided}
+ column_tw: {column_tw}\\column thickness
+ effective_length_web: {effective_length_web}
+ column_D:{column_D}
+ col thickness : {columnflange_tf}
+ """)
+ # for i in data:
+ # print(i)
+ self.column_len=column_D
+ self.column_width=column_bf
+ self.web_thickness=column_tw
+ self.column_thickness=columnflange_tf
+ self.detail_dict = {
+ f'{entry[1]} + {entry[0]}': entry[3]
+ for entry in data
+ }
+ for i in self.detail_dict.keys():
+ print(f'{i} : {self.detail_dict[i]}')
+ self.no_outsidebolts=self.detail_dict['No. of Anchors + Anchor Bolt.No of Anchor Bolts']
+ self.dia_outside_bolt=self.detail_dict['Diameter (mm) + Anchor Bolt.Diameter']
+ self.no_insidebolts=self.detail_dict['No. of Anchors + Anchor Bolt.No of Anchor Bolts_Uplift']
+ self.dia_inside_bolt=self.detail_dict['Diameter (mm) + Anchor Bolt.Diameter_Uplift']
+ self.plate_length=self.detail_dict['Length (mm) + Baseplate.Length']
+ self.plate_width=self.detail_dict['Width (mm) + Baseplate.Width']
+ self.Endout=self.detail_dict['End Distance (mm) + Detailing.EndDistanceOut']
+ self.Edgeout=self.detail_dict['Edge Distance (mm) + Detailing.EdgeDistanceOut']
+ self.pitchout=self.detail_dict['Pitch Distance (mm) + Detailing.PitchDistanceOut']
+ self.Gaugeout=self.detail_dict['Gauge Distance (mm) + Detailing.GaugeDistanceOut']
+ self.Endin=self.detail_dict['End Distance (mm) + Detailing.EndDistanceIn']
+ self.Edgein=self.detail_dict['Edge Distance (mm) + Detailing.EdgeDistanceIn']
+ self.pitchin=self.detail_dict['Pitch Distance (mm) + Detailing.PitchDistanceIn']
+ self.Gaugein=self.detail_dict['Gauge Distance (mm) + Detailing.GaugeDistanceIn']
+ print(f'Column Section : {main.column_section}')
+ self.column_section=main.column_section
+ stiffdata=main.stiffener_hollow_details(main,True)
+ self.stiff_D_len=stiffdata[1][3]
+ self.stiff_D_thickness=stiffdata[3][3]
+ self.stiff_B_len=stiffdata[9][3]
+ self.stiff_B_thickness=stiffdata[11][3]
+ self.stiff_OD_len=stiffdata[17][3]
+ self.stiff_OD_thickness=stiffdata[19][3]
+ for i in stiffdata:
+ print(i)
+
+ self.rows = rows
+ self.cols = cols
+ self.initUI()
+
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ print(f"""
+ Base Plate & Bolt Details:
+ --------------------------
+ No. of Outside Bolts : {self.no_outsidebolts}
+ Diameter Outside Bolt: {self.dia_outside_bolt}
+ No. of Inside Bolts : {self.no_insidebolts}
+ Diameter Inside Bolt : {self.dia_inside_bolt}
+ Base Plate Length : {self.plate_length}
+ Base Plate Width : {self.plate_width}
+ End Out Distance : {self.Endout}
+ Edge Out Distance : {self.Edgeout}
+ End In Distance : {self.Endin}
+ Edge In Distance : {self.Edgein}
+ Plate Width : {self.plate_width}
+ Plate Length : {self.plate_length}
+ Stiffener Plate Dimensions:
+ ---------------------------
+ STIFFENER_D - Length: {self.stiff_D_len}, Thickness: {self.stiff_D_thickness}
+ STIFFENER B - Length: {self.stiff_B_len}, Thickness: {self.stiff_B_thickness}
+ STIFFENER OD- Diameter: {self.stiff_OD_len}, Thickness: {self.stiff_OD_thickness}
+ """)
+ self.setGeometry(100, 100, 800, 500)
+ # Step 1: Create a central widget
+ central_widget = QWidget()
+ self.setCentralWidget(central_widget)
+
+ # Step 2: Create main layout
+ main_layout = QHBoxLayout()
+ central_widget.setLayout(main_layout)
+
+ # Step 3: Left panel for selected labels only
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+ left_panel.setLayout(left_layout)
+
+ # Only display selected keys
+ keys_to_display = [
+ "No. of Outside Bolts",
+ "Diameter Outside Bolt",
+ "No. of Inside Bolts",
+ "Diameter Inside Bolt",
+ "Base Plate Length",
+ "Base Plate Width",
+ "End Out Distance",
+ "Edge Out Distance",
+ "End In Distance",
+ "Edge In Distance",
+ "STIFFENER_D Length",
+ "STIFFENER_D Thickness",
+ "STIFFENER_B Length",
+ "STIFFENER_B Thickness",
+ "STIFFENER_OD Diameter",
+ "STIFFENER_OD Thickness",
+ "COLUMN WIDTH",
+ "COLUMN LENGTH"
+ ]
+
+
+ # Add labels
+ values_to_display = {
+ "No. of Outside Bolts": self.no_outsidebolts,
+ "Diameter Outside Bolt": self.dia_outside_bolt,
+ "Base Plate Length": self.plate_length,
+ "Base Plate Width": self.plate_width,
+ "End Distance": self.Endout,
+ "Edge Distance": self.Edgeout,
+ "COLUMN WIDTH": self.column_width,
+ "COLUMN LENGTH":self.column_len
+ }
+
+ for key in keys_to_display:
+ if key in values_to_display:
+ label = QLabel(f"{key}: {values_to_display[key]}")
+ left_layout.addWidget(label)
+ # Step 4: Graphics view and scene
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Background and test shape (optional)
+ self.scene.setBackgroundBrush(Qt.white)
+
+ # Step 5: Add to main layout
+ main_layout.addWidget(self.view, stretch=2)
+ main_layout.addWidget(left_panel, stretch=1)
+ # Step 6: Call parameter extraction and drawing
+ # self.get_parameters()
+ self.createDrawing()
+ if self.plate_length>600:
+ self.view.resetTransform()
+ self.view.scale(0.5, 0.5)
+ def createDrawing(self):
+ try:
+ plate_length = float(self.plate_length)
+ plate_width = float(self.plate_width)
+ except (TypeError, ValueError):
+ print("Invalid plate dimensions")
+ return
+ rect = QRectF(0, 0, plate_length, plate_width)
+ column_len=self.column_len
+ column_width=self.column_width
+ flange_thickness=self.column_thickness
+ web_thickness=self.web_thickness
+ # Create a rectangle item
+ rect_item = QGraphicsRectItem(rect)
+
+ # Set pen and brush (black border, transparent fill)
+ pen = QPen(Qt.black)
+ pen.setWidth(2)
+ rect_item.setPen(pen)
+ rect_item.setBrush(QBrush(Qt.NoBrush))
+
+ # Add rectangle to the scene
+ self.scene.addItem(rect_item)
+ # Extract parameters
+ outline_pen = QPen(Qt.black)
+ outline_pen.setWidth(1)
+
+ # === Draw Base Plate Rectangle ===
+ rect_item = QGraphicsRectItem(QRectF(0, 0, plate_length, plate_width))
+ rect_item.setPen(outline_pen)
+ rect_item.setBrush(QBrush(Qt.white))
+ self.scene.addItem(rect_item)
+ outline_pen = QPen(QColor("orange"))
+ # === Center of the base plate ===
+ center_x = plate_length / 2
+ center_y = plate_width / 2
+ print(self.column_section)
+ if self.column_section.startswith(' RHS') or self.column_section.startswith(' SHS'):
+ col_len=self.column_len
+ col_width=self.column_width
+ col_thickness=self.column_thickness
+ top_left_x = center_x - col_len / 2
+ top_left_y = center_y - col_width / 2
+
+ # Add rectangle
+ self.scene.addRect(top_left_x, top_left_y, col_len, col_width, outline_pen)
+ self.scene.addRect(top_left_x+col_thickness, top_left_y+col_thickness, col_len-2*col_thickness, col_width-2*col_thickness, outline_pen)
+ #innerrectangle
+ self.addHorizontalDimension(
+ top_left_x, # x1
+ top_left_y - 20, # y above the column
+ top_left_x + col_len, # x2
+ top_left_y - 20, # y2 (same as y1)
+ f"{col_len} mm", pen
+ )
+
+ # Vertical dimension (Width)
+ self.addVerticalDimension(
+ top_left_x - 20, # x to the left of column
+ top_left_y, # y1 (top)
+ top_left_x - 20, # x2 (same as x1)
+ top_left_y + col_width, # y2 (bottom)
+ f"{col_width} mm", pen
+ )
+ stiff_thickness = self.stiff_D_thickness
+ else:
+ col_len=self.column_len
+ col_width=self.column_width
+ col_thickness=self.column_thickness
+ top_left_x = center_x - col_len / 2
+ top_left_y = center_y - col_width / 2
+ self.scene.addEllipse(top_left_x, top_left_y, col_len, col_width, outline_pen)
+
+ # Inner ellipse (hollow cutout)
+ inner_x = top_left_x + col_thickness
+ inner_y = top_left_y + col_thickness
+ inner_len = col_len - 2 * col_thickness
+ inner_width = col_width - 2 * col_thickness
+ self.scene.addEllipse(inner_x, inner_y, inner_len, inner_width, outline_pen)
+ self.addHorizontalDimension(
+ top_left_x, # x1
+ center_y - 20, # y above the column
+ top_left_x + col_len, # x2
+ center_y - 20, # y2 (same as y1)
+ f"{col_len} mm", pen
+ )
+ stiff_thickness=self.stiff_OD_thickness
+ outline_pen = QPen(Qt.black)
+ outline_pen.setWidth(2)
+
+
+ stiff_top = 0 # Top of plate
+ stiff_start_y = center_y - col_width / 2 # col_width/2 above center
+ stiff_x = center_x - stiff_thickness / 2 # centered left
+
+ # Height from top of plate to start of stiffener
+ stiff_height = stiff_start_y - stiff_top
+
+ # Draw vertical stiffener rectangle
+ self.scene.addRect(
+ stiff_x,
+ stiff_top,
+ stiff_thickness,
+ stiff_height,
+ outline_pen,
+ QBrush(Qt.red) # Optional: red fill
+ )
+ stiff_start_y=center_y+col_width/2
+ stiff_x=center_x-stiff_thickness/2
+ self.scene.addRect(
+ stiff_x,stiff_start_y,
+ stiff_thickness,
+ stiff_height,
+ outline_pen,
+ QBrush(Qt.red)
+ )
+ self.addVerticalDimension(
+ stiff_x + stiff_thickness + 10, # x (offset right)
+ stiff_start_y, # y1 (top)
+ stiff_x + stiff_thickness + 10, # x2 (same x)
+ stiff_start_y + stiff_height, # y2 (bottom)
+ f"{round(stiff_height)} mm", pen
+ )
+ if self.column_section.startswith(' RHS') or self.column_section.startswith(' SHS'):
+ stiff_thickness=self.stiff_B_thickness
+ stiff_x=0
+ stiff_start_y=center_y-stiff_thickness/2
+ stiff_length=center_x-col_len/2
+ stiff_height=stiff_thickness
+ self.scene.addRect(
+ stiff_x,stiff_start_y,
+ stiff_length,
+ stiff_height,
+ outline_pen,
+ QBrush(Qt.red)
+ )
+ self.addHorizontalDimension(
+ 0, stiff_start_y + 35, # x1, y1 (slightly above the stiffener)
+ stiff_length, stiff_start_y +35, # x2, y2 (same y-level)
+ f"{round(stiff_length)} mm", pen
+ )
+ stiff_x=center_x+col_len/2
+ self.scene.addRect(
+ stiff_x,stiff_start_y,
+ stiff_length,
+ stiff_height,
+ outline_pen,
+ QBrush(Qt.red)
+ )
+ outline_pen = QPen(Qt.blue)
+ outline_pen.setWidth(2)
+ bolts=self.no_outsidebolts
+ hole_dia=self.dia_outside_bolt
+ edge=self.Edgeout
+ end=self.Endout
+ radius=hole_dia/2
+ gold_brush = QBrush(QColor("gold"))
+ x1 = edge
+ y1 = end
+ self.scene.addEllipse(x1 - radius, y1 - radius, hole_dia, hole_dia, outline_pen)
+ self.addHorizontalDimension(0, y1 + 20, x1, y1 + 20, f"{edge} mm", pen)
+ self.addVerticalDimension(x1 + 20, 0, x1 + 20, y1, f"{end} mm", pen)
+
+ # Top-right bolt
+ x2 = self.plate_length - edge
+ y2 = end
+ self.scene.addEllipse(x2 - radius, y2 - radius, hole_dia, hole_dia, outline_pen)
+ self.addHorizontalDimension(x2, y2 + 20, self.plate_length, y2 + 20, f"{edge} mm", pen)
+ self.addVerticalDimension(x2 + 20, 0, x2 + 20, y2, f"{end} mm", pen)
+
+ # Bottom-left bolt
+ x3 = edge
+ y3 = self.plate_width - end
+ self.scene.addEllipse(x3 - radius, y3 - radius, hole_dia, hole_dia, outline_pen)
+ self.addHorizontalDimension(0, y3 + 20, x3, y3 + 20, f"{edge} mm", pen)
+ self.addVerticalDimension(x3 + 20, y3, x3 + 20, self.plate_width, f"{end} mm", pen)
+
+ # Bottom-right bolt
+ x4 = self.plate_length - edge
+ y4 = self.plate_width - end
+ self.scene.addEllipse(x4 - radius, y4 - radius, hole_dia, hole_dia, outline_pen)
+ self.addHorizontalDimension(x4, y4 + 20, self.plate_length, y4 + 20, f"{edge} mm", pen)
+ self.addVerticalDimension(x4 + 20, y4, x4 + 20, self.plate_width, f"{end} mm", pen)
+
+ self.addHorizontalDimension(
+ 0, -30, # x1 at left edge, y above plate
+ self.plate_length, -30, # x2 at right edge, same y
+ f"{self.plate_length} mm", pen
+ )
+
+ # Vertical dimension for plate width (to the left of the plate)
+ self.addVerticalDimension(
+ self.plate_length+30, 0, # x left of plate, y1 at top
+ self.plate_length+30, self.plate_width, # x2 same, y2 at bottom
+ f"{self.plate_width} mm", pen
+ )
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
diff --git a/src/osdag/gui/beam2beamcoverplatedetailing.py b/src/osdag/gui/beam2beamcoverplatedetailing.py
new file mode 100644
index 000000000..80223eeec
--- /dev/null
+++ b/src/osdag/gui/beam2beamcoverplatedetailing.py
@@ -0,0 +1,393 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene,QGraphicsRectItem)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont , QColor
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+class B2Bcoverplate(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ print(main)
+
+ if main:
+ web=main[1]
+ main=main[0]
+ super().__init__()
+ self.connection = connection_obj
+ # return
+ data=main.output_values(main,True)
+ print(type(main))
+ dict1={i[0] : i[3] for i in data}
+
+
+ print("________________________DEBUG________________________")
+ print(dict1)
+ print("________________________DEBUG________________________")
+
+ for i in dict1:
+ print(f'{i} : {dict1[i]}')
+ if web==True:
+ self.plate_length=dict1['Web_Plate.Height (mm)']
+ self.plate_width=dict1['Web_Plate.Width']
+ self.bolt_diameter=dict1['Bolt.Diameter']
+ web_capcity=dict1['Web_plate.spacing'][1]
+ print(web_capcity(main,True))
+ data2=web_capcity(main,True)
+ for i in range(len(data2)):
+ print(f"{i} : {data2[i]}")
+ self.pitch=data2[2][3]
+ self.End=data2[3][3]
+ self.Gauge=data2[4][3]
+ self.Edge=data2[5][3]
+ bolt_cap=dict1['Web Bolt.Capacities'][1]
+ print(bolt_cap(main,True))
+ bolt_cap=bolt_cap(main,True)
+ elif web==False:
+ self.plate_length=dict1['Flange_Plate.Width (mm)']
+ self.plate_width=dict1['flange_plate.Length']
+ self.bolt_diameter=dict1['Bolt.Diameter']
+ flange_capcity=dict1['Flange_plate.spacing'][1]
+ data2=flange_capcity(main,True)
+ self.pitch=data2[2][3]
+ self.End=data2[3][3]
+ self.Gauge=data2[4][3]
+ self.Edge=data2[5][3]
+ bolt_cap=dict1['Bolt.Capacities'][1]
+ print(bolt_cap(main,True))
+ bolt_cap=bolt_cap(main,True)
+ self.cols=bolt_cap[1][3]
+ self.rows=bolt_cap[2][3]/self.cols
+ self.initUI()
+
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 800, 500)
+
+ # Print summary (optional debug/log info)
+ print(f"""
+ -----------------------------------------
+ Plate & Bolt Configuration Summary
+ -----------------------------------------
+ Plate Length : {self.plate_length} mm
+ Plate Width : {self.plate_width} mm
+ Bolt Diameter : {self.bolt_diameter} mm
+
+ Bolt Spacing Details:
+ ---------------------
+ Pitch Distance : {self.pitch} mm
+ End Distance : {self.End} mm
+ Gauge Distance : {self.Gauge} mm
+ Edge Distance : {self.Edge} mm
+
+ Bolt Arrangement:
+ -----------------
+ Number of Columns : {self.cols}
+ Number of Rows : {self.rows}
+ """)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+
+ # Get parameter dictionary
+ params = self.get_parameters()
+
+ for key, value in params.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Right panel: QGraphicsView with Scene
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Determine font and arrow size based on plate size
+ self.fontsize = 10
+ self.arrowsize = 10
+ if self.plate_length > 1200 or self.plate_width > 1200:
+ self.fontsize = 12
+ self.arrowsize = 12
+ elif self.plate_length > 600 or self.plate_width > 600:
+ self.fontsize = 7.5
+ self.arrowsize = 7.5
+
+ # Draw bolts and plate
+ self.createDrawing()
+ if self.plate_length>1200 or self.plate_width>1200:
+ self.view.resetTransform()
+ self.view.scale(0.35, 0.35)
+ elif self.plate_length>600 or self.plate_width>600:
+ self.view.resetTransform()
+ self.view.scale(0.5, 0.5)
+ # Add panels to layout
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(self.view, 3)
+
+ # Set central widget with main layout
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ # Automatically adjust view to fit scene
+ def get_parameters(self):
+ return {
+ 'Plate Length': self.plate_length,
+ 'Plate Width': self.plate_width,
+ 'Bolt Diameter': self.bolt_diameter,
+ 'Pitch Distance': self.pitch,
+ 'End Distance': self.End,
+ 'Gauge Distance': self.Gauge,
+ 'Edge Distance': self.Edge,
+ 'Number of Columns': self.cols,
+ 'Number of Rows': self.rows
+ }
+ def createDrawing(self):
+ try:
+ plate_length = float(self.plate_length)
+ plate_width = float(self.plate_width)
+ except (TypeError, ValueError):
+ print("Invalid plate dimensions")
+ return
+ rect = QRectF(0, 0, plate_length, plate_width)
+ # Create a rectangle item
+ rect_item = QGraphicsRectItem(rect)
+
+ # Set pen and brush (black border, transparent fill)
+ pen = QPen(Qt.black)
+ pen.setWidth(2)
+ rect_item.setPen(pen)
+ rect_item.setBrush(QBrush(Qt.NoBrush))
+
+ # Add rectangle to the scene
+ self.scene.addItem(rect_item)
+ # Extract parameters
+ outline_pen = QPen(Qt.black)
+ outline_pen.setWidth(1)
+
+ # === Draw Base Plate Rectangle ===
+ rect_item = QGraphicsRectItem(QRectF(0, 0, plate_length, plate_width))
+ rect_item.setPen(outline_pen)
+ rect_item.setBrush(QBrush(Qt.white))
+ self.scene.addItem(rect_item)
+ # === Center of the base plate ===
+ center_x = plate_length / 2
+ center_y = plate_width / 2
+ self.addHorizontalDimension(
+ 0, -30, # x1 at left edge, y above plate
+ self.plate_length, -30, # x2 at right edge, same y
+ f"{self.plate_length} mm", pen
+ )
+
+ # Vertical dimension for plate width (to the left of the plate)
+ self.addVerticalDimension(
+ self.plate_length+30, 0, # x left of plate, y1 at top
+ self.plate_length+30, self.plate_width, # x2 same, y2 at bottom
+ f"{self.plate_width} mm", pen
+ )
+ rows=int(self.rows)
+ cols=int(self.cols)
+ pitch=self.pitch
+ gauge=self.Gauge
+ end=self.End
+ edge=self.Edge
+ hole_dia = self.bolt_diameter
+ radius = hole_dia / 2
+ y_center = end # Y position is fixed for top row
+ # Center row if rows is odd
+ outline_pen = QPen(Qt.blue)
+ outline_pen.setWidth(1)
+ if rows % 2 != 0:
+ y_center = self.plate_width / 2
+ for i in range(cols // 2):
+ x_center = edge + i * gauge
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ for i in range(cols // 2):
+ x_center = self.plate_length - edge - i * gauge
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Center bolt if cols is also odd
+ if cols % 2 != 0:
+ x_center = self.plate_length / 2
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Center column if cols is odd (and rows is even)
+ if cols % 2 != 0 and rows % 2 == 0:
+ for j in range(rows // 2):
+ y_center_top = end + j * pitch
+ y_center_bottom = self.plate_width - end - j * pitch
+
+ x_center = self.plate_length / 2
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center_top - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center_bottom - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Draw left half bolts
+ for row in range(int(rows)):
+ if row < rows // 2:
+ y_center = end + row * pitch
+ else:
+ row_from_bottom = row - rows // 2
+ y_center = self.plate_width - end - row_from_bottom * pitch
+
+ # Left half bolts
+ for i in range(cols // 2):
+ x_center = edge + i * gauge
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Right half bolts
+ for i in range(cols // 2):
+ x_center = self.plate_length - edge - i * gauge
+ self.scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+ self.addHorizontalDimension(
+ 0, self.plate_width+10, # x1 at left edge, y above plate
+ self.Edge, self.plate_width+10, # x2 at right edge, same y
+ f"{self.Edge} mm", pen
+ )
+ self.addVerticalDimension(
+ -10, 0, # x left of plate, y1 at top
+ -10, self.End, # x2 same, y2 at bottom
+ f"{self.End} mm", pen
+ )
+ self.addHorizontalDimension(
+ self.Edge-hole_dia/2, 10,
+ self.Edge+hole_dia/2,10,
+ f"{hole_dia} mm", pen
+ )
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = int(self.arrowsize)
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(int(self.fontsize))
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = int(self.arrowsize)
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(int(self.fontsize))
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
diff --git a/src/osdag/gui/beam2beamcoverplatedetailing_capacity_details.py b/src/osdag/gui/beam2beamcoverplatedetailing_capacity_details.py
new file mode 100644
index 000000000..1a7353031
--- /dev/null
+++ b/src/osdag/gui/beam2beamcoverplatedetailing_capacity_details.py
@@ -0,0 +1,586 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene,QGraphicsRectItem, QFrame)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont, QColor
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+
+try:
+ pen_style_dash = Qt.PenStyle.DashLine
+except AttributeError:
+ raise RuntimeError("Your PyQt5 version does not support dashed lines via Qt.PenStyle.DashLine. Please update PyQt5.")
+
+class B2Bcoverplate_capacity_details(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ print(main)
+
+ if main:
+ self.drawing_type=main[2]
+ self.web=main[1]
+ web=main[1]
+ main=main[0]
+ super().__init__()
+ self.connection = connection_obj
+ # return
+ data=main.output_values(main,True)
+ print(type(main))
+ dict1={i[0] : i[3] for i in data}
+
+
+
+ for i in dict1:
+ print(f'{i} : {dict1[i]}')
+
+
+ if web==True:
+ self.plate_length=dict1['Web_Plate.Height (mm)']
+ self.plate_width=dict1['Web_Plate.Width']
+ self.bolt_diameter=dict1['Bolt.Diameter']
+ web_capcity=dict1['Web_plate.spacing'][1]
+ print(web_capcity(main,True))
+ data2=web_capcity(main,True)
+ for i in range(len(data2)):
+ print(f"{i} : {data2[i]}")
+ self.pitch=data2[2][3]
+ self.End=data2[3][3]
+ self.Gauge=data2[4][3]
+ self.Edge=data2[5][3]
+ bolt_cap=dict1['Web Bolt.Capacities'][1]
+ print(bolt_cap(main,True))
+ bolt_cap=bolt_cap(main,True)
+ elif web==False:
+ self.plate_length=dict1['Flange_Plate.Width (mm)']
+ self.plate_width=dict1['flange_plate.Length']
+ self.bolt_diameter=dict1['Bolt.Diameter']
+ flange_capcity=dict1['Flange_plate.spacing'][1]
+ data2=flange_capcity(main,True)
+ self.pitch=data2[2][3]
+ self.End=data2[3][3]
+ self.Gauge=data2[4][3]
+ self.Edge=data2[5][3]
+ bolt_cap=dict1['Bolt.Capacities'][1]
+ print(bolt_cap(main,True))
+ bolt_cap=bolt_cap(main,True)
+
+
+
+ #capacity
+ if web==True and self.drawing_type=="capacity":
+ #web capacity details
+ web_capacity_fnc=dict1['section.web_capacities'][1]
+ web_capacity_val=web_capacity_fnc(main,True)
+ self.web_capacity_details = {item[1]: float(item[3]) for item in web_capacity_val if item[2] == 'TextBox'}
+
+ #capacity
+ elif web==False and self.drawing_type=="capacity":
+ #flange capacity details
+ flange_capacity_fnc=dict1['section.flange_capacity'][1]
+ flange_capacity_val=flange_capacity_fnc(main,True)
+ self.flange_capacity_details={item[1]: float(item[3]) for item in flange_capacity_val if item[2] == 'TextBox'}
+
+
+
+
+ self.cols=bolt_cap[1][3]
+ self.rows=bolt_cap[2][3]/self.cols
+ self.initUI()
+
+
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 1050, 500)
+
+ # Print summary (optional debug/log info)
+ print(f"""
+ -----------------------------------------
+ Plate & Bolt Configuration Summary
+ -----------------------------------------
+ Plate Length : {self.plate_length} mm
+ Plate Width : {self.plate_width} mm
+ Bolt Diameter : {self.bolt_diameter} mm
+
+ Bolt Spacing Details:
+ ---------------------
+ Pitch Distance : {self.pitch} mm
+ End Distance : {self.End} mm
+ Gauge Distance : {self.Gauge} mm
+ Edge Distance : {self.Edge} mm
+
+ Bolt Arrangement:
+ -----------------
+ Number of Columns : {self.cols}
+ Number of Rows : {self.rows}
+ """)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+
+ # Get parameter dictionary
+ params = self.get_parameters((self.web,self.drawing_type))
+ count=0
+ for key, value in params.items():
+ if self.web==False and self.drawing_type=="capacity":
+ param_layout = QHBoxLayout()
+ space_label = QLabel(' ')
+ param_label = QLabel(f'{key.title()} (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+ # Add a blank label for vertical spacing
+ left_layout.addWidget(QLabel(''))
+ elif self.web==True and self.drawing_type=="capacity":
+ param_layout = QHBoxLayout()
+ space_label = QLabel(' ')
+ param_label = QLabel(f'{key.title()} (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+ # Add a blank label for vertical spacing
+ left_layout.addWidget(QLabel(''))
+
+ count+=1
+ else:
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Determine font and arrow size based on plate size
+ self.fontsize = 10
+ self.arrowsize = 10
+ if self.plate_length > 1200 or self.plate_width > 1200:
+ self.fontsize = 12
+ self.arrowsize = 12
+ elif self.plate_length > 600 or self.plate_width > 600:
+ self.fontsize = 7.5
+ self.arrowsize = 7.5
+
+ if self.web == True and self.drawing_type == "capacity":
+ # Two drawings, each with its own parameter set, separated by a horizontal line
+ self.scene1 = QGraphicsScene()
+ self.view1 = QGraphicsView(self.scene1)
+ self.view1.setRenderHint(QPainter.Antialiasing)
+
+ self.scene2 = QGraphicsScene()
+ self.view2 = QGraphicsView(self.scene2)
+ self.view2.setRenderHint(QPainter.Antialiasing)
+
+ self.createDrawing((self.web, self.drawing_type), self.scene1)
+ self.createDrawing((self.web, self.drawing_type), self.scene2)
+
+ if self.plate_length > 1200 or self.plate_width > 1200:
+ self.view1.resetTransform()
+ self.view1.scale(0.35, 0.35)
+ self.view2.resetTransform()
+ self.view2.scale(0.35, 0.35)
+ elif self.plate_length > 600 or self.plate_width > 600:
+ self.view1.resetTransform()
+ self.view1.scale(0.5, 0.5)
+ self.view2.resetTransform()
+ self.view2.scale(0.5, 0.5)
+
+ # Split parameters into two groups (first two, next two)
+ params = list(self.get_parameters((self.web, self.drawing_type)).items())
+ params1 = params[:2]
+ params2 = params[2:]
+
+ # Section 1: first two parameters and first drawing
+ section1_layout = QHBoxLayout()
+ section1_text_widget = QWidget()
+ section1_text_layout = QVBoxLayout(section1_text_widget)
+ param_label = QLabel('Failure Pattern due to tension in Member and Plate')
+ param_label.setFont(QFont('Arial',12,QFont.Bold))
+ section1_text_layout.addWidget(param_label)
+ for key, value in params1:
+ param_label = QLabel(f'{key}: {value}')
+ section1_text_layout.addWidget(param_label)
+ section1_text_layout.addStretch()
+ section1_text_widget.setMinimumWidth(180)
+ section1_layout.addWidget(section1_text_widget, 1)
+ section1_layout.addWidget(self.view1, 2)
+
+ # Section 2: next two parameters and second drawing
+ section2_layout = QHBoxLayout()
+ section2_text_widget = QWidget()
+ section2_text_layout = QVBoxLayout(section2_text_widget)
+ param_label = QLabel('Failure Pattern due to tension in Member and Plate')
+ param_label.setFont(QFont('Arial',12,QFont.Bold))
+ section2_text_layout.addWidget(param_label)
+ for key, value in params2:
+ param_label = QLabel(f'{key}: {value}')
+ section2_text_layout.addWidget(param_label)
+ section2_text_layout.addStretch()
+ section2_text_widget.setMinimumWidth(180)
+ section2_layout.addWidget(section2_text_widget, 1)
+ section2_layout.addWidget(self.view2, 2)
+
+ # Horizontal line between sections
+ line = QFrame()
+ line.setFrameShape(QFrame.HLine)
+ line.setFrameShadow(QFrame.Sunken)
+
+ # Main vertical layout
+ main_vlayout = QVBoxLayout()
+ main_vlayout.addLayout(section1_layout)
+ main_vlayout.addWidget(line)
+ main_vlayout.addLayout(section2_layout)
+
+ self.view1.setMaximumWidth(400)
+ self.view2.setMaximumWidth(400)
+
+ main_widget = QWidget()
+ main_widget.setLayout(main_vlayout)
+ self.setCentralWidget(main_widget)
+ else:
+ # Only one drawing (original layout)
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+ params = self.get_parameters((self.web, self.drawing_type))
+ for key, value in params.items():
+ if self.web==False and self.drawing_type=="capacity":
+ param_layout = QHBoxLayout()
+ space_label = QLabel(' ')
+ param_label = QLabel(f'{key.title()} (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+ left_layout.addWidget(QLabel(''))
+ else:
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+ self.createDrawing((self.web, self.drawing_type), self.scene)
+
+ if self.plate_length > 1200 or self.plate_width > 1200:
+ self.view.resetTransform()
+ self.view.scale(0.35, 0.35)
+ elif self.plate_length > 600 or self.plate_width > 600:
+ self.view.resetTransform()
+ self.view.scale(0.5, 0.5)
+
+ main_layout = QHBoxLayout()
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(self.view, 3)
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ # Automatically adjust view to fit scene
+ def get_parameters(self,type_):
+ if (type_[0]==True and type_[1]=="spacing") or (type_[0]==False and type_[1]=="spacing") :
+ return {
+ 'Plate Length': self.plate_length,
+ 'Plate Width': self.plate_width,
+ 'Bolt Diameter': self.bolt_diameter,
+ 'Pitch Distance': self.pitch,
+ 'End Distance': self.End,
+ 'Gauge Distance': self.Gauge,
+ 'Edge Distance': self.Edge,
+ 'Number of Columns': self.cols,
+ 'Number of Rows': self.rows
+ }
+ elif type_[0]==True and type_[1]=="capacity":
+ return self.web_capacity_details
+ elif type_[0]==False and type_[1]=="capacity":
+ return self.flange_capacity_details
+
+ def createDrawing(self, type_, scene):
+
+
+
+ try:
+ plate_length = float(self.plate_length)
+ plate_width = float(self.plate_width)
+ except (TypeError, ValueError):
+ print("Invalid plate dimensions")
+ return
+ rect = QRectF(0, 0, plate_length, plate_width)
+ # Create a rectangle item
+ rect_item = QGraphicsRectItem(rect)
+
+ # Set pen and brush (black border, transparent fill)
+ pen = QPen(QColor('black'))
+ pen.setWidth(2)
+ rect_item.setPen(pen)
+ rect_item.setBrush(QBrush()) # Default is NoBrush
+
+ # Add rectangle to the scene
+ scene.addItem(rect_item)
+
+
+ # Extract parameters
+ outline_pen = QPen(QColor('black'))
+ outline_pen.setWidth(1)
+
+ # === Draw Base Plate Rectangle ===
+ rect_item = QGraphicsRectItem(QRectF(0, 0, plate_length, plate_width))
+ rect_item.setPen(outline_pen)
+ rect_item.setBrush(QBrush(QColor('white')))
+ scene.addItem(rect_item)
+ dashed_pen = QPen(QColor('black'))
+ dashed_pen.setStyle(pen_style_dash)
+ dashed_pen.setWidth(2)
+ if type_[0]==False and type_[1]=="capacity":
+
+ #top drawing
+ scene.addLine(self.Edge, 0, self.Edge, self.End, dashed_pen)
+
+ scene.addLine(self.Edge, self.End, plate_length, self.End, dashed_pen)
+
+
+ #bottom drawing
+ scene.addLine(self.Edge, plate_width, self.Edge, plate_width-self.End, dashed_pen)
+
+ scene.addLine(self.Edge, plate_width-self.End, plate_length, plate_width-self.End, dashed_pen)
+
+ elif type_[0]==True and type_[1]=="capacity" and scene==self.scene1:
+
+ scene.addLine(self.End, self.Edge, self.End, plate_width-self.End, dashed_pen)
+
+ scene.addLine(self.End, self.Edge, plate_length, self.Edge, dashed_pen)
+
+ scene.addLine(self.End, plate_width-self.Edge, plate_length, plate_width-self.Edge, dashed_pen)
+
+
+ elif type_[0]==True and type_[1]=="capacity" and scene==self.scene2:
+
+ scene.addLine(0, self.Edge, plate_length-self.End, self.Edge, dashed_pen)
+
+ scene.addLine(plate_length-self.End, self.Edge, plate_length-self.End, plate_width, dashed_pen)
+
+
+ # === Center of the base plate ===
+ center_x = plate_length / 2
+ center_y = plate_width / 2
+ self.addHorizontalDimension(
+ 0, -30, # x1 at left edge, y above plate
+ self.plate_length, -30, # x2 at right edge, same y
+ f"{self.plate_length} mm", pen, scene
+ )
+
+ # Vertical dimension for plate width (to the left of the plate)
+ self.addVerticalDimension(
+ self.plate_length+30, 0, # x left of plate, y1 at top
+ self.plate_length+30, self.plate_width, # x2 same, y2 at bottom
+ f"{self.plate_width} mm", pen, scene
+ )
+
+ rows=int(self.rows)
+ cols=int(self.cols)
+ pitch=self.pitch
+ gauge=self.Gauge
+ end=self.End
+ edge=self.Edge
+ hole_dia = self.bolt_diameter
+ radius = hole_dia / 2
+ y_center = end # Y position is fixed for top row
+ # Center row if rows is odd
+ outline_pen = QPen(QColor('blue'))
+ outline_pen.setWidth(1)
+ if rows % 2 != 0:
+ y_center = self.plate_width / 2
+ for i in range(cols // 2):
+ x_center = edge + i * gauge
+ scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ for i in range(cols // 2):
+ x_center = self.plate_length - edge - i * gauge
+ scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Center bolt if cols is also odd
+ if cols % 2 != 0:
+ x_center = self.plate_length / 2
+ scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Center column if cols is odd (and rows is even)
+ if cols % 2 != 0 and rows % 2 == 0:
+ for j in range(rows // 2):
+ y_center_top = end + j * pitch
+ y_center_bottom = self.plate_width - end - j * pitch
+
+ x_center = self.plate_length / 2
+ scene.addEllipse(
+ x_center - radius,
+ y_center_top - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+ scene.addEllipse(
+ x_center - radius,
+ y_center_bottom - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Draw left half bolts
+ for row in range(int(rows)):
+ if row < rows // 2:
+ y_center = end + row * pitch
+ else:
+ row_from_bottom = row - rows // 2
+ y_center = self.plate_width - end - row_from_bottom * pitch
+
+ # Left half bolts
+ for i in range(cols // 2):
+ x_center = edge + i * gauge
+ scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+
+ # Right half bolts
+ for i in range(cols // 2):
+ x_center = self.plate_length - edge - i * gauge
+ scene.addEllipse(
+ x_center - radius,
+ y_center - radius,
+ hole_dia,
+ hole_dia,
+ outline_pen,
+ )
+ self.addHorizontalDimension(
+ 0, self.plate_width+10, # x1 at left edge, y above plate
+ self.Edge, self.plate_width+10, # x2 at right edge, same y
+ f"{self.Edge} mm", pen, scene
+ )
+ self.addVerticalDimension(
+ -10, 0, # x left of plate, y1 at top
+ -10, self.End, # x2 same, y2 at bottom
+ f"{self.End} mm", pen, scene
+ )
+ # self.addHorizontalDimension(
+ # self.Edge-hole_dia/2, 10,
+ # self.Edge+hole_dia/2,10,
+ # f"{hole_dia} mm", pen
+ # )
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen, scene):
+ scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = int(self.arrowsize)
+ ext_length = 10
+ scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(QColor('black')))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(QColor('black')))
+
+ text_item = scene.addText(text)
+ font = QFont()
+ font.setPointSize(int(self.fontsize))
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen, scene):
+ scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = int(self.arrowsize)
+ ext_length = 10
+ scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(QColor('black')))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(QColor('black')))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(QColor('black')))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(QColor('black')))
+
+ text_item = scene.addText(text)
+ font = QFont()
+ font.setPointSize(int(self.fontsize))
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
diff --git a/src/osdag/gui/capacity_details_finPlate.py b/src/osdag/gui/capacity_details_finPlate.py
new file mode 100644
index 000000000..ad4694aa2
--- /dev/null
+++ b/src/osdag/gui/capacity_details_finPlate.py
@@ -0,0 +1,444 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+from ..design_type.connection.end_plate_connection import EndPlateConnection
+
+class CapacityDetailsWindow(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+ self.connection = connection_obj
+ self.main=main
+ self.plate_height = main.plate.height
+ self.plate_width = main.plate.length
+ self.hole_dia=main.bolt.bolt_diameter_provided
+ self.rows=main.plate.bolts_one_line
+ self.cols=main.plate.bolt_line
+ self.plate_thickness=main.plate.thickness
+ print(self.plate_height,self.plate_width)
+ output=main.output_values(main,True)
+ dict1={i[0] : i[3] for i in output}
+
+ capacity_fnc = dict1['button1'][1]
+ print(capacity_fnc)
+ capacity_details = capacity_fnc(main,True)
+ print(capacity_details)
+ details_dict={i[1]:i[3] for i in capacity_details}
+
+ self.shear_yield_capacity=float(details_dict['Shear Yielding Capacity (kN)'])
+ self.rupture_capacity=float(details_dict['Rupture Capacity (kN)'])
+ self.Block_Shear_Capacity=float(details_dict['Block Shear Capacity (kN)'])
+ self.Tension_Yielding_Capacity=float(details_dict['Tension Yielding Capacity (kN)'])
+ self.Tension_rupture_Capacity=float(details_dict['Tension Rupture Capacity (kN)'])
+ self.axial_block_shear_capacity=float(details_dict['Axial Block Shear Capacity (kN)'])
+ self.moment_demand=float(details_dict['Moment Demand (kNm)'])
+ self.moment_capacity=float(details_dict['Moment Capacity (kNm)'])
+ print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
+ print("------------------------------------------------------------------")
+ self.dict_shear_failure={
+ 'Shear Yielding Capacity (kN)':self.shear_yield_capacity,
+ 'Rupture Capacity (kN)':self.rupture_capacity,
+ 'Block Shear Capacity (kN)':self.Block_Shear_Capacity
+ }
+ self.dict_tension_failure={
+ 'Tension Yielding Capacity (kN)':self.Tension_Yielding_Capacity,
+ 'Tension Rupture Capacity (kN)':self.Tension_rupture_Capacity,
+ 'Axial Block Shear Capacity (kN)':self.axial_block_shear_capacity
+ }
+ self.dict_section_3={
+ 'Moment Demand (kNm)':self.moment_demand,
+ 'Moment Capacity (kNm)':self.moment_capacity
+ }
+
+ print(self.dict_shear_failure)
+ print(self.dict_tension_failure)
+ print(self.dict_section_3)
+ print("------------------------------------------------------------------")
+ print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
+
+ for i in output:
+ print(i)
+ self.weldsize=0
+ if 'Weld.Size' in dict1:
+ self.weldsize=dict1['Weld.Size']
+ self.initUI()
+
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 1650, 1050)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+
+ # Parameter display labels
+ params = self.get_parameters()
+
+ heading_label = QLabel("Note: Representative image for Failure Pattern (Half Plate)- 2 x 3 Bolts pattern considered")
+ heading_label.setStyleSheet("font-size: 20px;")
+ left_layout.addWidget(heading_label)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 25px;")
+ left_layout.addWidget(space_label)
+
+ sub_heading_label1 = QLabel("Failure Pattern due to Shear in Plate")
+ sub_heading_label1.setStyleSheet("font-size: 18px; font-weight: bold;")
+ left_layout.addWidget(sub_heading_label1)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 15px;")
+ left_layout.addWidget(space_label)
+
+ # Display the parameter values
+ for key, value in self.dict_shear_failure.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(key.title())
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 5px;")
+ left_layout.addWidget(space_label)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 25px;")
+ left_layout.addWidget(space_label)
+
+ sub_heading_label2 = QLabel("Failure Pattern due to Tension in Plate")
+ sub_heading_label2.setStyleSheet("font-size: 18px; font-weight: bold;")
+ left_layout.addWidget(sub_heading_label2)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 15px;")
+ left_layout.addWidget(space_label)
+
+ for key, value in self.dict_tension_failure.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(key.title())
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 5px;")
+ left_layout.addWidget(space_label)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 25px;")
+ left_layout.addWidget(space_label)
+
+ sub_heading_label3 = QLabel("Section 3")
+ sub_heading_label3.setStyleSheet("font-size: 18px; font-weight: bold;")
+ left_layout.addWidget(sub_heading_label3)
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 15px;")
+ left_layout.addWidget(space_label)
+
+ for key, value in self.dict_section_3.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(key.title())
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 5px;")
+ left_layout.addWidget(space_label)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Right panel for the two vertical drawings
+ right_panel = QWidget()
+ right_layout = QVBoxLayout()
+ right_panel.setLayout(right_layout)
+
+ sub_heading_label1 = QLabel("Failure Pattern due to Shear in Plate:")
+ sub_heading_label1.setStyleSheet("font-size: 16px; font-weight: bold;")
+ right_layout.addWidget(sub_heading_label1)
+
+ # First drawing
+ self.scene1 = QGraphicsScene()
+ self.view1 = QGraphicsView(self.scene1)
+ self.view1.setRenderHint(QPainter.Antialiasing)
+ self.createDrawing(self.scene1)
+ self.view1.fitInView(self.scene1.sceneRect(), Qt.KeepAspectRatio)
+ right_layout.addWidget(self.view1)
+
+
+ space_label=QLabel(" ")
+ space_label.setStyleSheet("font-size: 15px;")
+ right_layout.addWidget(space_label)
+
+ sub_heading_label2 = QLabel("Failure Pattern due to Tension in Plate:")
+ sub_heading_label2.setStyleSheet("font-size: 16px; font-weight: bold;")
+ right_layout.addWidget(sub_heading_label2)
+
+ # Second drawing (identical to first)
+ self.scene2 = QGraphicsScene()
+ self.view2 = QGraphicsView(self.scene2)
+ self.view2.setRenderHint(QPainter.Antialiasing)
+ self.createSecondDrawing(self.scene2) # Using the same drawing function
+ self.view2.fitInView(self.scene2.sceneRect(), Qt.KeepAspectRatio)
+ right_layout.addWidget(self.view2)
+
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(right_panel, 3)
+
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ def get_parameters(self):
+ spacing_data = self.connection.spacing(status=True) # Get actual values
+ param_map = {}
+ print('spacing_data length' , len(spacing_data))
+ for item in spacing_data:
+ key, _, _, value = item
+ if key == KEY_OUT_PITCH:
+ param_map['pitch'] = float(value)
+ elif key == KEY_OUT_END_DIST:
+ param_map['end'] = float(value)
+ elif key == KEY_OUT_GAUGE1:
+ param_map['gauge1'] = float(value)
+ elif key == KEY_OUT_GAUGE2:
+ param_map['gauge2'] = float(value)
+ elif key == KEY_OUT_GAUGE:
+ param_map['gauge'] = float(value)
+ elif key == KEY_OUT_EDGE_DIST:
+ param_map['edge'] = float(value)
+
+ # Add hardcoded hole diameter
+ param_map['hole'] = self.main.bolt.bolt_diameter_provided
+
+ print("Extracted parameters:", param_map)
+ return param_map
+
+
+# failure due to shear in plate
+ def createDrawing(self, scene):
+ coeff = 2 # scaling coefficient
+ params = self.get_parameters()
+ pitch = params['pitch'] / coeff
+ end = params['end'] / coeff
+ if 'gauge' in params:
+ gauge1 = gauge2 = params['gauge'] / coeff
+ else:
+ gauge1 = params['gauge1'] / coeff
+ gauge2 = params['gauge2'] / coeff
+ edge = params['edge'] / coeff
+ width = self.plate_width / coeff
+ height = self.plate_height / coeff
+ hole_diameter = params['hole'] / coeff
+ weld_size = self.weldsize / coeff
+
+ outline_pen = QPen(Qt.blue, 2/coeff)
+ dimension_pen = QPen(Qt.black, 1.5/coeff)
+ red_brush = QBrush(Qt.red)
+
+ # Create dashed pen for failure patterns
+ dashed_pen = QPen(Qt.black, 1.5/coeff, Qt.DashLine)
+
+
+
+ h_offset = 40 / coeff
+ v_offset = 60 / coeff
+ scene.setSceneRect(-h_offset, -v_offset, width + 2*v_offset, height + 2*h_offset)
+ #adding the shear failure pattern
+ scene.addLine(width-end, 0, width-end, height-edge, dashed_pen)
+ scene.addLine(0, height-edge, width-end, height-edge, dashed_pen)
+ scene.addRect(0, 0, width, height, dimension_pen)
+
+ # Draw holes
+ for row in range(self.rows):
+ for col in range(self.cols):
+ x_center = width - edge
+ for i in range(col):
+ x_center -= gauge1 if i % 2 == 0 else gauge2
+ y_center = end + row * pitch
+ x = x_center - hole_diameter / 2
+ y = y_center - hole_diameter / 2
+ scene.addEllipse(x, y, hole_diameter, hole_diameter, outline_pen)
+ # Draw weld area
+ if weld_size > 0:
+ scene.addRect(0, 0, weld_size, height, dimension_pen, red_brush)
+ # Add dimensions
+ self.addDimensions(scene, width, height, pitch, end, gauge1, gauge2, edge, dimension_pen, coeff)
+
+
+ def createSecondDrawing(self, scene):
+ coeff = 2 # scaling coefficient
+ params = self.get_parameters()
+ pitch = params['pitch'] / coeff
+ end = params['end'] / coeff
+ if 'gauge' in params:
+ gauge1 = gauge2 = params['gauge'] / coeff
+ else:
+ gauge1 = params['gauge1'] / coeff
+ gauge2 = params['gauge2'] / coeff
+ edge = params['edge'] / coeff
+ width = self.plate_width / coeff
+ height = self.plate_height / coeff
+ hole_diameter = params['hole'] / coeff
+ weld_size = self.weldsize / coeff
+
+ outline_pen = QPen(Qt.blue, 2/coeff)
+ dimension_pen = QPen(Qt.black, 1.5/coeff)
+ red_brush = QBrush(Qt.red)
+
+ # Create dashed pen for failure patterns
+ dashed_pen = QPen(Qt.black, 1.5/coeff, Qt.DashLine)
+
+
+
+
+ if self.cols==1:
+ x_line_dist=width-end
+ else:
+ x_line_dist=width-end - (self.cols-1)*gauge1
+
+ h_offset = 40 / coeff
+ v_offset = 60 / coeff
+ scene.setSceneRect(-h_offset, -v_offset, width + 2*v_offset, height + 2*h_offset)
+ #adding the tension failure pattern
+ scene.addLine(x_line_dist, edge, width, edge, dashed_pen)
+ scene.addLine(x_line_dist, edge, x_line_dist, height-edge, dashed_pen)
+ scene.addLine(x_line_dist, height-edge, width, height-edge, dashed_pen)
+ scene.addRect(0, 0, width, height, dimension_pen)
+
+
+ # Draw holes
+ for row in range(self.rows):
+ for col in range(self.cols):
+ x_center = width - edge
+ for i in range(col):
+ x_center -= gauge1 if i % 2 == 0 else gauge2
+ y_center = end + row * pitch
+ x = x_center - hole_diameter / 2
+ y = y_center - hole_diameter / 2
+ scene.addEllipse(x, y, hole_diameter, hole_diameter, outline_pen)
+ # Draw weld area
+ if weld_size > 0:
+ scene.addRect(0, 0, weld_size, height, dimension_pen, red_brush)
+ # Add dimensions
+ self.addDimensions(scene, width, height, pitch, end, gauge1, gauge2, edge, dimension_pen, coeff)
+
+
+
+ def addDimensions(self, scene, width, height, pitch, end, gauge1, gauge2, edge, pen, coeff):
+ h_offset = 20 / coeff
+ v_offset = 30 / coeff
+ x_start = width
+ segments = []
+ segments.append(('edge', x_start-edge, x_start))
+ x_start -= edge
+ segments.append(('edge', 0, x_start))
+ for label, x1, x2 in segments:
+ value = x2 - x1
+ self.addHorizontalDimension(scene, x1, -h_offset, x2, -h_offset, f"{value:.1f}", pen)
+ # Add vertical dimensions
+ self.addVerticalDimension(scene, width + v_offset, 0, width + v_offset, end, str(end), pen)
+ for i in range(self.rows - 1):
+ self.addVerticalDimension(scene, width + v_offset, end + i * pitch,
+ width + v_offset, end + (i + 1) * pitch, str(pitch), pen)
+ self.addVerticalDimension(scene, width + v_offset, height, width + v_offset, height - end, str(end), pen)
+ total_height = 2 * end + (self.rows - 1) * pitch
+ self.addVerticalDimension(scene, -v_offset, 0, -v_offset, total_height, str(total_height), pen)
+
+ def addHorizontalDimension(self, scene, x1, y1, x2, y2, text, pen):
+ scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 2
+ ext_length = 10
+ scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = scene.addText(text)
+ font = QFont()
+ font.setPointSize(2)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, scene, x1, y1, x2, y2, text, pen):
+ scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 2
+ ext_length = 10
+ scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = scene.addText(text)
+ font = QFont()
+ font.setPointSize(2)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
\ No newline at end of file
diff --git a/src/osdag/gui/cleatangledetailing.py b/src/osdag/gui/cleatangledetailing.py
new file mode 100644
index 000000000..7684e2970
--- /dev/null
+++ b/src/osdag/gui/cleatangledetailing.py
@@ -0,0 +1,299 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+class CleatAngle(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+ (main,self.flag)=main
+ spacing_data = connection_obj.spacing(status=True)
+ output=connection_obj.output_values(True)
+ data1={ f'{i[1]} + {i[0]}' : i[3] for i in output}
+
+ self.angle_thickness=float(data1['Cleat Angle Designation + Cleat.Angle'].split(" ")[-1])
+
+ params= {
+ 'width' : int(data1['Height (mm) + Plate.Height']),
+ 'hole' : int(data1['Diameter (mm) + Bolt.Diameter']),
+ }
+ if self.flag==0:
+ params['length']=int(data1['Cleat Angle Designation + Cleat.Angle'][0:2])
+ params['rows']=int(data1['Bolt Rows (nos) + Bolt.OneLine'])
+ params['cols']=int(data1['Bolt Columns (nos) + Bolt.Line'])
+ else:
+ params['length']=int(data1['Cleat Angle Designation + Cleat.Angle'][5:7])
+ params['rows']=int(data1['Bolt Rows (nos) + Cleat.Spting_leg.OneLine'])
+ params['cols']=int(data1['Bolt Columns (nos) + Cleat.Spting_leg.Line'])
+ for i in spacing_data:
+ print(i)
+ for item in spacing_data:
+ if not isinstance(item[0], str):
+ continue
+ key = item[0].lower()
+ value = item[3]
+
+ if 'pitch' in key:
+ params['pitch'] = value
+ elif 'gauge1' in key:
+ params['gauge1'] = value
+ elif 'gauge2' in key:
+ params['gauge2'] = value
+ elif 'end' in key:
+ params['end']=value
+ elif 'edge' in key:
+ params['edge']=value
+ for i in params:
+ print(f'{i} : {params[i]}')
+ self.params=params
+ self.initUI()
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 1000, 600)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+
+ # Parameter display labels
+ params = self.params
+
+ # Display the parameter values
+ for key, value in params.items():
+ if key=='cols' or key=='rows' or key=='hole' or key=='length' or key=='width':
+ continue
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} Distance (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Right panel for the drawing using QGraphicsView
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Create and add the drawing to the scene
+ self.createDrawing(params)
+
+ # Add panels to main layout
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(self.view, 3)
+
+ # Set main widget
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ # Ensure the view shows all content
+ self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
+
+ def createDrawing(self, params):
+
+ # Extract parameters
+ pitch = params['pitch']
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ else:
+ gauge1 = params['gauge1']
+ gauge2 = params['gauge2']
+ edge = params['edge']
+ hole_diameter = params['hole']
+ self.rows=params['rows']
+ self.cols=params['cols']
+
+ # Calculate dimensions
+ if 'gauge' in params:
+ gauge1 = gauge
+ gauge2 = gauge
+ width = params['length']
+
+ height = params['width']
+ self.plate_width=width
+ self.plate_height=height
+ # Set up pens
+ outline_pen = QPen(Qt.blue, 2)
+ dimension_pen = QPen(Qt.black, 1.5)
+ angle_pen = QBrush(Qt.red)
+
+ # Dimension offsets
+ h_offset = 40
+ v_offset = 60
+
+ # Create scene rectangle with extra space for dimensions
+ self.scene.setSceneRect(-h_offset, -v_offset,
+ width + 2*v_offset, height + 2*h_offset)
+
+ # Draw rectangle
+ self.scene.addRect(0, 0, width, height, dimension_pen)
+ self.scene.addRect(0, 0, self.angle_thickness, height, dimension_pen, angle_pen)
+
+
+ # Draw holes
+ for row in range(self.rows):
+ for col in range(self.cols):
+ # Start from right edge (for example: total plate width - edge)
+ x_center = self.plate_width - edge
+
+ # Subtract gauges from right to left
+ for i in range(col):
+ x_center -= gauge1 if i % 2 == 0 else gauge2
+
+ # Y-position stays the same
+ y_center = end + row * pitch
+
+ # Top-left corner for drawing the circle
+ x = x_center - hole_diameter / 2
+ y = y_center - hole_diameter / 2
+
+ print(f"row: {row}, col: {col}, x: {x}, y: {y}")
+ self.scene.addEllipse(x, y, hole_diameter, hole_diameter, outline_pen)
+
+ print(params,dimension_pen)
+ # Add dimensions
+ self.addDimensions(params, dimension_pen)
+
+ def addDimensions(self, params, pen):
+ # Extract parameters
+ pitch = params['pitch']
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ else:
+ gauge1 = params['gauge1']
+ gauge2 = params['gauge2']
+ edge = params['edge']
+
+ if 'gauge' in params:
+ gauge1 = gauge
+ gauge2 = gauge
+
+ width = self.plate_width
+ height = self.plate_height
+
+ # Offsets for dimension lines
+ h_offset = 20
+ v_offset = 30
+
+ # Add horizontal dimensions
+ x_start = width
+ segments = []
+ # First edge
+ segments.append(('edge', x_start-edge, x_start ))
+ x_start -=edge
+
+ # Last edge
+ segments.append(('edge', 0, x_start))
+
+ # Draw each segment
+ for label, x1, x2 in segments:
+ value = x2 - x1
+ self.addHorizontalDimension(x1, -h_offset, x2, -h_offset, f"{value:.1f}", pen)
+ # Add vertical dimensions
+ self.addVerticalDimension(width + v_offset, 0, width + v_offset, end, str(end), pen)
+ for i in range(self.rows - 1):
+ self.addVerticalDimension(width + v_offset, end + i * pitch, width + v_offset, end + (i + 1) * pitch, str(pitch), pen)
+
+ # Add bottom end distance dimension
+ self.addVerticalDimension(width + v_offset, height, width + v_offset, height - end, str(end), pen)
+
+ # Add left side dimension
+ total_height = 2 * end + (self.rows - 1) * pitch
+ self.addVerticalDimension(-v_offset, 0, -v_offset, total_height, str(total_height), pen)
+
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
\ No newline at end of file
diff --git a/src/osdag/gui/endplatecnndetailnig.py b/src/osdag/gui/endplatecnndetailnig.py
new file mode 100644
index 000000000..35316e7f7
--- /dev/null
+++ b/src/osdag/gui/endplatecnndetailnig.py
@@ -0,0 +1,303 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+from ..design_type.connection.end_plate_connection import EndPlateConnection
+
+class EndPlateDetailer(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+ self.connection = connection_obj
+ self.main=main
+ output=main.output_values(main,True)
+ dict1={i[0] : i[3] for i in output}
+ self.plate_height = dict1['Plate.Height']
+ self.plate_width = dict1['Plate.Length']
+ self.hole_dia=dict1['Bolt.Diameter']
+ self.rows=dict1['Bolt.Rows']
+ self.cols=main.plate.bolt_line
+ print(self.cols)
+ for i in output:
+ print(i)
+ self.weldsize=0
+ if 'Weld.Size' in dict1:
+ self.weldsize=dict1['Weld.Size']
+ print(main.supported_section.web_thickness)
+ self.weldgap=main.supported_section.web_thickness
+ self.initUI()
+ # print(self.connection.spacing(status=True))
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 1200, 800)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+
+ # Parameter display labels
+ params = self.get_parameters()
+
+ # Display the parameter values
+ for key, value in params.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} Distance (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Right panel for the drawing using QGraphicsView
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Create and add the drawing to the scene
+ self.createDrawing(params)
+
+ # Add panels to main layout
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(self.view, 3)
+
+ # Set main widget
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ # Ensure the view shows all content
+ self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
+ def get_parameters(self):
+ spacing_data = self.connection.spacing(status=True) # Get actual values
+ param_map = {}
+ print('spacing_data length' , len(spacing_data))
+ for item in spacing_data:
+ key, _, _, value = item
+ # print('key : ', key)
+ if key == KEY_OUT_PITCH:
+ param_map['pitch'] = float(value)
+ elif key == KEY_OUT_END_DIST:
+ param_map['end'] = float(value)
+ elif key == KEY_OUT_GAUGE1:
+ param_map['gauge1'] = float(value)
+ elif key == KEY_OUT_GAUGE2:
+ param_map['gauge2'] = float(value)
+ elif key == KEY_OUT_GAUGE:
+ param_map['gauge'] = float(value)
+ elif key == KEY_OUT_EDGE_DIST:
+ param_map['edge'] = float(value)
+
+ # Add hardcoded hole diameter
+ param_map['hole'] = self.main.bolt.bolt_diameter_provided
+
+ print("Extracted parameters:", param_map)
+
+ return param_map
+
+ def createDrawing(self, params):
+
+ # Extract parameters
+ pitch = params['pitch']
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ else:
+ gauge1 = params['gauge1']
+ gauge2 = params['gauge2']
+ edge = params['edge']
+ hole_diameter = params['hole']
+
+ # Calculate dimensions
+ if 'gauge' in params:
+ gauge1 = gauge
+ gauge2 = gauge
+ width = self.plate_width
+
+ height = self.plate_height
+
+ # Set up pens
+ outline_pen = QPen(Qt.blue, 2)
+ dimension_pen = QPen(Qt.black, 1.5)
+ red_brush = QBrush(Qt.red)
+
+ # Dimension offsets
+ h_offset = 40
+ v_offset = 60
+
+ # Create scene rectangle with extra space for dimensions
+ self.scene.setSceneRect(-h_offset, -v_offset,
+ width + 2*v_offset, height + 2*h_offset)
+
+ # Draw rectangle
+ self.scene.addRect(0, 0, width, height, dimension_pen)
+
+ # Draw holes
+ for row in range(self.rows):
+ for col in range(self.cols):
+ # Start from right edge (for example: total plate width - edge)
+ x_center = self.plate_width - edge
+
+ # Subtract gauges from right to left
+ for i in range(col):
+ x_center -= gauge1 if i % 2 == 0 else gauge2
+
+ # Y-position stays the same
+ y_center = end + row * pitch
+
+ # Top-left corner for drawing the circle
+ x = x_center - hole_diameter / 2
+ y = y_center - hole_diameter / 2
+
+ print(f"row: {row}, col: {col}, x: {x}, y: {y}")
+ self.scene.addEllipse(x, y, hole_diameter, hole_diameter, outline_pen)
+ weld_size=self.weldsize
+ weld_gap=self.weldgap
+ x_center=self.plate_width/2
+ y_center=self.plate_height/2
+ self.scene.addRect(x_center-weld_gap/2-weld_size, 0, weld_size, height, dimension_pen,red_brush)
+ self.scene.addRect(x_center+weld_gap/2, 0, weld_size, height, dimension_pen,red_brush)
+ print(params,dimension_pen)
+ # Add dimensions
+ self.addDimensions(params, dimension_pen)
+
+ def addDimensions(self, params, pen):
+ # Extract parameters
+ pitch = params['pitch']
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ else:
+ gauge1 = params['gauge1']
+ gauge2 = params['gauge2']
+ edge = params['edge']
+
+ if 'gauge' in params:
+ gauge1 = gauge
+ gauge2 = gauge
+
+ width = self.plate_width
+ height = self.plate_height
+
+ # Offsets for dimension lines
+ h_offset = 20
+ v_offset = 30
+
+ # Add horizontal dimensions
+ x_start = width
+ segments = []
+ # First edge
+ segments.append(('edge', x_start-edge, x_start ))
+ x_start -=edge
+
+ # Last edge
+ segments.append(('edge', 0, x_start))
+
+ # Draw each segment
+ for label, x1, x2 in segments:
+ value = x2 - x1
+ self.addHorizontalDimension(x1, -h_offset, x2, -h_offset, f"{value:.1f}", pen)
+ # Add vertical dimensions
+ self.addVerticalDimension(width + v_offset, 0, width + v_offset, end, str(end), pen)
+ for i in range(self.rows - 1):
+ self.addVerticalDimension(width + v_offset, end + i * pitch, width + v_offset, end + (i + 1) * pitch, str(pitch), pen)
+
+ # Add bottom end distance dimension
+ self.addVerticalDimension(width + v_offset, height, width + v_offset, height - end, str(end), pen)
+
+ # Add left side dimension
+ total_height = 2 * end + (self.rows - 1) * pitch
+ self.addVerticalDimension(-v_offset, 0, -v_offset, total_height, str(total_height), pen)
+
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
\ No newline at end of file
diff --git a/src/osdag/gui/seatedanglespacing.py b/src/osdag/gui/seatedanglespacing.py
new file mode 100644
index 000000000..e246c5f78
--- /dev/null
+++ b/src/osdag/gui/seatedanglespacing.py
@@ -0,0 +1,303 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+class SeatedanglespacingOnCol(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+
+ self.connection = connection_obj
+ self.val=rows
+
+ if self.val==3 or self.val==4:
+ self.plate_width=main.seated_angle.width
+ self.plate_length=main.seated_angle.leg_a_length
+ self.plate_thickness=float(main.seated_angle.designation.split(" x ")[-1])
+ else:
+ self.plate_width=main.top_angle.width
+ self.plate_length=main.top_angle.leg_a_length
+ self.plate_thickness=float(main.top_angle.designation.split(" x ")[-1])
+
+
+ arr=[main.top_spacing_col(main,True),main.top_spacing_beam(main,True),main.seated_spacing_col(main,True),
+ main.seated_spacing_beam(main,True)]
+ val=self.val-1
+ print(val)
+ # print(arr[0],len(arr[0]))
+ # print('\n\n')
+ # for i in range(len(arr[0])):
+ # print(f"INDEX : {i} : {arr[0][i]} , {arr[0][i][3]}")
+ for i in arr[2]:
+ print(i)
+ print('\n\n')
+
+ data = {entry[0]: entry[3] for entry in arr[val] if entry[0]}
+ print(data)
+ self.rows = data['Bolt.Rows']
+ self.cols = data['Bolt.Cols']
+ self.End = data['Bolt.EndDist']
+ self.Gauge = data['Bolt.Gauge']
+ if self.Gauge==0 and 'Bolt.GaugeCentral' in data:
+ self.Gauge=data['Bolt.GaugeCentral']
+ self.Edge = data['Bolt.EdgeDist']
+ # return
+ print(f"""
+ Plate Dimensions
+ ----------------
+ Plate Width : {self.plate_width} mm
+ Plate Length : {self.plate_length} mm
+
+ Bolt Layout
+ -----------
+ Rows : {self.rows}
+ Columns : {self.cols}
+ End Distance : {self.End} mm
+ Gauge : {self.Gauge} mm
+ Edge Distance: {self.Edge} mm
+ """)
+ # self.initUI()
+ self.param_map = {
+ 'end': self.End,
+ 'gauge': self.Gauge,
+ 'edge': self.Edge,
+ 'hole': main.bolt.bolt_diameter_provided
+}
+
+ print(self.param_map)
+ self.initUI()
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 1050, 750)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+ params=self.param_map
+ # Parameter display labels
+ # Display the parameter values
+ for key, value in params.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} Distance (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Right panel for the drawing using QGraphicsView
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Create and add the drawing to the scene
+ self.createDrawing(params)
+
+ # Add panels to main layout
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(self.view, 3)
+
+ # Set main widget
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ # Ensure the view shows all content
+ self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
+
+
+
+ def createDrawing(self, params):
+
+ # Extract parameters
+
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ edge = params['edge']
+ hole_diameter = params['hole']
+ print(f"rows: {self.rows}, cols: {self.cols}")
+ # Calculate dimensions
+
+ width = self.plate_width
+
+ height = self.plate_length
+ # Set up pens
+ outline_pen = QPen(Qt.blue, 2)
+ dimension_pen = QPen(Qt.black, 1.5)
+ weld_fill = QBrush(Qt.red)
+
+ # Dimension offsets
+ h_offset = 40
+ v_offset = 60
+
+ # Create scene rectangle with extra space for dimensions
+ self.scene.setSceneRect(-h_offset, -v_offset,
+ width + 2*v_offset, height + 2*h_offset)
+
+ # Draw rectangle
+ self.scene.addRect(0, 0, width, height, dimension_pen)
+
+ if self.val==3 or self.val==1:
+ self.scene.addRect(0, height-self.plate_thickness, width, self.plate_thickness, dimension_pen, weld_fill)
+ elif self.val==4 or self.val==2:
+ self.scene.addRect(0, 0, width, self.plate_thickness, dimension_pen, weld_fill)
+
+
+ # Draw holes
+ for row in range(self.rows):
+ for col in range(self.cols):
+ # Start from edge distance (center of first hole)
+ x_center = edge
+ for i in range(col):
+ x_center += gauge
+
+ # Center of hole is at (x_center, y_center)
+ # Subtract hole_diameter/2 to draw ellipse properly from top-left
+ x = x_center - hole_diameter / 2
+ y_center = end
+ y = y_center - hole_diameter / 2
+
+ print(f"row: {row}, col: {col}, x: {x}, y: {y}")
+ self.scene.addEllipse(x, y, hole_diameter, hole_diameter, outline_pen)
+ print(params,dimension_pen)
+ # Add dimensions
+ self.addDimensions(params, dimension_pen)
+
+ def addDimensions(self, params, pen):
+ # Extract parameters
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+
+ edge = params['edge']
+
+
+
+ width=self.plate_width
+ height=self.plate_length
+
+ # Offsets for dimension lines
+ h_offset = 20
+ v_offset = 30
+
+ # Add horizontal dimensions
+ x_start = 0
+ segments = []
+ # First edge
+ segments.append(('edge', x_start, x_start + edge))
+ x_start += edge
+ segments.append(('edge' ,x_start,x_start+gauge ))
+ x_start+=gauge
+ # Last edge
+ segments.append(('edge', x_start, x_start + edge))
+
+ # Draw each segment
+ for label, x1, x2 in segments:
+ value = x2 - x1
+ self.addHorizontalDimension(x1, -h_offset, x2, -h_offset, f"{value:.1f}", pen)
+ self.addHorizontalDimension(0,height+h_offset,width,height+h_offset,f"{width} mm" , pen)
+ # Add vertical dimensions
+ # Add top end distance dimension (from 0 to end)
+ self.addVerticalDimension(width + v_offset, 0, width + v_offset, end, str(end), pen)
+
+ # Add remaining distance from end to height
+ self.addVerticalDimension(width + v_offset , end, width + v_offset , height, str(height - end), pen)
+
+ # Add left side dimension
+ total_height = 2 * end + (self.rows - 1)
+ self.addVerticalDimension(-v_offset/2, 0, -v_offset/2, height, str(height), pen)
+
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
\ No newline at end of file
diff --git a/src/osdag/gui/spacing.py b/src/osdag/gui/spacing.py
new file mode 100644
index 000000000..2290b04a1
--- /dev/null
+++ b/src/osdag/gui/spacing.py
@@ -0,0 +1,297 @@
+import sys
+from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
+ QHBoxLayout, QLabel, QGraphicsView,
+ QGraphicsScene)
+from PyQt5.QtGui import QPixmap
+from PyQt5.QtCore import Qt, QRectF
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtGui import QPolygonF, QBrush
+from PyQt5.QtCore import QPointF
+from ..Common import *
+from .additionalfns import calculate_total_width
+from ..design_type.connection.end_plate_connection import EndPlateConnection
+
+class BoltPatternGenerator(QMainWindow):
+ def __init__(self, connection_obj, rows=3, cols=2 , main = None):
+ super().__init__()
+ self.connection = connection_obj
+ self.main=main
+ self.plate_height = main.plate.height
+ self.plate_width = main.plate.length
+ self.hole_dia=main.bolt.bolt_diameter_provided
+ self.rows=main.plate.bolts_one_line
+ self.cols=main.plate.bolt_line
+ print(self.plate_height,self.plate_width)
+ output=main.output_values(main,True)
+ dict1={i[0] : i[3] for i in output}
+ for i in output:
+ print(i)
+ self.weldsize=0
+ if 'Weld.Size' in dict1:
+ self.weldsize=dict1['Weld.Size']
+ self.initUI()
+ # print(self.connection.spacing(status=True))
+ def initUI(self):
+ self.setWindowTitle('Bolt Pattern Generator')
+ self.setGeometry(100, 100, 800, 500)
+
+ # Main layout
+ main_layout = QHBoxLayout()
+
+ # Left panel for parameter display
+ left_panel = QWidget()
+ left_layout = QVBoxLayout()
+
+ # Parameter display labels
+ params = self.get_parameters()
+
+ # Display the parameter values
+ for key, value in params.items():
+ param_layout = QHBoxLayout()
+ param_label = QLabel(f'{key.title()} Distance (mm):')
+ value_label = QLabel(f'{value}')
+ param_layout.addWidget(param_label)
+ param_layout.addWidget(value_label)
+ left_layout.addLayout(param_layout)
+
+ left_layout.addStretch()
+ left_panel.setLayout(left_layout)
+
+ # Right panel for the drawing using QGraphicsView
+ self.scene = QGraphicsScene()
+ self.view = QGraphicsView(self.scene)
+ self.view.setRenderHint(QPainter.Antialiasing)
+
+ # Create and add the drawing to the scene
+ self.createDrawing(params)
+
+ # Add panels to main layout
+ main_layout.addWidget(left_panel, 1)
+ main_layout.addWidget(self.view, 3)
+
+ # Set main widget
+ main_widget = QWidget()
+ main_widget.setLayout(main_layout)
+ self.setCentralWidget(main_widget)
+
+ # Ensure the view shows all content
+ self.view.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
+ def get_parameters(self):
+ spacing_data = self.connection.spacing(status=True) # Get actual values
+ param_map = {}
+ print('spacing_data length' , len(spacing_data))
+ for item in spacing_data:
+ key, _, _, value = item
+ # print('key : ', key)
+ if key == KEY_OUT_PITCH:
+ param_map['pitch'] = float(value)
+ elif key == KEY_OUT_END_DIST:
+ param_map['end'] = float(value)
+ elif key == KEY_OUT_GAUGE1:
+ param_map['gauge1'] = float(value)
+ elif key == KEY_OUT_GAUGE2:
+ param_map['gauge2'] = float(value)
+ elif key == KEY_OUT_GAUGE:
+ param_map['gauge'] = float(value)
+ elif key == KEY_OUT_EDGE_DIST:
+ param_map['edge'] = float(value)
+
+ # Add hardcoded hole diameter
+ param_map['hole'] = self.main.bolt.bolt_diameter_provided
+
+ print("Extracted parameters:", param_map)
+
+ return param_map
+
+ def createDrawing(self, params):
+
+ # Extract parameters
+ pitch = params['pitch']
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ else:
+ gauge1 = params['gauge1']
+ gauge2 = params['gauge2']
+ edge = params['edge']
+ hole_diameter = params['hole']
+
+ # Calculate dimensions
+ if 'gauge' in params:
+ gauge1 = gauge
+ gauge2 = gauge
+ width = self.plate_width
+
+ height = self.plate_height
+
+ # Set up pens
+ outline_pen = QPen(Qt.blue, 2)
+ dimension_pen = QPen(Qt.black, 1.5)
+ red_brush = QBrush(Qt.red)
+
+ # Dimension offsets
+ h_offset = 40
+ v_offset = 60
+
+ # Create scene rectangle with extra space for dimensions
+ self.scene.setSceneRect(-h_offset, -v_offset,
+ width + 2*v_offset, height + 2*h_offset)
+
+ # Draw rectangle
+ self.scene.addRect(0, 0, width, height, dimension_pen)
+
+ # Draw holes
+ for row in range(self.rows):
+ for col in range(self.cols):
+ # Start from right edge (for example: total plate width - edge)
+ x_center = self.plate_width - edge
+
+ # Subtract gauges from right to left
+ for i in range(col):
+ x_center -= gauge1 if i % 2 == 0 else gauge2
+
+ # Y-position stays the same
+ y_center = end + row * pitch
+
+ # Top-left corner for drawing the circle
+ x = x_center - hole_diameter / 2
+ y = y_center - hole_diameter / 2
+
+ print(f"row: {row}, col: {col}, x: {x}, y: {y}")
+ self.scene.addEllipse(x, y, hole_diameter, hole_diameter, outline_pen)
+ weld_size=self.weldsize
+ self.scene.addRect(0, 0, weld_size, height, dimension_pen,red_brush)
+ print(params,dimension_pen)
+ # Add dimensions
+ self.addDimensions(params, dimension_pen)
+
+ def addDimensions(self, params, pen):
+ # Extract parameters
+ pitch = params['pitch']
+ end = params['end']
+ if 'gauge' in params:
+ gauge = params['gauge']
+ else:
+ gauge1 = params['gauge1']
+ gauge2 = params['gauge2']
+ edge = params['edge']
+
+ if 'gauge' in params:
+ gauge1 = gauge
+ gauge2 = gauge
+
+ width = self.plate_width
+ height = self.plate_height
+
+ # Offsets for dimension lines
+ h_offset = 20
+ v_offset = 30
+
+ # Add horizontal dimensions
+ x_start = width
+ segments = []
+ # First edge
+ segments.append(('edge', x_start-edge, x_start ))
+ x_start -=edge
+
+ # Last edge
+ segments.append(('edge', 0, x_start))
+
+ # Draw each segment
+ for label, x1, x2 in segments:
+ value = x2 - x1
+ self.addHorizontalDimension(x1, -h_offset, x2, -h_offset, f"{value:.1f}", pen)
+ # Add vertical dimensions
+ self.addVerticalDimension(width + v_offset, 0, width + v_offset, end, str(end), pen)
+ for i in range(self.rows - 1):
+ self.addVerticalDimension(width + v_offset, end + i * pitch, width + v_offset, end + (i + 1) * pitch, str(pitch), pen)
+
+ # Add bottom end distance dimension
+ self.addVerticalDimension(width + v_offset, height, width + v_offset, height - end, str(end), pen)
+
+ # Add left side dimension
+ total_height = 2 * end + (self.rows - 1) * pitch
+ self.addVerticalDimension(-v_offset, 0, -v_offset, total_height, str(total_height), pen)
+
+ def addHorizontalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1, y1 - ext_length/2, x1, y1 + ext_length/2, pen)
+ self.scene.addLine(x2, y2 - ext_length/2, x2, y2 + ext_length/2, pen)
+
+ points_left = [
+ (x1, y1),
+ (x1 + arrow_size, y1 - arrow_size/2),
+ (x1 + arrow_size, y1 + arrow_size/2)
+ ]
+ polygon_left = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_left]), pen)
+ polygon_left.setBrush(QBrush(Qt.black))
+
+ points_right = [
+ (x2, y2),
+ (x2 - arrow_size, y2 - arrow_size/2),
+ (x2 - arrow_size, y2 + arrow_size/2)
+ ]
+ polygon_right = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_right]), pen)
+ polygon_right.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if y1 < 0:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 - 25)
+ else:
+ text_item.setPos((x1 + x2) / 2 - text_item.boundingRect().width() / 2, y1 + 5)
+
+ def addVerticalDimension(self, x1, y1, x2, y2, text, pen):
+ self.scene.addLine(x1, y1, x2, y2, pen)
+ arrow_size = 5
+ ext_length = 10
+ self.scene.addLine(x1 - ext_length/2, y1, x1 + ext_length/2, y1, pen)
+ self.scene.addLine(x2 - ext_length/2, y2, x2 + ext_length/2, y2, pen)
+
+ if y2 > y1:
+ points_top = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 + arrow_size),
+ (x1 + arrow_size/2, y1 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 - arrow_size),
+ (x2 + arrow_size/2, y2 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+ else:
+ points_top = [
+ (x2, y2),
+ (x2 - arrow_size/2, y2 + arrow_size),
+ (x2 + arrow_size/2, y2 + arrow_size)
+ ]
+ polygon_top = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_top]), pen)
+ polygon_top.setBrush(QBrush(Qt.black))
+
+ points_bottom = [
+ (x1, y1),
+ (x1 - arrow_size/2, y1 - arrow_size),
+ (x1 + arrow_size/2, y1 - arrow_size)
+ ]
+ polygon_bottom = self.scene.addPolygon(QPolygonF([QPointF(x, y) for x, y in points_bottom]), pen)
+ polygon_bottom.setBrush(QBrush(Qt.black))
+
+ text_item = self.scene.addText(text)
+ font = QFont()
+ font.setPointSize(5)
+ text_item.setFont(font)
+
+ if x1 < 0:
+ text_item.setPos(x1 - 10 - text_item.boundingRect().width(), (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
+ else:
+ text_item.setPos(x1 + 15, (y1 + y2) / 2 - text_item.boundingRect().height() / 2)
\ No newline at end of file
diff --git a/src/osdag/gui/ui_aboutosdag.py b/src/osdag/gui/ui_aboutosdag.py
index 77b660425..5f9d2dc2f 100644
--- a/src/osdag/gui/ui_aboutosdag.py
+++ b/src/osdag/gui/ui_aboutosdag.py
@@ -7,6 +7,7 @@
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
+from .._version import __version__
class Ui_AboutOsdag(object):
def setupUi(self, Dialog):
@@ -35,7 +36,7 @@ def retranslateUi(self, Dialog):
"p, li { white-space: pre-wrap; }\n"
"\n"
"Osdag©
\n"
-"Version: 2021.02.a.a12f
\n"
+f"Version: {__version__}
\n"
"
\n"
"Osdag is a cross-platform, free, and open-source software for the design and detailing of steel structures, following the Indian Standard IS 800:2007. Osdag is primarily built using Python other Python-based FOSS tools, such as, PyQt, OpenCascade, PythonOCC, SQLite. It allows the user to design steel connections, members and systems using a graphical user interface. The interactive GUI provides a 3D visualisation of the designed component and an option to export the CAD model to any drafting software for the creation of construction/fabrication drawings. The design is typically optimised following industry best practices. Osdag is developed by the Osdag team at IIT Bombay under the initiative of FOSSEE funded by the Ministry of Education (MoE), Government of India.
\n"
"
\n"
diff --git a/src/osdag/gui/ui_template.py b/src/osdag/gui/ui_template.py
index c112b739e..0f94cd282 100644
--- a/src/osdag/gui/ui_template.py
+++ b/src/osdag/gui/ui_template.py
@@ -3,6 +3,8 @@
import shutil
import time
import pandas as pd
+import subprocess
+import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
@@ -19,7 +21,9 @@
from .customized_popup import Ui_Popup
# from .ui_summary_popup import Ui_Dialog1
#from .ui_design_preferences import Ui_Dialog
-
+from .beam2beamcoverplatedetailing import B2Bcoverplate
+from .b2cendplateSketch import B2BEndPlateSketch
+from .beam2beamcoverplatedetailing_capacity_details import B2Bcoverplate_capacity_details
from .ui_summary_popup import Ui_Dialog1
from ..design_report.reportGenerator import save_html
from .ui_OsdagSectionModeller import Ui_OsdagSectionModeller
@@ -54,19 +58,30 @@
from ..design_type.flexural_member.flexure import Flexure
from ..design_type.flexural_member.flexure_cantilever import Flexure_Cantilever
from ..design_type.flexural_member.flexure_othersupp import Flexure_Misc
+from ..design_type.flexural_member.flexure_purlin import Flexure_Purlin
from ..gusset_connection import GussetConnection
import logging
import subprocess
from ..get_DPI_scale import scale,height,width
from ..cad.cad3dconnection import cadconnection
from pynput.mouse import Button, Controller
-
+from osdag.gui.spacing import BoltPatternGenerator
+from osdag.gui.capacity_details_finPlate import CapacityDetailsWindow
+from .seatedanglespacing import SeatedanglespacingOnCol
+from .Beam2ColEnddetailing import BeamtoColDetailing
+from .baseplatedetailing import BasePlateDetailing
+from .baseplatedetailinghollow import BasePlateDetailingHollow
+from .b2bcoverplateweld import B2Bcoverplateweld
+
+from .cleatangledetailing import CleatAngle
+from .BC2Cendplate import BC2CEndPlate
+from .endplatecnndetailnig import EndPlateDetailer
class MyTutorials(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.ui = Ui_Tutorial()
self.ui.setupUi(self)
-
+ self.active_dialog = None
class MyAboutOsdag(QDialog):
def __init__(self, parent=None):
@@ -865,7 +880,6 @@ def setupUi(self, MainWindow, main,folder):
else:
for t in updated_list:
for key_name in t[0]:
-
key_changed = self.dockWidgetContents.findChild(QtWidgets.QWidget, key_name)
self.on_change_connect(key_changed, updated_list, data, main)
print(f"key_name{key_name} \n key_changed{key_changed} \n self.on_change_connect ")
@@ -1866,6 +1880,8 @@ def return_class(self,name):
return Flexure_Cantilever
elif name == KEY_DISP_FLEXURE3:
return Flexure_Misc
+ elif name == KEY_DISP_FLEXURE4:
+ return Flexure_Purlin
else:
return GussetConnection
# Function for getting inputs from a file
@@ -2105,7 +2121,7 @@ def common_function_for_save_and_design(self, main, data, trigger_type):
KEY_DISP_ENDPLATE, KEY_DISP_BASE_PLATE, KEY_DISP_SEATED_ANGLE, KEY_DISP_TENSION_BOLTED,
KEY_DISP_TENSION_WELDED, KEY_DISP_COLUMNCOVERPLATE, KEY_DISP_COLUMNCOVERPLATEWELD,
KEY_DISP_COLUMNENDPLATE, KEY_DISP_BCENDPLATE, KEY_DISP_BB_EP_SPLICE,
- KEY_DISP_COMPRESSION_COLUMN,KEY_DISP_FLEXURE,KEY_DISP_FLEXURE2,KEY_DISP_COMPRESSION_Strut]: # , KEY_DISP_FLEXURE
+ KEY_DISP_COMPRESSION_COLUMN,KEY_DISP_FLEXURE,KEY_DISP_FLEXURE2,KEY_DISP_FLEXURE3,KEY_DISP_FLEXURE4,KEY_DISP_COMPRESSION_Strut]: # , KEY_DISP_FLEXURE
# print(self.display, self.folder, main.module, main.mainmodule)
print("common start")
print(f"main object type: {type(main)}")
@@ -2113,7 +2129,7 @@ def common_function_for_save_and_design(self, main, data, trigger_type):
print("main.mainmodule",main.mainmodule)
self.commLogicObj = CommonDesignLogic(self.display, self.folder, main.module, main.mainmodule)
- print(main.module)
+ print(f"This is MAIN.MODULE {main.module}")
print(main.mainmodule)
# print("common start")
status = main.design_status
@@ -2134,24 +2150,7 @@ def common_function_for_save_and_design(self, main, data, trigger_type):
action.setEnabled(True)
fName = str('./ResourceFiles/images/3d.png')
file_extension = fName.split(".")[-1]
-
- # if file_extension == 'png':
- # self.display.ExportToImage(fName)
- # im = Image.open('./ResourceFiles/images/3d.png')
- # w,h=im.size
- # if(w< 640 or h < 360):
- # print('Re-taking Screenshot')
- # self.resize(700,500)
- # self.outputDock.hide()
- # self.inputDock.hide()
- # self.textEdit.hide()
- # QTimer.singleShot(0, lambda:self.retakeScreenshot(fName))
-
else:
- for fName in ['3d.png', 'top.png',
- 'front.png', 'side.png']:
- with open("./ResourceFiles/images/"+fName, 'w'):
- pass
self.display.EraseAll()
for chkbox in main.get_3d_components(main):
self.frame.findChild(QtWidgets.QCheckBox, chkbox[0]).setEnabled(False)
@@ -2192,7 +2191,30 @@ def osdag_header(self):
def output_button_connect(self, main, button_list, b):
b.clicked.connect(lambda: self.output_button_dialog(main, button_list, b))
+ def run_spacing_script(self,cols,rows,generator_class=BoltPatternGenerator , main=None):
+ print("Creating spacing window...")
+ self.spacing_window = generator_class(self.Obj,cols=cols,rows=rows,main=main)
+ self.spacing_window.setWindowTitle("Spacing Viewer")
+ self.spacing_window.raise_()
+ self.spacing_window.activateWindow()
+ self.spacing_window.show()
+
+ def run_capacity_details(self,cols,rows,generator_class=CapacityDetailsWindow , main=None):
+ print("Creating capacity details window...")
+ print("++++++++++++++++++++++++++++++DEBUG++++++++++++++++++++++++++++++")
+ print(generator_class)
+ print("++++++++++++++++++++++++++++++DEBUG++++++++++++++++++++++++++++++")
+ self.capacity_window = generator_class(self.Obj,cols=cols,rows=rows,main=main)
+ self.capacity_window.setWindowTitle("Capacity Details")
+ self.capacity_window.raise_()
+ self.capacity_window.activateWindow()
+ self.capacity_window.show()
+
+
+
+
def output_button_dialog(self, main, button_list, button):
+ import inspect
dialog = QtWidgets.QDialog()
dialog.setObjectName("Dialog")
@@ -2231,12 +2253,168 @@ def output_button_dialog(self, main, button_list, button):
section = 0
no_note = True
- for op in button_list:
+ for op in button_list:
+
if op[0] == button.objectName():
+ print(op)
+ print("DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG")
+ print(main)
+ print("DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG_DEBUG")
tup = op[3]
title = tup[0]
fn = tup[1]
+ cls = fn.__qualname__.split('.')[0]
+ if op[0] == 'spacing' or op[0]=='Cleat.Spting_leg.spacing':
+ # print(main)
+ self.active_dialog = QtWidgets.QDialog()
+ dialog = self.active_dialog
+ module = inspect.getmodule(fn) # Get the module where the function is defined
+ cls_obj = getattr(module, cls) # Get the actual class object
+ self.Obj = cls_obj()
+ if main is FinPlateConnection:
+ if hasattr(self.Obj, 'spting_leg') and \
+ hasattr(self.Obj.spting_leg, 'bolt_line') and \
+ hasattr(self.Obj.spting_leg, 'bolts_one_line'):
+ self.run_spacing_script(self.Obj.spting_leg.bolts_one_line,self.Obj.spting_leg.bolt_line,
+ main=main)
+ else:
+ self.run_spacing_script(rows=self.Obj.plate.bolts_one_line,cols=self.Obj.plate.bolt_line,
+ main=main)
+ elif main is CleatAngleConnection and op[0]=='spacing':
+ self.run_spacing_script(0,0,CleatAngle,(main,0))
+ elif op[0]!='spacing' and main is CleatAngleConnection:
+ self.run_spacing_script(0,0,CleatAngle,(main,1))
+ elif main is EndPlateConnection:
+ self.run_spacing_script(0,0,EndPlateDetailer,main)
+ # return
+ # Instantiate it
+
+ break
+
+ elif ((op[0]=='button1' or op[0]=='button2') and op[3][0]=='Capacity Details' and main is FinPlateConnection) :
+ self.active_dialog = QtWidgets.QDialog()
+ dialog = self.active_dialog
+ module = inspect.getmodule(fn) # Get the module where the function is defined
+ cls_obj = getattr(module, cls) # Get the actual class object
+ self.Obj = cls_obj()
+ if main is FinPlateConnection:
+ if hasattr(self.Obj, 'spting_leg') and \
+ hasattr(self.Obj.spting_leg, 'bolt_line') and \
+ hasattr(self.Obj.spting_leg, 'bolts_one_line'):
+ self.run_capacity_details(self.Obj.spting_leg.bolts_one_line,self.Obj.spting_leg.bolt_line,
+ main=main)
+ else:
+ self.run_capacity_details(rows=self.Obj.plate.bolts_one_line,cols=self.Obj.plate.bolt_line,
+ main=main)
+ break
+
+
+ elif op[0].startswith('SeatedAngle') or op[0].startswith('TopAngle'):
+
+ module = inspect.getmodule(fn) # Get the module where the function is defined
+ cls_obj = getattr(module, cls) # Get the actual class object
+ self.Obj = cls_obj() # Instantiate it
+ if op[0]=='SeatedAngle.Bolt_Spacing_col':
+ val=3
+ elif op[0]=='SeatedAngle.Bolt_Spacing_beam':
+ val=4
+ elif op[0]=='TopAngle.Bolt_Spacing_col':
+ val=1
+ else:
+ val=2
+ self.run_spacing_script(None,
+ val,#specifying which to use
+ SeatedanglespacingOnCol,main)
+ return
+ print(KEY_OUT_ROW_PROVIDED , KEY_OUT_COL_PROVIDED)
+ elif op[0]=='Detailing' and op[1]=='Typical Detailing':
+
+ module = inspect.getmodule(fn) # Get the module where the function is defined
+ cls_obj = getattr(module, cls) # Get the actual class object
+ self.Obj = cls_obj()
+ print(f'rows: {self.Obj.bolt_row} , cols : {self.Obj.bolt_column} , {self.Obj.bolt_row_web}')
+ self.run_spacing_script(0,0,BeamtoColDetailing,main)
+ data=main.output_values(main,True)
+ return
+ elif op[0]=='BasePlate.Detailing':
+
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+ if main.connectivity == 'Moment Base Plate' or main.connectivity=='Welded Column Base':
+ self.run_spacing_script(0,0,BasePlateDetailing,main)
+ else:
+ self.run_spacing_script(0,0,BasePlateDetailingHollow,main)
+ return
+ elif op[0]=='Web_plate.spacing':
+
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+
+ self.run_capacity_details(0,0,B2Bcoverplate,(main,True, "spacing"))
+ return
+ elif op[0]=='Flange_plate.spacing':
+
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+
+ self.run_capacity_details(0,0,B2Bcoverplate,(main,False, "spacing"))
+ return
+ elif op[0]=='Web detail' and main is BeamCoverPlateWeld:
+
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+
+ self.run_spacing_script(0,0,B2Bcoverplateweld,(main,True))
+ return
+ elif op[0]=='Flange detail' and main is BeamCoverPlateWeld:
+
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+
+ self.run_spacing_script(0,0,B2Bcoverplateweld,(main,False))
+ return
+
+
+ #im working here
+ elif op[0]=='section.web_capacities' and main is BeamCoverPlate:
+
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+ self.run_capacity_details(0,0,B2Bcoverplate_capacity_details,(main,True,"capacity"))
+ return
+
+ #im working here
+ elif op[0]=='section.flange_capacity' and main is BeamCoverPlate:
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+ self.run_capacity_details(0,0,B2Bcoverplate_capacity_details,(main,False,"capacity"))
+ return
+
+ #im working here
+ elif op[0]=="Stiffener.Sketch" and op[1]=="Typical Sketch":
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+ self.run_spacing_script(0,0,B2BEndPlateSketch,main)
+ return
+
+ elif op[0]=='Bolt.web_bolts' or op[0]=='Bolt.flange_bolts':
+ module=inspect.getmodule(fn)
+ cls_obj=getattr(module,cls)
+ self.Obj=cls_obj()
+ if op[0]=='Bolt.web_bolts':
+ self.run_spacing_script(0,0,BC2CEndPlate,(main,0))
+ else:
+ self.run_spacing_script(0,0,BC2CEndPlate,(main,1))
+ break
dialog.setWindowTitle(title)
j = 1
_translate = QtCore.QCoreApplication.translate
diff --git a/src/osdag/osdagMainPage.py b/src/osdag/osdagMainPage.py
index d49647a3b..13736a794 100644
--- a/src/osdag/osdagMainPage.py
+++ b/src/osdag/osdagMainPage.py
@@ -166,6 +166,7 @@
from .design_type.flexural_member.flexure import Flexure
from .design_type.flexural_member.flexure_cantilever import Flexure_Cantilever
+from .design_type.flexural_member.flexure_purlin import Flexure_Purlin
from .design_type.flexural_member.flexure_othersupp import Flexure_Misc
# from .design_type.plate_girder.weldedPlateGirder import PlateGirderWelded
# from .cad.cad_common import call_3DBeam
@@ -312,22 +313,21 @@ def __init__(self):
'Flexural Member' : [
('Simply Supported Beam', str(files("osdag.data.ResourceFiles.images").joinpath("simply-supported-beam.jpg")), 'Beam_flexure'),
('Cantilever Beam', str(files("osdag.data.ResourceFiles.images").joinpath("cantilever-beam.jpg")), 'Beam_flexure2'),
+ ('Purlin', str(files("osdag.data.ResourceFiles.images").joinpath("purlin.jpg")), 'Beam_flexure4'),
# ('Other Beams', str(files("osdag.data.ResourceFiles.images").joinpath("fixed-beam.png")), 'Beam_flexure3'),
-
# ('Laterally Unsupported Beam', str(files("osdag.data.ResourceFiles.images").joinpath("broken.png")), 'Truss_Welded'),
self.show_flexure_module,
],
'Beam-Column' : self.Under_Development,
- 'Plate Girder' : self.Under_Development,
# TODO @rutvik
# 'Beam-Column' :[
# ('Beam-Column Design', str(files("osdag.data.ResourceFiles.images").joinpath("broken.png")), 'Beam_Column_Design'),
# self.show_beamcolumn_module,
# ],
- # 'Plate Girder' : [ #TODO: Check number of sub modules required
- # ('Welded Girder Design', str(files("osdag.data.ResourceFiles.images").joinpath("broken.png")), 'Welded_Girder_Design'),
- # self.Show_Girder_Design,
- # ],
+ 'Plate Girder' : [ #TODO: Check number of sub modules required
+ ('Simply Supported', str(files('osdag.data.ResourceFiles.images').joinpath('simply-supported-beam.jpg')), 'Welded_Girder_Design'),
+ self.show_girder_design,
+ ],
'Truss' : self.Under_Development,
'2D Frame' : self.Under_Development,
'3D Frame' : self.Under_Development,
@@ -533,96 +533,95 @@ def ButtonConnection(self,Button,Modules,ModuleName):
@pyqtSlot()
def show_shear_connection(self):
- if self.findChild(QRadioButton,'Fin_Plate').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(FinPlateConnection, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton,'Cleat_Angle').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(CleatAngleConnection, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton,'Seated_Angle').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow( SeatedAngleConnection, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton,'End_Plate').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(EndPlateConnection, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- else:
- QMessageBox.about(self, "INFO", "Please select appropriate connection")
+ button_name_window_type_pairs = \
+ [("Fin_Plate", FinPlateConnection),
+ ("Cleat_Angle", CleatAngleConnection),
+ ("Seated_Angle", SeatedAngleConnection),
+ ("End_Plate", EndPlateConnection),]
+
+ for (button_name, window_type) in button_name_window_type_pairs:
+ btn = self.findChild(QRadioButton, button_name)
+ if btn is not None and btn.isChecked():
+ self.hide()
+ self.ui2 = Ui_ModuleWindow(window_type, ' ')
+ self.ui2.show()
+ self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate connection")
def show_moment_connection(self):
- if self.findChild(QRadioButton,'B2B_Cover_Plate_Bolted').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(BeamCoverPlate, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton,'B2B_Cover_Plate_Welded').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(BeamCoverPlateWeld, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- # elif self.findChild(QRadioButton,'B2B_End_Plate_Connection').isChecked():
- # self.hide()
- # self.ui2 = Ui_ModuleWindow(BeamBeamEndPlateSplice,' ')
- # self.ui2.show()
- # self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton, 'B2B_End_Plate_Splice').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(BeamBeamEndPlateSplice, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
+ button_name_window_type_pairs = \
+ [("B2B_Cover_Plate_Bolted", BeamCoverPlate),
+ ("B2B_Cover_Plate_Welded", BeamCoverPlateWeld),
+ # ("B2B_End_Plate_Connection", BeamBeamEndPlateSplice),
+ ("B2B_End_Plate_Splice", BeamBeamEndPlateSplice),]
+
+ for (button_name, window_type) in button_name_window_type_pairs:
+ btn = self.findChild(QRadioButton, button_name)
+ if btn is not None and btn.isChecked():
+ self.hide()
+ self.ui2 = Ui_ModuleWindow(window_type, ' ')
+ self.ui2.show()
+ self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate connection")
def show_moment_connection_bc(self):
- if self.findChild(QRadioButton,'BC_End_Plate').isChecked():
+ btn = self.findChild(QRadioButton, "BC_End_Plate")
+ if btn is not None and btn.isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BeamColumnEndPlate, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
+ else:
+ QMessageBox.about(self, "INFO", "Please select appropriate connection")
def show_base_plate(self):
- if self.findChild(QRadioButton, 'Base_Plate').isChecked():
+ btn = self.findChild(QRadioButton, "Base_Plate")
+ if btn is not None and btn.isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BasePlateConnection, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
-
- def show_truss_bolted(self):
- if self.findChild(QRadioButton, 'Truss_Bolted').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(TrussConnectionBolted, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- #elif self.findChild(QRadioButton,'Truss_Welded').isChecked():
- # self.hide()
- # self.ui2 = Ui_ModuleWindow(BasePlateConnection, ' ')
- # self.ui2.show()
- # self.ui2.closed.connect(self.show)
else:
QMessageBox.about(self, "INFO", "Please select appropriate connection")
- def show_moment_connection_cc(self):
- if self.findChild(QRadioButton,'C2C_Cover_Plate_Bolted').isChecked() :
- self.hide()
- self.ui2 = Ui_ModuleWindow(ColumnCoverPlate, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton,'C2C_Cover_Plate_Welded').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(ColumnCoverPlateWeld, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
+ def show_truss_bolted(self):
+ button_name_window_type_pairs = \
+ [
+ ("Truss_Bolted", TrussConnectionBolted),
+ # ("Truss_Welded", BasePlateConnection),
+ ]
+
+ for (button_name, window_type) in button_name_window_type_pairs:
+ btn = self.findChild(QRadioButton, button_name)
+ if btn is not None and btn.isChecked():
+ self.hide()
+ self.ui2 = Ui_ModuleWindow(window_type, ' ')
+ self.ui2.show()
+ self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate connection")
- elif self.findChild(QRadioButton,'C2C_End_Plate_Connection').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(ColumnEndPlate, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
+ def show_moment_connection_cc(self):
+ button_name_window_type_pairs = \
+ [("C2C_Cover_Plate_Bolted", ColumnCoverPlate),
+ ("C2C_Cover_Plate_Welded", ColumnCoverPlateWeld),
+ ("C2C_End_Plate_Connection", ColumnEndPlate),]
+
+ for (button_name, window_type) in button_name_window_type_pairs:
+ btn = self.findChild(QRadioButton, button_name)
+ if btn is not None and btn.isChecked():
+ self.hide()
+ self.ui2 = Ui_ModuleWindow(window_type, ' ')
+ self.ui2.show()
+ self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate connection")
# def show_compression_module(self):
# # folder = self.select_workspace_folder()
@@ -659,93 +658,73 @@ def show_moment_connection_cc(self):
# self.ui2.closed.connect(self.show)
def show_tension_module(self):
- # folder = self.select_workspace_folder()
- # folder = str(folder)
- # if not os.path.exists(folder):
- # if folder == '':
- # pass
- # else:
- # os.mkdir(folder, 0o755)
- #
- # root_path = folder
- # images_html_folder = ['images_html']
- # flag = True
- # for create_folder in images_html_folder:
- # if root_path == '':
- # flag = False
- # return flag
- # else:
- # try:
- # os.mkdir(os.path.join(root_path, create_folder))
- # except OSError:
- # shutil.rmtree(os.path.join(folder, create_folder))
- # os.mkdir(os.path.join(root_path, create_folder))
-
- if self.findChild(QRadioButton,'Tension_Bolted').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(Tension_bolted, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
+ button_name_window_type_pairs = \
+ [("Tension_Bolted", Tension_bolted),
+ ("Tension_Welded", Tension_welded),]
- elif self.findChild(QRadioButton,'Tension_Welded').isChecked():
- self.hide()
- self.ui2 = Ui_ModuleWindow(Tension_welded, ' ')
- self.ui2.show()
- self.ui2.closed.connect(self.show)
+ for (button_name, window_type) in button_name_window_type_pairs:
+ btn = self.findChild(QRadioButton, button_name)
+ if btn is not None and btn.isChecked():
+ self.hide()
+ self.ui2 = Ui_ModuleWindow(window_type, ' ')
+ self.ui2.show()
+ self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate tension module")
def show_compression_module(self):
""" Create radio buttons for the sub-modules under the compression module"""
- # print(f"Here8")
- if self.findChild(QRadioButton, 'Column_Design').isChecked():
- # print(f"Here9")
+ column_design_button = self.findChild(QRadioButton, 'Column_Design')
+ if column_design_button is not None and column_design_button.isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(ColumnDesign, ' ')
- # print(f"Here11")
self.ui2.show()
self.ui2.closed.connect(self.show)
+ return
- elif self.findChild(QRadioButton, 'Strut_Design').isChecked():
- print(f"Here9")
+ strut_design_button = self.findChild(QRadioButton, 'Strut_Design')
+ if strut_design_button is not None and strut_design_button.isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(Compression, ' ')
- print(f"Here11.2")
self.ui2.show()
self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate compression module")
def show_flexure_module(self):
""" Create radio buttons for the sub-modules under the compression module"""
- # print(f"Here8")
- if self.findChild(QRadioButton, 'Beam_flexure').isChecked():
- # print(f"Here9")
- self.hide()
- self.ui2 = Ui_ModuleWindow(Flexure, ' ')
- # print(f"Here11")
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton, 'Beam_flexure2').isChecked():
- # print(f"Here9")
- self.hide()
- self.ui2 = Ui_ModuleWindow(Flexure_Cantilever, ' ')
- # print(f"Here11")
- self.ui2.show()
- self.ui2.closed.connect(self.show)
- elif self.findChild(QRadioButton, 'Beam_flexure3').isChecked():
- # print(f"Here9")
- self.hide()
- self.ui2 = Ui_ModuleWindow(Flexure_Misc, ' ')
- # print(f"Here11")
- self.ui2.show()
- self.ui2.closed.connect(self.show)
+
+ button_name_window_type_pairs = \
+ [("Beam_flexure", Flexure),
+ ("Beam_flexure2", Flexure_Cantilever),
+ ("Beam_flexure3", Flexure_Misc),
+ ("Beam_flexure4", Flexure_Purlin)]
+
+ for (button_name, window_type) in button_name_window_type_pairs:
+ btn = self.findChild(QRadioButton, button_name)
+ if btn is not None and btn.isChecked():
+ self.hide()
+ self.ui2 = Ui_ModuleWindow(window_type, ' ')
+ self.ui2.show()
+ self.ui2.closed.connect(self.show)
+ return
+
+ QMessageBox.about(self, "INFO", "Please select appropriate flexure module")
+
def show_beamcolumn_module(self):
- if self.findChild(QRadioButton, 'Beam_flexure').isChecked():
- # print(f"Here9")
+ btn = self.findChild(QRadioButton, "Beam_flexure")
+ if btn is not None and btn.isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(Flexure, ' ')
- # print(f"Here11")
self.ui2.show()
self.ui2.closed.connect(self.show)
- def Show_Girder_Design(self):
- if self.findChild(QRadioButton, 'Welded_Girder_Design').isChecked():
+ return
+
+ def show_girder_design(self):
+ btn = self.findChild(QRadioButton, "Welded_Girder_Design")
+ if btn is not None and btn.isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(PlateGirderWelded, ' ')
self.ui2.show()
@@ -775,7 +754,7 @@ def open_question(self):
self.ask_question()
def design_examples(self):
- root_path = os.path.join('ResourceFiles', 'html_page', '_build', 'html')
+ root_path = files('osdag.data.ResourceFiles.html_page._build').joinpath('html')
for html_file in os.listdir(root_path):
# if html_file.startswith('index'):
print(os.path.splitext(html_file)[1])
@@ -969,5 +948,49 @@ def do_stuff():
except BaseException as e:
print("ERROR", e)
+
+import cProfile
+import pstats
+import threading
+import keyboard # Install with `pip install keyboard`
+
+profiler = cProfile.Profile()
+
+def start_profiling():
+ print("Profiling started...")
+ profiler.enable()
+
+def stop_profiling():
+ print("Profiling stopped...")
+ profiler.disable()
+ profiler.dump_stats("profile_output")
+
+ stats = pstats.Stats("profile_output")
+ stats.sort_stats("time")
+
+ # Print to console
+ stats.print_stats(50)
+
+ # Save output to a text file
+ with open("profile_output.txt", "w") as f:
+ stats.stream = f
+ stats.print_stats(50)
+
+ print("Profile output saved to profile_output.txt")
+
+
+# Run profiling triggers in a separate thread to avoid blocking Osdag
+def listen_for_keys():
+ keyboard.add_hotkey('p', start_profiling) # Press 'p' to start
+ keyboard.add_hotkey('s', stop_profiling) # Press 's' to stop
+ keyboard.wait('esc') # Keep listening until 'esc' is pressed
+
+# Start the keyboard listener in the background
+threading.Thread(target=listen_for_keys, daemon=True).start()
+
+def main():
+ while True:
+ do_stuff() # Your main Osdag loop
+
if __name__ == '__main__':
- do_stuff()
+ main()
diff --git a/src/osdag/print_trace_wrapper.py b/src/osdag/print_trace_wrapper.py
new file mode 100644
index 000000000..f6f577fc2
--- /dev/null
+++ b/src/osdag/print_trace_wrapper.py
@@ -0,0 +1,49 @@
+import sys
+import os
+import builtins
+
+# File to save the trace output
+TRACE_OUTPUT_FILE = "trace_output.txt"
+
+# Path to ignore (conda environment directory)
+CONDA_PATH = os.getenv('CONDA_PREFIX', '') # Automatically gets the current conda environment path
+
+# Backup original print function
+original_print = builtins.print
+
+def traced_print(*args, **kwargs):
+ # Get the current frame
+ frame = sys._getframe(1)
+ function_name = frame.f_code.co_name
+ line_number = frame.f_lineno
+ file_path = frame.f_globals.get("__file__", "")
+
+ # Ignore printing from files in the conda environment
+ if CONDA_PATH and file_path.startswith(CONDA_PATH):
+ original_print(*args, **kwargs)
+ return
+
+ # Log the print statement with UTF-8 encoding
+ with open(TRACE_OUTPUT_FILE, "a", encoding="utf-8") as f:
+ f.write(f"Print in function: {function_name}, line {line_number}, file: {file_path}\n")
+ f.write(f" Output: {' '.join(map(str, args))}\n\n")
+
+ # Call the original print function
+ original_print(*args, **kwargs)
+
+# Clear the output file before starting
+with open(TRACE_OUTPUT_FILE, "w", encoding="utf-8") as f:
+ f.write("Trace Log:\n\n")
+
+# Override built-in print
+builtins.print = traced_print
+
+# Import and execute the target script
+script_path = "osdag/osdagMainPage.py"
+
+with open(script_path) as f:
+ code = f.read()
+ exec(code)
+
+# Restore original print
+builtins.print = original_print
diff --git a/src/osdag/profile_output b/src/osdag/profile_output
new file mode 100644
index 000000000..dc8f0dd85
--- /dev/null
+++ b/src/osdag/profile_output
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/osdag/trace_wrapper.py b/src/osdag/trace_wrapper.py
index ce3c72700..d8899522b 100644
--- a/src/osdag/trace_wrapper.py
+++ b/src/osdag/trace_wrapper.py
@@ -1,45 +1,32 @@
import sys
import os
+import runpy
-# File to save the trace output
TRACE_OUTPUT_FILE = "trace_output.txt"
-
-# Path to ignore (conda environment directory)
-CONDA_PATH = os.getenv('CONDA_PREFIX', '') # Automatically gets the current conda environment path
+CONDA_PATH = os.getenv('CONDA_PREFIX', '')
def trace_calls(frame, event, arg):
- # Get the file path of the current frame
file_path = frame.f_globals.get("__file__", "")
-
- # Ignore calls from files in the conda environment
if CONDA_PATH and file_path.startswith(CONDA_PATH):
return
-
- # Log the function call to the output file
if event == "call":
- # Get the caller's frame
caller_frame = frame.f_back
caller_file = caller_frame.f_globals.get("__file__", "unknown file")
caller_line = caller_frame.f_lineno
-
with open(TRACE_OUTPUT_FILE, "a") as f:
f.write(f"Calling function: {frame.f_code.co_name} in {file_path}\n")
f.write(f" Called from: {caller_file}, line {caller_line}\n\n")
return trace_calls
-# Clear the output file before starting
+# Clear log
with open(TRACE_OUTPUT_FILE, "w") as f:
f.write("Trace Log:\n\n")
-# Enable tracing
+# Set trace
sys.settrace(trace_calls)
-# Import and execute the target script
-script_path = "osdag/osdagMainPage.py"
-
-with open(script_path) as f:
- code = f.read()
- exec(code)
+# Run osdagMainPage as a module
+runpy.run_module("osdag.osdagMainPage", run_name="__main__")
-# Disable tracing
+# Clear trace
sys.settrace(None)
diff --git a/src/osdag/trace_wrapper_unique.py b/src/osdag/trace_wrapper_unique.py
new file mode 100644
index 000000000..0a3505958
--- /dev/null
+++ b/src/osdag/trace_wrapper_unique.py
@@ -0,0 +1,61 @@
+import sys
+import os
+
+# Files to save the trace outputs
+TRACE_OUTPUT_FILE = "trace_output.txt"
+UNIQUE_FUNCTIONS_FILE = "trace_functions.txt"
+
+# Path to ignore (conda environment directory)
+CONDA_PATH = os.getenv('CONDA_PREFIX', '')
+
+# Set to store unique function calls
+unique_functions = set()
+
+def trace_calls(frame, event, arg):
+ # Get the file path of the current frame
+ file_path = frame.f_globals.get("__file__", "")
+
+ # Ignore calls from files in the conda environment
+ if CONDA_PATH and file_path.startswith(CONDA_PATH):
+ return
+
+ # Log function calls
+ if event == "call":
+ # Get caller information
+ caller_frame = frame.f_back
+ caller_file = caller_frame.f_globals.get("__file__", "unknown file")
+ caller_line = caller_frame.f_lineno
+
+ # Log all calls to trace_output.txt
+ with open(TRACE_OUTPUT_FILE, "a") as f:
+ f.write(f"Calling function: {frame.f_code.co_name} in {file_path}\n")
+ f.write(f" Called from: {caller_file}, line {caller_line}\n\n")
+
+ # Store unique function information
+ function_info = f"Function: {frame.f_code.co_name}\nLocation: {file_path}\n"
+ if function_info not in unique_functions:
+ unique_functions.add(function_info)
+ # Write to unique functions file
+ with open(UNIQUE_FUNCTIONS_FILE, "a") as f:
+ f.write(f"{function_info}\n")
+
+ return trace_calls
+
+# Clear both output files before starting
+with open(TRACE_OUTPUT_FILE, "w") as f:
+ f.write("Trace Log:\n\n")
+
+with open(UNIQUE_FUNCTIONS_FILE, "w") as f:
+ f.write("Unique Functions Log:\n\n")
+
+# Enable tracing
+sys.settrace(trace_calls)
+
+# Import and execute the target script
+script_path = "osdag/osdagMainPage.py"
+with open(script_path) as f:
+ code = f.read()
+ exec(code)
+
+# Disable tracing
+sys.settrace(None)
\ No newline at end of file
diff --git a/src/osdag/utilities/__init__.py b/src/osdag/utilities/__init__.py
index 3a50f50cc..12eeb7d3b 100644
--- a/src/osdag/utilities/__init__.py
+++ b/src/osdag/utilities/__init__.py
@@ -40,6 +40,8 @@
Graphic3d_AspectLine3d)
from OCC.Core.Aspect import Aspect_TOTP_RIGHT_LOWER, Aspect_FM_STRETCH, Aspect_FM_NONE
import traceback
+from OCC.Core.AIS import AIS_TextLabel
+
def color_the_edges(shp, display, color, width):
"""
@@ -106,27 +108,63 @@ def DisplayMsg(display, point, text_to_write, height=None, message_color=None, u
"""
:point: a gp_Pnt or gp_Pnt2d instance
:text_to_write: a string
- :message_color: triple with the range 0-1
+ :message_color: triple with the range 0-1, e.g., (1.0, 0.0, 0.0) for red
+ :height: float, text height
+ :update: bool, whether to repaint the display
"""
- aPresentation = Prs3d_Presentation(display._struc_mgr)
- text_aspect = Prs3d_TextAspect()
-
+ # Handle point
+ if isinstance(point, gp_Pnt):
+ pnt = point
+ elif isinstance(point, gp_Pnt2d):
+ pnt = gp_Pnt(point.X(), point.Y(), 0.0)
+ else:
+ raise TypeError("point must be gp_Pnt or gp_Pnt2d")
+
+ # Get the AIS_InteractiveContext from the display
+ # Try different ways to access the context
+ if hasattr(display, 'Context'):
+ ais_context = display.Context # Access as attribute
+ elif hasattr(display, '_context'):
+ ais_context = display._context
+ elif hasattr(display, 'GetContext'):
+ ais_context = display.GetContext() # Some implementations use methods
+ else:
+ # Fallback: try to create a text directly with the display object
+ return display.DisplayMessage(pnt, text_to_write, message_color or (0,0,0), height or 10)
+
+ # Set color
if message_color is not None:
- text_aspect.SetColor(rgb_color("RED"))
- # if height is not None:
- text_aspect.Aspect()
- # if isinstance(point, None):
- point = gp_Pnt(point.X(), point.Y(), point.Z())
- Prs3d_Text.Draw(aPresentation,
- text_aspect,
- to_string(text_to_write),
- point)
- aPresentation.Display()
- # @TODO: it would be more coherent if a AIS_InteractiveObject
- # is be returned
+ if len(message_color) != 3:
+ raise ValueError("message_color must be a tuple of three floats between 0 and 1")
+ r, g, b = message_color
+ if not (0 <= r <= 1 and 0 <= g <= 1 and 0 <= b <= 1):
+ raise ValueError("message_color values must be between 0 and 1")
+ color = Quantity_Color(r, g, b, Quantity_TOC_RGB)
+ else:
+ # Default color: black
+ color = Quantity_Color(0.0, 0.0, 0.0, Quantity_TOC_RGB)
+
+ # Create AIS_Text label
+ text_label = AIS_TextLabel()
+ text_label.SetText(text_to_write)
+ text_label.SetPosition(pnt)
+ text_label.SetColor(color)
+
+ # Set height
+ if height is not None:
+ text_label.SetHeight(height)
+ else:
+ # Default height: 10
+ text_label.SetHeight(20)
+
+ # Display the text
+ ais_context.Display(text_label, True)
+
+ # Update display if needed
if update:
display.Repaint()
- return aPresentation
+
+ return text_label
# def osdag_display_msg(display, shapes, material=None, texture=None, color=None, transparency=None, update=False):
# set_default_edge_style(shapes, display)
diff --git a/src/osdag/utils/common/component.py b/src/osdag/utils/common/component.py
index dd9ad13c9..d1ceade86 100644
--- a/src/osdag/utils/common/component.py
+++ b/src/osdag/utils/common/component.py
@@ -1266,7 +1266,10 @@ class ISection(Material):
def __init__(self, designation, material_grade="", table=""):
if table == "":
table = "Beams" if designation in connectdb("Beams", "popup") else "Columns"
- self.connect_to_database_update_other_attributes(table, designation, material_grade)
+ if table == "Channels":
+ self.connect_to_database_update_other_attributes_channels(table, designation, material_grade)
+ else:
+ self.connect_to_database_update_other_attributes(table, designation, material_grade)
self.design_status = True
self.designation = designation
self.type = "Rolled"
@@ -1359,6 +1362,61 @@ def connect_to_database_update_other_attributes(self, table, designation, materi
conn.close()
+ def connect_to_database_update_other_attributes_channels(self, table, designation, material_grade=""):
+ conn = sqlite3.connect(PATH_TO_DATABASE)
+ db_query = "SELECT * FROM " + table + " WHERE Designation = ?"
+ cur = conn.cursor()
+ cur.execute(db_query, (designation,))
+ row = cur.fetchone()
+ self.mass = row[2]
+ self.area = row[3] * 100
+ self.depth = row[4]
+ self.flange_width = row[5]
+ self.web_thickness = row[6]
+ self.flange_thickness = row[7]
+ max_thickness = max(self.flange_thickness, self.web_thickness)
+ super(ISection, self).__init__(material_grade, max_thickness)
+ self.flange_slope = row[8]
+ self.root_radius = round(row[9], 2)
+ self.toe_radius = round(row[10], 2)
+ self.centre_of_greavity = round(row[11], 2)
+ self.mom_inertia_z = round(row[12] * 10000, 2)
+ self.mom_inertia_y = round(row[13] * 10000, 2)
+ self.rad_of_gy_z = round(row[14] * 10, 2)
+ self.rad_of_gy_y = round(row[15] * 10, 2)
+ self.elast_sec_mod_z = round(row[16] * 1000, 2)
+ self.elast_sec_mod_y = round(row[17] * 1000, 2)
+ self.plast_sec_mod_z = round(row[18], 2)
+ from .Section_Properties_Calculator import I_sectional_Properties
+ if self.plast_sec_mod_z is None: # Todo: add in database
+ self.plast_sec_mod_z = round(I_sectional_Properties().calc_PlasticModulusZpz(self.depth, self.flange_width,
+ self.web_thickness,
+ self.flange_thickness) * 1000,
+ 2)
+ else:
+ self.plast_sec_mod_z = round(row[18] * 1000, 2)
+
+ self.plast_sec_mod_y = round(row[19] * 1000, 2)
+ if self.plast_sec_mod_y is None: # Todo: add in database
+ self.plast_sec_mod_y = round(I_sectional_Properties().calc_PlasticModulusZpy(self.depth, self.flange_width,
+ self.web_thickness,
+ self.flange_thickness) * 1000,
+ 2)
+ else:
+ self.plast_sec_mod_y = round(row[19] * 1000, 2)
+
+ self.It = round(I_sectional_Properties().calc_TorsionConstantIt(self.depth, self.flange_width,
+ self.web_thickness,
+ self.flange_thickness) * 10 ** 4, 2) \
+ if row[19] is None else round(row[20] * 10 ** 4, 2)
+ self.Iw = I_sectional_Properties().calc_WarpingConstantIw(self.depth, self.flange_width,
+ self.web_thickness, self.flange_thickness) * 10 ** 6 \
+ if row[20] is None else round(row[21] * 10 ** 6, 2)
+ self.source = row[22]
+ self.type = 'Rolled' if row[23] is None else row[23]
+
+ conn.close()
+
def tension_member_yielding(self, A_g, F_y):
"design strength of members under axial tension,T_dg,as governed by yielding of gross section"
"A_g = gross area of cross-section"
diff --git a/src/osdag/utils/common/load.py b/src/osdag/utils/common/load.py
index cbea3f876..537d46253 100644
--- a/src/osdag/utils/common/load.py
+++ b/src/osdag/utils/common/load.py
@@ -1,6 +1,15 @@
class Load(object):
- def __init__(self, axial_force=0.0, shear_force=0.0, moment=0.0, moment_minor=0.0, unit_kNm=False):
+ def __init__(self,
+ axial_force=0.0,
+ shear_force=0.0,
+ shear_force_zz=0.0,
+ shear_force_yy=0.0,
+ moment=0.0,
+ moment_zz=0.0,
+ moment_yy=0.0,
+ moment_minor=0.0,
+ unit_kNm=False):
force_multiplier = 1.0
moment_multiplier = 1.0
@@ -12,16 +21,44 @@ def __init__(self, axial_force=0.0, shear_force=0.0, moment=0.0, moment_minor=0.
self.axial_force = force_multiplier * float(axial_force)
else:
self.axial_force = 0.0
+
+ '''
+ Shear force
+ '''
if shear_force is not "":
self.shear_force = force_multiplier * float(shear_force)
else:
self.shear_force = 0.0
+ if shear_force_zz is not "":
+ self.shear_force_zz = force_multiplier * float(shear_force_zz)
+ else:
+ self.shear_force_zz = 0.0
+ if shear_force_yy is not "":
+ self.shear_force_yy = force_multiplier * float(shear_force_yy)
+ else:
+ self.shear_force_yy = 0.0
+
+ '''
+ Moment force
+ '''
if moment is not "":
self.moment = moment_multiplier * float(moment)
self.moment_minor = moment_multiplier * float(moment_minor)
else:
self.moment = 0.0
self.moment_minor = 0.0
+ if moment_yy is not "":
+ self.moment_yy = moment_multiplier * float(moment_yy)
+ self.moment_minor = moment_multiplier * float(moment_minor)
+ else:
+ self.moment_yy = 0.0
+ self.moment_minor = 0.0
+ if moment_zz is not "":
+ self.moment_zz = moment_multiplier * float(moment_zz)
+ self.moment_minor = moment_multiplier * float(moment_minor)
+ else:
+ self.moment_zz = 0.0
+ self.moment_minor = 0.0
print("setting factored input loads as, axial force = {0} N, shear force = {1} N, moment = {2} Nmm".format(
self.axial_force, self.shear_force, self.moment))
diff --git a/src/profile_output b/src/profile_output
new file mode 100644
index 000000000..55348d4a3
Binary files /dev/null and b/src/profile_output differ