# ----------------------------------------------------------------------------
# -- Components
# -- comps library
# -- Python classes that creates useful parts for FreeCAD
# ----------------------------------------------------------------------------
# -- (c) Felipe Machado
# -- Area of Electronics. Rey Juan Carlos University (urjc.es)
# -- October-2016
# ----------------------------------------------------------------------------
# --- LGPL Licence
# ----------------------------------------------------------------------------
import FreeCAD
import Part
import logging
import os
import inspect
import Draft
import DraftGeomUtils
import DraftVecUtils
import math
#import copy;
#import Mesh;
# ---------------------- can be taken away after debugging
# directory this file is
filepath = os.getcwd()
import sys
# to get the components
# In FreeCAD can be added: Preferences->General->Macro->Macro path
sys.path.append(filepath)
# ---------------------- can be taken away after debugging
import kcomp # before, it was called mat_cte
import fcfun
import shp_clss
import fc_clss
from fcfun import V0, VX, VY, VZ, V0ROT, addBox, addCyl, addCyl_pos, fillet_len
from fcfun import VXN, VYN, VZN
from fcfun import addBolt, addBoltNut_hole, NutHole
logging.basicConfig(level=logging.DEBUG,
format='%(%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
#
# _______ _______________________________ TotH = H
# | ___ |
# | / \ | __________ HoleH = h
# | \___/ | __
# __| |__ /| __
# |_____________|/ __ TotD = L ___________________
#
# <- TotW = W->
#
# hole_x: 1 the depth along X axis
# Hole facing X
# 0 the depth along Y axis
# Hole facing Y
# cx: 1 if you want the coordinates referenced to the x center of the piece
# it can be done because it is a new shape formed from the union
# cy: 1 if you want the coordinates referenced to the y center of the piece
# upsdown: NOT YET
# 0: Normal vertical position, referenced to 0
# 1: z0 is the center of the hexagon (nut)
# it can be done because it is a new shape formed from the union
class Sk (object):
"""
SK dimensions:
dictionary for the dimensions
mbolt: is mounting bolt. it corresponds to its metric
tbolt: is the tightening bolt.
SK12 = { 'd':12.0, 'H':37.5, 'W':42.0, 'L':14.0, 'B':32.0, 'S':5.5,
'h':23.0, 'A':21.0, 'b': 5.0, 'g':6.0, 'I':20.0,
'mbolt': 5, 'tbolt': 4}
"""
# separation of the upper side (it is not defined). Change it
# measured for sk12 is 1.2
up_sep_dist = 1.2
# tolerances for holes
holtol = 1.1
def __init__(self, size, name, hole_x = 1, cx=0, cy=0):
self.size = size
self.name = name
self.cx = cx
self.cy = cy
skdict = kcomp.SK.get(size)
if skdict == None:
logger.warning("Sk size %d not supported", size)
else:
doc = FreeCAD.ActiveDocument
# Total height:
sk_z = skdict['H'];
self.TotH = sk_z
# Total width (Y):
sk_w = skdict['W'];
self.TotW = sk_w
# Total depth (x):
sk_d = skdict['L'];
self.TotD = sk_d
# Base height
sk_base_h = skdict['g'];
# center width
sk_center_w = skdict['I'];
# Axis height:
sk_axis_h = skdict['h'];
self.HoleH = sk_axis_h;
# tightening bolt with added tolerances:
# Bolt's head radius
tbolt_head_r = (self.holtol
* kcomp.D912_HEAD_D[skdict['tbolt']])/2.0
# Bolt's head lenght
tbolt_head_l = (self.holtol
* kcomp.D912_HEAD_L[skdict['tbolt']] )
# Mounting bolt radius with added tolerance
mbolt_r = self.holtol * skdict['mbolt']/2.
# the total dimensions: LxWxH
# we will cut it
total_box = addBox(x = sk_d,
y = sk_w,
z = sk_z,
name = "total_box",
cx = False, cy=True)
# what we have to cut from the sides
side_box_y = (sk_w - skdict['I'])/2.
side_box_z = sk_z - skdict['g']
side_cut_box_r = addBox (sk_d, side_box_y, side_box_z,
"side_box_r")
side_cut_pos_r = FreeCAD.Vector(0,
skdict['I']/2.,
skdict['g'])
side_cut_box_r.Placement.Base = side_cut_pos_r
side_cut_box_l= addBox (sk_d, side_box_y, side_box_z,
"side_box_l")
side_cut_pos_l = FreeCAD.Vector(0,-sk_w/2.,skdict['g'])
side_cut_box_l.Placement.Base = side_cut_pos_l
# union
side_boxes = doc.addObject("Part::Fuse", "side_boxes")
side_boxes.Base = side_cut_box_r
side_boxes.Tool = side_cut_box_l
# difference
sk_shape = doc.addObject("Part::Cut", "sk_shape")
sk_shape.Base = total_box
sk_shape.Tool = side_boxes
# Shaft hole, its height has +2 to make it throughl L all de way
shaft_hole = addCyl(skdict['d']/2.,
sk_d+2,
"shaft_hole")
"""
First argument defines de position: -1, 0, h
Second argument rotation: 90 degrees rotation in Y.
Third argument the center of the rotation, in this case,
it is in the cylinder
axis at the base of the cylinder
"""
shaft_hole.Placement = FreeCAD.Placement(
FreeCAD.Vector(-1,0,skdict['h']),
FreeCAD.Rotation(VY,90),
V0)
# the upper sepparation
up_sep = addBox( sk_d +2,
self.up_sep_dist,
sk_z-skdict['h'] +1,
"up_sep")
up_sep_pos = FreeCAD.Vector(-1,
-self.up_sep_dist/2,
skdict['h']+1)
up_sep.Placement.Base = up_sep_pos
#Tightening bolt shaft hole, its height has +2 to make it
#throughl L all de way
#skdict['tbolt'] is the diameter of the bolt: (M..) M4, ...
#tbolt_head_r: is the radius of the tightening bolt's head
#(including tolerance), which its bottom either
#- is at the middle point between
# - A: the total height :sk_z
# - B: the top of the shaft hole: skdict['h']+skdict['d']/2
# - so the result will be (A + B)/2
#or it is aligned with the top of the 12mm shaft, whose height is:
# skdict['h']+skdict['d']/2
tbolt_shaft = addCyl(skdict['tbolt']/2,skdict['I']+2,
"tbolt_shaft")
tbolt_shaft_pos = FreeCAD.Vector(sk_d/2.,
skdict['I']/2.+1,
skdict['h']+skdict['d']/2.+tbolt_head_r/self.holtol)
#(sk_z + skdict['h']+skdict['d']/2.)/2.)
tbolt_shaft.Placement = FreeCAD.Placement(tbolt_shaft_pos,
FreeCAD.Rotation(VX,90),
V0)
# Head of the thigthening bolt
tbolt_head = addCyl(tbolt_head_r,tbolt_head_l+1, "tbolt_head")
tbolt_head_pos = FreeCAD.Vector(sk_d/2.,
skdict['I']/2.+1,
skdict['h']+skdict['d']/2+tbolt_head_r/self.holtol)
#(sk_z + skdict['h']+skdict['d']/2.)/2.)
tbolt_head.Placement = FreeCAD.Placement(tbolt_head_pos,
FreeCAD.Rotation(VX,90),
V0)
#Make an union of all these parts
fuse_shaft_holes = doc.addObject("Part::MultiFuse",
"fuse_shaft_holes")
fuse_shaft_holes.Shapes = [tbolt_head,
tbolt_shaft,
up_sep, shaft_hole]
#Cut from the sk_shape
sk_shape_w_holes = doc.addObject("Part::Cut", "sk_shape_w_holes")
sk_shape_w_holes.Base = sk_shape
sk_shape_w_holes.Tool = fuse_shaft_holes
#Mounting bolts
mbolt_sh_r = addCyl(mbolt_r,skdict['g']+2., "mbolt_sh_r")
mbolt_sh_l = addCyl(mbolt_r,skdict['g']+2., "mbolt_sh_l")
mbolt_sh_r_pos = FreeCAD.Vector(sk_d/2,
skdict['B']/2.,
-1)
mbolt_sh_l_pos = FreeCAD.Vector(sk_d/2,
-skdict['B']/2.,
-1)
mbolt_sh_r.Placement.Base = mbolt_sh_r_pos
mbolt_sh_l.Placement.Base = mbolt_sh_l_pos
# Equivalent expresions to the ones above
#mbolt_sh_l.Placement = FreeCAD.Placement(mbolt_sh_l_pos, v0rot, v0)
#mbolt_sh_r.Placement = FreeCAD.Placement(mbolt_sh_r_pos, v0rot, v0)
mbolts_sh = doc.addObject("Part::Fuse", "mbolts_sh")
mbolts_sh.Base = mbolt_sh_r
mbolts_sh.Tool = mbolt_sh_l
# Instead of moving all the objects from the begining. I do it here
# so it is easier, and since a new object will be created, it is
# referenced correctly
# Now, it is centered on Y, having the width on X, hole facing X
# on the positive side of X
if hole_x == 1:
# this is how it is, no rotation
rot = FreeCAD.Rotation(VZ,0)
if cx == 1: #we want centered on X,bring back the half of depth
xpos = -self.TotD/2.
else:
xpos = 0 # how it is
if cy == 1: # centered on Y, how it is
ypos = 0
else:
ypos = self.TotW/2.0 # bring forward the width
else: # hole facing Y
rot = FreeCAD.Rotation (VZ,90)
# After rotating, it is centered on X,
if cx == 1: # centered on X, how it is
xpos = 0
else:
xpos = self.TotW /2.0
if cy == 1: # we want centered on Y, bring back
ypos = - self.TotD/2.0
else:
ypos = 0
sk_shape_w_holes.Placement.Base = FreeCAD.Vector (xpos, ypos, 0)
mbolts_sh.Placement.Base = FreeCAD.Vector (xpos, ypos, 0)
sk_shape_w_holes.Placement.Rotation = rot
mbolts_sh.Placement.Rotation = rot
sk_final = doc.addObject("Part::Cut", name)
sk_final.Base = sk_shape_w_holes
sk_final.Tool = mbolts_sh
self.fco = sk_final # the FreeCad Object
[docs]class Sk_dir (object):
# Similar to Sk, but in any direction
"""
SK dimensions:
dictionary for the dimensions
::
mbolt: is mounting bolt. it corresponds to its metric
tbolt: is the tightening bolt.
SK12 = { 'd':12.0, 'H':37.5, 'W':42.0, 'L':14.0, 'B':32.0, 'S':5.5,
'h':23.0, 'A':21.0, 'b': 5.0, 'g':6.0, 'I':20.0,
'mbolt': 5, 'tbolt': 4}
::
fc_axis_h
:
___:___ _______________________________ tot_h
| ___ |
| / \ | __________ HoleH = h
| \___/ | __
__| |__ /| __
|_____________|/ __ TotD = L ___________________
___:___ ___
| ___ | |...|
| / 2 \ | 3 1 |.....> fc_axis_d
| \_*_/ | |...|
____| |____ |___|
8_:5_____4_____::_|..fc_axis_w 6_7_|....... fc_axis_d
: : : :
:... tot_w .......: :...:
tot_d
Parameters
----------
fc_axis_h : FreeCAD.Vector
Axis on the height direction
fc_axis_d : FreeCAD.Vector
Axis on the depth (rod) direction
fc_axis_w : FreeCAD.Vector
Width (perpendicular) dimension, only useful if I finally
include the tightening bolt, or if ref_wc != 1
ref_hr : int
* 1: reference at the Rod Height dimension (rod center):
points 1, 2, 3
* 0: reference at the base: points 4, 5
ref_wc : int
* 1: reference at the center on the width dimension (fc_axis_w)
points: 2, 4,
* 0: reference at one of the bolt holes, point 5
* -1: reference at one end. point 8
ref_dc : int
* 1: reference at the center of the depth dimension
(fc_axis_d) points: 1,7
* 0: reference at one of the ends on the depth dimension
points 3, 6
pillow : int
* 1 to make it the same height of a pillow block
pos : FreeCAD.Vector
Placement
wfco : int
* 1 to create a FreeCAD Object
tol : float
Tolerance of the axis
name : str
FreeCAD Object name
Returns
-------
FreeCAD Object
FreeCAD Object of a shaft holder
"""
# separation of the upper side (it is not defined). Change it
# measured for sk12 is 1.2
up_sep_dist = 1.2
# tolerances for holes
holtol = 1.1
def __init__(self, size,
fc_axis_h = VZ,
fc_axis_d = VX,
fc_axis_w = V0,
ref_hr = 1,
ref_wc = 1,
ref_dc = 1,
pillow = 0, #make it the same height of a pillow block
pos = V0,
wfco = 1,
tol = 0.3,
name= "shaft_holder"):
self.size = size
self.wfco = wfco
self.name = name
self.pos = pos
self.tol = tol
self.ref_hr = ref_hr
self.ref_wc = ref_wc
self.ref_dc = ref_dc
doc = FreeCAD.ActiveDocument
if pillow == 0:
skdict = kcomp.SK.get(size)
else:
skdict = kcomp.PILLOW_SK.get(size)
if skdict == None:
logger.error("Sk size %d not supported", size)
# normalize de axis
axis_h = DraftVecUtils.scaleTo(fc_axis_h,1)
axis_d = DraftVecUtils.scaleTo(fc_axis_d,1)
if fc_axis_w == V0:
axis_w = axis_h.cross(axis_d)
else:
axis_w = DraftVecUtils.scaleTo(fc_axis_w,1)
axis_h_n = axis_h.negative()
axis_d_n = axis_d.negative()
axis_w_n = axis_w.negative()
# Total height:
sk_h = skdict['H'];
self.tot_h = sk_h
# Total width (Y):
sk_w = skdict['W'];
self.tot_w = sk_w
# Total depth (x):
sk_d = skdict['L'];
self.tot_d = sk_d
# Base height
sk_base_h = skdict['g'];
# center width
sk_center_w = skdict['I'];
# Axis height:
sk_axis_h = skdict['h'];
self.axis_h = sk_axis_h;
# Mounting bolts separation
sk_mbolt_sep = skdict['B']
# tightening bolt with added tolerances:
tbolt_d = skdict['tbolt']
# Bolt's head radius
tbolt_head_r = (self.holtol
* kcomp.D912_HEAD_D[skdict['tbolt']])/2.0
# Bolt's head lenght
tbolt_head_l = (self.holtol
* kcomp.D912_HEAD_L[skdict['tbolt']] )
# Mounting bolt radius with added tolerance
mbolt_r = self.holtol * skdict['mbolt']/2.
if ref_hr == 1: # distance vectors on axis_h
ref2rod_h = V0
ref2base_h = DraftVecUtils.scale(axis_h, -sk_axis_h)
else:
ref2rod_h = DraftVecUtils.scale(axis_h, sk_axis_h)
ref2base_h = V0
if ref_wc == 1: # distance vectors on axis_w
ref2cen_w = V0
ref2bolt_w = DraftVecUtils.scale(axis_w, -sk_mbolt_sep/2.)
ref2end_w = DraftVecUtils.scale(axis_w, -sk_w/2.)
elif ref_wc == 0:
ref2cen_w = DraftVecUtils.scale(axis_w, sk_mbolt_sep/2.)
ref2bolt_w = V0
ref2end_w = DraftVecUtils.scale(axis_w, -(sk_w-sk_mbolt_sep)/2.)
else: # ref_wc == -1 at the end on the width dimension
ref2cen_w = DraftVecUtils.scale(axis_w, sk_w/2.)
ref2bolt_w = DraftVecUtils.scale(axis_w, (sk_w-sk_mbolt_sep)/2.)
if ref_dc == 1: # distance vectors on axis_d
ref2cen_d = V0
ref2end_d = DraftVecUtils.scale(axis_d, -sk_d/2.)
else:
ref2cen_d = DraftVecUtils.scale(axis_d, sk_d/2.)
ref2end_d = V0
basecen_pos = pos + ref2base_h + ref2cen_w + ref2cen_d
# Making the tall box:
shp_tall = fcfun.shp_box_dir (box_w = sk_center_w,
box_d = sk_d,
box_h = sk_h,
fc_axis_w = axis_w,
fc_axis_h = axis_h,
fc_axis_d = axis_d,
cw = 1, cd= 1, ch=0, pos = basecen_pos)
# Making the wide box:
shp_wide = fcfun.shp_box_dir (box_w = sk_w,
box_d = sk_d,
box_h = sk_base_h,
fc_axis_w = axis_w,
fc_axis_h = axis_h,
fc_axis_d = axis_d,
cw = 1, cd= 1, ch=0, pos = basecen_pos)
shp_sk = shp_tall.fuse(shp_wide)
doc.recompute()
shp_sk = shp_sk.removeSplitter()
holes = []
# Shaft hole,
rodcen_pos = pos + ref2rod_h + ref2cen_w + ref2cen_d
rod_hole = fcfun.shp_cylcenxtr(r= size/2. +self.tol,
h = sk_d,
normal = axis_d,
ch = 1,
xtr_top = 1,
xtr_bot = 1,
pos = rodcen_pos)
holes.append(rod_hole)
# the upper sepparation
shp_topopen = fcfun.shp_box_dir_xtr (
box_w = self.up_sep_dist,
box_d = sk_d,
box_h = sk_h-sk_axis_h,
fc_axis_w = axis_w,
fc_axis_h = axis_h,
fc_axis_d = axis_d,
cw = 1, cd= 1, ch=0,
xtr_h = 1, xtr_d = 1, xtr_nd = 1,
pos = rodcen_pos)
holes.append(shp_topopen)
# Tightening bolt hole
# tbolt_d is the diameter of the bolt: (M..) M4, ...
# tbolt_head_r: is the radius of the tightening bolt's head
# (including tolerance), which its bottom either
#- is at the middle point between
# - A: the total height :sk_h
# - B: the top of the shaft hole: axis_h + size/2.
# - so the result will be (A + B)/2
# tot_h - (axis_h + size/2.)
# _______..A........................
# | ___ |.B.......+ rodtop2top_dist = sk_h - (axis_h + size/2.)
# | / \ |.......+ size/2.
# | \___/ | :
# __| |__ + axis_h
# |_____________|....:
rodtop2top_dist = sk_h - (sk_axis_h + size/2.)
tbolt_pos = ( rodcen_pos
+ DraftVecUtils.scale(axis_w, sk_center_w/2.)
+ DraftVecUtils.scale(axis_h, size/2.)
+ DraftVecUtils.scale(axis_h, rodtop2top_dist/2.))
shp_tbolt = fcfun.shp_bolt_dir(r_shank= tbolt_d/2.,
l_bolt = sk_center_w,
r_head = tbolt_head_r,
l_head = tbolt_head_l,
hex_head = 0,
xtr_head = 1,
xtr_shank = 1,
support = 0,
fc_normal = axis_w_n,
fc_verx1 = axis_h,
pos = tbolt_pos)
holes.append(shp_tbolt)
#Mounting bolts
cen2mbolt_w = DraftVecUtils.scale(axis_w, sk_mbolt_sep/2.)
for w_pos in [cen2mbolt_w.negative(), cen2mbolt_w]:
mbolt_pos = basecen_pos + w_pos
mbolt_hole = fcfun.shp_cylcenxtr(r= mbolt_r,
h = sk_d,
normal = axis_h,
ch = 0,
xtr_top = 1,
xtr_bot = 1,
pos = mbolt_pos)
holes.append(mbolt_hole)
shp_holes = fcfun.fuseshplist(holes)
shp_sk = shp_sk.cut(shp_holes)
self.shp = shp_sk
if wfco == 1:
# a freeCAD object is created
fco = doc.addObject("Part::Feature", name )
fco.Shape = self.shp
self.fco = fco
def color (self, color = (1,1,1)):
if self.wfco == 1:
self.fco.ViewObject.ShapeColor = color
else:
logger.debug("Object with no fco")
#doc =FreeCAD.newDocument()
#h_sk = Sk_dir (size = 8,
# fc_axis_h = VX,
# fc_axis_d = VZ,
# fc_axis_w = V0,
# ref_hr = 0,
# ref_wc = 0,
# ref_dc = 0,
# pillow = 0,
# pos = V0,
# tol = 0.3,
# wfco = 1,
# name= "sk8_tol03")
# --------------------------------------------------------------------
# Creates a Misumi Aluminun Profile 30x30 Series 6 Width 8
# length: the length of the profile
# axis 'x', 'y' or 'z'
# 'x' will along the x axis
# 'y' will along the y axis
# 'z' will be vertical
# cx: 1 if you want the coordinates referenced to the x center of the piece
# it can be done because it is a new shape formed from the union
# cy: 1 if you want the coordinates referenced to the y center of the piece
# cz: 1 if you want the coordinates referenced to the z center of the piece
# ATTRIBUTES:
# fco: The freecad object
# Sk: The sketch of the aluminum profile
class MisumiAlu30s6w8 (object):
# filename of Aluminum profile sketch
skfilename = "misumi_profile_hfs_serie6_w8_30x30.FCStd"
ALU_W = 30.0
ALU_Wh = ALU_W / 2.0 # half of it
def __init__ (self, length, name, axis = 'x',
cx=False, cy=False, cz=False):
doc = FreeCAD.ActiveDocument
self.length = length
self.name = name
self.axis = axis
self.cx = cx
self.cy = cy
self.cz = cz
# filepath
path = os.getcwd()
#logging.debug(path)
self.skpath = path + '/../../freecad/comps/'
doc_sk = FreeCAD.openDocument(self.skpath + self.skfilename)
list_obj_alumprofile = []
for obj in doc_sk.Objects:
#if (hasattr(obj,'ViewObject') and obj.ViewObject.isVisible()
# and hasattr(obj,'Shape') and len(obj.Shape.Faces) > 0 ):
# # len(obj.Shape.Faces) > 0 to avoid sketches
# list_obj_alumprofile.append(obj)
if len(obj.Shape.Faces) == 0:
orig_alumsk = obj
FreeCAD.ActiveDocument = doc
self.Sk = doc.addObject("Sketcher::SketchObject", 'sk_' + name)
self.Sk.Geometry = orig_alumsk.Geometry
print (orig_alumsk.Geometry)
print (orig_alumsk.Constraints)
self.Sk.Constraints = orig_alumsk.Constraints
self.Sk.ViewObject.Visibility = False
FreeCAD.closeDocument(doc_sk.Name)
FreeCAD.ActiveDocument = doc #otherwise, clone will not work
doc.recompute()
# The sketch is on plane XY, facing Z
if axis == 'x':
self.Dir = (length,0,0)
# rotation on Y
rot = FreeCAD.Rotation(VY,90)
if cx == True:
xpos = - self.length / 2.0
else:
xpos = 0
if cy == True:
ypos = 0
else:
ypos = self.ALU_Wh # half of the aluminum profile width
if cz == True:
zpos = 0
else:
zpos = self.ALU_Wh
elif axis == 'y':
self.Dir = (0,length,0)
# rotation on X
rot = FreeCAD.Rotation(VX,-90)
if cx == True:
xpos = 0
else:
xpos = self.ALU_Wh
if cy == True:
ypos = - self.length / 2.0
else:
ypos = 0
if cz == True:
zpos = 0
else:
zpos = self.ALU_Wh
elif axis == 'z':
self.Dir = (0,0,length)
# no rotation
rot = FreeCAD.Rotation(VZ,0)
if cx == True:
xpos = 0
else:
xpos = self.ALU_Wh
if cy == True:
ypos = 0
else:
ypos = self.ALU_Wh
if cz == True:
zpos = - self.length / 2.0
else:
zpos = 0
else:
logging.debug ("wrong argument")
self.Sk.Placement.Rotation = rot
self.Sk.Placement.Base = FreeCAD.Vector(xpos,ypos,zpos)
alu_extr = doc.addObject("Part::Extrusion", name)
alu_extr.Base = self.Sk
alu_extr.Dir = self.Dir
alu_extr.Solid = True
self.fco = alu_extr # the FreeCad Object
# ----------- class RectRndBar ---------------------------------------------
# Creates a rectangular bar with rounded edges, and with the posibility
# to be hollow
#
# Base: the length of the base of the rectangle
# Height: the length of the height of the rectangle
# Length: the length of the bar, the extrusion
# Radius: the radius of the rounded edges (fillet)
# Thick: the thikness of the bar (hollow bar)
# If it is zero or larger than base or
# height, it will be full
# inrad_same : True: inradius = radius. When the radius is very small
# False: inradius = radius - thick
# axis 'x', 'y' or 'z'
# direction of the bar
# 'x' will along the x axis
# 'y' will along the y axis
# 'z' will be vertical
# baseaxis 'x', 'y' or 'z'
# in which axis the base is on. Cannot be the same as axis
# cx: 1 if you want the coordinates referenced to the x center of the piece
# it can be done because it is a new shape formed from the union
# cy: 1 if you want the coordinates referenced to the y center of the piece
# cz: 1 if you want the coordinates referenced to the z center of the piece
# attributes:
# inRad : radius of the inner radius
# inBase : lenght of the inner rectangle
# inHeight : height of the inner rectangle
# hollow : True, if it is hollow, False if it is not
# face : the face has been extruded
# fco : FreeCad Object
class RectRndBar (object):
def __init__ (self, Base, Height, Length, Radius, Thick = 0,
inrad_same = False, axis = 'x',
baseaxis = 'y', name = "rectrndbar",
cx=False, cy=False, cz=False):
doc = FreeCAD.ActiveDocument
self.Base = Base
self.Height = Height
self.Length = Length
self.Radius = Radius
self.Thick = Thick
self.inrad_same = inrad_same
self.name = name
self.axis = axis
self.baseaxis = baseaxis
self.cx = cx
self.cy = cy
self.cz = cz
self.inBase = Base - 2 * Thick
self.inHeight = Height - 2 * Thick
if Thick == 0 or Thick >= Base or Thick >= Height:
self.Thick = 0
self.hollow = False
self.inRad = 0
self.inrad_same = False
self.inBase = 0
self.inHeight = 0
else :
self.hollow = True
if inrad_same == True:
self.inRad = Radius
else:
if Radius > Thick:
self.inRad = Radius - Thick
else:
self.inRad = 0 # a rectangle, with no rounded edges (inside)
wire_ext = fcfun.shpRndRectWire (x=Base, y=Height, r=Radius,
zpos= Length/2.0)
face_ext = Part.Face(wire_ext)
if self.hollow == True:
wire_int = fcfun.shpRndRectWire (x=self.inBase,
y=self.inHeight,
r=self.inRad,
zpos= Length/2.0)
face_int = Part.Face(wire_int)
face = face_ext.cut(face_int)
else:
face = face_ext # is not hollow
self.face = face
# Rotate and extrude in the appropiate direction
# now is facing Z, I use vec2
if axis == 'x': # rotate to Z, the 1 or -1 makes the extrusion different
vec2 = (1,0,0)
dir_extr = FreeCAD.Vector(Length,0,0)
elif axis == 'y':
vec2 = (0,1,0)
dir_extr = FreeCAD.Vector(0,Length,0)
elif axis == 'z':
vec2 = (0,0,1)
dir_extr = FreeCAD.Vector(0,0,Length)
if baseaxis == 'x':
vec1 = (1,0,0)
elif baseaxis == 'y':
vec1 = (0,1,0)
elif baseaxis == 'z':
vec1 = (0,0,1)
vrot = fcfun.calc_rot (vec1,vec2)
vdesp = fcfun.calc_desp_ncen (
Length = self.Base,
Width = self.Height,
Height = self.Length ,
vec1 = vec1, vec2 = vec2,
cx = cx, cy=cy, cz=cz)
face.Placement.Base = vdesp
face.Placement.Rotation = vrot
shp_extr = face.extrude(dir_extr)
rndbar = doc.addObject("Part::Feature", name)
rndbar.Shape = shp_extr
self.fco = rndbar
# ----------- end class RectRndBar ----------------------------------------
# ----------- class AluProf ---------------------------------------------
# Creates a generic aluminum profile
# :----- width ----:
# : slot :
# : :--: :
# :______: :______:
# | __| |__ |
# | |\ \ / /| |
# |_| \ \____/ / |_| ...........
# | | ...... insquare
# | ( ) | ......indiam :
# _ | ____ | ..............:
# | | / / \ \ | |
# | |/ /_ _\ \| | ....
# |______| |______| ....thick
#
# width: the Width of the profile, it is squared
# length: the length of the bar, the extrusion
# thick: the thickness of the side
# slot: the width of the rail
# insquare: the width of the inner square
# indiam: the diameter of the inner hole. If 0, there is no hole
# axis 'x', 'y' or 'z'
# direction of the bar
# 'x' will be along the x axis
# 'y' will be along the y axis
# 'z' will be vertical
# cx: 1 if you want the coordinates referenced to the x center of the piece
# it can be done because it is a new shape formed from the union
# cy: 1 if you want the coordinates referenced to the y center of the piece
# cz: 1 if you want the coordinates referenced to the z center of the piece
# attributes:
# the arguments and
# ax_center : 1 if the profile is centered along its axis. 0 if not
# face : the face that has been extruded
# shp : the shape
# fco : the freecad object
# How rotation y movement works
# Initial
# Y
# :
# :
# _ : _
# |_|_:_|_|
# ........|.:.|........ X
# _|_:_|_
# |_| : |_|
# :
# :
# :
#
#
# Final axis = 'x' -> Rotation -90 on axis Y: pitch -90
# Z cx = 0
# : cy = 0 -> Translation Y: width/2
# : cz = 1 -> Translation Z: 0
# :
# :_ _
# |_|___|_|
# ..........:.|...|........ Y
# :_|___|_
# |_| |_|
# :
# :
# :
#
#
# Final axis = 'x' -> Rotation -90 on axis Y: pitch -90
# Z cx = 0
# : cy = 0 -> Translation Y: width/2
# : cz = 0 -> Translation Z: width/2
# :
# :_ _
# |_|___|_|
# : | |
# :_|___|_
# ..........|_|...|_|.......Y
# :
# :
# :
#
#
#
#
class AluProf (object):
def __init__ (self, width, length, thick, slot, insquare,
indiam, axis = 'x',
name = "genaluprof",
cx=False, cy=False, cz=False):
doc = FreeCAD.ActiveDocument
self.width = width
self.length = length
self.thick = thick
self.slot = slot
self.name = name
self.insquare = insquare
self.indiam = indiam
self.name = name
self.axis = axis
self.fcvec_axis = fcfun.getfcvecofname(axis)
self.cx = cx
self.cy = cy
self.cz = cz
fcvec_axis = self.fcvec_axis
# vectors of the points
vecpoints = fcfun.aluprof_vec (width, thick, slot, insquare)
doc.recompute()
# wire Face
wire_aluprof = fcfun.wire_sim_xy (vecpoints)
# if it is not centered on X, and the axis doesn't go along X
if cx == 0 and axis != 'x':
posx = width/2.
else:
posx = 0
if cy == 0 and axis != 'y':
posy = width/2.
else:
posy = 0
if cz == 0 and axis != 'z':
posz = width/2.
else:
posz = 0
if axis == 'x':
ax_center = cx
elif axis == 'y':
ax_center = cy
elif axis == 'z':
ax_center = cz
else:
ax_center = 0
logger.error("axis %s not defined. Supported: 'x', 'y', 'z', axis")
self.ax_center = ax_center
doc.recompute()
pos = FreeCAD.Vector(posx,posy,posz) # Position
vec_axis = fcfun.getfcvecofname(axis)
face_ext = Part.Face(wire_aluprof)
# since vec2 of calc_rot is referenced to VNZ, vec_facenomal is negated
vec_naxis = DraftVecUtils.neg(vec_axis)
vrot = fcfun.fc_calc_rot(V0, vec_naxis)
face_ext.Placement.Rotation = vrot
face_ext.Placement.Base = pos
# inner hole
if indiam > 0 :
hole = Part.makeCircle (indiam/2., # Radius
pos, # Position
vec_axis) # direction
wire_hole = Part.Wire(hole)
face_hole = Part.Face(wire_hole)
face_profile = face_ext.cut(face_hole)
else:
face_profile = face_ext
shp_profile = fcfun.shp_extrud_face (
face = face_profile,
length = length,
vec_extr_axis = vec_axis,
centered = ax_center)
self.shp = shp_profile
fco_profile = doc.addObject("Part::Feature", name)
fco_profile.Shape = shp_profile
self.fco = fco_profile
self.defaluline()
def color (self, color = (1,1,1)):
self.fco.ViewObject.ShapeColor = color
linecol = []
for col_i in color:
if col_i < 0.2:
linecol.append(0.)
else:
linecol.append(col_i - 0.2)
print (str(linecol))
self.fco.ViewObject.LineColor = tuple(linecol)
print(str(color) + ' - ' + str(self.fco.ViewObject.LineColor))
def linecolor (self, color = (1,1,1)):
self.fco.ViewObject.LineColor = color
def linewidth (self, width = 1.):
self.fco.ViewObject.LineWidth = width
def defaluline (self):
self.fco.ViewObject.LineColor = (0.5,0.5,0.5)
self.fco.ViewObject.LineWidth = 1.
# ----------- class AluProf_dir ---------------------------------------------
class AluProf_dir (object):
"""
Creates a generic aluminum profile in any direction
::
:----- width ----:
: slot :
: :--: :
:______: :______:
| __| |__ |
| |\ \ / /| |
|_| \ \____/ / |_| ...........
| | ...... insquare
| ( ) | ......indiam :
_ | ____ | ..............:
| | / / \ \ | |
| |/ /_ _\ \| | ....
|______| |______| ....thick
Parameters
----------
width : float
The Width of the profile, it is squared
length : float
The length of the bar, the extrusion
thick : float
The thickness of the side
slot : float
The width of the rail
insquare : float
The width of the inner square
indiam : float
The diameter of the inner hole. If 0, there is no hole
fc_axis_l : FreeCAD.Vector
axis on the length direction
fc_axis_w : FreeCAD.Vector
axis on the width direction
fc_axis_p : FreeCAD.Vector
axis on the other width direction (perpendicular)
can be V0 if ref_p = 1
ref_l : int
Reference (zero) on the fc_axis_l
* 1: reference at the center
* 2: reference at the end, the other end will be on the direction of
fc_axis_l
ref_w : int
Reference (zero) on the fc_axis_w
* 1: reference at the center
* 2: reference at the side, the other end side will be on the
direction of fc_axis_w
ref_p : int
Reference (zero) on the fc_axis_p
* 1: reference at the center
* 2: reference at the side, the other end side will be on the
direction of fc_axis_p
xtr_l : float
if >0 it will be that extra length on the direction of fc_axis_l
I dont think it is useful for a profile, but since it is easy to
do, I just do it
xtr_nl : float
if >0 it will be that extra height on the opositve direction of
fc_axis_l
pos : FreeCAD.Vector
FreeCAD vector of the position
wfco : int
1 a freecad object will be created. 0: only a shape
name : str
Name of the freecad object
Attributes
----------
face :
The face that has been extruded
shp :
The shape
fco :
The freecad object
::
ref_w = 1 ; ref_p = 1
fc_axis_w
:
:
_ : _
|_|_:_|_|
........|.:.|........ fc_axis_p
_|_:_|_
|_| : |_|
:
:
:
ref_w = 1 ; ref_p = 2
fc_axis_w
:
:
:
:_ _
|_|___|_|
..........:.|...|........ fc_axis_p
:_|___|_
|_| |_|
:
:
:
"""
#
# Final axis = 'x' -> Rotation -90 on axis Y: pitch -90
# Z cx = 0
# : cy = 0 -> Translation Y: width/2
# : cz = 0 -> Translation Z: width/2
# :
# :_ _
# |_|___|_|
# : | |
# :_|___|_
# ..........|_|...|_|.......Y
# :
# :
# :
#
#
#
#
def __init__ (self, width, length, thick, slot, insquare,
indiam, fc_axis_l = VX, fc_axis_w = VY, fc_axis_p = V0,
ref_l = 0, ref_w = 1, ref_p = 1,
xtr_l=0, xtr_nl=0, pos = V0,
wfco = 1, name = "aluprof"):
doc = FreeCAD.ActiveDocument
self.width = width
self.length = length
self.thick = thick
self.slot = slot
self.name = name
self.insquare = insquare
self.indiam = indiam
self.name = name
self.wfco = wfco
self.pos = pos
# normalize the axis
axis_l = DraftVecUtils.scaleTo(fc_axis_l,1)
axis_w = DraftVecUtils.scaleTo(fc_axis_w,1)
if fc_axis_p == V0:
axis_p = axis_l.cross(axis_w)
else:
axis_p = DraftVecUtils.scaleTo(fc_axis_p,1)
axis_l_n = axis_l.negative()
self.axis_l = axis_l
self.axis_w = axis_w
self.axis_p = axis_p
# getting the base position
if ref_l == 1: # move the postion half of the height down
base_pos = pos + DraftVecUtils.scale(axis_l_n, length/2. + xtr_nl)
else:
base_pos = pos + DraftVecUtils.scale(axis_l_n, xtr_nl)
# Get the center position
if ref_w == 2:
ref2center_w = DraftVecUtils.scale(axis_w, width/2.)
else:
ref2center_w = V0
if ref_p == 2:
ref2center_p = DraftVecUtils.scale(axis_p, width/2.)
else:
ref2center_p = V0
basecen_pos = base_pos + ref2center_w + ref2center_p
shp_alu_wire = fcfun.shp_aluwire_dir (width, thick, slot, insquare,
fc_axis_x = axis_w,
fc_axis_y = axis_p,
ref_x = 1, #already centered
ref_y = 1, #already centered
pos = basecen_pos)
# make a face of the wire
shp_alu_face = Part.Face (shp_alu_wire)
# inner hole
if indiam > 0 :
hole = Part.makeCircle (indiam/2., # Radius
basecen_pos, # Position
axis_l) # direction
wire_hole = Part.Wire(hole)
face_hole = Part.Face(wire_hole)
shp_alu_face = shp_alu_face.cut(face_hole)
# extrude it
dir_extrud = DraftVecUtils.scaleTo(axis_l, length + xtr_nl + xtr_l)
shp_aluprof = shp_alu_face.extrude(dir_extrud)
self.shp = shp_aluprof
if wfco == 1:
fco_aluprof = doc.addObject("Part::Feature", name)
fco_aluprof.Shape = shp_aluprof
self.fco = fco_aluprof
self.defaluline()
def color (self, color = (1,1,1)):
self.fco.ViewObject.ShapeColor = color
linecol = []
for col_i in color:
#print (str(col_i))
if col_i < 0.2:
linecol.append(0.)
else:
linecol.append(col_i - 0.2)
#print (str(linecol))
self.fco.ViewObject.LineColor = tuple(linecol)
#print(str(color) + ' - ' + str(self.fco.ViewObject.LineColor))
#print(str(linecol))
def linecolor (self, color = (1,1,1)):
self.fco.ViewObject.LineColor = color
def linewidth (self, width = 1.):
self.fco.ViewObject.LineWidth = width
def defaluline (self):
self.fco.ViewObject.LineColor = (0.5,0.5,0.5)
self.fco.ViewObject.LineWidth = 1.
# ----------- end class AluProf_dir ----------------------------------------
# Function that having a dictionary of the aluminum profile, just calls
# the class AluProf,
def getaluprof ( aludict, length,
axis = 'x',
name = "genaluprof",
cx=False, cy=False, cz=False):
h_aluprof = AluProf ( width=aludict['w'],
length = length,
thick = aludict['t'],
slot = aludict['slot'],
insquare = aludict['insq'],
indiam = aludict['indiam'],
axis = axis,
name = name,
cx=cx, cy=cy, cz=cz)
return (h_aluprof)
# Function that having a dictionary of the aluminum profile, just calls
# the class AluProf_dir,
def getaluprof_dir ( aludict, length,
fc_axis_l = VX, fc_axis_w = VY, fc_axis_p = V0,
ref_l = 0, ref_w = 1, ref_p = 1,
xtr_l=0, xtr_nl=0, pos = V0,
wfco = 1, name = "aluprof"):
h_aluprof = AluProf_dir ( width=aludict['w'],
length = length,
thick = aludict['t'],
slot = aludict['slot'],
insquare = aludict['insq'],
indiam = aludict['indiam'],
fc_axis_l = fc_axis_l,
fc_axis_w = fc_axis_w,
fc_axis_p = fc_axis_p,
ref_l = ref_l, ref_w = ref_w, ref_p = ref_p,
xtr_l = xtr_l, xtr_nl = xtr_nl,
pos = pos, wfco = wfco,
name = name)
return (h_aluprof)
#doc =FreeCAD.newDocument()
#h_aluprof = getaluprof_dir(aludict= kcomp.ALU_MOTEDIS_20I5,
# length=50,
# fc_axis_l = FreeCAD.Vector(1,1,0),
# fc_axis_w = FreeCAD.Vector(-1,1,0),
# fc_axis_p = V0,
# ref_l = 1, ref_w = 2, ref_p = 2,
# xtr_l=0, xtr_nl=0, pos = FreeCAD.Vector(1,2,4),
# wfco = 1, name = "aluprof")
#cls_aluprof = getaluprof(aludict= kcomp.ALU_MOTEDIS_20I5,
# length=80)
#
#cls_aluprof = getaluprof(aludict= kcomp.ALU_MOTEDIS_20I5,
# axis = 'z',
# length=100)
#
#cls_aluprof = getaluprof(aludict= kcomp.ALU_MOTEDIS_20I5,
# length=40,
# axis = 'y',
# cx=True, cy=False, cz=False)
##
#h_aluprof = getaluprof(aludict= kcomp.ALU_MAKERBEAM_10,
# length=60,
# axis = 'y',
# cx=True, cy=False, cz=True)
#
#h_aluprof = getaluprof(aludict= kcomp.ALU_MAKERBEAM_15,
# length=50,
# axis = 'x',
# cx=True, cy=True, cz=True)
#
# ----------- class ShpAluProf ---------------------------------------------
class ShpAluProf (shp_clss.Obj3D):
"""
Creates a shape of a generic aluminum profile in any direction
::
:----- width ----:
: slot :
: :--: :
:______: :______:
| __| |__ |
| |\ \ / /| |
|_| \ \____/ / |_| ...........
| | ...... insquare
| ( ) | ......indiam :
_ | ____ | ..............:
| | / / \ \ | |
| |/ /_ _\ \| | ....
|______| |______| ....thick
Parameters:
-----------
width: float
Width of the profile, it is squared
depth: float
(depth) length of the bar, the extrusion
thick: float
Thickness of the side
slot: float
Width of the rail slot
insquare: float
Width of the inner square
indiam: float
Diameter of the inner hole. If 0, there is no hole
xtr_d: float
If >0 it will be that extra depth (length) on the direction of axis_d
xtr_nd: float
If >0 it will be that extra depth (length) on the opositve direction of
axis_d
can be V0 if pos_h = 0
axis_d : FreeCAD.Vector
Axis along the length (depth) direction
axis_w : FreeCAD.Vector
Axis along the width direction
axis_h = axis on the other width direction (perpendicular)
Axis along the width direction
pos_d: int
Location of pos along axis_d (see drawing)
0: start point, counting xtr_nd,
if xtr_nd == 0 -> pos_d 0 and 1 will be the same
* 1: start point, not counting xtr_nd
* 2: middle point not conunting xtr_nd and xtr_d
* 3: middle point conunting xtr_nd and xtr_d
* 4: end point, not counting xtr_d
* 5: end point considering xtr_d
pos_w: int
Location of pos along axis_w (see drawing). Symmetric, negative indexes
means the other side
* 0: at the center of symmetry
* 1: at the inner square
* 2: at the interior side of the outer part of the rail (thickness of the4 side
* 3: at the end of the profile along axis_w
pos_h: int
Same as pos_w
pos : FreeCAD.Vector
Position of point defined by pos_d, pos_w, pos_h
Attributes:
-----------
pos_o: FreeCAD.Vector
origin, at pos_d=pos_w=pos_h = 0
Shown in the drawing with a o
::
axis_h
: xtr_nd depth xtr_d
: .+..........+.........+..
: : : : :
_ : _ :__:________________:___:
|_|_:_|_| |_______________________|
| o.|........ axis_w o |....... axis_d
_|___|_ |_______________________|
|_| |_| |_______________________|
0 123 0 1 23 4 5
||| : : :: : end
|| end : : :: end not counting xtr_d
|| : : :
|| : : : middle point considering total
| thickness : : : length (xtr_nd + depth + xtr_d)
| : : :
inner square : : middle poit considering depth only
: :
: start point, not counting xtr_nd
:
start point, counting xtr_nd
:______: :______:
| __| |__ |
| |\ \ / /| |
|_| \ \____/ / |_| ...........
| | ...... insquare
| ( ) | ......indiam :
_ | ____ | ..............:
| | / / \ \ | |
| |/ /_ _\ \| | ....
|______| |______| ....thick
0 1 2 3 pos_w = pos_h
"""
def __init__ (self, width, depth, thick, slot,
insquare, indiam,
xtr_d=0, xtr_nd=0,
axis_d = VX, axis_w = VY, axis_h = V0,
pos_d = 0, pos_w = 0, pos_h = 0,
pos = V0):
# either axis_w or axis_h can be V0, but not both
if (axis_w is None) or (axis_w == V0):
if (axis_h is None) or (axis_h == V0):
logger.error('Either axis_w or axis_h must be defined')
logger.warning('getting a random perpendicular verctor')
axis_w = fcfun.get_fc_perpend1(axis_d)
else:
axis_w = axis_h.cross(axis_d)
if (axis_h is None) or (axis_h == V0):
axis_h = axis_d.cross(axis_w)
shp_clss.Obj3D.__init__(self, axis_d, axis_w, axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
self.d0_cen = 0
self.w0_cen = 1 # symmetric
self.h0_cen = 1 # symmetric
# total length (depth)
self.tot_d = xtr_nd + depth + xtr_d
# vectors from the origin to the points along axis_d:
self.d_o[0] = V0 # origin
self.d_o[1] = self.vec_d(xtr_nd) #if xtr_nd= 0: same as d_o[0]
# middle point, not considering xtr_nd and xtr_d
self.d_o[2] = self.vec_d(xtr_nd + depth/2.)
# middle point considering xtr_nd and xtr_d
self.d_o[3] = self.vec_d(self.tot_d /2.)
self.d_o[4] = self.vec_d(xtr_nd + depth)
self.d_o[5] = self.vec_d(self.tot_d)
# vectors from the origin to the points along axis_w:
# symmetric: negative
self.w_o[0] = V0 # center: origin
self.w_o[1] = self.vec_w(-insquare/2.)
self.w_o[2] = self.vec_w(-(width/2. - thick))
self.w_o[3] = self.vec_w(-width/2.)
# vectors from the origin to the points along axis_h:
# symmetric: negative
self.h_o[0] = V0 # center: origin
self.h_o[1] = self.vec_h(-insquare/2.)
self.h_o[2] = self.vec_h(-(width/2. - thick))
self.h_o[3] = self.vec_h(-width/2.)
# calculates the position of the origin, and keeps it in attribute pos_o
self.set_pos_o()
shp_alu_wire = fcfun.shp_aluwire_dir (width, thick, slot, insquare,
fc_axis_x = self.axis_w,
fc_axis_y = self.axis_h,
ref_x = 1, # pos_o is centered
ref_y = 1, # pos_o is centered
pos = self.pos_o)
# make a face of the wire
shp_alu_face = Part.Face (shp_alu_wire)
# inner hole
if indiam > 0 :
hole = Part.makeCircle (indiam/2., # Radius
self.pos_o, # Position
self.axis_d) # direction
wire_hole = Part.Wire(hole)
face_hole = Part.Face(wire_hole)
shp_alu_face = shp_alu_face.cut(face_hole)
# extrude it
dir_extrud = DraftVecUtils.scaleTo(self.axis_d, self.tot_d)
shp_aluprof = shp_alu_face.extrude(dir_extrud)
self.shp = shp_aluprof
[docs]class PartAluProf (fc_clss.SinglePart, ShpAluProf):
"""
Integration of a ShpAluProf object into a PartAluProf
object, so it is a FreeCAD object that can be visualized in FreeCAD
Instead of using all the arguments of ShpAluProf, it will use
a dictionary
Parameters
----------
depth : float
(depth) length of the bar, the extrusion
aluprof_dict : dictionary
Dictionary with all the information about the profile
in kcomp.py there are some dictionaries that can be used, they are
not exact -- same as ShpAluProf
xtr_d : float
If >0 it will be that extra depth (length) on the direction of axis_d
xtr_nd : float
If >0 it will be that extra depth (length) on the opositve direction of
axis_d can be V0 if pos_h = 0
axis_d : FreeCAD.Vector
Axis along the length (depth) direction
axis_w : FreeCAD.Vector
Axis along the width direction
axis_h : FreeCAD.Vector
Axis along the width direction
pos_d : int
Location of pos along axis_d (see drawing)
* 0: start point, counting xtr_nd,
if xtr_nd == 0 -> pos_d 0 and 1 will be the same
* 1: start point, not counting xtr_nd
* 2: middle point not conunting xtr_nd and xtr_d
* 3: middle point conunting xtr_nd and xtr_d
* 4: end point, not counting xtr_d
* 5: end point considering xtr_d
pos_w : int
Location of pos along axis_w (see drawing). Symmetric, negative indexes
means the other side
* 0: at the center of symmetry
* 1: at the inner square
* 2: at the interior side of the outer part of the rail (thickness of the4 side)
* 3: at the end of the profile along axis_w
pos_h : int
Same as pos_w
pos : FreeCAD.Vector
Position of point defined by pos_d, pos_w, pos_h
model_type : int
Kind of model
* 1: dimensional model: it can be printed to assemble a model,but the part
will not work as defined. For example, if printed this aluminum
profile will not work as defined, and also, it is not exact
name : str
Name of the object
"""
def __init__( self, depth,
aluprof_dict,
xtr_d=0, xtr_nd=0,
axis_d = VX, axis_w = VY, axis_h = V0,
pos_d = 0, pos_w = 0, pos_h = 0,
pos = V0,
model_type = 1, # dimensional model
name = ''):
default_name = ( 'aluprof_w' + str(int(aluprof_dict['w']))
+ 'l_' + str(int(xtr_nd + depth + xtr_d)))
self.set_name (name, default_name, change=0)
ShpAluProf.__init__(self,
width = aluprof_dict['w'],
depth = depth,
thick = aluprof_dict['t'],
slot = aluprof_dict['slot'],
insquare = aluprof_dict['insq'],
indiam = aluprof_dict['indiam'],
xtr_d = xtr_d,
xtr_nd = xtr_nd,
axis_d = axis_d,
axis_w = axis_w,
axis_h = axis_h,
pos_d = pos_d, pos_w = pos_w, pos_h = pos_h,
pos = pos)
# creation of the part
fc_clss.SinglePart.__init__(self)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
self.set_line_width(1.)
self.set_point_size(1.)
self.set_line_color((.2, .2, .2))
#AluProf = PartAluProf(depth = 200,
# #aluprof_dict = kcomp.ALU_MOTEDIS_30B8,
# aluprof_dict = kcomp.ALU_MAKERBEAM_15,
# #xtr_d=10, xtr_nd=20,
# axis_d = VX, axis_w = VY, axis_h = V0,
# #pos_d = 3, pos_w = 1, pos_h = -2,
# pos = V0)
# ----------- NEMA MOTOR
# Creates NEMA motor including its hole to cut the piece where is going
# to be embebbed.
# ARGUMENTS:
# size: size of the motor: 11, 14, 17, 23, 34 or 42
# length: length of the motor
# shaft_l: length of the motor shaft
# chmf: the chamfer of the corners, as it were a radius
# 0: no chamfer
# circle_r: the radius of the little circle on the base of the shaft.
# if 0, not defined, I will take the half of the bolt separation
# circle_h: the height of the circle. If cero, no circle
# rshaft_l: length of the motor the rear shaft. 0 if it doesn't have
# bolt_depth: depth of the bolts holes inside the motor.
# bolt_out: length of the bolts holes outside the motor
# container: 1: if you want to have a container to make a hole to fit it in
# a piece
# normal: direction of the shaft
# pos : position of the base of the shaft. Not considering the circle that
# usually is on the base of the shaft
# ATTRIBUTES: all the arguments, and:
# shaft_d: diameter of the motor shaft
# fco: the FreeCad Object of the motor
# shp_cont: the container of the motor. To cut other pieces. It is a shape
# not a FreeCad Object (fco)
# fco_cont: Having problems with shapes and fco. So I will do it with fco
# instead of shapes To cut other pieces.
# Make decision about how to finally do it
# base_place: position of the 2 elements: All of them have the same base
# position.
# It is (0,0,0) when initialized, it has to be changed using the
# function base_place
# Bolts need to be debugged, for some cases they don't work properly
# _____ ______
# |_____| ______+ extra: 1 mm
# | | |
# |_____| + bolt_out
# | | |
# __|_|_____ _____j
# | : : + bolt_depth
# | :_: _____|
# |
#
class NemaMotor (object):
""" Not recommended for new designs, see ShpNemaMotor and PartNemaMotor
"""
def __init__ (self, size, length, shaft_l,
circle_r, circle_h, name = "nemamotor", chmf = 1,
rshaft_l=0, bolt_depth = 3, bolt_out = 2, container=1,
normal = VZ, pos = V0):
doc = FreeCAD.ActiveDocument
self.base_place = (0,0,0)
self.size = size
self.width = kcomp.NEMA_W[size]
self.length = length
self.shaft_l = shaft_l
self.shaft_d = kcomp.NEMA_SHAFT_D[size]
self.circle_r = circle_r
self.circle_h = circle_h
self.chmf = chmf
self.rshaft_l = rshaft_l
self.bolt_depth = bolt_depth
self.bolt_out = bolt_out
self.container = container
nnormal = DraftVecUtils.scaleTo(normal,1)
self.normal = nnormal
self.pos = pos
nemabolt_d = kcomp.NEMA_BOLT_D[size]
self.nemabolt_d = nemabolt_d
mtol = kcomp.TOL - 0.1
lnormal = DraftVecUtils.scaleTo(nnormal,length)
neg_lnormal = DraftVecUtils.neg(lnormal)
# motor shape
v1 = FreeCAD.Vector(self.width/2.-chmf, self.width/2.,0)
v2 = FreeCAD.Vector(self.width/2., self.width/2.-chmf,0)
motorwire = fcfun.wire_sim_xy([v1,v2])
# motor wire normal is VZ
# DraftVecUtils doesnt work as well
# rot = DraftVecUtils.getRotation(VZ, nnormal)
# the order matter VZ, nnormal. It seems it doent matter VZ or VZN
# this is valid:
#rot = DraftGeomUtils.getRotation(VZ,nnormal)
#print rot
rot = FreeCAD.Rotation(VZ,nnormal)
print(rot)
motorwire.Placement.Rotation = rot
motorwire.Placement.Base = pos
motorface = Part.Face(motorwire)
shp_motorbox = motorface.extrude(neg_lnormal)
# shaft shape
if rshaft_l == 0: # no rear shaft
shp_shaft = fcfun.shp_cyl (
r=self.shaft_d/2.,
h= shaft_l,
normal = nnormal,
pos = pos)
else:
rshaft_posend = DraftVecUtils.scaleTo(neg_lnormal, rshaft_l+length)
shp_shaft = fcfun.shp_cyl (
r = self.shaft_d/2.,
h = shaft_l + rshaft_l + length,
normal = nnormal,
pos = pos + rshaft_posend)
shp_motorshaft = shp_motorbox.fuse(shp_shaft)
# Bolt holes
# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# There is something wrong with the position of these bolts
# bhole00_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size]/2,
# -kcomp.NEMA_BOLT_SEP[size]/2,
# -bolt_depth) + pos
# bhole01_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size]/2,
# kcomp.NEMA_BOLT_SEP[size]/2,
# -bolt_depth) + pos
# bhole10_pos = FreeCAD.Vector( kcomp.NEMA_BOLT_SEP[size]/2,
# -kcomp.NEMA_BOLT_SEP[size]/2,
# -bolt_depth) + pos
# bhole11_pos = FreeCAD.Vector( kcomp.NEMA_BOLT_SEP[size]/2,
# kcomp.NEMA_BOLT_SEP[size]/2,
# -bolt_depth) + pos
# bhole00_posrot = DraftVecUtils.rotate(bhole00_pos, rot.Angle, rot.Axis)
# bhole01_posrot = DraftVecUtils.rotate(bhole01_pos, rot.Angle, rot.Axis)
# bhole10_posrot = DraftVecUtils.rotate(bhole10_pos, rot.Angle, rot.Axis)
# bhole11_posrot = DraftVecUtils.rotate(bhole11_pos, rot.Angle, rot.Axis)
# shp_bolt00 = fcfun.shp_cyl (
# r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
# h=bolt_depth + shaft_l,
# normal = nnormal,
# pos= bhole00_posrot)
# shp_bolt01 = fcfun.shp_cyl (
# r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
# h=bolt_depth + shaft_l,
# normal = nnormal,
# pos= bhole01_posrot)
# shp_bolt10 = fcfun.shp_cyl (
# r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
# h=bolt_depth + shaft_l,
# normal = nnormal,
# pos= bhole10_posrot)
# shp_bolt11 = fcfun.shp_cyl (
# r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
# h=bolt_depth + shaft_l,
# normal = nnormal,
# pos= bhole11_posrot)
# shp_bolts = shp_bolt00.multiFuse([shp_bolt01, shp_bolt10, shp_bolt11])
# list of shapes to make a fusion of the container
shp_contfuselist = []
# shp_contfuselist.append(shp_bolts)
b2hole00_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size]/2,
-kcomp.NEMA_BOLT_SEP[size]/2,
-bolt_depth)
b2hole01_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size]/2,
kcomp.NEMA_BOLT_SEP[size]/2,
-bolt_depth)
b2hole10_pos = FreeCAD.Vector( kcomp.NEMA_BOLT_SEP[size]/2,
-kcomp.NEMA_BOLT_SEP[size]/2,
-bolt_depth)
b2hole11_pos = FreeCAD.Vector( kcomp.NEMA_BOLT_SEP[size]/2,
kcomp.NEMA_BOLT_SEP[size]/2,
-bolt_depth)
b2hole00 = addBolt (
r_shank = nemabolt_d/2. + mtol/2.,
l_bolt = bolt_out + bolt_depth,
r_head = kcomp.D912_HEAD_D[nemabolt_d]/2. + mtol/2.,
l_head = kcomp.D912_HEAD_L[nemabolt_d] + mtol,
hex_head = 0, extra =1, support=1, headdown = 0, name ="b2hole00")
b2hole01 = Draft.clone(b2hole00)
b2hole01.Label = "b2hole01"
b2hole10 = Draft.clone(b2hole00)
b2hole10.Label = "b2hole10"
b2hole11 = Draft.clone(b2hole00)
b2hole11.Label = "b2hole11"
b2hole00.ViewObject.Visibility=False
b2hole01.ViewObject.Visibility=False
b2hole10.ViewObject.Visibility=False
b2hole11.ViewObject.Visibility=False
b2hole00.Placement.Base = b2hole00_pos
b2hole01.Placement.Base = b2hole01_pos
b2hole10.Placement.Base = b2hole10_pos
b2hole11.Placement.Base = b2hole11_pos
# it doesnt work if dont recompute here! probably the clones
doc.recompute()
b2holes_list = [b2hole00, b2hole01, b2hole10, b2hole11]
# not an efficient way, either use shapes or fco, but not both
shp_b2holes = b2hole00.Shape.multiFuse([b2hole01.Shape,
b2hole10.Shape,
b2hole11.Shape])
#Part.show(shp_b2holes)
b2holes = doc.addObject("Part::MultiFuse", "b2holes")
b2holes.Shapes = b2holes_list
b2holes.ViewObject.Visibility=False
shp_b2holes.Placement.Base = pos
shp_b2holes.Placement.Rotation = rot
shp_contfuselist.append(shp_b2holes)
# Circle on the base of the shaft
if circle_r == 0:
calcircle_r = kcomp.NEMA_BOLT_SEP[size]/2.
else:
calcircle_r = circle_r
if circle_h != 0:
shp_circle = fcfun.shp_cyl (
r=calcircle_r,
h= circle_h + 1, #supperposition for union
normal = nnormal,
#supperposition for union
pos = pos - nnormal)
# fmotor: fused motor
shp_fmotor = shp_motorshaft.fuse(shp_circle)
else:
shp_fmotor = shp_motorshaft
#fmotor = doc.addObject("Part::Feature", "fmotor")
#fmotor.Shape = shp_fmotor
#shp_motor = shp_fmotor.cut(shp_bolts)
shp_motor = shp_fmotor.cut(shp_b2holes)
#Part.show(shp_bolts)
# container
if container == 1:
# 2*TOL to make sure it fits
v1 = FreeCAD.Vector(self.width/2.-chmf/2. + 2*kcomp.TOL,
self.width/2. + 2*kcomp.TOL, 0)
v2 = FreeCAD.Vector(self.width/2.+ 2*kcomp.TOL,
self.width/2.-chmf/2. + 2*kcomp.TOL,0)
cont_motorwire = fcfun.wire_sim_xy([v1,v2])
cont_motorwire.Placement.Rotation = rot
cont_motorwire.Placement.Base = pos
cont_motorface = Part.Face(cont_motorwire)
shp_contmotor_box = cont_motorface.extrude(neg_lnormal)
# the container is much wider than the shaft
if rshaft_l == 0: # no rear shaft
shp_contshaft = fcfun.shp_cyl (
r=calcircle_r + kcomp.TOL,
h= shaft_l + 1,
normal = nnormal,
pos = pos - nnormal )
else:
shp_contshaft = fcfun.shp_cyl (
r=calcircle_r + kcomp.TOL,
h= shaft_l + rshaft_l + length,
normal = nnormal,
pos = pos + rshaft_posend)
shp_contfuselist.append(shp_contshaft)
shp_contmotor = shp_contmotor_box.multiFuse(shp_contfuselist)
else:
shp_contmotor = shp_motor # we put the same shape
doc.recompute()
#fco_motor = doc.addObject("Part::Cut", name)
#fco_motor.Base = fmotor
#fco_motor.Tool = b2holes
fco_motor = doc.addObject("Part::Feature", name)
fco_motor.Shape = shp_motor
self.fco = fco_motor
self.shp_cont = shp_contmotor
#Part.show(shp_contmotor)
doc.recompute()
# Move the motor and its container
def BasePlace (self, position = (0,0,0)):
self.base_place = position
self.fco.Placement.Base = FreeCAD.Vector(position)
#self.shp_cont.Placement.Base = FreeCAD.Vector(position)
self.fco_cont.Placement.Base = FreeCAD.Vector(position)
#doc =FreeCAD.newDocument()
# Revisar este caso AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# con los bolts
#nm = NemaMotor(size=17, length=40, shaft_l=24, circle_r = 0,
# circle_h=2, name='nema17', chmf=2.,
# rshaft_l = 10, bolt_depth = 3, bolt_out=5,
# #normal= FreeCAD.Vector(1,-0.75,1), pos = FreeCAD.Vector(0,5,2))
# normal= FreeCAD.Vector(0,0,-1), pos = FreeCAD.Vector(-2,5,2))
# ----------- NEMA MOTOR
class ShpNemaMotor (shp_clss.Obj3D):
""" Creates a shape of a Nema Motor
It can be a shape to cut the piece where it may be embedded
::
axis_h
:
:
2 ............................
| | :
| | + shaft_l
___|1|___............. :
_____|____0____|_____......:..circle_h.:
| :: 3 :: | : .. h=3 bolt_depth
| | :
| | :
| | + base_l
| | :
| | :
| | :
|__________4__________|.....:
: : :
: : :
: : :+ rear_shaft_l (optional)
: : :
:01...2..3..4.....:...........axis_d (same as axis_w)
axis_h:5
axis_w
:
:
__________:__________.....
/ \....: chmf_r
| O O |
| _ |
| . . |
| ( ( ) ) |........axis_d
| . . |
| - |
| O O |
\_____________________/
: :
:.....................:
+
motor_w (same as d): Nema size in inches /10
pos_o (origin) is at pos_h=0, pos_d=pos_w=0
Parameters:
-----------
nema_size : int
Nema size of the motor. Nema 17 means that the front is 1.7 inches
each side (it is a square)
base_l : float,
Length (height) of the base
shaft_l = float,
Length (height) of the shaft, including the small cylinder (circle)
at the base
shaft_r = float,
Radius of the shaft, if not defined, it will take the dimension defined
in kcomp
circle_r : float,
Radius of the cylinder (circle) at the base of the shaft
if 0 or circle_h = 0 -> no cylinder
circle_h : float,
Height of the cylinder at the base of the shaft
if 0 or circle_r = 0 -> no cylinder
chmf_r : float,
Chamfer radius of the chamfer along the base length (height)
rear_shaft_l : float,
Length of the rear shaft, 0 : no rear shaft
bolt_depth : 3.,
Depth of the bolt holes of the motor
bolt_out : 0,
Length of the bolts to be outside (to make holes), in case of a shape
to cut
cut_extra : 0,
In case that the shape is to make a hole for the motor, it will have
an extra size to make it fit. If 0, no extra size
axis_d : FreeCAD.Vector
Depth vector of coordinate system
axis_w : FreeCAD.Vector
Width vector of coordinate system
axis_h : FreeCAD.Vector
Height vector of coordinate system
pos_d : int
Location of pos along the axis_d (0,1,2,3,4), see drawing
* 0: at the axis of the shaft
* 1: at the radius of the shaft
* 2: at the end of the circle(cylinder) at the base of the shaft
* 3: at the bolts
* 4: at the end of the piece
pos_w : int
Same as pos_d
pos_h : int
Location of pos along the axis_h (0,1,2,3,4,5), see drawing
* 0: at the base of the shaft (not including the circle at the base
of the shaft)
* 1: at the end of the circle at the base of the shaft
* 2: at the end of the shaft
* 3: at the end of the bolt holes
* 4: at the bottom base
* 5: at the end of the rear shaft, if no rear shaft, it will be
the same as pos_h = 4
pos : FreeCAD.Vector
Position of the motor, at the point defined by pos_d, pos_w, pos_h
Attributes:
----------
"""
def __init__ (self,
nema_size = 17,
base_l = 32.,
shaft_l = 24.,
shaft_r = 0,
circle_r = 11.,
circle_h = 2.,
chmf_r = 1,
rear_shaft_l=0,
bolt_depth = 3.,
bolt_out = 2,
cut_extra = 0,
axis_d = VX,
axis_w = None,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 1,
pos = V0):
if (axis_w is None) or (axis_w == V0):
axis_w = axis_h.cross(axis_d)
shp_clss.Obj3D.__init__(self, axis_d, axis_w, axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
self.motor_w = kcomp.NEMA_W[nema_size]
if shaft_r == 0:
self.shaft_d = kcomp.NEMA_SHAFT_D[nema_size]
self.shaft_r = self.shaft_d /2.
shaft_r = self.shaft_r
self.nemabolt_sep = kcomp.NEMA_BOLT_SEP[nema_size]
nemabolt_d = kcomp.NEMA_BOLT_D[nema_size]
self.nemabolt_d = nemabolt_d
self.nemabolt_r = nemabolt_d/2.
mtol = kcomp.TOL - 0.1
if circle_r == 0 or circle_h == 0:
# No circle
circle_r = 0
circle_h = 0
self.circle_r = 0
self.circle_h = 0
self.h0_cen = 0
self.d0_cen = 1 # symmetrical
self.w0_cen = 1 # symmetrical
# vectors from the origin to the points along axis_h:
self.h_o[0] = V0 # base of the shaft: origin
self.h_o[1] = self.vec_h(self.circle_h)
self.h_o[2] = self.vec_h(self.shaft_l) #includes circle_h
self.h_o[3] = self.vec_h(-bolt_depth)
self.h_o[4] = self.vec_h(-self.base_l)
self.h_o[5] = self.vec_h(-self.base_l -self.rear_shaft_l)
# vectors from the origin to the points along axis_d:
# these are negative because actually the pos_d indicates a negative
# position along axis_d (this happens when it is symmetrical)
self.d_o[0] = V0
self.d_o[1] = self.vec_d(-self.shaft_r)
self.d_o[2] = self.vec_d(-self.circle_r)
self.d_o[3] = self.vec_d(-self.nemabolt_sep/2.)
self.d_o[4] = self.vec_d(-self.motor_w/2.)
# position along axis_w (similar to axis_d)
self.w_o[0] = V0
self.w_o[1] = self.vec_w(-self.shaft_r)
self.w_o[2] = self.vec_w(-self.circle_r)
self.w_o[3] = self.vec_w(-self.nemabolt_sep/2.)
self.w_o[4] = self.vec_w(-self.motor_w/2.)
# calculates the position of the origin, and keeps it in attribute pos_o
self.set_pos_o()
# ---------- building of the piece ------------------
# -------- base of the motor
# if cut_extra, there will be extra at each side, since the piece
# is built from the center of symmetry, it will be equally extended
# on each side
shp_base = fcfun.shp_box_dir(box_w = self.motor_w + 2*cut_extra,
box_d = self.motor_w + 2*cut_extra,
box_h = self.base_l,
fc_axis_w = self.axis_w,
fc_axis_d = self.axis_d,
fc_axis_h = self.axis_h,
cw = 1, cd = 1, ch = 0,
pos = self.get_pos_h(4))
shp_base = fcfun.shp_filletchamfer_dir (shp_base, self.axis_h,
fillet = 0, radius = chmf_r)
shp_base = shp_base.removeSplitter()
fuse_list = []
holes_list = []
# --------- bolts (holes or extensions if cut_extra > 0)
for pt_d in (-3,3):
for pt_w in (-3,3):
if cut_extra == 0: # there will be holes for the bolts
# pos_h=3 is at the end of the hole for the bolts
bolt_pos = self.get_pos_dwh(pt_d,pt_w,3)
shp_hole = fcfun.shp_cylcenxtr (r = self.nemabolt_r,
h = bolt_depth,
normal = self.axis_h,
ch = 0,
xtr_top = 1,
xtr_bot = 0,
pos = bolt_pos)
holes_list.append(shp_hole)
else: # the bolts will protude to make holes in the shape to cut
# pos_h=0 is at the the base of the shaft
bolt_pos = self.get_pos_dwh(pt_d,pt_w,0)
shp_hole = fcfun.shp_cylcenxtr (r = self.nemabolt_r,
h = bolt_out,
normal = self.axis_h,
ch = 0,
xtr_top = 0,
xtr_bot = 1,
pos = bolt_pos)
fuse_list.append(shp_hole)
if cut_extra == 0:
shp_holes = fcfun.fuseshplist(holes_list)
shp_base = shp_base.cut(shp_holes)
shp_base = shp_base.removeSplitter()
# -------- circle (flat cylinder) at the base of the shaft
# could add cut_extra to circle_h or circle_r, but it can be
# set in the arguments
if circle_r > 0 and circle_h > 0:
shp_circle = fcfun.shp_cylcenxtr(r = circle_r,
h = circle_h,
normal = self.axis_h,
ch = 0, # not centered
xtr_top = 0, # no extra at top
xtr_bot = 1, # extra to fuse
pos = self.pos_o)
fuse_list.append(shp_circle)
# ------- Shaft
shp_shaft = fcfun.shp_cylcenxtr(r = self.shaft_r,
h = self.shaft_l,
normal = self.axis_h,
ch = 0, # not centered
xtr_top = 0, # no extra at top
xtr_bot = 1, # extra to fuse
# shaft length stats from the base
# not from the circle
pos = self.pos_o)
fuse_list.append(shp_shaft)
if rear_shaft_l > 0:
shp_rearshaft = fcfun.shp_cylcenxtr(r = self.shaft_r,
h = self.rear_shaft_l,
normal = self.axis_h,
ch = 0, # not centered
xtr_top = 1, # to fuse
xtr_bot = 0, # no extra at bottom
pos = self.get_pos_h(5))
fuse_list.append(shp_rearshaft)
shp_motor = shp_base.multiFuse(fuse_list)
shp_motor = shp_motor.removeSplitter()
self.shp = shp_motor
#doc =FreeCAD.newDocument()
#snm = ShpNemaMotor(
# cut_extra = 1,
# pos_d = 2,
# pos_w = 1,
# pos_h = 1,
#)
#Part.show(snm.shp)
class PartNemaMotor (fc_clss.SinglePart, ShpNemaMotor):
""" Integration of a ShpNemaMotor objecto into a PartNemaMotor object
so it will create a FreeCAD object that can be shown in FreeCAD GUI
See ShpNemaMotor to get info about the parameters
"""
def __init__( self,
nema_size = 17,
base_l = 32.,
shaft_l = 20.,
shaft_r = 0,
circle_r = 11.,
circle_h = 2.,
chmf_r = 1,
rear_shaft_l=0,
bolt_depth = 3.,
bolt_out = 2.,
cut_extra = 0,
axis_d = VX,
axis_w = None,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = V0,
name = ''):
default_name = 'nema' + str(nema_size) + '_motor_l' + str(int(base_l))
self.set_name (name, default_name, change = 0)
# First the shape is created
ShpNemaMotor.__init__(self,
nema_size = nema_size,
base_l = base_l,
shaft_l = shaft_l,
shaft_r = shaft_r,
circle_r = circle_r,
circle_h = circle_h,
chmf_r = chmf_r,
rear_shaft_l = rear_shaft_l,
bolt_depth = bolt_depth,
bolt_out = bolt_out,
cut_extra = cut_extra,
axis_d = axis_d,
axis_w = axis_w,
axis_h = axis_h,
pos_d = pos_d,
pos_w = pos_w,
pos_h = pos_h,
pos = pos)
# Second, the part is created
fc_clss.SinglePart.__init__(self)
# Save the arguments that have not been created yet
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
self.model_type = 1 # Dimensional model
# ---------- class LinBearing ----------------------------------------
# Creates a cylinder with a thru-hole object
# it also creates a copy of the cylinder without the hole, but a little
# bit larger, to be used to cut other shapes where this cylinder will be
# This will be useful for linear bearing/bushings container
# r_ext: external radius,
# r_int: internal radius,
# h: height
# name
# axis: 'x', 'y' or 'z'
# 'x' will along the x axis
# 'y' will along the y axis
# 'z' will be vertical
# h_disp: displacement on the height.
# if 0, the base of the cylinder will be on the plane
# if -h/2: the plane will be cutting h/2
# r_tol : What to add to r_ext for the container cylinder
# h_tol : What to add to h for the container cylinder, half on each side
# ARGUMENTS:
# bearing: the fco (FreeCAD object) of the bearing
# bearing_cont: the fco (FreeCAD object) of the container bearing.
# to cut it
# base_place: position of the 3 elements: All of them have the same base
# position.
# It is (0,0,0) when initialized, it has to be changed using the
# function base_place
class LinBearing (object):
def __init__ (self, r_ext, r_int, h, name, axis = 'z', h_disp = 0,
r_tol = 0, h_tol = 0):
self.base_place = (0,0,0)
self.r_ext = r_ext
self.r_int = r_int
self.h = h
self.name = name
self.axis = axis
self.h_disp = h_disp
self.r_tol = r_tol
self.h_tol = h_tol
bearing = fcfun.addCylHole (r_ext = r_ext,
r_int = r_int,
h= h,
name = name,
axis = axis,
h_disp = h_disp)
self.bearing = bearing
bearing_cont = fcfun.addCyl_pos (r = r_ext + r_tol,
h= h + h_tol,
name = name + "_cont",
axis = axis,
h_disp = h_disp - h_tol/2.0)
# Hide the container
self.bearing_cont = bearing_cont
if bearing_cont.ViewObject != None:
bearing_cont.ViewObject.Visibility=False
# Move the bearing and its container
def BasePlace (self, position = (0,0,0)):
self.base_place = position
self.bearing.Placement.Base = FreeCAD.Vector(position)
self.bearing_cont.Placement.Base = FreeCAD.Vector(position)
# ---------- class LinBearingClone ----------------------------------------
# Creates an object that is like LinBearing, but it has clones of it
# instead of original Cylinders
# h_bearing: is a LinBearing object. It has the h to indicate that it is
# a handler, not a FreeCAD object. To get to the FreeCad object
# take the attributes: bearing and bearing_cont (container)
# name : name of the objects, depending on namadd, it will add it
# to the original or not
# namadd : 1: add to the original name
# 0: creates a new name
class LinBearingClone (LinBearing):
def __init__ (self, h_bearing, name, namadd = 1):
self.base_place = h_bearing.base_place
self.r_ext = h_bearing.r_ext
self.r_int = h_bearing.r_int
self.h = h_bearing.h
if namadd == 1:
self.name = h_bearing.name + "_" + name
else:
self.name = name
self.axis = h_bearing.axis
self.h_disp = h_bearing.h_disp
self.r_tol = h_bearing.r_tol
self.h_tol = h_bearing.h_tol
bearing_clone = Draft.clone(h_bearing.bearing)
bearing_clone.Label = self.name
self.bearing = bearing_clone
bearing_cont_clone = Draft.clone(h_bearing.bearing_cont)
bearing_cont_clone.Label = self.name + "_cont"
self.bearing_cont = bearing_cont_clone
if bearing_cont_clone.ViewObject != None:
bearing_cont_clone.ViewObject.Visibility=False
# ---------- class T8Nut ----------------------
# T8 Nut of a leadscrew
# nutaxis: where the nut is going to be facing
# 'x', '-x', 'y', '-y', 'z', '-z'
#
# __
# |__|
# |__|
# ______| |_
# |___________|
# |___________| ------- nutaxis = 'x'
# |_______ _|
# |__|
# |__|
# |__|
#
# |
# ------ this is the zero. Plane YZ=0
class T8Nut (object):
NutL = kcomp.T8N_L
FlangeL = kcomp.T8N_FLAN_L
ShaftOut = kcomp.T8N_SHAFT_OUT
LeadScrewD = kcomp.T8N_D_T8
LeadScrewR = LeadScrewD / 2.0
# Hole for the nut and the lead screw
ShaftD = kcomp.T8N_D_SHAFT_EXT
ShaftR = ShaftD / 2.0
FlangeD = kcomp.T8N_D_FLAN
FlangeR = FlangeD / 2.0
# hole for the M3 bolts to attach the nut to the housing
FlangeBoltHoleD = kcomp.T8N_BOLT_D
FlangeBoltDmetric = int(kcomp.T8N_BOLT_D)
# Diameter where the Flange Screws are located
FlangeBoltPosD = kcomp.T8N_D_BOLT_POS
def __init__ (self, name, nutaxis = 'x'):
doc = FreeCAD.ActiveDocument
self.name = name
self.nutaxis = nutaxis
flange_cyl = addCyl_pos (r = self.FlangeR,
h = self.FlangeL,
name = "flange_cyl",
axis = 'z',
h_disp = - self.FlangeL)
shaft_cyl = addCyl_pos ( r = self.ShaftR,
h = self.NutL,
name = "shaft_cyl",
axis = 'z',
h_disp = - self.NutL + self.ShaftOut)
holes_list = []
leadscrew_hole = addCyl_pos ( r = self.LeadScrewR,
h = self.NutL + 2,
name = "leadscrew_hole",
axis = 'z',
h_disp = - self.NutL + self.ShaftOut -1)
holes_list.append (leadscrew_hole)
flangebolt_hole1 = addCyl_pos ( r = self.FlangeBoltHoleD/2.0,
h = self.FlangeL + 2,
name = "flangebolt_hole1",
axis = 'z',
h_disp = - self.FlangeL -1)
flangebolt_hole1.Placement.Base.x = self.FlangeBoltPosD /2.0
holes_list.append (flangebolt_hole1)
flangebolt_hole2 = addCyl_pos ( r = self.FlangeBoltHoleD/2.0,
h = self.FlangeL + 2,
name = "flangebolt_hole2",
axis = 'z',
h_disp = - self.FlangeL -1)
flangebolt_hole2.Placement.Base.x = - self.FlangeBoltPosD /2.0
holes_list.append (flangebolt_hole2)
flangebolt_hole3 = addCyl_pos ( r = self.FlangeBoltHoleD/2.0,
h = self.FlangeL + 2,
name = "flangebolt_hole3",
axis = 'z',
h_disp = - self.FlangeL -1)
flangebolt_hole3.Placement.Base.y = self.FlangeBoltPosD /2.0
holes_list.append (flangebolt_hole3)
flangebolt_hole4 = addCyl_pos ( r = self.FlangeBoltHoleD/2.0,
h = self.FlangeL + 2,
name = "flangebolt_hole4",
axis = 'z',
h_disp = - self.FlangeL -1)
flangebolt_hole4.Placement.Base.y = - self.FlangeBoltPosD /2.0
holes_list.append (flangebolt_hole4)
nut_holes = doc.addObject("Part::MultiFuse", "nut_holes")
nut_holes.Shapes = holes_list
nut_cyls = doc.addObject("Part::Fuse", "nut_cyls")
nut_cyls.Base = flange_cyl
nut_cyls.Tool = shaft_cyl
if nutaxis == 'x':
vrot = FreeCAD.Rotation (VY,90)
elif nutaxis == '-x':
vrot= FreeCAD.Rotation (VY,-90)
elif nutaxis == 'y':
vrot= FreeCAD.Rotation (VX,-90)
elif nutaxis == '-y':
vrot = FreeCAD.Rotation (VX,90)
elif nutaxis == '-z':
vrot = FreeCAD.Rotation (VX,180)
else: # nutaxis =='z' no rotation
vrot = FreeCAD.Rotation (VZ,0)
nut_cyls.Placement.Rotation = vrot
nut_holes.Placement.Rotation = vrot
t8nut = doc.addObject("Part::Cut", "t8nut")
t8nut.Base = nut_cyls
t8nut.Tool = nut_holes
# recompute before color
doc.recompute()
t8nut.ViewObject.ShapeColor = fcfun.YELLOW
self.fco = t8nut # the FreeCad Object
# ---------- class T8NutHousing ----------------------
# Housing for a T8 Nut of a leadscrew
# nutaxis: where the nut is going to be facing
# 'x', '-x', 'y', '-y', 'z', '-z'
# boltface_axis: where the bolts are going to be facing
# it cannot be the same axis as the nut
# 'x', '-x', 'y', '-y', 'z', '-z'
# cx, cy, cz, if it is centered on any of the axis
class T8NutHousing (object):
Length = kcomp.T8NH_L
Width = kcomp.T8NH_W
Height = kcomp.T8NH_H
# separation between the bolts that attach to the moving part
BoltLenSep = kcomp.T8NH_BoltLSep
BoltWidSep = kcomp.T8NH_BoltWSep
# separation between the bolts to the end
BoltLen2end = (Length - BoltLenSep)/2
BoltWid2end = (Width - BoltWidSep)/2
# Bolt dimensions, that attach to the moving part: M4 x 7
BoltD = kcomp.T8NH_BoltD
BoltR = BoltD / 2.0
BoltL = kcomp.T8NH_BoltL + kcomp.TOL
# Hole for the nut and the leadscrew
ShaftD = kcomp.T8N_D_SHAFT_EXT + kcomp.TOL # I don't know the tolerances
ShaftR = ShaftD / 2.0
FlangeD = kcomp.T8N_D_FLAN + kcomp.TOL # I don't know the tolerances
FlangeR = FlangeD / 2.0
FlangeL = kcomp.T8N_FLAN_L + kcomp.TOL
FlangeBoltD = kcomp.T8NH_FlanBoltD
FlangeBoltR = FlangeBoltD / 2.0
FlangeBoltL = kcomp.T8NH_FlanBoltL + kcomp.TOL
# Diameter where the Flange Bolts are located
FlangeBoltPosD = kcomp.T8N_D_BOLT_POS
def __init__ (self, name, nutaxis = 'x', screwface_axis = 'z',
cx = 1, cy= 1, cz = 0):
self.name = name
self.nutaxis = nutaxis
self.screwface_axis = screwface_axis
self.cx = cx
self.cy = cy
self.cz = cz
doc = FreeCAD.ActiveDocument
# centered so it can be rotated without displacement, and everything
# will be in place
housing_box = fcfun.addBox_cen (self.Length, self.Width, self.Height,
name= name + "_box",
cx=True, cy=True, cz=True)
hole_list = []
leadscr_hole = addCyl_pos (r=self.ShaftR, h= self.Length + 1,
name = "leadscr_hole",
axis = 'x', h_disp = -self.Length/2.0-1)
hole_list.append(leadscr_hole)
nutflange_hole = addCyl_pos (r=self.FlangeR, h= self.FlangeL + 1,
name = "nutflange_hole",
axis = 'x',
h_disp = self.Length/2.0 - self.FlangeL)
hole_list.append(nutflange_hole)
# bolts to attach the nut flange to the housing
# M3 x 10
boltflange_l = addCyl_pos (r = self.FlangeBoltR,
h = self.FlangeBoltL + 1,
name = "boltflange_l",
axis = 'x',
h_disp = self.Length/2.0
- self.FlangeL
- self.FlangeBoltL)
boltflange_l.Placement.Base = FreeCAD.Vector(0,
- self.FlangeBoltPosD / 2.0,
)
hole_list.append(boltflange_l)
boltflange_r = addCyl_pos (r = self.FlangeBoltR,
h = self.FlangeBoltL + 1,
name = "boltflange_r",
axis = 'x',
h_disp = self.Length/2.0
- self.FlangeL
- self.FlangeBoltL)
boltflange_r.Placement.Base = FreeCAD.Vector (0,
self.FlangeBoltPosD / 2.0,
0)
hole_list.append(boltflange_r)
# bolts to attach the housing to the moving part
# M4x7
boltface_1 = fcfun.addCyl_pos (r = self.BoltR, h = self.BoltL + 1,
name="boltface_1",
axis = 'z',
h_disp = -self.Height/2 -1)
boltface_1.Placement.Base = FreeCAD.Vector (
- self.Length/2.0 + self.BoltLen2end,
- self.Width/2.0 + self.BoltWid2end,
0)
hole_list.append (boltface_1)
boltface_2 = fcfun.addCyl_pos (r = self.BoltR, h = self.BoltL + 1,
name="boltface_2",
axis = 'z',
h_disp = -self.Height/2 -1)
boltface_2.Placement.Base = FreeCAD.Vector(
self.BoltLenSep /2.0,
- self.Width/2.0 + self.BoltWid2end,
0)
hole_list.append (boltface_2)
boltface_3 = fcfun.addCyl_pos (r = self.BoltR, h = self.BoltL + 1,
name="boltface_3",
axis = 'z',
h_disp = -self.Height/2 -1)
boltface_3.Placement.Base = FreeCAD.Vector (
- self.Length/2.0 + self.BoltLen2end,
self.BoltWidSep /2.0,
0)
hole_list.append (boltface_3)
boltface_4 = fcfun.addCyl_pos (r = self.BoltR, h = self.BoltL + 1,
name="boltface_4",
axis = 'z',
h_disp = -self.Height/2 -1)
boltface_4.Placement.Base = FreeCAD.Vector(
self.BoltLenSep /2.0,
self.BoltWidSep /2.0,
0)
hole_list.append (boltface_4)
nuthouseholes = doc.addObject ("Part::MultiFuse", "nuthouse_holes")
nuthouseholes.Shapes = hole_list
# rotation vector calculation
if nutaxis == 'x':
vec1 = (1,0,0)
elif nutaxis == '-x':
vec1 = (-1,0,0)
elif nutaxis == 'y':
vec1 = (0,1,0)
elif nutaxis == '-y':
vec1 = (0,-1,0)
elif nutaxis == 'z':
vec1 = (0,0,1)
elif nutaxis == '-z':
vec1 = (0,0,-1)
if screwface_axis == 'x':
vec2 = (1,0,0)
elif screwface_axis == '-x':
vec2 = (-1,0,0)
elif screwface_axis == 'y':
vec2 = (0,1,0)
elif screwface_axis == '-y':
vec2 = (0,-1,0)
elif screwface_axis == 'z':
vec2 = (0,0,1)
elif screwface_axis == '-z':
vec2 = (0,0,-1)
vrot = fcfun.calc_rot (vec1,vec2)
vdesp = fcfun.calc_desp_ncen (
Length = self.Length,
Width = self.Width,
Height = self.Height,
vec1 = vec1, vec2 = vec2,
cx = cx, cy=cy, cz=cz)
housing_box.Placement.Rotation = vrot
nuthouseholes.Placement.Rotation = vrot
housing_box.Placement.Base = vdesp
nuthouseholes.Placement.Base = vdesp
t8nuthouse = doc.addObject ("Part::Cut", "t8nuthouse")
t8nuthouse.Base = housing_box
t8nuthouse.Tool = nuthouseholes
self.fco = t8nuthouse # the FreeCad Object
# ---------- class MisumiMinLeadscrewNut ----------------------
# L = lead :.flan_cut.
# : :
# __ ..... flan_d : _______ :
# |..| :/ \:
# |..| ---- bolt_pos_d | O O | bolt_d
# ______| | .... sh_ext_d | ___ |
# |......|..| .... | / \ |
# |......|..| .... T (thread_d) | | | |
# |______| | | \___/ |
# : |..| | |
# : |..| | O O |
# : |__|...... .\ _____ /.
# : : : . : .
# : : : . : .
# : : : . : .
# : : : . : .
# : : : :bolt_ang .
# : : :
# : : +------ this is the zero. Plane YZ=0
# : : :
# : :..:
# : + flan_h
# :...H.....:
#
#
# Z
# :
# : this is rounded
# __: : _______ :
# |..| Y :/ \:
# |..| / | O O |
# ______| | / | ___ | This is flat
# | | |/ | / \ |
# -|------|--|----- nutaxis (X) | | x--|-|------ Y
# |______| | | \_:_/ | cutaxis (z)
# |..| | : |
# |..| | O : O |
# |__| \ __:__ /
# : :
# : :
# + Zero. Plane YZ=0 -Z roundflan_axis (-Z) (also (Z)
# :
# -Z (roundflan_axis
#
# Parameters
# - thread_d: thread diameter
# - sh_ext_d: exterior diameter of the nut shaft
# - flan_d : diameter of flange
# - H : height (or length) of the nut
# - flan_cut: Cut of the flange (compact nut)
# - bolt_pos_d: Diameter of the position of the bolt holes
# - bolt_d: Diameter of the position of the bolt holes
# - bolt_ang: Angle of the position of the bolts, referred to the vertical
# in degrees
# - nutaxis: 'x', '-x', 'y', '-y', 'z', '-z': axis of the leadscrew.
# Positive or negative will change the orientation:
# ___
# nutaxis = 'z' | |
# : __| |__
# ____:____ . . |_________| . . . z = 0
# |__ __| :
# | | :
# |___| nutaxis = '-z'
#
#
# - cutaxis: 'x', 'y', 'z' : axis parallel the cut of the flange.
# it doesn't matter positive or negative, because it is symmetrical
# But it would not be an error
#
# Z
# :
# :
# / : \
# | : | cutaxis = 'z'
# | : |
# | :..|...... Y
# | |
# | |
# | |
# \ _ /
#
#
# - axis_pos: position of the nut along its axis. The position is independent
# on the sign of nutaxis. So the sign it is not referenced to
# the sign of nutaxis
class MisMinLScrNut (object):
def __init__ (self, thread_d, sh_ext_d,
flan_d, H, flan_h, flan_cut,
bolt_pos_d, bolt_d, bolt_ang = 30,
nutaxis='x',
cutaxis = '-z',
name='lscrew_nut',
axis_pos = 0):
self.thread_d = thread_d
self.sh_ext_d = sh_ext_d
self.flan_d = flan_d
self.H = H
self.flan_h = flan_h
self.flan_cut = flan_cut
self.bolt_pos_d = bolt_pos_d
self.bolt_d = bolt_d
self.bolt_ang = bolt_ang
self.bolt_ang_rad = math.radians(bolt_ang)
self.nutaxis = nutaxis
self.cutaxis = cutaxis
# to make it independent on the orientation of the nut
if nutaxis == '-x' or nutaxis == '-y' or nutaxis == '-z':
ax_pos_sign = - axis_pos
else:
ax_pos_sign = axis_pos
self.ax_pos_sign = ax_pos_sign
doc = FreeCAD.ActiveDocument
basepos = FreeCAD.Vector(ax_pos_sign, 0,0)
# Flange Cylinder
flange_cyl = fcfun.shp_cyl (r= flan_d/2.,
h= flan_h,
normal = VXN,
pos = basepos)
#Part.show(flange_cyl)
# Box that will make the intersection with the flange to make the cut
# Since the nut axis is on X, that will be the flan_h
# the Cut is on Y
flange_box = fcfun.shp_boxcen (
x = flan_h,
y = flan_cut,
z = flan_d,
cx=0, cy=1, cz=1,
pos = FreeCAD.Vector(-flan_h+ax_pos_sign,0,0))
#Part.show(flange_box)
flange_cut = flange_cyl.common(flange_box)
#Part.show(flange_cut)
# Nut Cylinder
nut_cyl = fcfun.shp_cyl (r = sh_ext_d/2,
h = H,
normal = VXN,
pos = basepos)
nut_shape = nut_cyl.fuse(flange_cut)
# ----------------- Hole for the thread
thread_hole = fcfun.shp_cylcenxtr (
r = thread_d/2,
h = H ,
normal = VXN,
ch = 0,
xtr_top = 1,
xtr_bot = 1,
pos = basepos)
# -------- Holes in the flange for the bolts
# Position on Axis Z, It will be rotated 30 degrees
bolthole_pos_z = FreeCAD.Vector(0,0,bolt_pos_d/2.)
# the 4 angles that rotate bolthole_pos_z :
angle = self.bolt_ang_rad
rot_angles = [angle, -angle, angle + math.pi, -angle + math.pi]
bolthole_list = []
for angle_i in rot_angles:
bolthole_pos_i = DraftVecUtils.rotate(bolthole_pos_z,
angle_i,
VX)
bolthole_i = fcfun.shp_cylcenxtr (r=bolt_d/2.,
h=flan_h,
normal= VXN,
ch=0,
xtr_top=1,
xtr_bot=1,
pos = bolthole_pos_i + basepos)
#Part.show(bolthole_i)
bolthole_list.append(bolthole_i)
# fusion of holes
nutholes = thread_hole.multiFuse(bolthole_list)
# rotation of the nut and the holes before the cut
vrot = fcfun.calc_rot(fcfun.getvecofname(nutaxis),
fcfun.getvecofname(cutaxis))
nutholes.Placement.Rotation = vrot
nut_shape.Placement.Rotation = vrot
shp_lscrewnut = nut_shape.cut(nutholes)
shp_lscrewnut = shp_lscrewnut.removeSplitter()
#Part.show(shp_lscrewnut)
# Creation of the FreeCAD Object
fco_lscrewnut = doc.addObject("Part::Feature", name)
fco_lscrewnut.Shape = shp_lscrewnut
self.fco = fco_lscrewnut
self.shp = shp_lscrewnut
# creates a misumi miniature leadscrew nut using a dictionary from kcomp
def get_mis_min_lscrnut (nutdict,
nutaxis='x',
cutaxis='-z',
name='lscrew_nut',
axis_pos = 0):
h_lscrew = MisMinLScrNut (
thread_d = nutdict['T'],
sh_ext_d = nutdict['sh_ext_d'],
flan_d = nutdict['flan_d'],
H = nutdict['H'],
flan_h = nutdict['flan_h'],
flan_cut = nutdict['flan_cut'],
bolt_pos_d = nutdict['bolt_pos_d'],
bolt_d = nutdict['bolt_d'],
bolt_ang = nutdict['bolt_ang'],
nutaxis = nutaxis,
cutaxis = cutaxis,
name = name,
axis_pos = axis_pos)
return h_lscrew
#get_mis_min_lscrnut (kcomp.MIS_LSCRNUT_C_L1_T4,
# nutaxis = 'y',
# cutaxis = 'x',
# name = 'lscrew_nut',
# axis_pos = 10)
# -------------------- FlexCoupling
# Creates a flexible Shaft Coupling
# ARGUMENTS:
# ds: diameter of the smaller shaft
# dl: diameter of the larger shaft
# ctype: rb, xb
# axis: 'x', 'y' or 'z'
# 'x' will along the x axis
# 'y' will along the y axis
# 'z' will be vertical
# center: 1, 0: centered or not on the axis
# larg_neg: 1, 0: if the large diameter is on the negative side or not
# ATTRIBUTES
# The arguments and:
# length: Length of the coupler
# diam: External diameter of the coupler
# fco: The freecad object
class FlexCoupling (object):
def __init__ (self, ds, dl, ctype='rb', name='flexcoupling',
axis='z', center = 1, larg_neg = 1):
doc = FreeCAD.ActiveDocument
self.ds = ds
self.dl = ds
self.ctype = ctype
self.axis = axis
self.center = center
self.larg_neg = larg_neg
self.name = name
if ctype == 'rb':
self.length = kcomp.FLEXSC_RB_L[(ds,dl)]
self.diam = kcomp.FLEXSC_RB_D[(ds,dl)]
else:
logger.error('Type not yet defined')
# Shape of the larger diameter
if larg_neg == 1:
hpos_larg = -self.length/2
hpos_smal = 0
else:
hpos_larg = -1 # superposition
hpos_smal = -self.length/2
shp_dl = fcfun.shp_cylhole (self.diam/2., dl/2., self.length/2.+1,
axis=axis, h_disp = hpos_larg)
shp_ds = fcfun.shp_cylhole (self.diam/2., ds/2., self.length/2.,
axis=axis, h_disp = hpos_smal)
shp_FlexCoupling = shp_dl.fuse(shp_ds)
doc.recompute()
fco_FlexCoupling = doc.addObject ("Part::Feature", name)
fco_FlexCoupling.Shape = shp_FlexCoupling
self.fco = fco_FlexCoupling
# ---------------------- LinGuide -----------------------------------
# ---------------------- LinGuideRail -------------------------------
# Makes the Rail of a linear guide
# Arguments:
# rail_l : length of the rail
# rail_w : width of the rail
# rail_h : height of the rail
# bolt_lsep : separation between bolts on the length dimension
# bolt_wsep : separation between bolts on the width dimension, it it is 0
# there is only one bolt
# bolt_d : diameter of the hole for the bolt
# bolth_d : diameter of the hole for the head of the bolt
# bolth_h : heigth of the hole for the head of the bolt
# boltend_sep : separation on one end, from the bolt to the end
# axis_l : the axis where the lenght of the rail is: 'x', 'y', 'z'
# axis_b : the axis where the base of the rail is pointing:
# 'x', 'y', 'z', '-x', '-y', '-z',
# It will be centered on the width axis, and zero on the length and height
# Optional holes for the bolts, that go beyon the rail to cut 3D printed pieces.
# to be designed. Zero if you dont want to have them
# bolthole_d: diameter of the hole
# bolthole_l: length of the hole
# NOT IMPLEMENTED YET, NOW ONLY ON THE DIRECTION OF AXIS_B (SAME):
# bolthole_dir: direction of the hole, it would be:
# 'same' same direction of axis_b
# 'opp' oposite direction of axis_b
# 'both' both directions
# bolthole_nutd: diameter of the nut
# bolthole_nuth: length of the nut (including the head)
# name : name of the freecad object
# Attributes:
# The Arguments and:
# ###shp_face_rail : the shape of the face of the section of the rail
# shp_plainrail : the shape of the plain rail
# nbolt_l : number of bolts lines (can be pairs, counted as one) on the l
# direction
# fco : the freecad object of the rail
class LinGuideRail (object):
def __init__ (self, rail_l, rail_w, rail_h,
bolt_lsep, bolt_wsep, bolt_d,
bolth_d, bolth_h, boltend_sep = 0,
axis_l = 'x', axis_b = '-z', name='linguiderail',
bolthole_d = 0, bolthole_l = 0, bolthole_dir = 0,
bolthole_nutd = 0, bolthole_nuth = 0):
self.base_place = (0,0,0)
self.rail_l = rail_l
self.rail_w = rail_w
self.rail_h = rail_h
self.bolt_lsep = bolt_lsep
self.bolt_wsep = bolt_wsep
self.bolt_d = bolt_d
self.bolth_d = bolth_d
self.bolth_h = bolth_h
self.axis_l = axis_l
self.axis_b = axis_b
doc = FreeCAD.ActiveDocument
shp_face_rail = fcfun.shp_face_lgrail(rail_w, rail_h, axis_l, axis_b)
#self.shp_face_rail = shp_face_rail
# vector on the direction of the rail length. Extrusion
vdir_l = fcfun.getfcvecofname(axis_l)
vdir_extr = DraftVecUtils.scaleTo(vdir_l, rail_l)
shp_plainrail = shp_face_rail.extrude(vdir_extr)
self.shp_plainrail = shp_plainrail
if boltend_sep != 0:
nbolt_l = (rail_l - boltend_sep) // bolt_lsep #integer division
self.boltend_sep = boltend_sep
else: # leave even distance
# number of bolt lines, on the length axis
nbolt_l = rail_l // bolt_lsep # integer division
#dont use % in case is not int
rail_rem = rail_l - nbolt_l * bolt_lsep
# separation between the bolt and the end
self.boltend_sep = rail_rem / 2.
# there will be one bolt more than nbolt_l
self.nbolt_l = nbolt_l + 1
# bolt holes
bolth_posz = rail_h - bolth_h
doc.recompute()
if bolt_wsep == 0: # just one bolt hole per line
shp_boltshank = fcfun.shp_cyl(r=bolt_d/2., h=rail_h-bolth_h+2,
normal=VZ, pos=FreeCAD.Vector(0,0,-1))
shp_bolthead = fcfun.shp_cyl(r=bolth_d/2., h=bolth_h+1,
normal=VZ, pos=FreeCAD.Vector(0,0,bolth_posz))
shp_bolt = shp_boltshank.fuse(shp_bolthead)
if bolthole_d != 0:
fco_bolthole = addBolt(bolthole_d/2., bolthole_l,
bolthole_nutd/2., bolthole_nuth,
hex_head = 1, extra=1, support=1,
headdown = 1, name= name +"_bolthole")
else:
shp_boltshank1 = fcfun.shp_cyl(r=bolt_d/2., h=rail_h-bolth_h+2,
normal=VZ, pos= FreeCAD.Vector(0,bolt_wsep/2.,-1))
shp_bolthead1 = fcfun.shp_cyl(r=bolth_d/2., h=bolth_h+1,
normal=VZ,
pos=FreeCAD.Vector(0,bolt_wsep/2.,bolth_posz))
shp_bolt1 = shp_boltshank1.fuse(shp_bolthead1)
shp_boltshank2 = fcfun.shp_cyl(r=bolt_d/2., h=rail_h-bolth_h+2,
normal=VZ, pos=FreeCAD.Vector(0,-bolt_wsep/2.,-1))
shp_bolthead2 = fcfun.shp_cyl(r=bolth_d/2., h=bolth_h+1,
normal=VZ,
pos=FreeCAD.Vector(0,-bolt_wsep/2.,bolth_posz))
shp_bolt2 = shp_boltshank2.fuse(shp_bolthead2)
shp_bolt = shp_bolt2.fuse(shp_bolt1)
if bolthole_d != 0:
fco_bolthole1 = addBolt(bolthole_d/2., bolthole_l,
bolthole_nutd/2., bolthole_nuth,
hex_head = 1, extra=1, support=1,
headdown = 1, name =name+"_bolthole_1")
fco_bolthole1.Placement.Base = FreeCAD.Vector(0,bolt_wsep/2.,0)
fco_bolthole2 = addBolt(bolthole_d/2., bolthole_l,
bolthole_nutd/2., bolthole_nuth,
hex_head = 1, extra=1, support=1,
headdown = 1, name =name +"_bolthole_2")
fco_bolthole2.Placement.Base =FreeCAD.Vector(0,-bolt_wsep/2.,0)
fco_bolthole = doc.addObject("Part::Fuse",name+"_bolthole")
fco_bolthole.Base = fco_bolthole1
fco_bolthole.Tool = fco_bolthole2
# Rotation of the bolt holes
vrot = fcfun.calc_rot(fcfun.getvecofname(axis_l),
fcfun.getvecofname(axis_b))
shp_bolt.Placement.Rotation = vrot
doc.recompute()
# replicate the bolt holes:
boltpos = DraftVecUtils.scaleTo(vdir_l, self.boltend_sep)
addpos = DraftVecUtils.scaleTo(vdir_l, bolt_lsep)
shp_bolt.Placement.Base = boltpos
if bolthole_d != 0:
vdir_b = fcfun.getfcvecofname(axis_b)
bolthole_posz = DraftVecUtils.scaleTo(vdir_b, rail_h)
fco_bolthole.Placement.Base = boltpos + bolthole_posz
fco_bolthole.Placement.Rotation = vrot
bolthole_list = [ fco_bolthole ]
shp_bolt_list = []
# starts on 0, because it is one more bolt than nbolt
for ibolt in range(0, int(nbolt_l)):
boltpos += addpos
shp_bolt_i = shp_bolt.copy()
shp_bolt_i.Placement.Base = boltpos
shp_bolt_list.append(shp_bolt_i)
if bolthole_d != 0:
fco_bolthole_clone = Draft.clone(fco_bolthole)
fco_bolthole_clone.Label = fco_bolthole.Label + str(ibolt)
fco_bolthole_clone.Placement.Base = boltpos + bolthole_posz
bolthole_list.append(fco_bolthole_clone)
shp_bolts = shp_bolt.multiFuse(shp_bolt_list)
shp_rail = shp_plainrail.cut(shp_bolts)
if bolthole_d != 0:
fco_bolthole = doc.addObject("Part::MultiFuse", name + "_bolt_hole")
fco_bolthole.Shapes = bolthole_list
fco_bolthole.ViewObject.Visibility = False
self.fco_bolthole = fco_bolthole
doc.recompute()
fco_rail = doc.addObject("Part::Feature", name)
fco_rail.Shape = shp_rail
self.fco = fco_rail
def BasePlace (self, position = (0,0,0)):
self.base_place = position
self.fco.Placement.Base = FreeCAD.Vector(position)
# a dictionary is used with the constants. Defined in kcomp.py
# hl = f_linguiderail(200, kcomp.SEBWM16_R, 'y', '-z')
def f_linguiderail (rail_l, d_rail, axis_l, axis_b, boltend_sep = 0,
name ='linguiderail'):
if boltend_sep == 0:
boltends = d_rail['boltend_sep']
else:
boltends = boltend_sep
h_lgrail = LinGuideRail(rail_l = rail_l,
rail_w = d_rail['rw'],
rail_h = d_rail['rh'],
bolt_lsep = d_rail['boltlsep'],
bolt_wsep = d_rail['boltwsep'],
bolt_d = d_rail['boltd'],
bolth_d = d_rail['bolthd'],
bolth_h = d_rail['bolthh'],
boltend_sep = boltends,
axis_l = axis_l,
axis_b = axis_b,
name = name)
return h_lgrail
# a dictionary is used with the constants. Defined in kcomp.py
# Includes the bolt holes (BH) to pass through another 3D piece
def f_linguiderail_bh (rail_l, d_rail, axis_l, axis_b, boltend_sep = 0,
bolthole_d = 0, bolthole_l = 0, bolthole_dir = 0,
bolthole_nutd = 0, bolthole_nuth = 0,
name ='linguiderail'):
if boltend_sep == 0:
boltends = d_rail['boltend_sep']
else:
boltends = boltend_sep
h_lgrail = LinGuideRail(rail_l = rail_l,
rail_w = d_rail['rw'],
rail_h = d_rail['rh'],
bolt_lsep = d_rail['boltlsep'],
bolt_wsep = d_rail['boltwsep'],
bolt_d = d_rail['boltd'],
bolth_d = d_rail['bolthd'],
bolth_h = d_rail['bolthh'],
boltend_sep = boltends,
axis_l = axis_l,
axis_b = axis_b,
bolthole_d = bolthole_d,
bolthole_l = bolthole_l,
bolthole_dir = bolthole_dir,
bolthole_nutd = bolthole_nutd,
bolthole_nuth = bolthole_nuth,
name = name)
return h_lgrail
#hl = f_linguiderail_bh(200, kcomp.SEBWM16_R, 'y', '-z',
# bolthole_d = 2 * kcomp.M3_SHANK_R_TOL,
# bolthole_l = 10.,
# bolthole_dir = 'same',
# bolthole_nutd = 2 * kcomp.M3_NUT_R_TOL,
# bolthole_nuth = 2 * kcomp.M3_NUT_L,
# name = 'linguiderail' )
# ---------------------- ShpLinGuideRail -------------------------------
class ShpLinGuideRail (shp_clss.Obj3D):
""" Creates a shape of a linear guide rail
The linear guide rail has a dent, but it is just to show the shape,
the dimensions are not exact
::
axis_h
:
:
:
:bolth_d
....:.+...
: : :
___:____3____:___...................
| : : | :bolth_h :
| :....2....: |....: :
\ : : / A little dent to see that it is a rail
/ : 1 : \ ..... :
| : : | : :+ rail_h
| : : | + rail_h/2. :
| : : | : :
|______:_o_:______|.....:...........:...... axis_w
: : 0 : 1 2
: : : :
: :...: :
: bolt_d :
: :
:.................:
+
rail_w
bolt_wsep: if 0, only one hole (common)
...+...
: :
_________o_________.....................
|: :| : :
|: :| :+ boltend_sep :
|: ( ) 1 ( ) :|---- :
|: :| : :
|: :| :+ bolt_lsep :
|: :| : :
|: :| : :+ rail_d
|: ( ) :|---- :
|: 2 :| only one bolt (either case, not like this
|: :| :
|: :| :
|: :| :
|: (3) :| :
|: :| :
|: :| :
|:_______4_______:|.....................:...axis_w
:
:
:
:
v
axis_d
Parameters:
-----------
rail_d : float
Length (depth) of the rail
rail_w : float
Width of the rail
rail_h : float
Height of the rail
bolt_lsep : float
Separation between bolts on the depth (length) dimension
bolt_wsep : float
Separation between bolts on the width dimension,
0: there is only one bolt
bolt_d : float
Diameter of the hole for the bolt
bolth_d : float
Diameter of the hole for the head of the bolt
bolth_h : float
Heigth of the hole for the head of the bolt
boltend_sep : float
Separation on one end, from the bolt to the end
0: evenly distributed
axis_d : FreeCAD.Vector
The axis along the depth (lenght) of the rail
axis_w : FreeCAD.Vector
The axis along the width of the rail
axis_h : FreeCAD.Vector
The axis along the height of the rail, pointing up
pos_d : int
Location of pos along axis_d (see drawing)
0: at the beginning of the rail
1: at the first bolt hole
2: at the middle of the rail (not necessary at a bolt hole)
3: at the last bolt hole
4: at the end of the rail
pos_w : int
Location of pos along axis_w (see drawing). Symmetric, negative indexes
means the other side
0: at the center of symmetry
1: at the bolt holes (only make sense if there are 2 bolt holes)
otherwise it will be like pos_w = 0
2: at the end of the rail along axis_w
pos_h : int
Location of pos along axis_h (see drawing)
0: at the bottom
1: at the middle (it is not a specific place)
1: at the bolt head
3: at the top end
pos : FreeCAD.Vector
Position at the point defined by pos_d, pos_w, pos_h
"""
def __init__ (self, rail_d, rail_w, rail_h,
bolt_lsep, bolt_wsep, bolt_d,
bolth_d, bolth_h, boltend_sep = 0,
axis_d = VX, axis_w = V0, axis_h = VZ,
pos_d = 0, pos_w = 0, pos_h = 0,
pos = V0):
if (axis_w is None) or (axis_w == V0):
axis_w = axis_h.cross(axis_d)
shp_clss.Obj3D.__init__(self, axis_d, axis_w, axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
self.d0_cen = 0
self.w0_cen = 1 # symmetric
self.h0_cen = 0
# calculation of the number of bolt holes along axis_d
if boltend_sep != 0:
nbolt_l = (rail_d - boltend_sep) // bolt_lsep #integer division
rail_rem = rail_d - boltend_sep - nbolt_l * bolt_lsep
if rail_rem > bolth_d:
# one bolt more
nbolt_l = nbolt_l + 1
self.boltend_sep = boltend_sep
else: # leave even distance
# number of bolt lines, on the depth (length) axis
nbolt_l = rail_d // bolt_lsep # integer division
#dont use % in case is not int
rail_rem = rail_d - nbolt_l * bolt_lsep
if rail_rem > 2* bolth_d :
# one bolt more
nbolt_l = nbolt_l + 1
# separation between the bolt and the end
self.boltend_sep = rail_rem / 2.
else:
self.boltend_sep = (bolt_lsep + rail_rem) / 2.
self.nbolt_l = int(nbolt_l)
# vectors from the origin to the points along axis_d:
self.d_o[0] = V0 # origin
self.d_o[1] = self.vec_d(self.boltend_sep)
self.d_o[2] = self.vec_d(rail_d/2.)
self.d_o[3] = self.vec_d((self.nbolt_l-1)*bolt_lsep + self.boltend_sep)
self.d_o[4] = self.vec_d(rail_d)
# vectors from the origin to the points along axis_w:
# symmetric: negative
self.w_o[0] = V0 # base: origin
self.w_o[1] = self.vec_w(-bolt_wsep/2.) #if 0: same as w_o[0]
self.w_o[2] = self.vec_w(-rail_w/2.)
# vectors from the origin to the points along axis_h:
self.h_o[0] = V0 # base: origin
self.h_o[1] = self.vec_h(rail_h/2.)
self.h_o[2] = self.vec_h(rail_h - bolth_h)
self.h_o[3] = self.vec_h(rail_h)
# calculates the position of the origin, and keeps it in attribute pos_o
self.set_pos_o()
wire_rail = fcfun.wire_lgrail( rail_w = rail_w,
rail_h = rail_h,
axis_w = self.axis_w,
axis_h = self.axis_h,
pos_w = 0, pos_h = 0,
pos = self.pos_o)
# make a face of the wire
shp_face_rail = Part.Face(wire_rail)
shp_plainrail = shp_face_rail.extrude(self.vec_d(rail_d))
holes_list = []
# bolt holes
bolthole_pos = self.get_pos_dwh(1,0,3)
for i in range (0,self.nbolt_l):
if bolt_wsep == 0: # just one bolt
shp_bolt = fcfun.shp_bolt_dir (r_shank = bolt_d/2.,
l_bolt = rail_h,
r_head = bolth_d/2.,
l_head = bolth_h,
xtr_head = 1, xtr_shank = 1,
support = 0,
fc_normal = self.axis_h.negative(),
pos_n = 0, pos = bolthole_pos)
holes_list.append(shp_bolt)
else:
for i in (-1,1):
bolthole_pos_i = bolthole_pos + self.get_pos_w(i)
shp_bolt = fcfun.shp_bolt_dir (r_shank = bolt_d/2.,
l_bolt = rail_h,
r_head = bolth_d/2.,
l_head = bolth_h,
xtr_head = 1, xtr_shank = 1,
support = 0,
fc_normal = self.axis_h.negative(),
pos_n = 0, pos = bolthole_pos_i)
holes_list.append(shp_bolt)
bolthole_pos = bolthole_pos + self.vec_d(bolt_lsep)
shp_holes = fcfun.fuseshplist(holes_list)
shp_rail = shp_plainrail.cut(shp_holes)
shp_rail = shp_rail.removeSplitter()
self.shp = shp_rail
#Part.show(shp_rail)
#shp_lgrail = ShpLinGuideRail( rail_d = 79., rail_w=40., rail_h=20.,
# bolt_lsep=20., bolt_wsep=15, bolt_d=3.,
# bolth_d=5., bolth_h=2., boltend_sep = 10,
# axis_d = VX, axis_w = V0, axis_h = VZ,
# pos_d = 0, pos_w = 0, pos_h = 0,
# pos = V0)
class PartLinGuideRail (fc_clss.SinglePart, ShpLinGuideRail):
""" Integration of a ShpLinGuideRail object into a PartLinGuideRail
object, so it is a FreeCAD object that can be visualized in FreeCAD
Instead of using all the arguments of ShpLinGuideRail, it will use
a dictionary
Parameters:
-----------
rail_d : float
Length (depth) of the rail
rail_dict : dictionary
Dictionary with all the information about the rail
in kcomp.py there are some dictionaries of linear guide rails that
can be used
boltend_sep : float
Separation on one end, from the bolt to the end
it can be given by the dictionary as a default value
>0: the value that will be take
0: evenly distributed
<0: value from the dictionary
axis_d : FreeCAD.Vector
The axis along the depth (lenght) of the rail
axis_w : FreeCAD.Vector
The axis along the width of the rail
axis_h : FreeCAD.Vector
The axis along the height of the rail, pointing up
pos_d : int
Location of pos along axis_d (see drawing of ShpLinGuideRail)
0: at the beginning of the rail
1: at the first bolt hole
2: at the middle of the rail (not necessary at a bolt hole)
3: at the last bolt hole
4: at the end of the rail
pos_w : int
Location of pos along axis_w (see drawing). Symmetric, negative indexes
means the other side
0: at the center of symmetry
1: at the bolt holes (only make sense if there are 2 bolt holes)
otherwise it will be like pos_w = 0
2: at the end of the rail along axis_w
pos_h : int
Location of pos along axis_h (see drawing of ShpLinGuideRail)
0: at the bottom
1: at the middle (it is not a specific place)
1: at the bolt head
3: at the top end
pos : FreeCAD.Vector
Position at the point defined by pos_d, pos_w, pos_h
"""
def __init__ (self, rail_d,
rail_dict,
boltend_sep = 0,
axis_d = VX, axis_w = V0, axis_h = VZ,
pos_d = 0, pos_w = 0, pos_h = 0,
pos = V0,
model_type = 1, # dimensional model,
name = ''):
default_name = rail_dict['name']
self.set_name (name, default_name, change=0)
if boltend_sep == 0:
boltends = 0
elif boltend_sep < 0:
boltends = rail_dict['boltend_sep']
else:
boltends = boltend_sep
# creation of the shape
ShpLinGuideRail.__init__(self,
rail_d = rail_d,
rail_w = rail_dict['rw'],
rail_h = rail_dict['rh'],
bolt_lsep = rail_dict['boltlsep'],
bolt_wsep = rail_dict['boltwsep'],
bolt_d = rail_dict['boltd'],
bolth_d = rail_dict['bolthd'],
bolth_h = rail_dict['bolthh'],
boltend_sep = boltends,
axis_d = axis_d,
axis_w = axis_w,
axis_h = axis_h,
pos_d = pos_d,
pos_w = pos_w,
pos_h = pos_h,
pos = pos)
# creation of the part
fc_clss.SinglePart.__init__(self)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
#doc = FreeCAD.newDocument()
#partLinGuideRail = PartLinGuideRail (
# rail_d = 100.,
# rail_dict = kcomp.SEBWM16_R,
# boltend_sep = 0,
# axis_d = VX, axis_w = V0, axis_h = VZ,
# pos_d = 0, pos_w = 0, pos_h = 0,
# pos = V0)
# ---------------------- LinGuideBlock -------------------------------
# Creates the block of the linear guide
# Arguments:
# block_l: Total length of the block
# block_ls: Small length of the block. Usually there is a plastic end, for
# lubricant or whatever
# block_w: Total Width of the block
# block_ws: Small width of the block (the plastic end)
# linguide_h: Height of the linear guide. Total, Rail + Block
# bolt_lsep: separation of the bolts, on the length direction
# bolt_wsep: separation of the bolts, on the width direction
# bolt_d: diameter of the hole of the bolt
# bolt_l: length of the hole. if 0, it is a thru-hole
# h_lgrail: handler of the linear guide rail
# block_pos_l: position of the block relative to the rail. From 0 to 1
# Attributes:
# axis_l: direction of the rail: 'x', 'y', 'z'
# axis_b: direction of the bottom of the rail: 'x', '-x', 'y', '-y', 'z', '-z'
#
# __________________ _____________
# __|__________________|__ ___ |
# | | | |
# | 0 --- bolt_wsep --- 0 | | |
# | : | | |
# | : | + block_ls + block_l
# | + bolt_lsep | | |
# | : | | |
# | 0 0 | | |
# |________________________| ___| |
# |__________________| ______________|
#
# | | | |
# | |____ block_ws ____| |
# |_______ block_w ________|
#
class LinGuideBlock (object):
def __init__ (self, block_l, block_ls, block_w,
block_ws, block_h,
linguide_h,
bolt_lsep, bolt_wsep,
bolt_d, bolt_l,
h_lgrail,
block_pos_l,
name):
doc = FreeCAD.ActiveDocument
self.base_place = (0,0,0)
self.block_l = block_l
self.block_ls = block_ls
self.block_w = block_w
self.block_ws = block_ws
self.block_h = block_h
self.linguide_h = linguide_h
self.bolt_lsep = bolt_lsep
self.bolt_wsep = bolt_wsep
self.bolt_d = bolt_d
if bolt_l == 0:
self.bolt_l = block_h
else:
self.bolt_l = bolt_l
self.h_lgrail = h_lgrail
self.block_pos_l = block_pos_l
shp_plainrail = h_lgrail.shp_plainrail
self.axis_l = h_lgrail.axis_l
self.axis_b = h_lgrail.axis_b
blockend_l = (block_l - block_ls)/2.
b_pos=FreeCAD.Vector(block_pos_l,0,linguide_h-block_h)
# central block
shp_cen_bl_box = fcfun.shp_boxcen(x=block_ls,
y=block_w,
z=block_h,
cx= 0, cy=1, cz=0,
pos=b_pos)
# bolt holes
boltpos_z = linguide_h+1
if bolt_l == 0:
bolt_h = self.bolt_l + 2
else:
bolt_h = self.bolt_l + 1
#if bolt_l == 0:
#boltpos_z = linguide_h-block_h-1
#else:
# boltpos_z = linguide_h-block_h
boltpos00 = FreeCAD.Vector(block_pos_l + block_ls/2- bolt_lsep/2,
-bolt_wsep/2.,boltpos_z)
shp_bolt00=fcfun.shp_cyl (r=bolt_d/2., h=bolt_h, normal=VZN,
pos = boltpos00)
boltpos01 = FreeCAD.Vector(block_pos_l + block_ls/2+ bolt_lsep/2,
-bolt_wsep/2.,boltpos_z)
shp_bolt01=fcfun.shp_cyl (r=bolt_d/2., h=bolt_h, normal=VZN,
pos = boltpos01)
boltpos10 = FreeCAD.Vector(block_pos_l + block_ls/2- bolt_lsep/2,
bolt_wsep/2.,boltpos_z)
shp_bolt10=fcfun.shp_cyl (r=bolt_d/2., h=bolt_h, normal=VZN,
pos = boltpos10)
boltpos11 = FreeCAD.Vector(block_pos_l + block_ls/2+ bolt_lsep/2,
bolt_wsep/2.,boltpos_z)
shp_bolt11=fcfun.shp_cyl (r=bolt_d/2., h=bolt_h, normal=VZN,
pos = boltpos11)
shp_bolts = shp_bolt00.multiFuse([shp_bolt01,shp_bolt10, shp_bolt11])
shp_cen_blhole = shp_cen_bl_box.cut(shp_bolts)
# end blocks
bbot_pos=FreeCAD.Vector(block_pos_l-blockend_l,0,linguide_h-block_h)
shp_botend_bl_box = fcfun.shp_boxcen(x=blockend_l,
y=block_ws,
z=block_h,
cx= 0, cy=1, cz=0,
pos=bbot_pos)
btop_pos=FreeCAD.Vector(block_pos_l+block_ls,0,linguide_h-block_h)
shp_topend_bl_box = fcfun.shp_boxcen(x=blockend_l,
y=block_ws,
z=block_h,
cx= 0, cy=1, cz=0,
pos=btop_pos)
shp_bl_box = shp_cen_blhole.multiFuse([shp_botend_bl_box,
shp_topend_bl_box])
vrot = fcfun.calc_rot(fcfun.getvecofname(self.axis_l),
fcfun.getvecofname(self.axis_b))
shp_bl_box.Placement.Rotation = vrot
shp_bl = shp_bl_box.cut(shp_plainrail)
doc.recompute()
fco_bl = doc.addObject("Part::Feature", name + '_block')
fco_bl.Shape = shp_bl
self.fco = fco_bl
def BasePlace (self, position = (0,0,0)):
self.base_place = position
self.fco.Placement.Base = FreeCAD.Vector(position)
# ---------------------- f_linguide -------------------------------
# Arguments:
# rail_l: length of the linear guide
# dlg: a dictionary is used for the constants. Defined in kcomp.py
# axis_l : the axis where the lenght of the rail is: 'x', 'y', 'z'
# axis_b : the axis where the base of the rail is pointing:
# boltend_sep : separation on one end, from the bolt to the end
# bl_pos : Position of the block, relative to the length: 0. to 1.
# hl = f_linguiderail(200, kcomp.SEBWM16_R, 'y', '-z')
def f_linguide (rail_l, dlg, axis_l, axis_b, boltend_sep = 0,
bl_pos = 0.,
name ='linguide'):
print(axis_l)
d_rail = dlg['rail']
if boltend_sep == 0:
boltends = d_rail['boltend_sep']
else:
boltends = boltend_sep
h_lgrail = LinGuideRail(rail_l = rail_l,
rail_w = d_rail['rw'],
rail_h = d_rail['rh'],
bolt_lsep = d_rail['boltlsep'],
bolt_wsep = d_rail['boltwsep'],
bolt_d = d_rail['boltd'],
bolth_d = d_rail['bolthd'],
bolth_h = d_rail['bolthh'],
boltend_sep = boltends,
axis_l = axis_l,
axis_b = axis_b,
name = name)
d_block = dlg['block']
# position of the block refered to the rail
# rail_l - d_block['b'] : the length of the rail - length of the block
block_pos_l = bl_pos * (rail_l - d_block['bl'])
h_brail = LinGuideBlock (
block_l = d_block['bl'],
block_ls = d_block['bls'],
block_w = d_block['bw'],
block_ws = d_block['bws'],
block_h = d_block['bh'],
linguide_h = d_block['lh'],
bolt_lsep = d_block['boltlsep'],
bolt_wsep = d_block['boltwsep'],
bolt_d = d_block['boltd'],
bolt_l = d_block['boltl'],
h_lgrail = h_lgrail,
block_pos_l = block_pos_l,
name = name)
return h_lgrail
# ---------------------- class LinGuide -------------------------------
# Arguments:
# rail_l: length of the linear guide
# dlg: a dictionary is used for the constants. Defined in kcomp.py
# axis_l : the axis where the lenght of the rail is: 'x', 'y', 'z'
# axis_b : the axis where the base of the rail is pointing:
# boltend_sep : separation on one end, from the bolt to the end
# bl_pos : Position of the block, relative to the length: 0. to 1.
# hl = f_linguiderail(200, kcomp.SEBWM16_R, 'y', '-z')
class LinGuide(object):
def __init__ (self, rail_l, dlg,
axis_l,
axis_b, boltend_sep = 0,
bl_pos = 0.,
name ='linguide'):
self.base_place = (0,0,0)
self.rail_l = rail_l
self.dlg = dlg
self.axis_l = axis_l
self.axis_b = axis_b
self.bl_pos = bl_pos
d_rail = dlg['rail']
self.d_rail = d_rail
d_block = dlg['block']
self.d_block = dlg['block']
if boltend_sep == 0:
boltend_sep = d_rail['boltend_sep']
else:
boltend_sep = boltend_sep
self.boltend_sep = boltend_sep
h_lgrail = LinGuideRail(rail_l = rail_l,
rail_w = d_rail['rw'],
rail_h = d_rail['rh'],
bolt_lsep = d_rail['boltlsep'],
bolt_wsep = d_rail['boltwsep'],
bolt_d = d_rail['boltd'],
bolth_d = d_rail['bolthd'],
bolth_h = d_rail['bolthh'],
boltend_sep = boltend_sep,
axis_l = axis_l,
axis_b = axis_b,
name = name)
self.h_lgrail = h_lgrail
# position of the block refered to the rail
# rail_l - d_block['b'] : the length of the rail - length of the block
block_pos_l = bl_pos * (rail_l - d_block['bl'])
self.block_pos_l = block_pos_l
h_brail = LinGuideBlock (
block_l = d_block['bl'],
block_ls = d_block['bls'],
block_w = d_block['bw'],
block_ws = d_block['bws'],
block_h = d_block['bh'],
linguide_h = d_block['lh'],
bolt_lsep = d_block['boltlsep'],
bolt_wsep = d_block['boltwsep'],
bolt_d = d_block['boltd'],
bolt_l = d_block['boltl'],
h_lgrail = h_lgrail,
block_pos_l = block_pos_l,
name = name)
self.h_brail = h_brail
def BasePlace (self,position = (0,0,0)):
self.base_place = position
self.h_brail.BasePlace(position)
self.h_lgrail.BasePlace(position)
#hl = f_linguide(200, kcomp.SEB15A, 'y', '-z',
#hl = f_linguide(200, kcomp.SEBWM16, 'y', '-z',
# boltend_sep = 0,
# bl_pos = 0.5,
# #bolthole_d = 2 * kcomp.M3_SHANK_R_TOL,
# #bolthole_l = 10.,
# #bolthole_dir = 'same',
# #bolthole_nutd = 2 * kcomp.M3_NUT_R_TOL,
# #bolthole_nuth = 2 * kcomp.M3_NUT_L,
# name = 'linguiderail' )
#lg_nx = LinGuide (rail_l= 136.,
# dlg= kcomp.SEBWM16,
# axis_l = 'z',
# axis_b='x',
# boltend_sep = 8., bl_pos=0.5, name='lg_nx')
class ShpLinGuideBlock (shp_clss.Obj3D):
""" Creates a shape of a linear guide rail
Creates a hole for the rail, no exact shape
::
axis_h
:
:
____________3_____________.........................
|::| 2 |::|...bolt_l : :
| | ____1____ | | : :+linguide_h
| | | : | | | :+ block_h :
| | \ : / | | : :
|__|_____/ o \______|__|............:..........:..> axis_w
: : : : :
: : : : :
: :....4....: :.........................:
: + :
: rail_w :
: :
:......................:
+
bolt_wsep
axis_d (direction of the rail)
:
:
_________3_________ ....................
__|____:____2____:____|__ ... :
| : : | : :
| 0 : 1 : 0 | : :
| : : : | : :
| : : : | : :
| : : o 1 32 4.......................> axis_w
| + bolt_dsep : | : :
| : : : | + block_ds :
| 0 : : 0 | : :+ block_d
|_______:_________:_______|....: :
: |____:_________:____| ................:
: : : :
: :.... block_ws ....: :
: :
:....... block_w ........:
Origin at pos_o: pos_d = pos_w = pos_h = 0
Parameters:
-----------
block_d: float
Total length (depth) of the block
block_ds: float
Small length (depth) of the block. Usually there is a plastic end,
for lubricant or whatever
block_w: float
Total Width of the block
block_ws: float
Small width of the block (the plastic end)
block_h: float
Height of the block
bolt_dsep: float
Separation of the bolts, on the depth (length) direction
bolt_wsep: float
Separation of the bolts, on the width direction
bolt_d: float
Diameter of the hole of the bolt
bolt_l: float
Length of the hole. if 0, it is a thru-hole
linguide_h: float
Height of the linear guide. Total, Rail + Block
if 0: there will be internal hole for the rail
rail_h: float
Height of the rail
if 0: there will be internal hole for the rail
rail_w: float
Width of the rail
if 0: there will be internal hole for the rail
axis_d : FreeCAD.Vector
The axis along the depth (lenght) of the block (and rail)
axis_w : FreeCAD.Vector
The axis along the width of the block
axis_h : FreeCAD.Vector
The axis along the height of the block, pointing up
pos_d : int
Location of pos along axis_d (see drawing). Symmetric, negative indexes
means the other side
0: at the center (symmetric)
1: at the bolt hole
2: at the end of the smaller part of the block
3: at the end of the end of the block
pos_w : int
Location of pos along axis_w (see drawing). Symmetric, negative indexes
means the other side
0: at the center of symmetry
1: at the inner hole of the rail
2: at the bolt holes (it can be after the smaller part of the block)
3: at the end of the smaller part of the block
4: at the end of the end of the block
pos_h : int
Location of pos along axis_h (see drawing)
0: at the bottom (could make more sense to have 0 at the top instead
1: at the top of the rail hole
2: at the bottom of the bolt holes, if thruholes, same as 0
3: at the top end
4: at the bottom of the rail (not the block), if the rail has been
defined
pos : FreeCAD.Vector
Position at the point defined by pos_d, pos_w, pos_h
::
axis_h
:
:
____________3_____________.........................
|::| 2 |::| :
| | ____1____ | |................ :+linguide_h
| | | : | | | : : :
| | \ : / | | :rail_ins_h : :
|__|_____/ o \______|__|..: : :
: : : : :rail_h :
: : : : : :
: :....4....: :.................:.......:
: + :
: rail_w :
rail_ins_h = block_h - (linguide_h - rail_h)
"""
def __init__( self,
block_d,
block_ds,
block_w,
block_ws,
block_h,
bolt_dsep,
bolt_wsep,
bolt_d,
bolt_l,
linguide_h=0,
rail_h=0,
rail_w=0,
axis_d = VX,
axis_w = VY,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = V0):
if (axis_w is None) or (axis_w == V0):
axis_w = axis_h.cross(axis_d)
shp_clss.Obj3D.__init__(self, axis_d, axis_w, axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
self.d0_cen = 1 # symmetric
self.w0_cen = 1 # symmetric
self.h0_cen = 0
if bolt_l == 0: # thruhole
self.bolt_l = block_h
self.thruhole = 1
else:
self.thruhole = 0
if rail_h == 0 or linguide_h == 0:
self.rail_h = 0
self.linguide_h = 0
self.rail_ins_h = 0
self.rail_bot_h = 0
else:
self.rail_ins_h = block_h - (linguide_h - rail_h)
self.rail_bot_h = rail_h - self.rail_ins_h
# vectors from the origin to the points along axis_d:
self.d_o[0] = V0 # Origin (center symmetric)
self.d_o[1] = self.vec_d(-self.bolt_dsep/2.)
self.d_o[2] = self.vec_d(-self.block_ds/2.)
self.d_o[3] = self.vec_d(-self.block_d/2.)
# vectors from the origin to the points along axis_w:
self.w_o[0] = V0 # Origin (center symmetric)
self.w_o[1] = self.vec_w(-self.rail_w/2.)
self.w_o[2] = self.vec_w(-self.bolt_wsep/2.)
self.w_o[3] = self.vec_w(-self.block_ws/2.)
self.w_o[4] = self.vec_w(-self.block_w/2.)
# vectors from the origin to the points along axis_h:
# could make more sense to have the origin at the top
self.h_o[0] = V0 # Origin at the bottom
self.h_o[1] = self.vec_h(self.rail_ins_h)
self.h_o[2] = self.vec_h(self.block_h - self.bolt_l)
self.h_o[3] = self.vec_h(self.block_h)
self.h_o[4] = self.vec_h(-self.rail_bot_h)
# calculates the position of the origin, and keeps it in attribute pos_o
self.set_pos_o()
# the main block
shp_mblock = fcfun.shp_box_dir (box_w = self.block_w,
box_d = self.block_ds,
box_h = self.block_h,
fc_axis_w = self.axis_w,
fc_axis_d = self.axis_d,
fc_axis_h = self.axis_h,
cw = 1, cd = 1, ch = 0,
pos = self.pos_o)
# the extra block
shp_exblock = fcfun.shp_box_dir (box_w = self.block_ws,
box_d = self.block_d,
box_h = self.block_h,
fc_axis_w = self.axis_w,
fc_axis_d = self.axis_d,
fc_axis_h = self.axis_h,
cw = 1, cd = 1, ch = 0,
pos = self.pos_o)
# fusion of these blocks
shp_block = shp_mblock.fuse(shp_exblock)
holes_list = []
# rail hole:
if self.rail_h > 0 and rail_w > 0:
wire_rail = fcfun.wire_lgrail( rail_w = rail_w,
rail_h = self.rail_h,
axis_w = self.axis_w,
axis_h = self.axis_h,
pos_w = 0, pos_h = 0,
pos = self.get_pos_h(4))
face_rail = Part.Face(wire_rail)
shp_rail = fcfun.shp_extrud_face (face = face_rail,
length = self.block_d + 2,
vec_extr_axis = self.axis_d,
centered = 1)
#Part.show(shp_rail)
holes_list.append(shp_rail)
# bolt holes:
for d_i in (-1, 1): # positions of the holes along axis_d
for w_i in (-2, 2): # positions of the holes along axis_w
shp_bolt = fcfun.shp_cylcenxtr (
r = bolt_d/2.,
h = self.bolt_l,
normal = axis_h,
ch = 0,
xtr_top = 1,
xtr_bot = self.thruhole,
pos = self.get_pos_dwh(d_i, w_i, 2))
holes_list.append(shp_bolt)
shp_holes = fcfun.fuseshplist(holes_list)
shp_block = shp_block.cut(shp_holes)
shp_block = shp_block.removeSplitter()
self.shp = shp_block
#Part.show(shp_block)
#shp_linguide_block = ShpLinGuideBlock (
# block_d = kcomp.SEB10_B['bl'],
# block_ds = kcomp.SEB10_B['bls'],
# block_w = kcomp.SEB10_B['bw'],
# block_ws = kcomp.SEB10_B['bws'],
# block_h = kcomp.SEB10_B['bh'],
#
# #linguide_h = kcomp.SEB10_B['lh'],
# #rail_h = kcomp.SEB10_R['rh'],
# #rail_w = kcomp.SEB10_R['rw'],
#
# bolt_dsep = kcomp.SEB10_B['boltlsep'],
# bolt_wsep = kcomp.SEB10_B['boltwsep'],
# bolt_d = kcomp.SEB10_B['boltd'],
# bolt_l = kcomp.SEB10_B['boltl'],
#
# axis_d = VX,
# axis_w = VY,
# axis_h = VZ,
# pos_d = 0,
# pos_w = 0,
# pos_h = 0,
# pos = V0)
[docs]class PartLinGuideBlock (fc_clss.SinglePart, ShpLinGuideBlock):
"""
Integration of a ShpLinGuideBlock object into a PartLinGuideBlock
object, so it is a FreeCAD object that can be visualized in FreeCAD
Instead of using all the arguments of ShpLinGuideBlock, it will use
a dictionary
Parameters
----------
block_dict: dictionary
Dictionary with the information about the block
rail_dict: dictionary
Dictionary with the information about the rail,
it is not necessary, but if not provided, the block will not have
the rail hole
axis_d: FreeCAD.Vector
The axis along the depth (lenght) of the block (and rail)
axis_w: FreeCAD.Vector
The axis along the width of the block
axis_h: FreeCAD.Vector
The axis along the height of the block, pointing up
pos_d: int
Location of pos along axis_d (see drawing). Symmetric, negative indexes
means the other side
* 0: at the center (symmetric)
* 1: at the bolt hole
* 2: at the end of the smaller part of the block
* 3: at the end of the end of the block
pos_w: int
Location of pos along axis_w (see drawing). Symmetric, negative indexes
means the other side
* 0: at the center of symmetry
* 1: at the inner hole of the rail
* 2: at the bolt holes (it can be after the smaller part of the block)
* 3: at the end of the smaller part of the block
* 4: at the end of the end of the block
pos_h: int
Location of pos along axis_h (see drawing)
* 0: at the bottom (could make more sense to have 0 at the top instead
* 1: at the top of the rail hole
* 2: at the bottom of the bolt holes, if thruholes, same as 0
* 3: at the top end
* 4: at the bottom of the rail (not the block), if the rail has been
defined
pos: FreeCAD.Vector
Position at the point defined by pos_d, pos_w, pos_h
"""
def __init__ (self, block_dict, rail_dict,
axis_d = VX, axis_w = V0, axis_h = VZ,
pos_d = 0, pos_w = 0, pos_h = 0,
pos = V0,
model_type = 1, # dimensional model
name = ''):
default_name = block_dict['name'] + '_block'
self.set_name (name, default_name, change=0)
if rail_dict is None:
self.rail_h = 0
self.rail_w = 0
else:
self.rail_h = rail_dict['rh']
self.rail_w = rail_dict['rw']
# creation of the shape
ShpLinGuideBlock.__init__( self,
block_d = block_dict['bl'],
block_ds = block_dict['bls'],
block_w = block_dict['bw'],
block_ws = block_dict['bws'],
block_h = block_dict['bh'],
linguide_h = block_dict['lh'],
rail_h = self.rail_h,
rail_w = self.rail_w,
bolt_dsep = block_dict['boltlsep'],
bolt_wsep = block_dict['boltwsep'],
bolt_d = block_dict['boltd'],
bolt_l = block_dict['boltl'],
axis_d = axis_d,
axis_w = axis_w,
axis_h = axis_h,
pos_d = pos_d,
pos_w = pos_w,
pos_h = pos_h,
pos = pos)
# creation of the part
fc_clss.SinglePart.__init__(self)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
#doc = FreeCAD.newDocument()
#partLinGuideBlock = PartLinGuideBlock (
# block_dict = kcomp.SEBWM16_B,
# rail_dict = kcomp.SEBWM16_R,
# axis_d = VX, axis_w = VY, axis_h = VZ,
# pos_d = 0, pos_w = -2, pos_h = 0,
# pos = V0)
class ShpGtPulley (shp_clss.Obj3D):
""" Creates a GT pulley, no exact dimensions, just for the model
::
flange_d
......+......
: :
:_____________:....................
|_____:_:_____|...: top_flange_h :
| : : | : :
| : : | :+ toothed_h :
__|__:_:__|__....: :
| ____:_:_____|....+ bot_flange_h :
| : : | + tot_h
| : : | :
| : : | :
|____:_:____|_....................:
: : : :
: :.: :
: + :
: shaft_d :
: :
:............:
+
base_d
Parameters:
-----------
pitch: float/int
Distance between teeth: Typically 2mm, or 3mm
n_teeth: int
Number of teeth of the pulley
toothed_h: float
Height of the toothed part of the pulley
top_flange_h: float
Height (thickness) of the top flange, if 0, no top flange
bot_flange_h: float
Height (thickness) of the bot flange, if 0, no bottom flange
tot_h: float
Total height of the pulley
flange_d: float
Flange diameter, if 0, it will be the same as the base_d
base_d: float
Base diameter
shaft_d: float
Shaft diameter
tol: float
Tolerance for radius (it will substracted to the radius)
twice for the diameter. Or added if a shape to substract
axis_h: FreeCAD.Vector
Height vector of coordinate system (this is required)
axis_d: FreeCAD.Vector
Depth vector of coordinate system (perpendicular to the height)
can be NULL
axis_w: FreeCAD.Vector
Width vector of coordinate system
if V0: it will be calculated using the cross product: axis_h x axis_d
pos_h: int
Location of pos along the axis_h (0,1,2,3,4,5)
* 0: at the base
* 1: at the base of the bottom flange
* 2: at the base of the toothed part
* 3: at the center of the toothed part
* 4: at the end (top) of the toothed part
* 5: at the end (top) of the pulley
pos_d: int
Location of pos along the axis_d (0,1,2,3,4,5,6)
* 0: at the center of symmetry
* 1: at the shaft radius
* 2: at the inner radius
* 3: at the external radius
* 4: at the pitch radius (outside the toothed part)
* 5: at the end of the base (not the toothed part)
* 6: at the end of the flange (V0 is no flange)
pos_w: int
Location of pos along the axis_w (0,1,2,3,4,5,6)
same as pos_d
pos: FreeCAD.Vector
Position of the piece
The toothed part of the pulley has 2 diameters, besides there also is
the pitch diameter that is external to the outer diameter (related to
the belt pitch)
::
tooth_outd : external diameter of the toothed part
.....+..... of the pulley
: :
: :
| | | : : | | |
| | | : : | | |
| | | : : | | |
| | | : : | | |
| | | : : | | |
: : : :
: :.......: :
: + :
: tooth_ind : internal diameter of the toothed part
: : of the pulley
:...............:
+
pitch_d = (n_teeth x pitch) / pi (diameter)
|
v
perimeter (n_teeth x pitch)
_ _ _ _ ...............................
_/ \_/ \_/ \_/ \_....:+ tooth_height: 0.75 + belt_height: 1.38
....:+ PLD: 0.254 :
_________________.............................:
: :
:...:
+ tooth separation 2mm (pitch)
PLD: Pitch Line Distance (I think), where the tensile cord is
when the belt is on a pulley, that would be the distance added
to the outside diameter of the belt. What is called the pitch
diameter: for a GT2 is
axis_h
:
:
_______:_______ .....5
|______:_:______|.....4
| : : |
| : : |........3
| : : |
___|__:_:__|___ .....2
|______:_:______|.....1
| : : |
| : : |
| : : |
|_____:o:_____|......0
: : :
: : :
01..23456.......axis_d, axis_w
pos_o (origin) is at pos_h=0, pos_d=0, pos_w=0 (marked with o)
"""
def __init__(self,
pitch = 2.,
n_teeth = 20,
toothed_h = 7.5,
top_flange_h = 1.,
bot_flange_h = 0,
tot_h = 16.,
flange_d = 15.,
base_d = 15.,
shaft_d = 5.,
tol = 0,
axis_d = None,
axis_w = None,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = V0):
if (((axis_d is None) or (axis_d == V0)) and
((axis_w is None) or (axis_w == V0))):
# both are null, we create a random perpendicular vectors
axis_d = fcfun.get_fc_perpend1(axis_h)
axis_w = axis_h.cross(axis_d)
else:
if ((axis_d is None) or (axis_d == V0)):
axis_d = axis_w.cross(axis_h)
elif ((axis_w is None) or (axis_w == V0)):
axis_w = axis_h.cross(axis_d)
# all axis are defined
shp_clss.Obj3D.__init__(self, axis_d, axis_w, axis_h)
if (top_flange_h > 0 or bot_flange_h > 0) and flange_d == 0:
logger.debug("Flange height is not null, but diameter is null")
logger.debug("Flange diameter will be the same as the base")
flange_d = base_d
self.flange_d = flange_flange_d
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
# belt dictionary:
self.belt_dict = kcomp.GT[pitch]
# diameters of the pulley:
# pitch diameter, it is not on the pulley, but outside, on the belt
self.pitch_d = n_teeth * pitch / math.pi
self.pitch_r = self.pitch_d /2.
# out radius and diameter, diameter at the outer part of the teeth
self.tooth_out_r = self.pitch_r - self.belt_dict['PLD']
self.tooth_out_d = 2 * self.tooth_out_r
# inner radius and diameter, diameter at the inner part of the teeth
self.tooth_in_r = self.tooth_out_r - self.belt_dict['TOOTH_H']
self.tooth_in_d = 2 * self.tooth_in_r
self.base_r = base_d / 2.
self.shaft_r = shaft_d / 2.
self.flange_r = flange_d / 2.
# height of the base, without the toothed part and the flange
self.base_h = tot_h - toothed_h - top_flange_h - bot_flange_h
self.h0_cen = 0
self.d0_cen = 1 # symmetrical
self.w0_cen = 1 # symmetrical
# vectors from the origin to the points along axis_h:
self.h_o[0] = V0
self.h_o[1] = self.vec_h(self.base_h)
self.h_o[2] = self.vec_h(self.base_h + bot_flange_h)
self.h_o[3] = self.vec_h(self.base_h + bot_flange_h + toothed_h/2.)
self.h_o[4] = self.vec_h(self.tot_h - top_flange_h)
self.h_o[5] = self.vec_h(self.tot_h)
# vectors from the origin to the points along axis_d:
# these are negative because actually the pos_d indicates a negative
# position along axis_d (this happens when it is symmetrical)
self.d_o[0] = V0
self.d_o[1] = self.vec_d(-self.shaft_r)
self.d_o[2] = self.vec_d(-self.tooth_in_r)
self.d_o[3] = self.vec_d(-self.tooth_out_r)
self.d_o[4] = self.vec_d(-self.pitch_r)
self.d_o[5] = self.vec_d(-self.base_r)
self.d_o[6] = self.vec_d(-self.flange_r)
# position along axis_w
self.w_o[0] = V0
self.w_o[1] = self.vec_w(-self.shaft_r)
self.w_o[2] = self.vec_w(-self.tooth_in_r)
self.w_o[3] = self.vec_w(-self.tooth_out_r)
self.w_o[4] = self.vec_w(-self.pitch_r)
self.w_o[5] = self.vec_w(-self.base_r)
self.w_o[6] = self.vec_w(-self.flange_r)
# calculates the position of the origin, and keeps it in attribute pos_o
self.set_pos_o()
shp_fuse_list = []
# Cilynder with a hole, with an extra for the fusion
# calculation of the extra at the bottom to make the fusion
if self.bot_flange_h > 0:
xtr_bot = self.bot_flange_h/2.
elif self.base_d > self.tooth_out_d:
xtr_bot = self.base_h/2.
else:
xtr_bot = 0
# external diameter (maybe later teeth will be made
shp_tooth_cyl = fcfun.shp_cylhole_gen(r_out = self.tooth_out_r,
r_in = self.shaft_r + tol,
h = self.toothed_h,
axis_h = self.axis_h,
pos_h = 1, #position at the bottom
xtr_top = top_flange_h/2.,
xtr_bot = xtr_bot,
pos = self.get_pos_h(2))
shp_fuse_list.append(shp_tooth_cyl)
if self.bot_flange_h > 0:
# same width
if self.flange_d == self.base_d:
shp_base_flg_cyl = fcfun.shp_cylholedir(
r_out = self.base_r,
r_in = self.shaft_r + tol,
h = self.base_h + self.bot_flange_h,
normal = self.axis_h,
pos = self.pos_o)
shp_fuse_list.append(shp_base_flg_cyl)
else:
shp_base_cyl = fcfun.shp_cylholedir(
r_out = self.base_r,
r_in = self.shaft_r + tol,
h = self.base_h,
normal = self.axis_h,
pos = self.pos_o)
shp_bot_flange_cyl = fcfun.shp_cylholedir(
r_out = self.flange_r,
r_in = self.shaft_r + tol,
h = self.bot_flange_h,
normal = self.axis_h,
pos = self.get_pos_h(1))
shp_fuse_list.append(shp_base_cyl)
shp_fuse_list.append(shp_bot_flange_cyl)
else: #no bottom flange
shp_base_cyl = fcfun.shp_cylholedir(
r_out = self.base_r,
r_in = self.shaft_r + tol,
h = self.base_h,
normal = self.axis_h,
pos = self.pos_o)
shp_fuse_list.append(shp_base_cyl)
if self.top_flange_h > 0:
shp_top_flange_cyl = fcfun.shp_cylholedir(
r_out = self.flange_r,
r_in = self.shaft_r + tol,
h = self.top_flange_h,
normal = self.axis_h,
pos = self.get_pos_h(4))
shp_fuse_list.append(shp_top_flange_cyl)
shp_pulley = fcfun.fuseshplist(shp_fuse_list)
shp_pulley = shp_pulley.removeSplitter()
self.shp = shp_pulley
# normal axes to print without support
self.prnt_ax = self.axis_h
#shpObjPulley = ShpGtPulley()
#doc = FreeCAD.newDocument()
#shpObjPulley = ShpGtPulley(
# pitch = 2.,
# n_teeth = 20,
# toothed_h = 7.5,
# top_flange_h = 1.,
# bot_flange_h = 2,
# tot_h = 16.,
# flange_d = 18.,
# base_d = 15.,
# shaft_d = 5.,
# tol = 0,
# axis_d = VX,
# axis_w = VY,
# axis_h = VZ,
# pos_d = 0,
# pos_w = 0,
# pos_h = 0,
# pos = FreeCAD.Vector(3,2,10))
#
#Part.show(shpObjPulley.shp)
class PartGtPulley (fc_clss.SinglePart, ShpGtPulley):
""" Integration of a ShpGtPulley object into a PartGtPulley
object, so it is a FreeCAD object that can be visualized in FreeCAD
"""
def __init__(self,
pitch = 2.,
n_teeth = 20,
toothed_h = 7.5,
top_flange_h = 1.,
bot_flange_h = 0,
tot_h = 16.,
flange_d = 15.,
base_d = 15.,
shaft_d = 5.,
tol = 0,
axis_d = VX,
axis_w = VY,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = V0,
model_type = 1, # dimensional model
name = ''):
default_name = 'gt' + str(int(pitch)) + '_pulley_' + str(n_teeth)
self.set_name (name, default_name, change = 0)
# First the shape is created
ShpGtPulley.__init__(self,
pitch = pitch,
n_teeth = n_teeth,
toothed_h = toothed_h,
top_flange_h = top_flange_h,
bot_flange_h = bot_flange_h,
tot_h = tot_h,
flange_d = flange_d,
base_d = base_d,
shaft_d = shaft_d,
tol = tol,
axis_d = axis_d,
axis_w = axis_w,
axis_h = axis_h,
pos_d = pos_d,
pos_w = pos_w,
pos_h = pos_h,
pos = pos)
# Then the Part
fc_clss.SinglePart.__init__(self)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
#doc = FreeCAD.newDocument()
#partPulley = PartGtPulley(
# pitch = 2.,
# n_teeth = 20,
# toothed_h = 7.5,
# top_flange_h = 1.,
# bot_flange_h = 2,
# tot_h = 16.,
# flange_d = 18.,
# base_d = 8.,
# shaft_d = 5.,
# tol = 0,
# axis_d = VX,
# axis_w = VY,
# axis_h = VZ,
# pos_d = 0,
# pos_w = 0,
# pos_h = 0,
# pos = FreeCAD.Vector(3,2,10))