Quantcast
Channel: Scripting - McNeel Forum
Viewing all articles
Browse latest Browse all 5938

Working script to create metric bolts on the fly as block items (but some feedback needed)

$
0
0

@Gijs wrote:

addBolt.py (10.7 KB)

Attached is a working script that adds metric bolts (hex, flat head, socket allen, M3 - M8). I wrote this mainly as a coding exercise.

Would like to get some feedback from more experienced coders if the way i did this with classes is done properly or not. Suggestions for optimizing the structure of the code highly appreciated…

edit: would like to record last selected bolt options to change the defaults at next run…how?

If you have additional suggestions for improvement of the functionality that would be nice too.

show the code (or download the above .py file)
import rhinoscriptsyntax as rs
from Rhino.ApplicationSettings import *
import Rhino
import math
import scriptcontext as sc

"""
addBolt version 0.1

this script will add a bolt (named block) in Metric size to the rhino document
Bolt must be oriented on a surface and can be aligned with a center point
needed user input : metric size, length, bolt type, (center)point on (poly)surface
to do:
-rewrite Bolt creation in Rhino Common so that redraw can stay on for showing selected center point

script written by Gijs de Zwart
www.studiogijs.nl

"""

class Bolt():
    def __init__(self,msize,length):
        diameter         = { 'M3':3, 'M4':4, 'M5':5, 'M6':6, 'M8':8 }
        pitch            = { 'M3':0.5, 'M4':0.7, 'M5':1, 'M6':1, 'M8':1.25 }
        self.diameter    = diameter[msize]
        self.length      = length
        self.pitch       = pitch[msize]
        self.name        = msize+"x"+str(length)

class hexBolt(Bolt):
    def __init__(self, msize, length):
        Bolt.__init__(self, msize, length)
        head_width       = { 'M3':5.5, 'M4':7, 'M5':8, 'M6':10, 'M8':13 }
        head_height      = { 'M3':2.2, 'M4':3, 'M5':3.2, 'M6':4, 'M8':5.3 }
        self.head_width  = head_width[msize]
        self.head_height = head_height[msize]
        self.name       += "(DIN993)"

class flatBolt(Bolt):
    def __init__(self,msize,length):
        Bolt.__init__(self, msize, length)
        head_width       = { 'M3':6, 'M4':8, 'M5':10, 'M6':12, 'M8':16 }
        head_height      = { 'M3':1.7, 'M4':2.3, 'M5':2.8, 'M6':3.3, 'M8':4.4 }
        hex_socket       = { 'M3':2, 'M4':2.5, 'M5':3, 'M6':4, 'M8':5 }
        self.head_width  = head_width[msize]
        self.head_height = head_height[msize]
        self.head_dheight= self.head_height-(self.head_width-self.diameter)/2
        self.hex_socket  = hex_socket[msize]
        self.name       += "(DIN7991)"
class DIN912Bolt(Bolt):
    def __init__(self,msize,length):
        Bolt.__init__(self, msize, length)
        head_width       = { 'M3':5.5, 'M4':7, 'M5':8.5, 'M6':10, 'M8':13 }
        head_height      = { 'M3':3, 'M4':4, 'M5':5, 'M6':6, 'M8':8 }
        hex_socket       = { 'M3':2.5, 'M4':3, 'M5':4, 'M6':5, 'M8':6 }
        hex_socket_depth = { 'M3':1.3, 'M4':2, 'M5':2.5, 'M6':3, 'M8':3.5 }
        self.head_width  = head_width[msize]
        self.head_height = head_height[msize]
        self.hex_socket  = hex_socket[msize]
        self.hex_socket_depth = hex_socket_depth[msize]
        self.name       += "(DIN912)"

def cen():
    #this function turns off all Osnaps except center Osnap
    cen = Rhino.ApplicationSettings.OsnapModes.Center
    Rhino.ApplicationSettings.ModelAidSettings.Osnap = True
    Rhino.ApplicationSettings.ModelAidSettings.OsnapModes = cen

def CreateBolt():
    #this function asks the user to choose a metric size, length and bolt type,
    #then creates the geometry for the bolt
    # ****************************************
    # ************   USER OPTIONS   **********
    # ****************************************
    #get metric size
    go1 = Rhino.Input.Custom.GetOption()
    go1.SetCommandPrompt("Select bolt size")
    msizes = ['M3','M4','M5','M6','M8']
    go1.AddOptionList("Metric_size", msizes, 0)
    size = None
    if go1.Get() == Rhino.Input.GetResult.Option:
        size = msizes[go1.Option().CurrentListOptionIndex]
    if size == None:
        size = 'M3'
    #get length for the bolt
    go2 = Rhino.Input.Custom.GetOption()
    go2.SetCommandPrompt("Select bolt length")
    lengths=['12mm','16mm','20mm','25mm','30mm','40mm','50mm','60mm','70mm','80mm']
    go2.AddOptionList("Bolt_Length", lengths, 0)
    length=None
    if go2.Get() == Rhino.Input.GetResult.Option:
        length = lengths[go2.Option().CurrentListOptionIndex]
    if length == None:
        length = '12mm'
    #convert length for further use
    length = int(length[:-2])
    #get type of bolt
    go3=Rhino.Input.Custom.GetOption()
    go3.SetCommandPrompt("Select headstyle")
    headstyles=['hex_head','flat_head','socket_allen']
    go3.AddOptionList("Bolt_Type", headstyles, 0)
    headstyle=None
    if go3.Get() == Rhino.Input.GetResult.Option:
        headstyle = headstyles[go3.Option().CurrentListOptionIndex]
    if headstyle == None:
        headstyle = 'hex_head'



    # *************************************************
    # *********** CREATE THE BOLT GEOMETRY ************
    # *************************************************
    #add bolt to the rhino scene
    rs.EnableRedraw(False)

    if headstyle=='hex_head':
        #create a hex bolt object
        bolt      = hexBolt(size, length)
        #creat the head
        radius    = bolt.head_width/2/math.cos(math.pi/6)#calculate radius of circle that circumscribes the hexagon
        hexagon   = rs.AddCircle([0,0,0],radius)
        rs.RebuildCurve(hexagon, 1, 6)
        head      = rs.ExtrudeCurveStraight(hexagon, [0,0,0], [0,0,bolt.head_height])
        rs.CapPlanarHoles(head)
        rs.DeleteObject(hexagon)
        #create threaded part
        thread    = rs.AddCylinder([0,0,0],[0,0,-bolt.length],bolt.diameter/2)
        hexbolt   = rs.BooleanUnion([head, thread])[0]
        rs.ObjectName(hexbolt, bolt.name)
        #add cosmetic thread
        turns=bolt.length/bolt.pitch
        spiral=rs.AddSpiral([0,0,0],[0,0,-bolt.length],
                    bolt.pitch,turns,bolt.diameter/2, bolt.diameter/2)
        rs.ObjectName(spiral, bolt.name)
        #add objects to the scene
        rs.AddGroup(bolt.name)
        rs.AddObjectsToGroup([hexbolt, spiral], bolt.name)
        addBolt(bolt)

    if headstyle=='flat_head':
        #create a flat head bolt object and some helper points
        bolt      = flatBolt(size,length)
        point1    = [0,0,0]
        point2    = [0,0,-bolt.head_height]#position of head end
        point3    = [0,0,-bolt.head_dheight]#position of edge start
        #create the hexagon socket
        radius    = bolt.hex_socket/2/math.cos(math.pi/6)#calculate radius of circle that circumscribes the hexagon
        hexagon   = rs.AddCircle(point2,radius)
        rs.RebuildCurve(hexagon, 1, 6)
        socket    = rs.ExtrudeCurveStraight(hexagon, point2, point1)
        rs.CapPlanarHoles(socket)
        rs.DeleteObject(hexagon)
        #create the head
        circle1   = rs.AddCircle(point2,bolt.diameter/2)
        circle2   = rs.AddCircle(point3,bolt.head_width/2)
        edge      = rs.AddCylinder(point3,point1,bolt.head_width/2)
        head      = rs.AddLoftSrf([circle1, circle2], loft_type=0)
        rs.CapPlanarHoles(head)
        rs.DeleteObjects([circle1, circle2])
        #create threaded part
        thread    = rs.AddCylinder(point2,[0,0,-bolt.length],bolt.diameter/2)
        flatbolt  = rs.BooleanUnion([head, thread, edge])[0]
        flatbolt  = rs.BooleanDifference(flatbolt, socket)
        rs.ObjectName(flatbolt, bolt.name)
        #add cosmetic thread
        turns     = (bolt.length-bolt.head_height)/bolt.pitch
        spiral    = rs.AddSpiral([0,0,-bolt.head_height],[0,0,-bolt.length],
                    bolt.pitch,turns,bolt.diameter/2, bolt.diameter/2)
        rs.ObjectName(spiral, bolt.name)
        rs.AddGroup(bolt.name)
        rs.AddObjectsToGroup([flatbolt, spiral], bolt.name)
        #add objects to the scene
        addBolt(bolt)

    if headstyle=='socket_allen':
        #create a flat head bolt object and some helper points
        bolt      = DIN912Bolt(size,length)
        point1    = [0,0,0]
        point2    = [0,0,bolt.head_height]#position of head end
        point3    = [0,0,(bolt.head_height-bolt.hex_socket_depth)]
        #create the hexagon socket
        radius    = bolt.hex_socket/2/math.cos(math.pi/6)#calculate radius of circle that circumscribes the hexagon
        hexagon   = rs.AddCircle(point2,radius)
        rs.RebuildCurve(hexagon, 1, 6)
        socket    = rs.ExtrudeCurveStraight(hexagon, point3, point1)
        rs.CapPlanarHoles(socket)
        rs.DeleteObject(hexagon)
        #create the head
        head      = rs.AddCylinder(point1,point2,bolt.head_width/2,True)
        #create threaded part
        thread    = rs.AddCylinder(point2,[0,0,-bolt.length],bolt.diameter/2)
        din912bolt  = rs.BooleanUnion([head, thread])[0]
        din912bolt  = rs.BooleanDifference(din912bolt, socket)
        rs.ObjectName(din912bolt, bolt.name)
        #add cosmetic thread
        turns     = bolt.length/bolt.pitch
        spiral    = rs.AddSpiral(point1,[0,0,-bolt.length],
                    bolt.pitch,turns,bolt.diameter/2, bolt.diameter/2)
        rs.ObjectName(spiral, bolt.name)
        #add objects to the scene
        rs.AddGroup(bolt.name)
        rs.AddObjectsToGroup([din912bolt, spiral], bolt.name)
        addBolt(bolt)
    rs.EnableRedraw(True)

def addBolt(bolt):
    # this function ask the user to select a point on a surface to insert the bolt on
    # Surface to orient on
    gs = Rhino.Input.Custom.GetObject()
    gs.SetCommandPrompt("Surface to orient on")
    gs.GeometryFilter = Rhino.DocObjects.ObjectType.Surface
    gs.SubObjectSelect = True
    gs.DeselectAllBeforePostSelect = False
    gs.OneByOnePostSelect = True
    gs.Get()
    if gs.CommandResult()!=Rhino.Commands.Result.Success:
        objs=rs.ObjectsByGroup(bolt.name)
        rs.DeleteObjects(objs)
        return gs.CommandResult()

    objref = gs.Object(0)
    # get selected surface object
    obj = objref.Object()
    if not obj: return Rhino.Commands.Result.Failure
    # get selected surface (face)
    surface = objref.Surface()
    if not surface: return Rhino.Commands.Result.Failure
    # Unselect surface
    obj.Select(False)

    # Point on surface to orient to / activate center Osnap
    old_osnap_state = ModelAidSettings.OsnapModes #record Osnap state to reset later
    cen()

    gp=Rhino.Input.Custom.GetPoint()
    gp.SetCommandPrompt("Point on surface to orient to")
    gp.Constrain(surface, False)
    gp.Get()
    if gp.CommandResult()!=Rhino.Commands.Result.Success:
        ModelAidSettings.OsnapModes = old_osnap_state #reset to previous Osnap state
        return gp.CommandResult()

    rc = Rhino.Commands.Result.Failure
    getrc, u, v = surface.ClosestPoint(gp.Point())
    if getrc:
        getrc, target_plane = surface.FrameAt(u,v)
        if getrc:
            # Build transformation
            source_plane = Rhino.Geometry.Plane.WorldXY
            xform = Rhino.Geometry.Transform.PlaneToPlane(source_plane, target_plane)
            # Do the transformation
            objs=rs.ObjectsByGroup(bolt.name)
            rs.AddBlock(objs,[0,0,0],bolt.name, True)
            newbolt = rs.InsertBlock2(bolt.name, xform)
            rs.ObjectName(newbolt, bolt.name)
            ModelAidSettings.OsnapModes = old_osnap_state #reset to previous Osnap state
            rc = Rhino.Commands.Result.Success
    
    return rc

CreateBolt()

Posts: 3

Participants: 2

Read full topic


Viewing all articles
Browse latest Browse all 5938

Trending Articles