Back to SDS/2 Parametric Scripts

 

## ColumnFraming.py Version 1.02 (1/30/07)

## Copyright (c) 2007 Bruce Vaughan, BV Detailing & Design, Inc.

## All rights reserved.

## NOT FOR SALE. The software is provided "as is" without any warranty.

##

## Version 1.01 - Added method frmg_face() (same as beam_face())

##                frmg_face is a more appropriate term

##                beam_face is maintained for compatibility

## Version 1.02 - Test for 'None' in ColumnCondition() and methods

##                Set instance attributes to None

##############################################################################

from macrolib.L3D import DistancePointLine3D

from point import Point

from member import Member, MemberAllocated

from math import atan, tan, cos, sin

from macrolib.angle import rtod, dtor

##

## Determine supporting column member objects or set attributes 'left_member' and 'right_member' to string "None"

##

class ColumnSupport:

    def __init__(self, mem1, prox = 0.06):        # mem1 is a beam member object - look for supporting columns

        mem_index = 1

        self.left_member  = "None"

        self.right_member = "None"

       

        while mem_index < MemberAllocated() and (self.right_member == "None" or self.left_member == "None"):

            try:

                mem2 = Member(mem_index)

            except:

                mem_index = mem_index + 1

            else:

                if mem2.type == "Column":

                    a = DistancePointLine3D(mem2.left.location, mem2.right.location, mem1.left.location)

                    b = DistancePointLine3D(mem2.left.location, mem2.right.location, mem1.right.location)

                   

                    if self.left_member == "None":

                        if a.on_segment == 1 and a.dist < prox:

                            self.left_member = mem2

                           

                    if self.right_member == "None":

                        if b.on_segment == 1 and b.dist < prox:

                            self.right_member = mem2

                           

                mem_index = mem_index + 1

## End class definition

#####################################################################

## Class definition to determine member framing conditions

class ColumnCondition:

    def __init__(self, memA, memB, prox = 0.06):

        self.mem1 = memA # Column member object

        self.mem2 = memB # Beam member object

        self.prox = prox # Member WPs must be within this distance to find the member

        if memA != 'None':

            a = DistancePointLine3D(memA.left.location, memA.right.location, memB.left.location)

            b = DistancePointLine3D(memA.left.location, memA.right.location, memB.right.location)

            self.a = a

            self.b = b

            self.pt_loc = self.mem1.trans_to_local(self.bm_pt() - self.mem1.left.location)

        else:

            self.a = None

            self.b = None

            self.pt_loc = None

            self.frm_face = 'None'

            self.bm_WP = None

            self.relrotation = None

       

    def beam_side(self):

        # determine which end of the beam frames into the column

        if self.a.on_segment == 1 and self.a.dist <= self.prox:

            side = "Left"

            self.bm_WP = self.mem2.left.location

        elif self.b.on_segment == 1 and self.b.dist <= self.prox:

            side = "Right"

            self.bm_WP = self.mem2.right.location

        else:

            side = "None"

            self.bm_WP = None

        return side

   

    def bm_pt(self):

        if self.beam_side() == "Left":

            return self.mem2.left.location

        elif self.beam_side() == "Right":

            return self.mem2.right.location

        else:

            return None       

   

    def beam_angle(self):

        bm_end = self.beam_side()

        # round off net rotation to 4 decimal places

        nr = round((self.mem2.plan_rotation - self.mem1.rotation), 4)

        if bm_end == "Right":

            r = nr + 180.0000

        elif bm_end == "Left":

            r = nr

        else:

            r = "None"

        if r < 0.0000 and r <> "None":

            r = r + 360.0000

        self.relrotation = r

        return r

   

    def beam_face(self):

        if self.pt_loc == None:

            return 'None'

        else:

            # calculate angle from beam WP location to each corner of column

            # sfl 'shape face limit' from beam WP

            # pt = column member coordinate of beam WP

            pt = self.pt_loc

            # print "%0.4f, %0.4f, %0.4f" % (pt.x, pt.y, pt.z)

            sfla = rtod(atan((self.mem1.bf/2+pt.z) / (self.mem1.depth/2+pt.y)))

            sflb = 180.0 + rtod(atan((self.mem1.bf/2+pt.z) / (-self.mem1.depth/2+pt.y)))

            sflc = 180.0 + rtod(atan((-self.mem1.bf/2+pt.z) / (-self.mem1.depth/2+pt.y)))

            sfld = 360.0 + rtod(atan((-self.mem1.bf/2+pt.z) / (self.mem1.depth/2+pt.y)))

            # print "sfla = %0.4f\nsflb = %0.4f\nsflc = %0.4f\nsfld = %0.4f" % (sfla, sflb, sflc, sfld)

            r = self.beam_angle()

            if r >= 0.0 and r <= sfla:

                f = "Face C"

            elif r > sfla and r <= sflb:

                f = "Face D"

            elif r > sflb and r <= sflc:

                f = "Face A"

            elif r > sflc and r <= sfld:

                f = "Face B"

            elif r > sfld and r <= 360.0:

                f = "Face C"

            else:

                f = "None"

            self.frm_face = f

            return f

 

    # frmg_face is the same as beam_face

    def frmg_face(self):

        if self.pt_loc == None:

            return 'None'

        else:

            # calculate angle from beam WP location to each corner of column

            # sfl 'shape face limit' from beam WP

            # pt = column member coordinate of beam WP

            pt = self.pt_loc

            # print "%0.4f, %0.4f, %0.4f" % (pt.x, pt.y, pt.z)

            sfla = rtod(atan((self.mem1.bf/2+pt.z) / (self.mem1.depth/2+pt.y)))

            sflb = 180.0 + rtod(atan((self.mem1.bf/2+pt.z) / (-self.mem1.depth/2+pt.y)))

            sflc = 180.0 + rtod(atan((-self.mem1.bf/2+pt.z) / (-self.mem1.depth/2+pt.y)))

            sfld = 360.0 + rtod(atan((-self.mem1.bf/2+pt.z) / (self.mem1.depth/2+pt.y)))

            # print "sfla = %0.4f\nsflb = %0.4f\nsflc = %0.4f\nsfld = %0.4f" % (sfla, sflb, sflc, sfld)

            r = self.beam_angle()

            if r >= 0.0 and r <= sfla:

                f = "Face C"

            elif r > sfla and r <= sflb:

                f = "Face D"

            elif r > sflb and r <= sflc:

                f = "Face A"

            elif r > sflc and r <= sfld:

                f = "Face B"

            elif r > sfld and r <= 360.0:

                f = "Face C"

            else:

                f = "None"

            self.frm_face = f

            return f 

## End class definition

 

#####################################################################

## Class definition to determine tab location and orientation

class TabData:

    def __init__ (self, col_face, col_depth, relrotation, tab_thk, col_mem, bm_mem, tab_offset = 0.0):

        self.f = col_face

        self.d = col_depth

        self.r = relrotation

        self.t = tab_thk + tab_offset*2.0

        self.t_off = tab_offset

        self.col = col_mem

        self.bm = bm_mem

        self.off = tab_offset # offset from CL of tab material to beam member CL

        self.a = ColumnCondition(col_mem, bm_mem, col_mem.depth/2.0)

        self.end = a.beam_side()

 

 

    def touch_ptx(self):        # relative to column CL

        r_rad = dtor(self.r)    # net roation in radians

       

        if self.f == "Face A":

            self.x = self.d/2

           

        elif self.f == "Face C":

            self.x = -self.d/2

           

        elif self.f == "Face D":

            if self.r > 0.0 and self.r <= 90.0: # thickness ref is NS

                if self.r == 90.0:

                    self.x = -self.t/2 + self.a.pt_loc.y

                else:

                    self.x = -(self.d/2 + self.a.pt_loc.z)/tan(r_rad) - (self.t/2)/sin(r_rad) + self.a.pt_loc.y

            else: # relative rotation exceeds 90.0, thickness ref is FS

                self.x = -(self.d/2 + self.a.pt_loc.z)/tan(r_rad) + (self.t/2)/sin(r_rad) + self.a.pt_loc.y

               

        elif self.f == "Face B":

            if self.r > 180.0 and self.r <= 270.0: # thickness ref is NS

                if self.r == 270.0:

                    self.x = -self.t/2 + self.a.pt_loc.y

                else:

                    self.x = (self.d/2 - self.a.pt_loc.z)/tan(r_rad) - (self.t/2)/sin(r_rad) + self.a.pt_loc.y

            else: # relative rotation exceeds 270.0, thickness ref is FS

                self.x = (self.d/2 - self.a.pt_loc.z)/tan(r_rad) + (self.t/2)/sin(r_rad) + self.a.pt_loc.y

 

        else:

            self.x = None

        return self.x

 

   

    def touch_pty(self):

        r_rad = dtor(self.r)

       

        if self.f == "Face B":

            self.y = self.d/2

           

        elif self.f == "Face D":

            self.y = -self.d/2

           

        elif self.f == "Face A":

            if self.r > 90.0 and self.r <= 180.0: # thickness ref is NS

                self.y = (self.d/2 - self.a.pt_loc.y)*tan(r_rad) + (self.t/2)/cos(r_rad) + self.a.pt_loc.z

            else: # relative rotation exceeds 180.0, thickness ref is FS

                self.y = (self.d/2 - self.a.pt_loc.y)*tan(r_rad) - (self.t/2)/cos(r_rad) + self.a.pt_loc.z

               

        elif self.f == "Face C":

            if self.r > 270.0 and self.r <= 360.0: # thickness ref is NS

                self.y = (-self.d/2 - self.a.pt_loc.y)*tan(r_rad) + (self.t/2)/cos(r_rad) + self.a.pt_loc.z

            else: # relative rotation exceeds 0.0, thickness ref is FS

                self.y = (-self.d/2 - self.a.pt_loc.y)*tan(r_rad) - (self.t/2)/cos(r_rad) + self.a.pt_loc.z

               

        else:

            self.y = None

        return self.y

 

 

    def plate_rot(self):            # calculate rotation of plate to pass to material add function

       

        if self.f == "Face A":

            if self.r > 90.0 and self.r <= 180.0:

                self.rot = (self.r, 0.0, 0.0)

            else:

                self.rot = (-self.r, 180.0, 0.0)

 

        if self.f == "Face B":

            if self.r > 180.0 and self.r <= 270.0:

                self.rot = (self.r, 0.0, 0.0)

            else:

                self.rot = (-self.r, 180.0, 0.0)

 

        if self.f == "Face C":

            if self.r > 270.0 and self.r < 360.0:

                self.rot = (self.r, 0.0, 0.0)

            else:

                self.rot = (-self.r, 180.0, 0.0)

 

        if self.f == "Face D":

            if self.r > 0.0 and self.r <= 90.0:

                self.rot = (self.r, 0.0, 0.0)

            else:

                self.rot = (-self.r, 180.0, 0.0)

 

        return self.rot

## End class definition

 

#####################################################################

## Test ColFraming

def test_ColumnSupport():

    from member import Member, MemberLocate

    from param import yes_or_no, Warning, ClearSelection, dim_print

    # Test mem_splice_object()

    while 1:

        ClearSelection()

        mem1 = MemberLocate("Select a BEAM, VB, or HB MEMBER")

        a = ColumnSupport(mem1, 6.0)

       

        for i in dir(a):

            try:

                _value_ = eval('a.' + i)

            except:

                'a.' + i, "is not a valid attribute or method for this member type."

            else:

                print 'a.' + i, "=", _value_

           

        if a.left_member != "None":

            c = ColumnCondition(a.left_member, mem1)

            Warning("A left end %s member object was found.\nMember # = %s\nMember piecemark = %s\nSection size = %s\n\n" % \

                    (a.left_member.type, a.left_member.number, a.left_member.piecemark, a.left_member.section_size))

            print "\n\nA left end %s member object was found.\nMember # = %s\nMember piecemark = %s\nSection size = %s" % \

                    (a.left_member.type, a.left_member.number, a.left_member.piecemark, a.left_member.section_size)

            print "The beam frames into the column at %s" % (c.beam_face())

            print "The relative rotation between the beam and column is %0.4f degrees" % (c.beam_angle())

            p2 = c.bm_pt()

            print "The intersecting point is %s, %s, %s\n\n" % (dim_print(p2.x), dim_print(p2.y), dim_print(p2.z))

           

        else:

            Warning("There was no left end member object found.\n\n")

 

        if a.right_member != "None":

            b = ColumnCondition(a.right_member, mem1)

            Warning("A right end %s member object was found.\nMember # = %s\nMember piecemark = %s\nSection size = %s\n\n" % \

                    (a.right_member.type, a.right_member.number, a.right_member.piecemark, a.right_member.section_size))

            print "A right end %s member object was found.\nMember # = %s\nMember piecemark = %s\nSection size = %s" % \

                    (a.right_member.type, a.right_member.number, a.right_member.piecemark, a.right_member.section_size)

            print "The beam frames into the column at %s" % (b.beam_face())

            print "The relative rotation between the beam and column is %0.4f degrees" % (b.beam_angle())

            p1 = b.bm_pt()

            print "The intersecting point is %s, %s, %s" % (dim_print(p1.x), dim_print(p1.y), dim_print(p1.z))

           

        else:

            Warning("There was no right end member object found.")

           

        if not yes_or_no("Again?"):

            break

    ## END test_mem_splice_object() #################################################

if __name__ == '__main__':

    try:

        test_ColumnSupport()

    finally:

        del test_ColumnSupport

        del ColumnSupport

        del ColumnCondition

        del TabData