Source code for tensioner_clss

# ----------------------------------------------------------------------------
# -- Set of idler tensioner and its holder
# ----------------------------------------------------------------------------
# -- (c) Felipe Machado
# -- Area of Electronic Technology. Rey Juan Carlos University (urjc.es)
# -- https://github.com/felipe-m/freecad_filter_stage
# -- January-2018
# ----------------------------------------------------------------------------
# --- LGPL Licence
# ----------------------------------------------------------------------------


#                           axis_h            axis_h 
#                            :                  :
# ....................... ___:___               :______________
# :                      |  ___  |     pos_h:   |  __________  |---
# :                      | |   | |        3     | |__________| | : |
# :+hold_h              /| |___| |\       1,2   |________      |---
# :                    / |_______| \            |        |    /      
# :             . ____/  |       |  \____       |________|  /
# :..hold_bas_h:.|_::____|_______|____::_|0     |___::___|/......axis_d
#                                               0    1           2: pos_d
#
#
#
#                 .... hold_bas_w ........
#                :        .hold_w.        :
#              aluprof_w :    wall_thick  :
#                :..+....:      +         :
#                :       :     : :        :
#       pos_w:   2__1____:___0_:_:________:........axis_w
#                |    |  | :   : |  |     |    :
#                |  O |  | :   : |  |  O  |    + hold_bas_d
#                |____|__| :   : |__|_____|....:
#                        | :   : |
#                        |_:___:_|
#                          |   |
#                           \_/
#                            :
#                            :
#                           axis_d
#
# min_width = 1 Mininum width
#
#                 .... hold_bas_w ........
#                :        .hold_w.        :
#             washer diam:    wall_thick  :
#                :..+....:      +         :
#                :       :     : :        :
#       pos_w:   2__1____:___0_:_:________:........axis_w
#                |    |  | :   : |  |     |    :
#                |  O |  | :   : |  |  O  |    + hold_bas_d
#                |____|__| :   : |__|_____|....:
#                        | :   : |
#                        |_:___:_|
#                          |   |
#                           \_/
#                            :
#                            :
#                           axis_d


# the tensioner set is referenced on 3 perpendicular axis:
# - axis_d: depth
# - axis_w: width
# - axis_h: height
# There is a position of the piece:
# - that can be in a different point

import os
import sys
import inspect
import logging
import math
import FreeCAD
import FreeCADGui
import Part
import DraftVecUtils

# to get the current directory. Freecad has to be executed from the same
# directory this file is
filepath = os.getcwd()
# to get the components
# In FreeCAD can be added: Preferences->General->Macro->Macro path
sys.path.append(filepath) 
#sys.path.append(filepath + '/' + 'comps')
sys.path.append(filepath + '/../../' + 'comps')

# path to save the FreeCAD files
fcad_path = filepath + '/../freecad/'

# path to save the STL files
stl_path = filepath + '/../stl/'

import kcomp   # import material constants and other constants
import fcfun   # import my functions for freecad. FreeCad Functions
import shp_clss # import my TopoShapes classes 
import fc_clss # import my freecad classes 
import comps   # import my CAD components
import partset 

from fcfun import V0, VX, VY, VZ, V0ROT
from fcfun import VXN, VYN, VZN

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

class ShpIdlerTensioner (shp_clss.Obj3D):
    """ Creates the idler pulley tensioner shape

                       nut_space 
                       .+..
                       :  :
       nut_holder_thick:  :nut_holder_thick
                      +:  :+
                     : :  : :    pulley_stroke_dist
           :         : :  : :       .+.
           :         : :  : :       : : idler_r_ext
           :         : :  : :       : :.+..
           :         : :  : :       : :   : idler_r_int
           :         : :  : :       : :   :.+...
           :         : :  : :       : :   :    :
        ________     : :__:_:_______:_:___:____:..................
       |___::___|     /       ____     __:_:___|.....+wall_thick :
       |    ....|    |  __   /     \  |            :             + tens_h
       |   ()...|    |:|  |:|       | |            + idler_h     :
       |________|    |  --   \_____/  |________....:             :
       |___::___|     \__________________:_:___|.................:
       :        :    :      :       :          :
       :........:    :      :...+...:          :
           +         :......:  tens_stroke     :
         tens_w      :  +                      :
    (2*idler_r_int)  : nut_holder_tot          :
                     :                         :
                     :.........tens_d..........:


                 pos_h
        ________       ________________________
       |___::___|     /       ____     ___::___|
       |    ....|    |  __   /     \  | 
       |   ()...|  0 o:|  |:|       | |        -----> axis_d
       |________|  1 |  --   \_____/  |________
       |___::___|  2  \___________________::___|
       1   0         0  1   2       3      4   5  : pos_d 
       pos_w

        pos_o (origin) is at pos_d=0, pos_w=0, pos_h=0, It marked with o

    Parameters:
    -----------
    wall_thick : float
        Thickness of the walls
    tens_stroke : float
        Length of the idler tensioner body, the stroke. Not including the pulley
        neither the space for the tensioner bolt
    pulley_stroke_dist : float
        Distance along axis_d from between the end of the pulley and the stroke
        Not including the pulley. See picture dimensions
        if 0: it will be the same as wall_thick
    nut_holder_thick : float
        Length of the space along axis_d above and below the nut, for the bolt
    in_fillet: float
        radius of the inner fillets
    idler_h : float
        height of the idler pulley
    idler_r_in : float
        internal radius of the idler pulley. This is the radius of the surface
        where the belt goes
    idler_r_ext : float
        external radius of the idler pulley. This is the most external part of
        the pulley (for example the radius of the large washer)
    boltidler_mtr : integer (could be float 2.5)
        diameter (metric) of the bolt for the idler pulley
    bolttens_mtr : integer (could be float 2.5)
        diameter (metric) of the bolt for the tensioner
    opt_tens_chmf : int
        1: there is a chamfer at every edge of tensioner, inside the holder
        0: there is a chamfer only at the edges along axis_w, not along axis_h
    tol : float
        Tolerances to print
    axis_d : FreeCAD.Vector
        length vector of coordinate system
    axis_w : FreeCAD.Vector
        width vector of coordinate system
        if V0: it will be calculated using the cross product: axis_d x axis_h
    axis_h : FreeCAD.Vector
        height vector of coordinate system
    pos_d : int
        location of pos along the axis_d (0,1,2,3,4,5), see drawing
        0: at the back of the holder
        1: at the beginning of the hole for the nut (position for the nut)
        2: at the beginning of the tensioner stroke hole
        3: at the end of the tensioner stroke hole
        4: at the center of the idler pulley hole
        5: at the end of the piece
    pos_w : int
        location of pos along the axis_w (0,1) almost symmetrical
        0: at the center of symmetry
        1: at the end of the piece along axis_w at the negative side
    pos_h : int
        location of pos along the axis_h (0,1,2), symmetrical
        0: at the center of symmetry
        1: at the inner base: where the base of the pulley goes
        2: at the bottom of the piece (negative side of axis_h)
    pos : FreeCAD.Vector
        Position of the cylinder, taking into account where the center is

    Attributes:
    -----------
    All the parameters and attributes of father class SinglePart

    Dimensional attributes:
    tens_d : float
        total length (depth) of the idler tensioner
    tens_w : float
        total width of the idler tensioner
    tens_h : float
        total height of the idler tensioner
    tens_d_inside : float
        length (depth) of the idler tensioner that can be inside the holder

    prnt_ax : FreeCAD.Vector
        Best axis to print (normal direction, pointing upwards)
    d0_cen : int
    w0_cen : int
    h0_cen : int
        indicates if pos_h = 0 (pos_d, pos_w) is at the center along
        axis_h, axis_d, axis_w, or if it is at the end.
        1 : at the center (symmetrical, or almost symmetrical)
        0 : at the end

    """
    def __init__(self,
                 idler_h ,
                 idler_r_in ,
                 idler_r_ext ,
                 in_fillet = 2.,
                 wall_thick = 5.,
                 tens_stroke = 20. ,
                 pulley_stroke_dist = 0,
                 nut_holder_thick = 4. ,
                 boltidler_mtr = 3,
                 bolttens_mtr = 3,
                 opt_tens_chmf = 1,
                 tol = kcomp.TOL,
                 axis_d = VX,
                 axis_w = VY,
                 axis_h = VZ,
                 pos_d = 0,
                 pos_w = 0,
                 pos_h = 0,
                 pos = V0):
        
        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])

        # calculation of the dimensions:
        if pulley_stroke_dist == 0: # default value
            self.pulley_stroke_dist = wall_thick

        # dictionary of the bolt for the idler pulley
        # din 912 bolts are used:
        self.boltidler_dict = kcomp.D912[boltidler_mtr]
        self.boltidler_r_tol = self.boltidler_dict['shank_r_tol']

        # --- tensioner bolt and nut values
        # dictionary of the bolt tensioner
        self.bolttens_dict = kcomp.D912[bolttens_mtr]
        # the shank radius including tolerance
        self.bolttens_r_tol = self.bolttens_dict['shank_r_tol']
        # dictionary of the nut
        self.nuttens_dict = kcomp.D934[bolttens_mtr]
        self.nut_space = kcomp.NUT_HOLE_MULT_H + self.nuttens_dict['l_tol']
        self.nut_holder_tot = self.nut_space + 2* self.nut_holder_thick
        # circum diameter of the nut
        self.tensnut_circ_d = self.nuttens_dict['circ_d']
        # circum radius of the nut, with tolerance
        self.tensnut_circ_r_tol = self.nuttens_dict['circ_r_tol']
        # the apotheme of the nut
        self.tensnut_ap_tol = (self.nuttens_dict['a2']+tol/2.)/2.

        # --- idler tensioner dimensions
        self.tens_h = self.idler_h + 2*wall_thick
        self.tens_d = (  self.nut_holder_tot
                       + tens_stroke
                       + self.pulley_stroke_dist
                       + idler_r_ext
                       + idler_r_in)

        self.tens_d_inside = (   self.nut_holder_tot
                               + tens_stroke
                               + self.pulley_stroke_dist)

        self.tens_w = max(2 * idler_r_in, self.tensnut_circ_d)

        self.d0_cen = 0
        self.w0_cen = 1 # symmetrical
        self.h0_cen = 1 # symmetrical

        self.d_o[0] = V0
        self.d_o[1] = self.vec_d(nut_holder_thick)
        self.d_o[2] = self.vec_d(self.nut_holder_tot)
        self.d_o[3] = self.vec_d(self.nut_holder_tot + tens_stroke)
        self.d_o[4] = self.vec_d(self.tens_d - idler_r_in)
        self.d_o[5] = self.vec_d(self.tens_d)

        # these are negative because actually the pos_w indicates a negative
        # position along axis_w
        self.w_o[0] = V0
        self.w_o[1] = self.vec_w(-self.tens_w/2.)

        self.h_o[0] = V0
        self.h_o[1] = self.vec_h(-idler_h/2.)
        self.h_o[2] = self.vec_h(-self.tens_h/2.)

        # calculates the position of the origin, and keeps it in attribute pos_o
        self.set_pos_o()

        # ------------- building of the piece --------------------

        #  --------------- step 01-04 ------------------------      
        #  rectangular cuboid with basic dimensions, but chamfered
        #  at the inner end
        # 
        #       axis_h
        #          : .....tens_d.......
        #          : : ________________:
        #          : /               /|
        #           /               / |
        #       .. /_______________/  |.......
        #       : /                |  /     . 
        # tens_h  |                | /     . tens_w
        #       :. \_______________|/......
        #
        #
        #     o: shows the position of the origin: pos_o
        #
        #                axis_h       axis_h
        #                  :            :
        #         .... ____:____        : ______________________
        #         :   |.........|     ch2/                      |
        #         :   |:       :|       |                       |      
        #  tens_h +   |:   o   :|       o                       |-----> axis_d
        #         :   |:.......:|       |                       |
        #         :...|_________|     ch1\______________________|
        #             :         :       :                       :
        #             :.tens_h..:       :...... tens_d .........:
        #
        #              ____o____ ....> axis_w
        #          ch3/_________\ch4
        #             |         |          chamfer ch3 and ch4 are optional
        #             |         |          Depending on opt_tens_chmf
        #             |         |
        #             |         |
        #             |         |
        #             |         |
        #             |.........|
        #             |         |
        #             |         |
        #             |         |
        #             |_________|
        #                  :
        #                  :
        #                  V
        #                 axis_d

        if opt_tens_chmf == 0: # no optional chamfer, only along axis_w
            edge_dir = self.axis_w
        else:
            edge_dir = V0
   
        shp01chmf = fcfun.shp_boxdir_fillchmfplane(
                               box_w = self.tens_w,
                               box_d = self.tens_d,
                               box_h = self.tens_h,
                               axis_d = self.axis_d,
                               axis_h = self.axis_h,
                               cd=0, cw=1, ch=1,
                               # no tolerances, this is the piece
                               fillet = 0, # chamfer
                               radius = 2*in_fillet,
                               plane_fill = self.axis_d.negative(),
                               both_planes = 0,
                               edge_dir = edge_dir,
                               pos = self.pos_o)
        #  --------------- step 02 ---------------------------  
        # Space for the idler pulley
        #    axis_h
        #      :
        #      : ______________________
        #       /               _______|....
        #      |               |           + idler_h
        #      |               |       5   :----------->axis_d
        #      |               |_______....:
        #       \______________________|...wall_thick
        #                      :       :
        #                      :.......:
        #                         +
        #                       2 * idler_r_xtr
        #
        # the position is pos_d = 5
        # maybe should be advisable to have tolerance, but usually, the 
        # washers have tolerances, and usually are less thick than the nominal
        idler_h_hole =  idler_h # + tol
        if idler_h_hole != idler_h:
            self.idler_h_hole = idler_h_hole
        # NO CHAMFER to be able to fit the pulley well
        shp02cut = fcfun.shp_box_dir_xtr(
                               box_w = self.tens_w,
                               box_d = idler_r_in + idler_r_ext,
                               box_h = idler_h_hole,
                               fc_axis_d = self.axis_d.negative(),
                               fc_axis_h = self.axis_h,
                               cd=0, cw=1, ch=1,
                               xtr_w = 1,
                               xtr_nw = 1,
                               xtr_d = tol, # tol to fit the large washer
                               xtr_nd = 1, # extra along axis_d (positive)
                               pos = self.get_pos_d(5))
        shp02 = shp01chmf.cut(shp02cut)
        shp02 = shp02.removeSplitter() # refine shape
        #  --------------- step 03 --------------------------- 
        # Fillets at the idler end:
        #
        #    axis_h
        #      :
        #      :_______________________f2
        #      |                 ______|
        #      |                /      f4
        #      |               |       5    ------> axis_d
        #      |                \______f3...
        #      |_______________________|....+ wall_thick.....> Y
        #      :                       f1
        #      :...... tens_d .........:
        #
        pt_f1 = self.get_pos_d(5) + self.vec_h( -self.tens_h/2.)
        pt_f2 = self.get_pos_d(5) + self.vec_h(  self.tens_h/2.)
        pt_f3 = self.get_pos_d(5) + self.vec_h( -idler_h_hole/2.)
        pt_f4 = self.get_pos_d(5) + self.vec_h(  idler_h_hole/2.)

        if wall_thick/2. <= in_fillet:
            msg1 = 'Radius of fillet is larger than 2 x wall thick'
            msg2 = ' making fillet smaller: '
            wall_fillet_r = self.wall_thick /2. - 0.1
            logger.warning(msg1 + msg2 + str(wall_fillet_r))
        else:
            wall_fillet_r = in_fillet
        shp03 = fcfun.shp_filletchamfer_dirpts (
                                            shp=shp02,
                                            fc_axis=self.axis_w,
                                            fc_pts=[pt_f1,pt_f2, pt_f3, pt_f4],
                                            fillet = 1,
                                            radius=wall_fillet_r)
        #  --------------- step 04 done at step 01 ------------------------ 

        #  --------------- step 05 --------------------------- 
        # Shank hole for the idler pulley:

        #    axis_h                  idler_r_xtr
        #      :                    .+..
        #      : ___________________:__:
        #       /                __:_:_|
        #      |                /             
        #      |               |    4   ----------> axis_d
        #      |                \______
        #       \__________________:_:_|
        #      :                       :
        #      :...... tens_d .........:
        #                     
        # pos_d = 4
        shp05 = fcfun.shp_cylcenxtr (r = self.boltidler_r_tol,
                                     h = self.tens_h,
                                     normal = self.axis_h,
                                     ch = 1, xtr_top = 1, xtr_bot = 1,
                                     pos = self.get_pos_d(4))
        #  --------------- step 06 --------------------------- 
        # Hole for the leadscrew (stroke):

        #    axis_h
        #      :
        #      : ______________________
        #       /      _____     __:_:_|
        #      |    f2/     \f4 /             
        #      |     2       | |        -------> axis_d
        #      |    f1\_____/f3 \______
        #       \__________________:_:_|
        #      :     :       :         :
        #      :     :.......:         :
        #      :     :   +             :
        #      :.....:  tens_stroke    :
        #      :  +                    :
        #      : nut_holder_tot        :
        #      :                       :
        #      :...... tens_d .........:
        # 
        #  pos_d = 2
        shp06a = fcfun.shp_box_dir_xtr(box_w = self.tens_w,
                                       box_d = self.tens_stroke,
                                       box_h = self.idler_h,
                                       fc_axis_h = self.axis_h,
                                       fc_axis_d = self.axis_d,
                                       xtr_w = 1, xtr_nw = 1,
                                       cw=1, cd=0, ch=1,
                                       pos=self.get_pos_d(2))
        shp06 =  fcfun.shp_filletchamfer_dir (shp=shp06a,
                                              fc_axis=self.axis_w,
                                              fillet = 0, radius=self.in_fillet)

        #  --------------- step 07 --------------------------- 
        # Hole for the leadscrew shank at the beginning

        #    axis_h
        #      :
        #      : ______________________
        #       /      _____     __:_:_|
        #      |      /     \   /
        #      |:::::|       | |        ---->axis_d
        #      |      \_____/   \______
        #       \__________________:_:_|
        #      :     :                 :
        #      :     :                 :
        #      :     :                 :
        #      :.....:                 :
        #      :  +                    :
        #      : nut_holder_tot        :
        #      :                       :
        #      :...... tens_d .........:
        #
        shp07 = fcfun.shp_cylcenxtr (r = self.bolttens_r_tol,
                                     h = self.nut_holder_tot,
                                     normal = self.axis_d,
                                     ch = 0, xtr_top = 1, xtr_bot = 1,
                                     pos = self.pos_o)
        #  --------------- step 08 --------------------------- 
        # Hole for the leadscrew nut

        #    axis_h
        #      :
        #      : ______________________
        #       /      _____     __:_:_|
        #      |  _   /     \   /
        #      |:1_|:|       | |       -----> axis_d
        #      |      \_____/   \______
        #       \__________________:_:_|
        #      : :   :                 :
        #      :+    :                 :
        #      :nut_holder_thick       :
        #      :.....:                 :
        #      :  +                    :
        #      : nut_holder_total      :
        #      :                       :
        #      :...... tens_d .........:
        #
        # position at pos_d = 1

        shp08 = fcfun.shp_nuthole (
                               nut_r = self.tensnut_circ_r_tol,
                               nut_h = self.nut_space,
                               hole_h = self.tens_w/2,
                               xtr_nut = 1, xtr_hole = 1, 
                               fc_axis_nut = self.axis_d,
                               fc_axis_hole = self.axis_w,
                               ref_nut_ax = 2, # pos not centered on axis nut 
                               # pos at center of nut on axis hole 
                               ref_hole_ax = 1, 
                               pos = self.get_pos_d(1))

        # --------- step 09:
        # --------- Last step, union and cut of the steps 05, 06, 07, 08
        shp09cut = fcfun.fuseshplist([shp05, shp06, shp07, shp08])
        shp09_final = shp03.cut(shp09cut)

        self.shp = shp09_final

        # normal axes to print without support
        self.prnt_ax = self.axis_w


#shp= ShpIdlerTensioner(idler_h = 10. ,
#                 idler_r_in  = 5,
#                 idler_r_ext = 6,
#                 in_fillet = 2.,
#                 wall_thick = 5.,
#                 tens_stroke = 20. ,
#                 pulley_stroke_dist = 0,
#                 nut_holder_thick = 4. ,
#                 boltidler_mtr = 3,
#                 bolttens_mtr = 3,
#                 opt_tens_chmf = 1,
#                 tol = kcomp.TOL,
#                 axis_d = VX,
#                 axis_w = VY,
#                 axis_h = VZ,
#                 pos_d = 0,
#                 pos_w = 0,
#                 pos_h = 0,
#                 pos = V0)

class PartIdlerTensioner (fc_clss.SinglePart, ShpIdlerTensioner):
    """ Integration of a ShpIdlerTensioner object into a PartIlderTensioner
    object, so it is a FreeCAD object that can be visualized in FreeCAD
    """

    def __init__(self,
                 idler_h ,
                 idler_r_in ,
                 idler_r_ext ,
                 in_fillet = 2.,
                 wall_thick = 5.,
                 tens_stroke = 20. ,
                 pulley_stroke_dist = 0,
                 nut_holder_thick = 4. ,
                 boltidler_mtr = 3,
                 bolttens_mtr = 3,
                 opt_tens_chmf = 1,
                 tol = kcomp.TOL,
                 axis_d = VX,
                 axis_w = VY,
                 axis_h = VZ,
                 pos_d = 0,
                 pos_w = 0,
                 pos_h = 0,
                 pos = V0,
                 model_type = 0, # exact
                 name = ''):

        default_name = 'idler_tensioner'
        self.set_name (name, default_name, change = 0)
        # First the shape is created
        ShpIdlerTensioner.__init__(self,
                                  idler_h = idler_h ,
                                  idler_r_in  = idler_r_in,
                                  idler_r_ext = idler_r_ext,
                                  in_fillet = in_fillet,
                                  wall_thick = wall_thick,
                                  tens_stroke = tens_stroke,
                                  pulley_stroke_dist = pulley_stroke_dist,
                                  nut_holder_thick = nut_holder_thick ,
                                  boltidler_mtr = boltidler_mtr,
                                  bolttens_mtr = bolttens_mtr,
                                  opt_tens_chmf = opt_tens_chmf,
                                  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): # so we keep the attributes by CylHole
                setattr(self, i, values[i])

#part= PartIdlerTensioner(idler_h = 10. ,
#                 idler_r_in  = 5,
#                 idler_r_ext = 6,
#                 in_fillet = 2.,
#                 wall_thick = 5.,
#                 tens_stroke = 20. ,
#                 pulley_stroke_dist = 0,
#                 nut_holder_thick = 4. ,
#                 boltidler_mtr = 3,
#                 bolttens_mtr = 3,
#                 opt_tens_chmf = 1,
#                 tol = kcomp.TOL,
#                 axis_d = VX,
#                 axis_w = VY,
#                 axis_h = VZ,
#                 pos_d = 0,
#                 pos_w = 0,
#                 pos_h = 0,
#                 pos = V0)


class IdlerTensionerSet (fc_clss.PartsSet):
    """ Set composed of the idler pulley and the tensioner

    Parameter:
    ---------
    in_fillet: float
        Radius of the inner fillets
    pos_d : int
        Location of pos along the axis_d (0,1,2,3,4,5), see drawing

            * 0: at the back of the holder
            * 1: at the beginning of the hole for the nut (position for the nut)
            * 2: at the beginning of the tensioner stroke hole
            * 3: at the end of the tensioner stroke hole
            * 4: at the inner end of the bearing. It didnt exist in ShpIdlerTensioner
              Therefore, from this, numbers change compared with ShpIdlerTensioner
            * 5: at the center of the idler pulley hole
              it is 4 in ShpIdlerTensioner)
            * 6: at the end of the piece (it is 5 in ShpIdlerTensioner)

    pos_w : int
        Location of pos along the axis_w (0,1) almost symmetrical

            * 0: at the center of symmetry
            * 1: at the end of the tensioner along axis_w
            * 2: at the end of the larger washer along axis_w

    pos_h : int
        Location of pos along the axis_h (0,1,2), symmetrical

            * 0: at the center of symmetry
            * 1: at the inner base: where the base of the pulley goes
            * 2: at the bottom of the piece

    pos : FreeCAD.Vector
        Position of the piece


    See drawing:
    ::

                      nut_holder_thick:  :nut_holder_thick
                                     +:  :+
                                    : :  : :    pulley_stroke_dist
                                    : :  : :       .+.
                                    : :  : :       : :
                                    : :  : :       : :  boltidler_mtr
                                    : :  : :       : :   +
        ________                    : :__:_:_______:_:__:_:___ ....
       |___::___|                    /       ____     __:_:___|....+wall_thick
       |    ....|                   |  __   /     \  |
       |   ()...|     bolttens_mtr::|:|  |:|       | |
       |________|                   |  --   \_____/  |________
       |___::___|                    \__________________:_:___|
                                           :       :
                                           :...+...:
                                              tens_stroke

       origin: pos_o is at point o


          axis_h 
            :                                             pos_h
        ____:____              ____________________________
       |___:_:___|            /       ____     _____:_:____|
      |___________|          |       /     \  ||____:_:____|  large washer
       |_________|           |      |       | |   |_:_:_|     regular wahser
       |     ....|           |  ..  |       | |   | : : |     bearing
       |   :o:   |->axis_w   o::  ::|       | |   | : : |   0 -----> axis_d
       |_________|           |  ..  |       | |   |_:_:_|
       |_________|           |      |       | | __|_:_:_|__ 1
      |___________|          |       \_____/  ||___________|2
       |___:_:___|            \_____________________:_:____|3
      21    0                0  1   2       3     4  5     6 : pos_d 
       pos_w


       tensioner_width is the same as the idler internal diameter


    Attributes:
    -----------
    d0_cen : 0 (int)
    w0_cen : 1 (int)
    h0_cen : 1 (int)
        indicates if pos_h = 0 (pos_d, pos_w) is at the center along
        its axis, or if it is at the end (symmetrical or not)
    tens_d : float
        Depth of the tensioner
    tens_w : float
        width of the tensioner
    tens_h : float
        height of the tensioner
    tens_d_inside : float
        length (depth) of the idler tensioner that can be inside the holder

    """

    def __init__(self, 
                 boltidler_mtr = 3,
                 bolttens_mtr = 3,
                 tens_stroke = 20. ,
                 wall_thick = 5.,
                 in_fillet = 2.,
                 pulley_stroke_dist = 0,
                 nut_holder_thick = 4. ,
                 opt_tens_chmf = 1,
                 tol = kcomp.TOL,
                 axis_d = VX,
                 axis_w = VY,
                 axis_h = VZ,
                 pos_d = 0,
                 pos_w = 0,
                 pos_h = 0,
                 pos = V0,
                 group = 0,
                 name = ''):

        default_name = 'idler_tensioner_set'
        self.set_name (name, default_name, change = 0)

        fc_clss.PartsSet.__init__(self, axis_d = axis_d,
                                  axis_w = axis_w, axis_h = axis_h)

        # save the arguments as attributes:
        frame = inspect.currentframe()
        args, _, _, values = inspect.getargvalues(frame)
        for i in args:
            if not hasattr(self,i): # so we keep the attributes by CylHole
                setattr(self, i, values[i])

        # pos_h/w = 0 are at the center, not pos_d
        self.d0_cen = 0
        self.w0_cen = 1
        self.h0_cen = 1

        # before creating the idler_pulley and the tensioner, we dont
        # know their dimensions and positions. We could calculate them
        # here, but it would be to calculate twice. Instead, we create
        # them, and then move them and calculate the vectors h_o, d_o, w_o

        # Creation of the idler pulley, we put it in the center
        pulley = partset.BearWashSet(metric = boltidler_mtr,
                                            axis_h = axis_h, pos_h = 0,
                                            axis_d = axis_d, pos_d = 0,
                                            axis_w = axis_w, pos_w = 0,
                                            pos = pos)
        self.append_part(pulley)
        pulley.parent = self
        #self.pulley_h =  pulley.tot_h
        #self.pulley_r_in =  pulley.r_in
        #self.pulley_r_ext =  pulley.r_ext
        # Creation of the tensioner, with pos_h,d,w = 0 because we dont know
        # the dimensions yet
        idler_tens_part =  PartIdlerTensioner(
                                     idler_h     = pulley.tot_h ,
                                     idler_r_in  = pulley.r_in,
                                     idler_r_ext = pulley.r_ext,
                                     in_fillet   = in_fillet,
                                     wall_thick  = wall_thick,
                                     tens_stroke = tens_stroke ,
                                     pulley_stroke_dist = pulley_stroke_dist,
                                     nut_holder_thick = nut_holder_thick,
                                     boltidler_mtr = boltidler_mtr,
                                     bolttens_mtr  = bolttens_mtr,
                                     opt_tens_chmf = opt_tens_chmf,
                                     tol    = tol,
                                     axis_d = self.axis_d,
                                     axis_w = self.axis_w,
                                     axis_h = self.axis_h,
                                     pos_d  = 0,
                                     pos_w  = 0,
                                     pos_h  = 0,
                                     pos    = pos)
        self.append_part(idler_tens_part)
        idler_tens_part.parent = self

        self.tens_d = idler_tens_part.tens_d
        self.tens_w = idler_tens_part.tens_w
        self.tens_h = idler_tens_part.tens_h
        self.tens_d_inside = idler_tens_part.tens_d_inside
        self.nut_holder_tot = idler_tens_part.nut_holder_tot

        

        # Now we have to move them and calculate the distance vectors h_o,..
        # pos_d, pos_w, pos_w: are different for the components and the set
        #       axis_h 
        #         :                                     pos_h for Pulley-\
        #         :                           pos_h for idlerTensPart-\
        #         :                         pos_h for TensionerSet-\
        #     ____:____              ____________________________   3  2
        #    |___:_:___|            /       ____     _____:_:____|  2  1  3
        #   |___________|          |       /     \  ||____:_:____|        2
        #    |_________|           |      |       | |   |_:_:_|     1     1
        #    |     ....|           |  ..  |       | |   | : : |   
        #    |   :o:   |           o::  ::|       | |   | : : |     0  0  0
        #    |_________|           |  ..  |       | |   |_:_:_|          -1
        #    |_________|           |      |       | | __|_:_:_|__  -1    -2
        #   |___________|          |       \_____/  ||___________| -2 -1 -3
        #    |___:_:___|            \_____________________:_:____| -3 -2
        #  -21    0    12  TensSet 0  1   2       3     4  5     6 : pos_d 
        #   -1    0    1 iTensPart 0  1   2       3        4     5
        #  -32  -101   23   Pulley                  -3 -2-101 2  3  
        #
        #         |-->axis_w       |---> axis_d

        # When pos_d,w,h are centered, d0_cen, w0_cen, h0_cen = 1
        # h_o[1] is the distance from o to -1, or from 1 to o
        self.d_o[0] = V0
        self.d_o[1] = idler_tens_part.d_o[1]
        self.d_o[2] = idler_tens_part.d_o[2]
        self.d_o[3] = idler_tens_part.d_o[3]
        # He have to add them because pulley.d_o is in opposite direction
        # pulley.d_o[2] is the  distance from o to -2, or from 2 to o
        #             pulley axis -->        + axis to pulley r_in  <--
        self.d_o[4] = idler_tens_part.d_o[4] + pulley.d_o[2]
        self.d_o[5] = idler_tens_part.d_o[4]
        self.d_o[6] = idler_tens_part.d_o[5]

        self.w_o[0] = V0
        self.w_o[1] = pulley.w_o[2]
        self.w_o[2] = pulley.w_o[3]

        # h_o[1] is the distance from o to -1, or from 1 to o
        self.h_o[0] = V0
        self.h_o[1] = pulley.h_o[2]
        self.h_o[2] = pulley.h_o[3]
        self.h_o[3] = idler_tens_part.h_o[2]

        # Now we place the idler tensioner according to pos_d,w,h
        # argument 1 means that pos_o wasnt in place and has to be
        # adjusted
        self.set_pos_o(adjust = 1)

        # Now we have the position where the origin is, but:
        # - we havent located the idler_tensioner at pos_o
        # - we havent located the pulley at pos_o + dist to axis

        # we should have call PartIdlerTensioner (pos = self.pos_o)
        # instead, we have it at (pos = self.pos)
        # so we have to move PartIdlerTensioner self.pos_o - self.pos
        self.set_part_place(idler_tens_part)

        self.set_part_place(pulley, self.get_o_to_d(5))

        # the bolt for the pulley
        bolt_length_list = kcomp.D912_L[boltidler_mtr]
        min_pulley_bolt_l = (  self.tens_h
                             + kcomp.D912[boltidler_mtr]['head_l'])
        pulley_bolt = partset.Din912BoltWashSet(metric  = boltidler_mtr,
                                         shank_l = min_pulley_bolt_l,
                                         # larger considering the washer
                                         shank_l_adjust = 2,
                                         axis_h  = self.axis_h.negative(),
                                         pos_h   = 3,
                                         pos_d   = 0,
                                         pos_w   = 0,
                                         pos     = self.get_pos_dwh(5,0,3))
        self.pulley_bolt_l = pulley_bolt.shank_l
        self.append_part(pulley_bolt)
        pulley_bolt.parent = self

        # the nut for the pulley
        pulley_nut = partset.Din934NutWashSet(metric  = boltidler_mtr,
                                              axis_h = self.axis_h.negative(),
                                              pos_h = 0,
                                              pos = self.get_pos_dwh(5,0,-3))
        self.append_part(pulley_nut)
        pulley_nut.parent = self

        # the nut for the leadscrew
        nut = fc_clss.Din934Nut(metric = bolttens_mtr,
                                axis_h = self.axis_d,
                                axis_d = self.axis_w,
                                pos_h = -1,
                                pos = self.get_pos_d(1), name = 'leadscrew_nut')
        self.append_part(nut)
        nut.parent = self
                                   

        self.place_fcos()
        if group == 1:
            self.make_group()

    def get_idler_tensioner(self):
        """gets the idler tensioner"""
        part_list = self.get_parts()
        for part_i in part_list:
            if isinstance(part_i,PartIdlerTensioner):
                return part_i 

    def get_bear_wash_set(self):
        """gets the idler tensioner"""
        part_list = self.get_parts()
        for part_i in part_list:
            if isinstance(part_i,partset.BearWashSet):
                return part_i 



#idlertensioner= IdlerTensionerSet (
#                 boltidler_mtr = 3,
#                 bolttens_mtr = 3,
#                 tens_stroke = 20. ,
#                 wall_thick = 3.,
#                 in_fillet = 1.,
#                 pulley_stroke_dist = 0,
#                 nut_holder_thick = 4. ,
#                 opt_tens_chmf = 1,
#                 tol = kcomp.TOL,
#                 axis_d = VX,
#                 axis_w = VY,
#                 axis_h = VZ,
#                 pos_d = 0,
#                 pos_w = 0,
#                 pos_h = 3,
#                 pos = FreeCAD.Vector(3,10,5),
#                 name = 'tensioner_group')




class ShpTensionerHolder (shp_clss.Obj3D):
    """ Creates the idler pulley tensioner shape


                              axis_h            axis_h 
                               :                  :
                            ___:___               :______________
                           |  ___  |              |  __________  |---
                           | |   | |              | |__________| | : |
    .---- belt_pos_h------/| |___| |\             |________      |---
    :                    / |_______| \            |        |    /      
    :             . ____/  |       |  \____       |________|  /
    :..hold_bas_h:.|_::____|_______|____::_|      |___::___|/......>axis_d
   
                                wall_thick
                                  +
                                 : :         
                    _____________:_:________.........>axis_w
                   |    |  | :   : |  |     |    :
                   |  O |  | :   : |  |  O  |    + aluprof_w
                   |____|__| :   : |__|_____|....:
                           | :   : |
                           |_:___:_|
                             |   |
                              \_/
                               :
                               :
                             axis_l

                             axis_h            axis_h 
                               :         pos_h    :
    ....................... ___:___         4     :______________
    :                      |  ___  |              |  __________  |---
    :                      | |   | |        3     | |__________| | : |
    :+hold_h              /| |___| |\       2     |________      |---
    :                    / |_______| \            |        |    /      
    :             . ____/  |       |  \____ 1     |________|  /
    :..hold_bas_h:.|_::____|___o___|____::_|0     o___::___|/......>axis_d
                                                  01   2   3     4: pos_d
   
   
   
                    .... hold_bas_w ........
                   :        .hold_w.        :
                   :       :    wall_thick  :
                   :       :      +         :
                   :       :     : :        :
          pos_w:   4__3____2_1_0_:_:________:........>axis_w
                   |    |  | :   : |  |     |    :
                   |  O |  | :   : |  |  O  |    + hold_bas_l
                   |____|__| :   : |__|_____|....:
                           | :   : |
                           |_:___:_|
                             |   |
                              \_/
                               :
                               :
                             axis_d

        pos_o (origin) is at pos_d=0, pos_w=0, pos_h=0, It's marked with o

    The part is referenced along 3 perpendicular axis
      (cartesian coordinate systems):
      - axis_d: depth
      - axis_w: width
      - axis_h: height
    There is a position of the piece:
      - pos: FreeCAD Vector
    This position of the piece (pos) can be at different locations within
      the piece. These locations are defined by:
      - pos_d: location of pos along the axis_d (0,1,2)
         - 0: at the back of the holder
         - 1: at the place where the tensioner can reach all the way inside
         - 2: at the center of the base along axis_d, where the bolts to attach
              the holder base to the aluminum profile
         - 3: at the end of the base
         - 4: at the end of the holder
      - pos_w: location of pos along the axis_w (0,1,2)
         - 0: at the center of symmetry
         - 1: at the inner walls of the holder
         - 2: at the end of the holder (the top part, where the base starts)
         - 3: at the center of the bolt holes to attach the holder base to the
              aluminum profile
         - 4: at the end of the piece along axis_w
              axes have direction. So if pos_w == 3, the piece will be drawn
              along the positive side of axis_w
      - pos_h: location of pos along the axis_h (0,1,2,3)
         - 0: at the bottom of the holder
         - 1: at the top of the base of the holder (for the bolts)
         - 2: at the bottom of the hole where the idler tensioner goes
         - 3: at the middle point of the hole where the idler tensioner goes
         - 4: at the top of the holder

    Parameters
    ----------
    aluprof_w : float
        Width of the aluminum profile
    belt_pos_h : float
        The position along axis_h where the idler pulley that conveys the belt
        starts. THIS POSITION IS CENTERED at the ilder pulley
    tens_h : float
        height of the ilder tensioner
    tens_w : float
        width of the ilder tensioner
    tens_d_inside : float
        Max length (depth) of the ilder tensioner that is inside the holder
    wall_thick : float
        Thickness of the walls
    in_fillet: float
        radius of the inner fillets
    boltaluprof_mtr : integer (could be float 2.5)
        diameter (metric) of the bolt that attachs the tensioner holder to the
        aluminum profile (or whatever is attached to)
    bolttens_mtr : integer (could be float 2.5)
        diameter (metric) of the bolt for the tensioner
    hold_bas_h : float
        height of the base of the tensioner holder
        if 0, it will take wall_thick
    opt_tens_chmf : int
        1: there is a chamfer at every edge of tensioner, inside the holder
        0: there is a chamfer only at the edges along axis_w, not along axis_h
    hold_hole_2sides : int
        In the tensioner holder there is a hole to see inside, it can be at
        each side of the holder or just on one side
        0: only at one side
        1: at both sides
    min_width: make the rim the minimum: the diameter of the washer
        0: normal width: the width of the aluminum profile
        1: minimum width: diameter of the washer
    tol : float
        Tolerances to print
    axis_d : FreeCAD.Vector
        depth vector of coordinate system
    axis_w : FreeCAD.Vector
        width vector of coordinate system
        if V0: it will be calculated using the cross product: axis_l x axis_h
    axis_h : FreeCAD.Vector
        height vector of coordinate system
    pos_d : int
        location of pos along the axis_d (0,1,2,3,4)
        0: at the back of the holder
        1: at the place where the tensioner can reach all the way inside
        2: at the center of the base along axis_d, where the bolts to attach
           the holder base to the aluminum profile
        3: at the end of the base
        4: at the end of the holder
    pos_w : int
        location of pos along the axis_w (0,1,2)
        0: at the center of symmetry
        1: at the inner walls of the holder
        2: at the end of the holder (the top part, where the base starts)
        3: at the center of the bolt holes to attach the holder base to the
           aluminum profile
        4: at the end of the piece along axis_w
              axes have direction. So if pos_w == 3, the piece will be drawn
              along the positive side of axis_w
    pos_h : int
        location of pos along the axis_h (0,1,2,3,4)
        0: at the bottom of the holder
        1: at the top of the base of the holder (for the bolts)
        2: at the bottom of the hole where the idler tensioner goes
        3: at the middle point of the hole where the idler tensioner goes
        4: at the top of the holder
    pos : FreeCAD.Vector
        position of the piece

    Parameters for the set

    tens_in_ratio : float
        from 0 to 1, the ratio of the stroke that the tensioner is inside.
        if 1: it is all the way inside
        if 0: it is all the way outside (all the tens_stroke)





    Attributes:
    -----------
    All the parameters and attributes of father class SinglePart

    prnt_ax : FreeCAD.Vector
        Best axis to print (normal direction, pointing upwards)
    d0_cen : int
    w0_cen : int
    h0_cen : int
        indicates if pos_h = 0 (pos_d, pos_w) is at the center along
        axis_h, axis_d, axis_w, or if it is at the end.
        1 : at the center (symmetrical, or almost symmetrical)
        0 : at the end

    """
    def __init__(self,
                 aluprof_w,
                 belt_pos_h,
                 tens_h,
                 tens_w,
                 tens_d_inside,
                 wall_thick = 3.,
                 in_fillet = 1.,
                 boltaluprof_mtr = 3,
                 bolttens_mtr = 3,
                 hold_bas_h = 0,
                 opt_tens_chmf = 1,
                 hold_hole_2sides = 1,
                 min_width = 0,
                 tol = kcomp.TOL,
                 axis_d = VX,
                 axis_w = VY,
                 axis_h = VZ,
                 pos_d = 0,
                 pos_w = 0,
                 pos_h = 0,
                 pos = V0):
        
        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])

        # pos_w = 0 is at the center, not pos_d, pos_h
        self.d0_cen = 0
        self.w0_cen = 1
        self.h0_cen = 0

        # --- bolt to attach to the aluminum profile
        # dictionary of the bolt
        d_boltaluprof = kcomp.D912[boltaluprof_mtr]
        self.d_boltaluprof = d_boltaluprof
        self.boltaluprof_head_r_tol = d_boltaluprof['head_r_tol']
        self.boltaluprof_r_tol = d_boltaluprof['shank_r_tol']
        self.boltaluprof_head_l = d_boltaluprof['head_l']
        # better to make a hole for the washer
        self.washer_aluprof_d = kcomp.D125[boltaluprof_mtr]['do']
        self.washer_aluprof_r_tol = self.washer_aluprof_d/2.+tol

        # calculation of the dimensions:
        self.hold_w = tens_w + 2*wall_thick

        self.hold_d = tens_d_inside + wall_thick
        # base of the tensioner holder
        if min_width == 0:
            self.rim_w = aluprof_w
        else:
            self.rim_w = self.washer_aluprof_d
        self.hold_bas_w = self.hold_w + 2*self.rim_w
        self.hold_bas_d = aluprof_w
        if hold_bas_h == 0:
            self.hold_bas_h = wall_thick
        else:
            self.hold_bas_h = hold_bas_h

        # --- bolt of the tensioner
        self.bolttens_dict = kcomp.D912[bolttens_mtr]
        # the shank radius including tolerance
        self.bolttens_r_tol = self.bolttens_dict['shank_r_tol']



        #  check that the position of the belt is higher than the minimum
        #                            axis_h
        #                           ___:___
        #                          /  ___  \
        #            ..............| |   | |......
        #            :             | |___| |.....:tens_h/2
        # belt_pos_h +             |_______|
        #            :      _______|       |_______.....
        #            :.....(_______|_______|_______)...+hold_bas_h
        #                                                : :          :
        #  
        if belt_pos_h < tens_h/2. + self.hold_bas_h:
            self.belt_pos_h = tens_h/2. + self.hold_bas_h
            msg = 'argument belt_pos_h is smaller than minimum, new value: '
            logger.warning(msg + str(self.belt_pos_h))
        self.hold_h = self.belt_pos_h + tens_h/2. + wall_thick


        # ------ vectors from the different position points
        # d_o[1] is the distance from o to 1
        self.d_o[0] = V0
        self.d_o[1] = self.vec_d(wall_thick)
        self.d_o[2] = self.vec_d(self.hold_bas_d/2.)
        self.d_o[3] = self.vec_d(self.hold_bas_d)
        self.d_o[4] = self.vec_d(self.hold_d)

        self.w_o[0] = V0
        self.w_o[1] = self.vec_w(-self.tens_w/2.)
        self.w_o[2] = self.vec_w(-self.hold_w/2.)
        self.w_o[3] = self.vec_w(-self.hold_w/2. - self.rim_w/2.)
        self.w_o[4] = self.vec_w(-self.hold_w/2. - self.rim_w)

        # h_o[1] is the distance from o to 1
        self.h_o[0] = V0
        self.h_o[1] = self.vec_h(self.hold_bas_h)
        self.h_o[2] = self.vec_h(self.belt_pos_h - tens_h/2.)
        self.h_o[3] = self.vec_h(self.belt_pos_h)
        self.h_o[4] = self.vec_h(self.hold_h)

        # calculates the position of the origin, and keeps it in attribute pos_o
        self.set_pos_o()


        # --------------- step 01 --------------------------- 
        #    the base, to attach it to the aluminum profiles
        #    
        #
        #                         axis_h                axis_h
        #                            :                  :
        #              .. ___________:___________       :________
        #  hold_bas_h.+..|___________:___________|      |________|...axis_d
        #
        #                 .... hold_bas_w ........
        #                :                        :
        #                :________________________:......axis_w
        #                |           :            |    :
        #                |           :            |    + hold_bas_d
        #                |___________:____________|....:
        #                            :            :
        #                          axis_d
        shp01 = fcfun.shp_box_dir(box_w = self.hold_bas_w,
                                  box_d = self.hold_bas_d,
                                  box_h = self.hold_bas_h,
                                  fc_axis_h = self.axis_h,
                                  fc_axis_d = self.axis_d,
                                  cw=1, cd=0, ch=0, pos=self.pos_o)
        #    --------------- step 02 --------------------------- 
        #    Fillet the base
        #    The piece will be printed on the h w plane, so this fillet will be 
        #    raising
        #  
        #                          axis_h
        #                             :
        #                f4___________:___________f2
        #                 (_______________________)... axis_w
        #                f3                        f1
        #
        bas_fil_r = self.in_fillet
        if self.hold_bas_h/2. <= self.in_fillet:
            msg1 = 'Radius of holder base fillet is larger than 2 x base height'
            msg2 = ' making fillet smaller: '
            bas_fil_r = self.hold_bas_h /2. - 0.1
            logger.warning(msg1 + msg2 + str(bas_fil_r))
        # fillet along axis_d :
        shp02 = fcfun.shp_filletchamfer_dir (shp=shp01, fc_axis=self.axis_d,
                                             fillet = 1, radius=bas_fil_r)

        #    --------------- step 03 --------------------------- 
        #    The main box
        #                          axis_h              axis_h
        #                             :    rim_w         :
        #                             :    ..+....       :
        #           .............. ___:___:       :      :____________
        #           :             |       |       :      |            |
        #           :             |       |       :      |            |
        #   hold_h +:             |       |       :      |            |
        #           :             |       |       :      |            |     
        #           :      _______|       |_______:      |________    |
        #           :.....(_______|_______|_______)      |________|___|...axis_d
        #                                                :            :
        #                  .... hold_bas_w ........      :.. hold_d...:
        #                 :                        :
        #                 :        .hold_w.        :
        #                 :       :       :        :
        #                 :_______:_______:________:.......axis_w
        #                 |       |       |        |    :
        #                 |       |       |        |    + hold_bas_d
        #                 |_______|       |________|....:
        #                         |       |
        #                         |_______|
        #                             :
        #                             :
        #                           axis_d 

        shp03 = fcfun.shp_box_dir(box_w = self.hold_w,
                                  box_d = self.hold_d,
                                  box_h = self.hold_h,
                                  fc_axis_h = self.axis_h,
                                  fc_axis_d = self.axis_d,
                                  cw=1, cd=0, ch=0, pos=self.pos_o)
        #    --------------- step 04 --------------------------- 
        #    Fillets on top
        #                          axis_h   rim_w
        #                             :    ..+....:
        #           .............  ___4___        : 
        #           :             /       \       :
        #           :             |       |       :
        #   hold_h +:             |       |       :
        #           :             |       |       :
        #           :      _______|       |_______:
        #           :.....(_______|_______|_______).... axis_w
    
        #                 :______-2___0___2________:.......axis_w
        #                 |       |       |        |    :
        #                 |       |       |        |    + hold_bas_d
        #                 |_______|       |________|....:
        #                         |       |
        #                         |_______|

        # fillet along axis_d and the vertex should contain points:
        # d=0, w=(-2,2) , h = 4
        pts_list = [self.get_pos_dwh(0,2,4), self.get_pos_dwh(0,-2,4)]
        shp04 = fcfun.shp_filletchamfer_dirpts (shp=shp03,
                                                fc_axis=self.axis_d,
                                                fc_pts=pts_list,
                                                fillet = 1,
                                                radius=self.in_fillet)



        #    --------------- step 05 --------------------------- 
        #    large chamfer at the bottom
        #                axis_h                 axis_h
        #                  :                      :
        #   Option A    ___:___                   :____________
        #              /       \                  |            |
        #              |       |                  |            |
        #              |_______|                  |            |
        #              |       |                  |           /       
        #       _______|_______|_______           |________ /  
        #      (___________C___________)..axis_w  |________|...C...axis_d

        #  
        #               axis_h                 axis_h
        #                  :                      :
        #   Option B    ___:___                   :____________
        #              /       \                  |            |
        #              |       |                  |            |
        #              |       |                  |            |
        #              |_______|                  |            |      
        #       _______|       |_______           |________   /  
        #      (_______|___4___|_______)..axis_w  |________|/..4...axis_d
        #                                         :            :
        #                                         :............:
        #                                               +  
        #                                             hold_d
        #
        # option B: using more material (probably sturdier)
        #chmf_rad = min(self.hold_d - self.hold_bas_d,
        #               self.hold_h - (self.tens_h + 2*wall_thick))
        # option A: using less material
        chmf_rad = min(self.hold_d-self.hold_bas_d + self.hold_bas_h,
                       self.hold_h - (self.tens_h + 2*wall_thick))
        
        print(chmf_rad)
        # Find a point along the vertex that is going to be chamfered.
        # See drawings: Point C:
        if chmf_rad > 0:
            pt_c = self.get_pos_d(4)
            shp05 = fcfun.shp_filletchamfer_dirpt (shp = shp04,
                                                   fc_axis = self.axis_w,
                                                   fc_pt = pt_c,
                                                   fillet = 0,
                                                   radius = chmf_rad)
        else:
            shp05 = shp04

        #    --------------- step 06 --------------------------- 
        #    Hole for the tensioner
        #                                             axis_h
        #                                                :
        #                                                : tens_d_inside
        #                        axis_h                  :  ....+.....
        #                       ___:___                  :_:__________:
        #                      /  ___  \                 |  ..........|
        #                      | | 3 | | pos_d=1,pos_h=3 | 1          |
        #            ..........| |___| |                 | :..........|
        # tens_pos_h +         |_______|                 |            |      
        #            :  _______|       |_______          |________   /  
        #            :.(_______|_______|_______).axis_w  |________|/....axis_d
        #                                                : :          :
        #                                                :+           :
        #                                                :wall_thick  :
        #                                                :            :
        #                                                :............:
        #                                                      +
        #                                                    hold_l
        #

        # position of point A is pos_tens0
        if self.opt_tens_chmf == 0: # no optional chamfer, only along axis_w
            edge_dir = self.axis_w
        else:
            edge_dir = V0

        pos_06 = self.get_pos_dwh(1,0,3)
   
        shp06 = fcfun.shp_boxdir_fillchmfplane(
                               box_w = self.tens_w,
                               box_d = self.hold_d,
                               box_h = self.tens_h,
                               axis_d = self.axis_d,
                               axis_h = self.axis_h,
                               cd=0, cw=1, ch=1,
                               xtr_nd = tol,  #tolerance inside
                               xtr_w  = tol/2.,  #tolerances on each side
                               xtr_nw = tol/2.,
                               xtr_h  = tol/2.,
                               xtr_nh = tol/2.,
                               fillet = 0, # chamfer
                               radius = 2*self.in_fillet-kcomp.TOL,
                               plane_fill = self.axis_d.negative(),
                               both_planes = 0,
                               edge_dir = edge_dir,
                               pos = pos_06)

        #    --------------- step 07 --------------------------- 
        #    A hole to be able to see inside, could be on one side or both
        #
        #    hold_hole_2sides = 1:
        #              axis_h                   axis_h
        #                :                        :
        #             ___:___                     :____________
        #            /  ___  \                    |  ._______ .|
        #            |:|   |:|                    | :|_______| |
        #            | |___| |                    |  ..........|
        #            |_______|                    |            |      
        #     _______|       |_______             |________   /  
        #    (_______|_______|_______)..>axis_w   |________|/......>axis_d
        #
        #    hold_hole_2sides = 0:
        #              axis_h                   axis_h
        #                :                        :
        #             ___:___                     :____________
        #            /  ___  \                    |  ._______ .|
        #            2:|   | |<-Not a hole here   3 *________| |
        #            | |___| |                    |  ..........|
        #            |_______|                    |            |      
        #     _______|       |_______             |________   /  
        #    (_______|_______|_______)..>axis_w   |________|/......>axis_d
        #           -2 pos_w                pos_d = 1

        if self.hold_hole_2sides == 1:
            hold_hole_w = self.hold_w
        else:
            hold_hole_w = self.wall_thick
        # position of point 7:
        # height of point 7, is the center of the tensioner:
        pos_07 = self.get_pos_dwh(1,-2,3)
        shp07 = fcfun.shp_box_dir_xtr (
                                       box_w = hold_hole_w,
                                       box_d =  self.hold_d
                                              - 2*wall_thick,
                                       box_h = tens_h/2.,
                                       fc_axis_h = self.axis_h,
                                       fc_axis_d = self.axis_d,
                                       fc_axis_w = self.axis_w,
                                       ch = 1, cd = 0, cw = 0,
                                       xtr_w = 1, xtr_nw = 1,
                                       pos=pos_07)
        # chamfer the edges
        shp07 = fcfun.shp_filletchamfer_dir (shp=shp07, fc_axis=self.axis_w,
                                             fillet = 0, radius=tens_h/6)
        # /* --------------- step 08 --------------------------- 
        #    A hole for the leadscrew
        #            axis_h             axis_h
        #              :                  :
        #           ___:___               :____________
        #          /  ___  \              |  ._______ .|
        #          |:| O |:|              |::|_______| |
        #          | |___| |              |  ..........|
        #          |_______|              |            |      
        #   _______|       |_______       |________   /  
        #  (_______|_______|_______)      |________|/......> axis_d
        #
        pos_08 = self.get_pos_h(3)
        shp08 = fcfun.shp_cylcenxtr (r = self.bolttens_r_tol,
                                     h = wall_thick,
                                     normal = self.axis_d,
                                     ch = 0, xtr_top=1, xtr_bot=1,
                                     pos = pos_08)

        #    --------------- step 09 --------------------------- 
        #    09a: Fuse all the elements to cut
        #    09b: Cut the box with the elements to cut
        #    09c: Fuse the base with the holder
        #    09d: chamfer the union
        #            axis_h           axis_h
        #              :               :
        #           ___:___            :____________
        #          /  ___  \           |  ._______ .|
        #          |:| O |:|           |::|_______| |...
        #         /| |___| |\          |  ..........|...belt_h/2 -tensnut_ap_tol
        #        / |_______| \         |            |  :+tens_pos_h
        #   ____/__A       B__\____    A________   /   :  ...
        #  (_______|_______|_______)   |________|/.....:.....hold_bas_h
        #
        shp09a = fcfun.fuseshplist([shp06, shp07, shp08])
        shp09b = shp05.cut(shp09a)
        shp09c = shp09b.fuse(shp02) # fuse with the base
        shp09c = shp09c.removeSplitter() # refine shape

        # chamfer the union, points A and B:
        # Radius of chamfer
        chmf_rad = min(self.rim_w/2, self.belt_pos_h - tens_h/2.)
        # add the points A,B to the list to have the edges chamfered
        pts = [self.get_pos_dwh(0,2,1), self.get_pos_dwh(0,-2,1)]
        shp09d = fcfun.shp_filletchamfer_dirpts (shp=shp09c,
                                                 fc_axis=self.axis_d,
                                                 fc_pts=pts,
                                                 fillet = 0,
                                                 radius=chmf_rad)
        shp09d = shp09d.removeSplitter() # refine shape


        #    --------------- step 10 --------------------------- 
        #    Bolt holes to attach the piece to the aluminum profile
        #                                
        #             axis_h            axis_h
        #            ___:___              :____________
        #           /  ___  \             |  ._______ .|
        #           |:| O |:|             |::|_______| |
        #          /| |___| |\            |  ..........|
        #         / |_______| \           |            |
        #    ____/__|       |__\____      |________   /
        #   (__::___|_______|___::__)     |___::___|/....axis_d
        #      -3   pos_w        3      pos_d 2

        #             hold_w   aluprof_w
        #            ...+... ...+...
        #    _______:_______:_______:.......axis_w
        #   |       |       |       |    :
        #   |   A   |       |   B   |    + hold_bas_d
        #   |_______|       |_______|....:
        #           |       |   :
        #           |_______|   :
        #               :       :
        #               :.......:
        #                   +
        #               (hold_w+aluprof_w)/2

        shp_bolt_list = []
        for w_i in [-3,3]:
            # points A and B
            pt_i = self.get_pos_dwh(2,w_i,0)
            shp_i = fcfun.shp_bolt_dir(
                       r_shank = self.boltaluprof_r_tol,
                       l_bolt = self.hold_bas_h +2*self.boltaluprof_head_r_tol,
                       r_head = self.washer_aluprof_r_tol,
                       # extra head, just in case
                       l_head = 2*self.boltaluprof_head_l,
                       xtr_head = 1, xtr_shank = 1,
                       support = 0,
                       fc_normal = self.axis_h.negative(),
                       pos_n = 2, #at the end of the shank
                       pos = pt_i)
            shp_bolt_list.append(shp_i)
        shp10_bolts = fcfun.fuseshplist(shp_bolt_list)
        shp10_final = shp09d.cut(shp10_bolts)
        shp10_final = shp10_final.removeSplitter()

        self.shp = shp10_final
 
        #Part.show(shp10_final)

#doc = FreeCAD.newDocument()
#shp_hold = ShpTensionerHolder(
#                              aluprof_w = 15,
#                              belt_pos_h = 22.,
#                              tens_h = 10.,
#                              tens_w = 10.,
#                              tens_d_inside = 25.,
#                              wall_thick = 3.,
#                              in_fillet = 2.,
#                              boltaluprof_mtr = 3,
#                              bolttens_mtr = 3,
#                              hold_bas_h = 0,
#                              opt_tens_chmf = 1,
#                              hold_hole_2sides = 1,
#                              tol = kcomp.TOL,
#                              axis_d = VX,
#                              axis_w = VY,
#                              axis_h = VZ,
#                              pos_d = 0,
#                              pos_w = 0,
#                              pos_h = 0,
#                              pos = V0)

class PartTensionerHolder (fc_clss.SinglePart, ShpTensionerHolder):
    """ Integration of a ShpTensionerHolder object into a PartTensionerHolder
    object, so it is a FreeCAD object that can be visualized in FreeCAD
    """
    def __init__(self,
                 aluprof_w,
                 belt_pos_h,
                 tens_h,
                 tens_w,
                 tens_d_inside,
                 wall_thick = 3.,
                 in_fillet = 1.,
                 boltaluprof_mtr = 3,
                 bolttens_mtr = 3,
                 hold_bas_h = 0,
                 opt_tens_chmf = 1,
                 hold_hole_2sides = 1,
                 min_width = 0,
                 tol = kcomp.TOL,
                 axis_d = VX,
                 axis_w = VY,
                 axis_h = VZ,
                 pos_d = 0,
                 pos_w = 0,
                 pos_h = 0,
                 pos = V0,
                 model_type = 0, #exact
                 name = ''):

        default_name = 'tensioner_holder'
        self.set_name (name, default_name, change = 0)
        # First the shape is created
        ShpTensionerHolder.__init__(self,
                               aluprof_w = aluprof_w,
                               belt_pos_h = belt_pos_h,
                               tens_h = tens_h,
                               tens_w = tens_w,
                               tens_d_inside = tens_d_inside,
                               wall_thick = wall_thick,
                               in_fillet = in_fillet,
                               boltaluprof_mtr = boltaluprof_mtr,
                               bolttens_mtr = bolttens_mtr,
                               hold_bas_h = hold_bas_h,
                               opt_tens_chmf = opt_tens_chmf,
                               hold_hole_2sides = hold_hole_2sides,
                               min_width = min_width,
                               #tol = tol,
                               tol = 3.5*tol, #extra tol needed
                               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)
        fc_clss.SinglePart.__init__(self)


#doc = FreeCAD.newDocument()
#holder = PartTensionerHolder(
#                              aluprof_w = 15,
#                              belt_pos_h = 22.,
#                              tens_h = 10.,
#                              tens_w = 10.,
#                              tens_d_inside = 25.,
#                              wall_thick = 3.,
#                              in_fillet = 2.,
#                              boltaluprof_mtr = 3,
#                              bolttens_mtr = 3,
#                              hold_bas_h = 0,
#                              opt_tens_chmf = 1,
#                              hold_hole_2sides = 1,
#                              tol = kcomp.TOL,
#                              axis_d = VX,
#                              axis_w = VY,
#                              axis_h = VZ,
#                              pos_d = 0,
#                              pos_w = 0,
#                              pos_h = 0,
#                              pos = V0,
#                              name = 'tensioner_holder')


[docs]class TensionerSet (fc_clss.PartsSet): """ Set composed of the idler pulley and the tensioner :: axis_h axis_h : : ___:___ :______________ | ___ | | __________ |--- | | | | | |__________| | : | .---- belt_pos_h------/| |___| |\ |________ |--- : / |_______| \ | | / : . ____/ | | \____ |________| / :..hold_bas_h:.|_::____|_______|____::_| |___::___|/......>axis_d wall_thick + : : _____________:_:________.........>axis_w | | | : : | | | : | O | | : : | | O | + aluprof_w |____|__| : : |__|_____|....: | : : | |_:___:_| | | \_/ : : axis_d axis_h axis_h : pos_h : ....................... ___:___ 4 :______________ : | ___ | | __________ |--- : | | | | 3 | |__________| | : | :+hold_h /| |___| |\ 2 |________ |--- : / |_______| \ | | / : . ____/ | | \____ 1 |________| / :..hold_bas_h:.|_::____|___o___|____::_|0 o___::___|/......>axis_d 01 2 3 4 5 6: pos_d having the tensioner extended: 7 8 _____________ : : |--------- | : | |--------- .... hold_bas_w ........ : .hold_w. : : : wall_thick : : : + : : : : : : pos_w: 4__3____2_1_0_:_:________:........>axis_w | | | : : | | | : | O | | : : | | O | + hold_bas_l |____|__| : : |__|_____|....: | : : | |_:___:_| | | \_/ : : axis_d pos_o (origin) is at pos_d=0, pos_w=0, pos_h=0, It marked with o Parameters ---------- aluprof_w : float Width of the aluminum profile belt_pos_h : float The position along axis_h where the idler pulley that conveys the belt starts. THIS POSITION IS CENTERED at the ilder pulley tens_h : float Height of the ilder tensioner tens_w : float Width of the ilder tensioner tens_d_inside : float Max length (depth) of the ilder tensioner that is inside the holder wall_thick : float Thickness of the walls in_fillet: float Radius of the inner fillets boltaluprof_mtr : float Diameter (metric) of the bolt that attachs the tensioner holder to the aluminum profile (or whatever is attached to) bolttens_mtr : float Diameter (metric) of the bolt for the tensioner hold_bas_h : float Height of the base of the tensioner holder if 0, it will take wall_thick opt_tens_chmf : int * 1: there is a chamfer at every edge of tensioner, inside the holder * 0: there is a chamfer only at the edges along axis_w, not along axis_h hold_hole_2sides : int In the tensioner holder there is a hole to see inside, it can be at each side of the holder or just on one side * 0: only at one side * 1: at both sides min_width: int Make the rim the minimum: the diameter of the washer * 0: normal width: the width of the aluminum profile * 1: minimum width: diameter of the washer tol : float Tolerances to print axis_d : FreeCAD.Vector Depth vector of coordinate system axis_w : FreeCAD.Vector Width vector of coordinate system if V0: it will be calculated using the cross product: axis_l x axis_h axis_h : FreeCAD.Vector Height vector of coordinate system pos_d : int Location of pos along the axis_d * 0: at the back of the holder * 1: at the place where the tensioner can reach all the way inside * 2: at the center of the base along axis_d, where the bolts to attach * the holder base to the aluminum profile * 3: at the end of the base * 4: at the end of the holder * 5: at the center of the pulley * 6: at the end of the idler tensioner * 7: at the center of the pulley, when idler is all the way out * 8: at the end of the idler tensioner, whenit is all the way out pos_w : int Location of pos along the axis_w * 0: at the center of symmetry * 1: at the inner walls of the holder, which is the pulley radius * 2: at the end of the holder (the top part, where the base starts) * 3: at the center of the bolt holes to attach the holder base to the aluminum profile * 4: at the end of the piece along axis_w axes have direction. So if pos_w == 3, the piece will be drawn along the positive side of axis_w pos_h : int Location of pos along the axis_h (0,1,2,3,4) * 0: at the bottom of the holder * 1: at the top of the base of the holder (for the bolts) * 2: at the bottom of the hole where the idler tensioner goes * 3: at the middle point of the hole where the idler tensioner goes * 4: at the top of the holder pos : FreeCAD.Vector position of the piece Paramenters for the set tens_in_ratio : float from 0 to 1, the ratio of the stroke that the tensioner is inside. * if 1: it is all the way inside * if 0: it is all the way outside (all the tens_stroke) Note ---- All the parameters and attributes of father class SinglePart Attributes ----------- prnt_ax : FreeCAD.Vector Best axis to print (normal direction, pointing upwards) d0_cen : int w0_cen : int h0_cen : int indicates if pos_h = 0 (pos_d, pos_w) is at the center along axis_h, axis_d, axis_w, or if it is at the end. * 1 : at the center (symmetrical, or almost symmetrical) * 0 : at the end tot_d : float total depth, including the idler tensioner tot_d_extend : float total depth including the idler tensioner, having it extended """ def __init__(self, aluprof_w = 20., belt_pos_h = 20., hold_bas_h = 0, hold_hole_2sides = 0, boltidler_mtr = 3, bolttens_mtr = 3, boltaluprof_mtr = 3, tens_stroke = 20. , wall_thick = 3., in_fillet = 2., pulley_stroke_dist = 0, nut_holder_thick = 4. , opt_tens_chmf = 1, min_width = 0, tol = kcomp.TOL, axis_d = VX, axis_w = VY, axis_h = VZ, pos_d = 0, pos_w = 0, pos_h = 0, pos = V0, group = 0, name = ''): default_name = 'tensioner_set' self.set_name (name, default_name, change = 0) fc_clss.PartsSet.__init__(self, axis_d = axis_d, axis_w = axis_w, axis_h = axis_h) # save the arguments as attributes: frame = inspect.currentframe() args, _, _, values = inspect.getargvalues(frame) for i in args: if not hasattr(self,i): # so we keep the attributes by CylHole setattr(self, i, values[i]) # pos_w = 0 is at the center, not pos_d, pos_h self.d0_cen = 0 self.w0_cen = 1 self.h0_cen = 0 # Creation of the idler pulley set, we cannot know the relative # position from pos, so we put it at pos_d,w,h = 0 idler_tensioner = IdlerTensionerSet( boltidler_mtr = boltidler_mtr, bolttens_mtr = bolttens_mtr, tens_stroke = tens_stroke, wall_thick = wall_thick, in_fillet = in_fillet, pulley_stroke_dist = pulley_stroke_dist, nut_holder_thick = nut_holder_thick , opt_tens_chmf = opt_tens_chmf, tol = tol, axis_d = self.axis_d, axis_w = self.axis_w, axis_h = self.axis_h, pos_d = 0, pos_w = 0, pos_h = 0, pos = pos) self.append_part(idler_tensioner) idler_tensioner.parent = self # creation of the holder tensioner_holder = PartTensionerHolder( aluprof_w = aluprof_w, belt_pos_h = belt_pos_h, tens_h = idler_tensioner.tens_h, tens_w = idler_tensioner.tens_w, tens_d_inside = idler_tensioner.tens_d_inside, wall_thick = wall_thick, in_fillet = in_fillet, boltaluprof_mtr = boltaluprof_mtr, bolttens_mtr = bolttens_mtr, hold_bas_h = hold_bas_h, opt_tens_chmf = opt_tens_chmf, hold_hole_2sides = hold_hole_2sides, min_width = min_width, tol = tol, axis_d = self.axis_d, axis_w = self.axis_w, axis_h = self.axis_h, pos_d = 0, pos_w = 0, pos_h = 0, pos = pos, model_type = 0) #exact self.append_part(tensioner_holder) idler_tensioner.parent = self self.d_o[0] = V0 self.d_o[1] = tensioner_holder.d_o[1] self.d_o[2] = tensioner_holder.d_o[2] self.d_o[3] = tensioner_holder.d_o[3] self.d_o[4] = tensioner_holder.d_o[4] self.d_o[5] = self.d_o[1] + idler_tensioner.d_o[5] self.d_o[6] = self.d_o[1] + idler_tensioner.d_o[6] self.d_o[7] = self.d_o[5] + self.vec_d(tens_stroke) self.d_o[8] = self.d_o[6] + self.vec_d(tens_stroke) self.tot_d = self.d_o[6].Length self.tot_d_extend = self.d_o[8].Length # these are the same for i in tensioner_holder.w_o: self.w_o[i] = tensioner_holder.w_o[i] for i in tensioner_holder.h_o: self.h_o[i] = tensioner_holder.h_o[i] # Now we place the idler tensioner according to pos_d,w,h # argument 1 means that pos_o wasnt in place and has to be # adjusted self.set_pos_o(adjust = 1) # Now we have the position where the origin is, but: # - we havent located the idler_tensioner at pos_o # - we havent located the pulley at pos_o + dist to axis # we should have call PartIdlerTensioner (pos = self.pos_o) # instead, we have it at (pos = self.pos) # so we have to move PartIdlerTensioner self.pos_o - self.pos self.set_part_place(tensioner_holder) self.set_part_place(idler_tensioner, self.get_o_to_d(1) + self.get_o_to_h(3)) # bolt and washer for the leadscrew bolt_length_list = kcomp.D912_L[bolttens_mtr] max_tens_bolt_l = ( idler_tensioner.tens_stroke + idler_tensioner.nut_holder_tot + tensioner_holder.wall_thick) print('max tens:' + str(max_tens_bolt_l)) tens_bolt = partset.Din912BoltWashSet( metric = bolttens_mtr, shank_l = max_tens_bolt_l, # smaller considering the washer shank_l_adjust = -2, axis_h = self.axis_d, pos_h = 3, pos_d = 0, pos_w = 0, pos = self.get_pos_dwh(0,0,3)) self.append_part(tens_bolt) tens_bolt.parent = self self.place_fcos() if group == 1: self.make_group() def get_tensioner_holder(self): """ gets the tensioner holder""" part_list = self.get_parts() for part_i in part_list: if isinstance(part_i, PartTensionerHolder): return part_i def get_idler_tensioner(self): """ gets the idler tensioner set""" part_list = self.get_parts() for part_i in part_list: if isinstance(part_i, IdlerTensionerSet): return part_i def set_pos_tensioner (self, new_tens_out_ratio = None): """ Sets the tensioner place, depending on the attributes tens_in_ratio and tens_stroke Parameters: ----------- new_tens_out_ratio : float [0,1] ratio of the tensioner that is outside. It can be any value from 0 to 1 0: all the way inside 1: maximum value outside (tens_stroke) """ if new_tens_out_ratio is not None: # set the new tens_in_ratio self.tens_out_ratio = new_tens_out_ratio self.tens_out = self.tens_out_ratio * self.tens_stroke idler_tensioner = self.get_idler_tensioner() idler_tensioner.extra_mov = idler_tensioner.vec_d(self.tens_out) self.place_fcos()
""" doc = FreeCAD.newDocument() t_set1 = TensionerSet( aluprof_w = 20., #belt_pos_h = 32.5, #bottom of belt:30 + 2.5 to center #belt_pos_h = 37.5, #bottom of belt:35 + 2.5 to center #belt_pos_h = 47.5, #bottom of belt:45 + 2.5 to center belt_pos_h = 20., # to center of belt hold_bas_h = 0, hold_hole_2sides = 1, boltidler_mtr = 3, bolttens_mtr = 3, boltaluprof_mtr = 3, tens_stroke = 12. , wall_thick = 3., in_fillet = 2., pulley_stroke_dist = 0, nut_holder_thick = 3. , opt_tens_chmf = 0, min_width = 0, tol = kcomp.TOL, axis_d = VX, axis_w = VYN, axis_h = VZ, pos_d = 0, pos_w = 0, pos_h = 0, #pos = FreeCAD.Vector(1,0,10), pos = FreeCAD.Vector(0,0,0), name = 'tensioner_set') # get the set, and the the part t_set1.get_idler_tensioner().get_idler_tensioner().set_color(fcfun.ORANGE) t_set1.get_tensioner_holder().set_color(fcfun.LSKYBLUE) t_set2 = TensionerSet( aluprof_w = 20., #belt_pos_h = 32.5, #bottom of belt:30 + 2.5 to center #belt_pos_h = 37.5, #bottom of belt:35 + 2.5 to center #belt_pos_h = 47.5, #bottom of belt:45 + 2.5 to center belt_pos_h = 20., # to center of belt hold_bas_h = 0, hold_hole_2sides = 1, boltidler_mtr = 3, bolttens_mtr = 3, boltaluprof_mtr = 3, tens_stroke = 12. , wall_thick = 3., in_fillet = 2., pulley_stroke_dist = 0, nut_holder_thick = 3. , opt_tens_chmf = 0, min_width = 0, tol = kcomp.TOL, axis_d = VX, axis_w = VYN, axis_h = VZ, pos_d = 0, pos_w = 0, pos_h = 0, pos = FreeCAD.Vector( t_set1.get_tensioner_holder().hold_bas_w,0,0), name = 'tensioner_set_extend') # get the set, and the the part t_set2.get_idler_tensioner().get_idler_tensioner().set_color(fcfun.ORANGE) t_set2.get_tensioner_holder().set_color(fcfun.LSKYBLUE) t_set2.set_pos_tensioner(1) # --------- doc = FreeCAD.newDocument() t_set1 = TensionerSet( aluprof_w = 20., #belt_pos_h = 32.5, #bottom of belt:30 + 2.5 to center #belt_pos_h = 37.5, #bottom of belt:35 + 2.5 to center #belt_pos_h = 47.5, #bottom of belt:45 + 2.5 to center belt_pos_h = 45., # to center of belt hold_bas_h = 0, hold_hole_2sides = 1, boltidler_mtr = 3, bolttens_mtr = 3, boltaluprof_mtr = 3, tens_stroke = 12. , wall_thick = 3., in_fillet = 2., pulley_stroke_dist = 0, nut_holder_thick = 3. , opt_tens_chmf = 0, min_width = 0, tol = kcomp.TOL, axis_d = VX, axis_w = VYN, axis_h = VZ, pos_d = 0, pos_w = 0, pos_h = 0, #pos = FreeCAD.Vector(1,0,10), pos = FreeCAD.Vector(0,0,0), name = 'tensioner_set') # get the set, and the the part t_set1.get_idler_tensioner().get_idler_tensioner().set_color(fcfun.ORANGE) t_set1.get_tensioner_holder().set_color(fcfun.LSKYBLUE) t_set2 = TensionerSet( aluprof_w = 20., #belt_pos_h = 32.5, #bottom of belt:30 + 2.5 to center #belt_pos_h = 37.5, #bottom of belt:35 + 2.5 to center #belt_pos_h = 47.5, #bottom of belt:45 + 2.5 to center belt_pos_h = 25., # to center of belt hold_bas_h = 0, hold_hole_2sides = 1, boltidler_mtr = 3, bolttens_mtr = 3, boltaluprof_mtr = 3, tens_stroke = 12. , wall_thick = 3., in_fillet = 2., pulley_stroke_dist = 0, nut_holder_thick = 3. , opt_tens_chmf = 0, min_width = 0, tol = kcomp.TOL, axis_d = VX, axis_w = VYN, axis_h = VZ, pos_d = 0, pos_w = 0, pos_h = 0, pos = FreeCAD.Vector( 55,0,0), name = 'tensioner_set_extend') # get the set, and the the part t_set2.get_idler_tensioner().get_idler_tensioner().set_color(fcfun.ORANGE) t_set2.get_tensioner_holder().set_color(fcfun.LSKYBLUE) # all the way extended #t_set2.set_pos_tensioner(1) t_set3 = TensionerSet( aluprof_w = 20., #belt_pos_h = 32.5, #bottom of belt:30 + 2.5 to center #belt_pos_h = 37.5, #bottom of belt:35 + 2.5 to center #belt_pos_h = 47.5, #bottom of belt:45 + 2.5 to center belt_pos_h = 5., # to center of belt hold_bas_h = 0, hold_hole_2sides = 1, boltidler_mtr = 3, bolttens_mtr = 3, boltaluprof_mtr = 3, tens_stroke = 12. , wall_thick = 3., in_fillet = 2., pulley_stroke_dist = 0, nut_holder_thick = 3. , opt_tens_chmf = 0, min_width = 0, tol = kcomp.TOL, axis_d = VX, axis_w = VYN, axis_h = VZ, pos_d = 0, pos_w = 0, pos_h = 0, pos = FreeCAD.Vector( 100,0,0), name = 'tensioner_set_extend') # get the set, and the the part t_set3.get_idler_tensioner().get_idler_tensioner().set_color(fcfun.ORANGE) t_set3.get_tensioner_holder().set_color(fcfun.LSKYBLUE) # all the way extended #t_set3.set_pos_tensioner(1) """ #t_set30 = TensionerSet( # aluprof_w = 30., # #belt_pos_h = 32.5, #bottom of belt:30 + 2.5 to center # #belt_pos_h = 37.5, #bottom of belt:35 + 2.5 to center # #belt_pos_h = 47.5, #bottom of belt:45 + 2.5 to center # belt_pos_h = 33.5, # hold_bas_h = 8, # hold_hole_2sides = 1, # boltidler_mtr = 4, # bolttens_mtr = 4, # boltaluprof_mtr = 4, # tens_stroke = 20. , # wall_thick = 5., # in_fillet = 2., # pulley_stroke_dist = 0, # nut_holder_thick = 4. , # opt_tens_chmf = 1, # min_width = 0, # tol = kcomp.TOL, # axis_d = VX, # axis_w = VYN, # axis_h = VZ, # pos_d = 0, # pos_w = 0, # pos_h = 0, # #pos = FreeCAD.Vector(1,0,10), # pos = FreeCAD.Vector(-80,0,0), # name = 'tensioner_set') # ## get the set, and the the part #t_set30.get_idler_tensioner().get_idler_tensioner().set_color(fcfun.ORANGE) #t_set30.get_tensioner_holder().set_color(fcfun.LSKYBLUE)