Source code for comp_optic

# ----------------------------------------------------------------------------
# -- Components
# -- comps library
# -- Python classes that creates optical components
# ----------------------------------------------------------------------------
# -- (c) Felipe Machado
# -- Area of Electronic Techonology. Rey Juan Carlos University (urjc.es)
# -- July-2017
# ----------------------------------------------------------------------------
# --- LGPL Licence
# ----------------------------------------------------------------------------


import FreeCAD
import Part
import logging
import os
import Draft
import DraftGeomUtils
import DraftVecUtils
import math
#import copy
import Mesh
import MeshPart

# ---------------------- 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 
import kcomp_optic
import fcfun
import kparts 

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__)

# ---------------------- CageCube -------------------------------

class CageCube (object):

    """ 
    Creates Cage Cube for optics
    taps are only drawn with their max diameter, 
    setscrews and taps to secure the rods are not drawn
    
    Parameters
    ----------
    side_l: float
        Length of the side of the cube
    thru_hole_d: float
        Big thru-hole on 2 sides, not threaded, centered
    thru_thread_d: float
        2 big thru-hole threaded, on 4 sides, centered
    thru_rod_d: float 
        4 thru holes, on 2 sides
    thru_rod_sep: float
        Separation of the rods
    rod_thread_d: float
        On the sides other than the thru_rods, there are threads
        to insert a rod
    rod_thread_l: float
        Depth of the thread for the rods
    tap_d: float
        Diameter of the tap to connect accesories
    tap_l: float
        Depth of the taps to connect accesories
    tap_sep_l: float
        Separation of the tap to connect, large
    tap_sep_s: float
        Separation of the tap to connect, sort
    axis_thru_rods: str
        Direction of rods: 'x', 'y', 'z'
    axis_thru_hole: str
        Direction big thru_hole: 'x', 'y', 'z'.
        
        Note
        ----
        Cannot be the same as axis_thru_rods
        There are 6 posible orientations:
        Thru-rods can be on X, Y or Z axis
        thru-hole can be on X, Y, or Z axis, but not in the same as thru-rods
    """
    ROD_SCREWS = kcomp_optic.ROD_SCREWS
    THRU_RODS = kcomp_optic.THRU_RODS
    THRU_HOLE = kcomp_optic.THRU_HOLE  

    def __init__ (self, side_l,
                        thru_hole_d,
                        thru_thread_d,
                        thru_rod_d,
                        thru_rod_sep,
                        rod_thread_d,
                        rod_thread_l,
                        tap_d,
                        tap_l,
                        tap_sep_l,
                        tap_sep_s,
                        axis_thru_rods = 'x',
                        axis_thru_hole = 'y',
                        name = 'cagecube'):

        doc = FreeCAD.ActiveDocument

        self.base_place = (0,0,0)
        self.side_l  = side_l
        self.thru_hole_d = thru_hole_d
        self.thru_thread_d = thru_thread_d
        self.thru_rod_d = thru_rod_d
        self.axis_thru_rods = axis_thru_rods
        self.axis_thru_hole = axis_thru_hole
        # getting the freecad vector of the axis
        self.v_thru_rods = fcfun.getfcvecofname(axis_thru_rods)
        self.v_thru_hole = fcfun.getfcvecofname(axis_thru_hole)
        # get the 3rd perpendicular vector
        self.v_rod_screws =  self.v_thru_rods.cross (self.v_thru_hole)

        # cage
        shp_cage_box = fcfun.shp_boxcen(x=side_l,
                                        y=side_l,
                                        z=side_l, 
                                        cx=1, cy=1, cz=1,
                                        pos=V0)

        # centered Thru hole: 1
        shp_thru_hole_cen0 = fcfun.shp_cylcenxtr (r= thru_hole_d/2.,
                                             h = side_l,
                                             normal = self.v_thru_hole,
                                             ch=1, xtr_top=1., xtr_bot=1.,
                                             pos = V0)
        holes = []
        #holes.append(shp_thru_hole_cen0)

        # threaded thru-holes, centered:2
        # getting the perpendicular directions of v_thru_hole
        # if (1,0,0) -> (0,1,0)
        v_thru_hole_perp1 = FreeCAD.Vector(self.v_thru_hole.y,
                                           self.v_thru_hole.z,
                                           self.v_thru_hole.x);
        shp_thru_hole_cen1 = fcfun.shp_cylcenxtr (r= thru_thread_d/2.,
                                             h = side_l,
                                             normal = v_thru_hole_perp1,
                                             ch=1, xtr_top=1., xtr_bot=1.,
                                             pos = V0)

        holes.append(shp_thru_hole_cen1)
        v_thru_hole_perp2 = FreeCAD.Vector(self.v_thru_hole.z,
                                           self.v_thru_hole.x,
                                           self.v_thru_hole.y);
        shp_thru_hole_cen2 = fcfun.shp_cylcenxtr (r= thru_thread_d/2.,
                                             h = side_l,
                                             normal = v_thru_hole_perp2,
                                             ch=1, xtr_top=1., xtr_bot=1.,
                                             pos = V0)
        holes.append(shp_thru_hole_cen2)

        # thru-holes for the rods:
        # dimensions are added to the axis other than the normal
        fc_list = fcfun.get_fclist_4perp2_vecname(axis_thru_rods)
        for fcvec in fc_list: 
          fc_dist = DraftVecUtils.scale(fcvec, thru_rod_sep/2.)
          shp_thru_hole_rod = fcfun.shp_cylcenxtr (r= thru_rod_d/2.,
                                             h = side_l,
                                             normal = self.v_thru_rods,
                                             ch=1, xtr_top=1., xtr_bot=1.,
                                             pos = fc_dist)
          holes.append(shp_thru_hole_rod)

        # taps to connect rods. 4 in 4 sides (not on the side of the thru-holes
        # for the rods
        # get the four directions, of the normals
        fc_rodtap_list = fcfun.get_fclist_4perp_vecname(axis_thru_rods)
        for vnormal in fc_rodtap_list:
            # for each normal, we take the other 4 perpendicular axis
            # for example, is vnormal is (1,0,0), the 4 perpendicular axis
            # will be (0,1,1), (0,-1,1), (0,-1,-1), (0,1,-1)
            fc_perp_coord_list = fcfun.get_fclist_4perp2_fcvec(vnormal)
            vnormal_coord = DraftVecUtils.scale(vnormal,
                                                 (side_l/2. -rod_thread_l))
            for fc_perp_coord in fc_perp_coord_list:
                fc_perp_coord_scale = DraftVecUtils.scale(fc_perp_coord,
                                                     thru_rod_sep/2.)
                fc_coord = fc_perp_coord_scale + vnormal_coord
                shp_rodtap = fcfun.shp_cylcenxtr (r= rod_thread_d/2,
                                                  h = rod_thread_l,
                                                  normal = vnormal,
                                                  ch=0, xtr_top =1.,
                                                  xtr_bot=0,
                                                  pos = fc_coord)
                holes.append (shp_rodtap)



        # taps for mounting a cover, on the 2 sides of the centered thru-hole
        # direction: self.v_thru_hole and negated
        for vnormal in [self.v_thru_hole, DraftVecUtils.neg(self.v_thru_hole)]:
            vnormal_coord = DraftVecUtils.scale(vnormal,
                                               (side_l/2. -tap_l))
            # the large separation is the same as the thru rods
            for vdir_large in [self.v_thru_rods,
                                DraftVecUtils.neg(self.v_thru_rods)]:
                #scale this direction to the length of the separation (half)
                fc_coord_large =  DraftVecUtils.scale(vdir_large, tap_sep_l/2.)
                # the sort separation: cross product
                vdir_short = vnormal.cross (vdir_large)
                vdir_short.normalize()
                for vdir_short_i in [vdir_short, DraftVecUtils.neg(vdir_short)]:
                    fc_coord_short = DraftVecUtils.scale(vdir_short_i,
                                                         tap_sep_s/2.)
                    fc_coord = vnormal_coord + fc_coord_large + fc_coord_short
                    shp_tap = fcfun.shp_cylcenxtr (r= tap_d/2,
                                                  h = tap_l,
                                                  normal = vnormal,
                                                  ch=0, xtr_top =1.,
                                                  xtr_bot=0,
                                                  pos = fc_coord)
                    holes.append (shp_tap)
  
       


        shp_holes = shp_thru_hole_cen0.multiFuse(holes)
        shp_holes = shp_holes.removeSplitter()

        shp_cage = shp_cage_box.cut(shp_holes)


        doc.recompute()
        fco_cage = doc.addObject("Part::Feature", name )
        fco_cage.Shape = shp_cage
        self.fco = fco_cage


    def BasePlace (self, position = (0,0,0)):
        self.base_place = position
        self.fco.Placement.Base = FreeCAD.Vector(position)

    def color (self, color = (1,1,1)):
        self.fco.ViewObject.ShapeColor = color

    def vec_face (self, fcv):
        """Return which face of the cube corresponds to the direction fcv

        Arguments:
        fcf -- FreeCAD.Vector pointing to the normal of the cube face
               we want to check

        returns: a string indicating the face. There are 3 different cube
               faces:
            'thruhole' : the face with the big central hole is a thruhole
                         without threads
            'thrurods' : the face that has 4 thruholes for the rods and a 
                         threaded big central hole 
            'rodscrews': the face has 4 tapped holes for screwing the
                         end of the rods and a threaded big central hole
            'none': the vector isn't parallel to any of the faces of the cube
 
        """
        #normalize the vector:
        nv = DraftVecUtils.scaleTo(fcv,1)
        if fcfun.fc_isparal(self.v_thru_hole, nv):
            return self.THRU_HOLE
        elif fcfun.fc_isparal(self.v_thru_rods, nv):
            return self.THRU_RODS
        elif fcfun.fc_isparal(self.v_rod_screws, nv):
            return self.ROD_SCREWS
        else:
            return 0

    def get_cenhole_d (self, face):
        """ Given a face defined in kcomp_optic.py, returns the size of the
            central hole

        Arguments:
            face: THRU_HOLE (3), THRU_RODS (2), ROD_SCREWS (1)

        """

        if face == self.THRU_HOLE:
            return self.thru_hole_d
        elif face == self.THRU_RODS or face == self.ROD_SCREWS:
            return self.thru_thread_d
        else:
            logger.debug('wrong value of face of cage cube')
            return 0

        


# ------------------ END CageCube ------------------------------



# ------------------ f_cagecube   ------------------------------

[docs]def f_cagecube (d_cagecube, axis_thru_rods = 'x', axis_thru_hole = 'y', name = 'cagecube', toprint_tol = 0): """ Creates a cage cube, it creates from a dictionary Parameters ---------- d_cagecube: Dictionary with the dimensions of the cage cube, defined in kcomp_optic.py axis_thru_rods: str Direction of rods: 'x', 'y', 'z' axis_thru_hole: str Direction big thru_hole: 'x', 'y', 'z'. Note ---- Cannot be the same as axis_thru_rods There are 6 posible orientations: Thru-rods can be on X, Y or Z axis thru-hole can be on X, Y, or Z axis, but not in the same as thru-rods toprint_tol: float * 0, dimensions as they are. * >0 value of tolerances of the holes. multiplies the normal tolerance in kcomp.TOL Returns ------- CageCube. The freeCAD object can be accessed by the attribute .fco """ if toprint_tol > 0: tol = toprint_tol * kcomp.TOL tol_plus = 1.5 * toprint_tol * kcomp.TOL else: tol = 0 tol_plus = 0 print ('tol: ' + str(tol)) print ('tol_plus: ' + str(tol_plus)) cage = CageCube(side_l = d_cagecube['L'], thru_hole_d = d_cagecube['thru_hole_d'] + tol, thru_thread_d = d_cagecube['thru_thread_d'] + tol, thru_rod_d = d_cagecube['thru_rod_d'] + tol_plus, thru_rod_sep = d_cagecube['thru_rod_sep'], rod_thread_d = d_cagecube['rod_thread_d'] + tol, rod_thread_l = d_cagecube['rod_thread_l'] + tol, tap_d = d_cagecube['tap_d'] + tol, tap_l = d_cagecube['tap_l'] + tol, tap_sep_l = d_cagecube['tap_sep_l'], tap_sep_s = d_cagecube['tap_sep_s'], axis_thru_rods = axis_thru_rods, axis_thru_hole = axis_thru_hole, name = name) return cage
#doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument # Cage cube to print, with tolerances #dcube = kcomp_optic.CAGE_CUBE_60 #h_cage_c = f_cagecube(dcube, # axis_thru_rods= 'z', axis_thru_hole='x', # name = "cube60_tol", # toprint_tol = 1) # ---------------------- CageCubeHalf ------------------------------- class CageCubeHalf (object): """ Creates a Half Cage Cube for optics, so you can put the lense at 45 taps are only drawn with their max diameter, setscrews and taps to secure the rods are not drawn Many other details are not drawn, neither the cover for the lense The right angle sides are identical, but there is a difference regarding to the tapped holes on the sides, the can have different sizes Parameters ---------- side_l: float Length of the side of the cube (then it will be halved) thread_d: float 2 big threads, on the 2 perpendicular sides, centered thru_hole_d: float Internal hole after the thread thru_hole_depth: float Depth from which the thru hole starts lenshole_45_d: float Hole from the 45 angle side that will go to the center rod_d: float 4 holes, on 2 sides, perpendicular sides. The rods will be secured with screws, but those screws are not drawn rod_sep: float Separation of the rods rod_depth: float How deep are the holes rod_thread_l: float Depth of the thread for the rods tap_d: float Diameter of the tap to connect accesories tap_l: float Depth of the taps to connect accesories tap_sep_l: float Separation of the tap to connect, large tap_sep_s: float Separation of the tap to connect, sort axis_1: str Direction of the first right side: 'x', 'y', 'z', '-x', '-y', '-z' axis_2: str Direction big the other right side: 'x', 'y', 'z', '-x', '-y', '-z' Note ----- Cannot be the same as axis_1, or its negated. Has to be perpendicular There are 24 posible orientations: 6 posible axis_1 and 4 axis_2 for each axis_1 name: str Name of the freecad object """ def __init__ (self, side_l, thread_d, thru_hole_d, thru_hole_depth, lenshole_45_d, rod_d, rod_sep, rod_depth, tap12_d, tap12_l, tap21_d, tap21_l, tap_dist, axis_1 = 'x', axis_2 = 'y', name = 'cagecube'): doc = FreeCAD.ActiveDocument self.base_place = (0,0,0) self.side_l = side_l self.thread_d = thread_d self.thru_hole_d = thru_hole_d self.thru_hole_depth = thru_hole_depth self.lenshole_45_d = lenshole_45_d self.rod_d = rod_d self.rod_sep = rod_sep self.rod_depth = rod_depth self.axis_1 = axis_1 self.axis_2 = axis_2 # getting the freecad vector of the axis self.v_1 = fcfun.getfcvecofname(axis_1) self.v_2 = fcfun.getfcvecofname(axis_2) # cage shp_cage_box = fcfun.shp_boxcen(x=side_l, y=side_l, z=side_l, cx=1, cy=1, cz=1, pos=V0) # taking the half away (it is less than the half) # the normal is on the opposite direction of the sum of axis_1 and # axis_2 v_halfout = DraftVecUtils.neg(self.v_1 + self.v_2) v_halfout.normalize() # Making the cut with a cilinder, because it is easier, since the # function is already availabe # radius is smaller: pythagoras, but to make it simpler # the position is not just the half, about a centimeter less, but # just thake the thru_hole_depth pos_halfout = DraftVecUtils.scaleTo(v_halfout, thru_hole_depth) shp_halfout = fcfun.shp_cyl(r= side_l, h=side_l, normal = v_halfout, pos = pos_halfout) doc.recompute() #Part.show(shp_halfout) # hole on the 45 face, for the lense # on position (0,0,0) but the same direction as the previous # the heigth is hypotenuse, but to symplify and to cut over the total # length, we make it twice the cathetus shp_lensehole = fcfun.shp_cyl(r= lenshole_45_d/2., h=2*thru_hole_depth, normal = v_halfout, pos = V0) # make the cut know because freecad was having problems making the cut # all together, maybe because there 45 degrees cuts that shp_45cut = shp_halfout.fuse(shp_lensehole) shp_cage_half = shp_cage_box.cut(shp_45cut) shp_cage_half = shp_cage_half.removeSplitter() doc.recompute() #Part.show(shp_cage_half) holes = [] # threaded holes, centered:2 pos_thread_1 = DraftVecUtils.scale(self.v_1, side_l/2.-thru_hole_depth) shp_thread_1 = fcfun.shp_cylcenxtr (r= thread_d/2., h = thru_hole_depth, normal = self.v_1, ch=0, xtr_top=1., xtr_bot=0., pos = pos_thread_1) # Not included in the list, because one element has to be out #holes.append(shp_thread_1) pos_thread_2 = DraftVecUtils.scale(self.v_2, side_l/2.-thru_hole_depth) shp_thread_2 = fcfun.shp_cylcenxtr (r= thread_d/2., h = thru_hole_depth, normal = self.v_2, ch=0, xtr_top=1., xtr_bot=0., pos = pos_thread_2) holes.append(shp_thread_2) # thru holes, centered:2, on the direction of right angles shp_thru_1 = fcfun.shp_cylcenxtr (r= thru_hole_d/2., h = side_l, normal = self.v_1, ch=1, xtr_top=1., xtr_bot=1., pos = V0) holes.append(shp_thru_1) shp_thru_2 = fcfun.shp_cylcenxtr (r= thru_hole_d/2., h = side_l, normal = self.v_2, ch=1, xtr_top=1., xtr_bot=1., pos = V0) holes.append(shp_thru_2) # holes to connect rods. 4 in 2 sides (perpendicular sides) # get the four directions, of the normals for vnormal in [self.v_1, self.v_2]: # for each normal, we take the other 4 perpendicular axis # for example, is vnormal is (1,0,0), the 4 perpendicular axis # will be (0,1,1), (0,-1,1), (0,-1,-1), (0,1,-1) fc_perp_coord_list = fcfun.get_fclist_4perp2_fcvec(vnormal) # position on the normal dimension (where the rod hole starts) vnormal_coord = DraftVecUtils.scale(vnormal, (side_l/2. -rod_depth)) for fc_perp_coord in fc_perp_coord_list: fc_perp_coord_scale = DraftVecUtils.scale(fc_perp_coord, rod_sep/2.) fc_coord = fc_perp_coord_scale + vnormal_coord shp_rodhole = fcfun.shp_cylcenxtr (r= rod_d/2, h = rod_depth, normal = vnormal, ch=0, xtr_top =1., xtr_bot=0, pos = fc_coord) holes.append (shp_rodhole) # taps to mount to posts # get the direction axis_1 x axis_2 vdir_12 = self.v_1.cross (self.v_2) vdir_21 = self.v_2.cross (self.v_1) axis1_coord = DraftVecUtils.scale(self.v_1, tap_dist) axis2_coord = DraftVecUtils.scale(self.v_2, tap_dist) axis12_coord = DraftVecUtils.scale(vdir_12, side_l/2. - tap12_l) axis21_coord = DraftVecUtils.scale(vdir_21, side_l/2. - tap21_l) fc_pos12 = axis1_coord + axis2_coord + axis12_coord fc_pos21 = axis1_coord + axis2_coord + axis21_coord shp_tap12 = fcfun.shp_cylcenxtr (r = tap12_d/2, h = tap12_l, normal = vdir_12, ch=0, xtr_top =1., xtr_bot=0, pos = fc_pos12) shp_tap21 = fcfun.shp_cylcenxtr (r = tap21_d/2, h = tap21_l, normal = vdir_21, ch=0, xtr_top =1., xtr_bot=0, pos = fc_pos21) holes.append (shp_tap12) holes.append (shp_tap21) shp_holes = shp_thread_1.multiFuse(holes) shp_holes = shp_holes.removeSplitter() doc.recompute() #Part.show(shp_holes) shp_cage_holes = shp_cage_half.cut(shp_holes) doc.recompute() fco_cage = doc.addObject("Part::Feature", name ) fco_cage.Shape = shp_cage_holes self.fco = fco_cage def BasePlace (self, position = (0,0,0)): self.base_place = position self.fco.Placement.Base = FreeCAD.Vector(position) def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
[docs]def f_cagecubehalf (d_cagecubehalf, axis_1 = 'x', axis_2 = 'y', name = 'cagecubehalf' ): """ Dreates a half cage cube: 2 perpendicular sides, and a 45 degree angle side. It creates from a dictionary Parameters ---------- d_cagecubehalf: dict Dictionary with the dimensions of the cage cube, defined in kcomp_optic.py axis_1: str Direction of the first right side: 'x', 'y', 'z', '-x', '-y', '-z' axis_2: str Direction big the other right side: 'x', 'y', 'z', '-x', '-y', '-z' Note ---- Cannot be the same as axis_1, or its negated. Has to be perpendicular There are 24 posible orientations: 6 posible axis_1 and 4 axis_2 for each axis_1 name: str Name of the freecad object """ cage = CageCubeHalf( side_l = d_cagecubehalf['L'], thread_d = d_cagecubehalf['thread_d'], thru_hole_d = d_cagecubehalf['thru_hole_d'], thru_hole_depth = d_cagecubehalf['thru_hole_depth'], lenshole_45_d = d_cagecubehalf['lenshole_45_d'], rod_d = d_cagecubehalf['rod_d'], rod_sep = d_cagecubehalf['rod_sep'], rod_depth = d_cagecubehalf['rod_depth'], tap12_d = d_cagecubehalf['tap12_d'], tap12_l = d_cagecubehalf['tap12_l'], tap21_d = d_cagecubehalf['tap21_d'], tap21_l = d_cagecubehalf['tap21_l'], tap_dist = d_cagecubehalf['tap_dist'], axis_1 = axis_1, axis_2 = axis_2, name = name) return cage
#cage = f_cagecubehalf(kcomp_optic.CAGE_CUBE_HALF_60) #cage = CageCube(side_l = kcomp_optic.CAGE_CUBE_60['L'], # thru_hole_d = kcomp_optic.CAGE_CUBE_60['thru_hole_d'], # thru_thread_d = kcomp_optic.CAGE_CUBE_60['thru_thread_d'], # thru_rod_d = kcomp_optic.CAGE_CUBE_60['thru_rod_d'], # thru_rod_sep = kcomp_optic.CAGE_CUBE_60['thru_rod_sep'], # rod_thread_d, # rod_thread_l, # tap_d, # tap_l, # tap_sep_l, # tap_sep_s, # axis_thru_rods = 'x', # axis_thru_hole = 'y', # name = 'cagecube')
[docs]class Lb1cPlate (object): """ Creates a LB1C/M plate from thorlabs. The plate is centered :: fc_axis_l: axis on the large separation | | :-- sy_hole_sep -: : : :cbore_hole_sep_s: : : : : _______________________ | O O | ------------------- | 0 0 | .... : | | : : | | : : | ( ) | +sym_hole_sep + cbore_hole_sep_l | | : : | 0 0 | .... : | O O | ------------------- |______________________| ________________________ | :: : ::..: | fc_axis_h |__::___H______________| if ref_in=1 | -> h=0 ________________________ if ref_in=0 -> h=0 | :: : ::..: | | |__::___H______________| V fc_axis_h Parameters ---------- d_plate: dict Dictionary with the dimensions fc_axis_h: FreeCAD.Vector Direction of the vertical (thickness) fc_axis_l: FreeCAD.Vector Direction of the large distance of the counterbored asymetrical holes ref_in: int * 1: fc_axis_h starts on the inside to outside of the plate * 0: fc_axis_h starts on the outside to inside of the plate pos: FreeCAD.Vector Position of the center. The center is on the center of the plate, but on the axis_h can be in either side depending on ref_in name: str Name """ def __init__ (self, d_plate, fc_axis_h = VZ, fc_axis_l = VX, ref_in = 1, pos = V0, name = 'lb1c_plate'): doc = FreeCAD.ActiveDocument # dictionary with the dimensions self.d_plate = d_plate side_l = d_plate['L'] thick = d_plate['thick'] sym_hole_d = d_plate['sym_hole_d'] sym_hole_sep = d_plate['sym_hole_sep'] cbore_hole_d = d_plate['cbore_hole_d'] cbore_hole_head_d =d_plate['cbore_hole_head_d'] cbore_hole_head_l =d_plate['cbore_hole_head_l'] cbore_hole_sep_l =d_plate['cbore_hole_sep_l'] cbore_hole_sep_s =d_plate['cbore_hole_sep_s'] # normalize de axis axis_h = DraftVecUtils.scaleTo(fc_axis_h,1) axis_l = DraftVecUtils.scaleTo(fc_axis_l,1) axis_s = fc_axis_l.cross(fc_axis_h) shp_box = fcfun.shp_box_dir(side_l, side_l, thick, axis_h, axis_l, cw = 1, cd = 1, ch = 0, pos = pos) if ref_in == 1: # the holes mounting hole (center) and the cap holes will start # on the other side, and will go on negated axis_h. # For the other holes (thruholes) it doesn't matter pos_h_add = DraftVecUtils.scale(axis_h, thick) axis_hole = DraftVecUtils.neg(axis_h) # for the ring: axis_ring = axis_h pos_ring = pos + DraftVecUtils.scale(axis_h, - d_plate['seal_ring_thick'] ) else: pos_h_add = V0 axis_hole = axis_h axis_ring = DraftVecUtils.neg(axis_h) pos_ring = pos + DraftVecUtils.scale(axis_h, thick + d_plate['seal_ring_thick'] ) shp_cenhole = fcfun.shp_cylcenxtr(r=d_plate['mhole_d']/2., h=d_plate['mhole_depth'], normal=axis_hole, ch = 0, xtr_top=0, xtr_bot=1, pos=pos + pos_h_add) # Retaining ring hole shp_ringhole = fcfun.shp_cylholedir ( r_out = ( d_plate['seal_ring_d']/2. + d_plate['seal_ring_thick']/2.), r_in = ( d_plate['seal_ring_d']/2. - d_plate['seal_ring_thick']/2.), h = 2 * d_plate['seal_ring_thick'], normal = axis_ring, pos = pos_ring) holes = [shp_ringhole] # symetrical holes for add_l in (DraftVecUtils.scaleTo(axis_l, sym_hole_sep/2), DraftVecUtils.scaleTo(axis_l, - sym_hole_sep/2)) : for add_s in (DraftVecUtils.scaleTo(axis_s, sym_hole_sep/2), DraftVecUtils.scaleTo(axis_s, - sym_hole_sep/2)) : pos_hole = pos + add_l + add_s shp_hole = fcfun.shp_cylcenxtr(r=sym_hole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_hole) holes.append(shp_hole) # asymetrical hole for add_l in (DraftVecUtils.scaleTo(axis_l, cbore_hole_sep_l/2), DraftVecUtils.scaleTo(axis_l, - cbore_hole_sep_l/2)) : for add_s in (DraftVecUtils.scaleTo(axis_s, cbore_hole_sep_s/2), DraftVecUtils.scaleTo(axis_s, - cbore_hole_sep_s/2)) : pos_hole = pos + add_l + add_s shp_hole = fcfun.shp_cylcenxtr(r=cbore_hole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_hole) shp_hole_head = fcfun.shp_cylcenxtr(r=cbore_hole_head_d/2., h=cbore_hole_head_l, normal=axis_hole, ch = 0, xtr_top=0, xtr_bot=1, pos=pos_hole + pos_h_add) shp_cbore_hole = shp_hole.fuse(shp_hole_head) holes.append(shp_cbore_hole) shp_holes = shp_cenhole.multiFuse(holes) shp_plate = shp_box.cut(shp_holes) doc.recompute() fco_plate = doc.addObject("Part::Feature", name ) fco_plate.Shape = shp_plate self.fco = fco_plate def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
#doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument #Lb1cPlate (kcomp_optic.LB1CM_PLATE) #Lb1cPlate (kcomp_optic.LB1CM_PLATE, # fc_axis_h = VY, # fc_axis_l = VXN, # ref_in = 0, # pos = V0) def plate_thruhole_hole8 (side_l, thick, thruhole_d, sym_hole_d, sym_hole_sep, cbore_hole_d, cbore_hole_head_d, cbore_hole_head_l, cbore_hole_sep_l, cbore_hole_sep_s, fc_axis_h, fc_axis_l, cl=1, cw=1, ch=1, pos = V0, name = 'plate'): """ Draws a square plate, with a thru-hole in the center. * 4 sets of holes in symetrical positions for screws * 4 sets of holes for cap-screws :: fc_axis_l: axis on the large separation | | :-- sy_hole_sep -: : : :cbore_hole_sep_s: : : : : _______________________ | O O | ------------------- | 0 .... 0 | .... : | / \ | : : | | | | : : | | | | +sym_hole_sep + cbore_hole_sep_s | \ .... / | : : | 0 0 | .... : | O O | ------------------- |______________________| Parameters ---------- side_l: float Length of the plate (two sides) thick: float Thickness (height of the plate) thruhole_d: float Diamenter of the central hole sym_hole_d: float Diamenter of the symetrical holes sym_hole_sep: float Distance between the centers of the symetrical holes cbore_hole_d: float Diameter of the shank of the counter bored hole cbore_hole_head_d: float Diameter of the cap of the counterbored screw cbore_hole_head_l: float Length of the cap (head) of the counterbored screw cbore_hole_sep_l: float Large separation of the counterbored holes cbore_hole_sep_s: float Small separation of the counterbored holes fc_axis_h: FreeCAD.Vector Direction of the vertical (thickness) from the inside of the plate fc_axis_l: FreeCAD.Vector Direction of the large distance of the counterbored asymetrical holes cl: int 1: centered on the fc_axis_l direction cw: int * 1: centered on the axis_small direction (perpendicular to fc_axis_l and fc_axis_h) ch: int * 1: centered on the vertical direction (thickness) pos: FreeCAD.Vector Position of the center. name: str name """ doc = FreeCAD.ActiveDocument # normalize de axis axis_h = DraftVecUtils.scaleTo(fc_axis_h,1) axis_l = DraftVecUtils.scaleTo(fc_axis_l,1) axis_s = fc_axis_l.cross(fc_axis_h) shp_box = fcfun.shp_box_dir(side_l, side_l, thick, axis_h, axis_l, cw = cl, cd = cw, ch = ch, pos = pos) # getting the offset of the center coordinates if cl == 1: l_0 = V0 # already centered else: l_0 = DraftVecUtils.scaleTo(axis_l, side_l/2.) if cw == 1: s_0 = V0 else: s_0 = DraftVecUtils.scaleTo(axis_s, side_l/2.) if ch == 1: # for the height, we want the lower side h_0 = DraftVecUtils.scaleTo(axis_h, -thick/2.) else: h_0 = V0 pos_center = pos + l_0 + s_0 + h_0 shp_cenhole = fcfun.shp_cylcenxtr(r=thruhole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_center) # symetrical holes holes = [] for add_l in (DraftVecUtils.scaleTo(axis_l, sym_hole_sep/2), DraftVecUtils.scaleTo(axis_l, - sym_hole_sep/2)) : for add_s in (DraftVecUtils.scaleTo(axis_s, sym_hole_sep/2), DraftVecUtils.scaleTo(axis_s, - sym_hole_sep/2)) : pos_hole = pos_center + add_l + add_s shp_hole = fcfun.shp_cylcenxtr(r=sym_hole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_hole) holes.append(shp_hole) # asymetrical hole for add_l in (DraftVecUtils.scaleTo(axis_l, cbore_hole_sep_l/2), DraftVecUtils.scaleTo(axis_l, - cbore_hole_sep_l/2)) : for add_s in (DraftVecUtils.scaleTo(axis_s, cbore_hole_sep_s/2), DraftVecUtils.scaleTo(axis_s, - cbore_hole_sep_s/2)) : pos_hole = pos_center + add_l + add_s shp_hole = fcfun.shp_cylcenxtr(r=cbore_hole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_hole) pos_head = ( pos_hole + DraftVecUtils.scaleTo(axis_h, thick-cbore_hole_head_l)) shp_hole_head = fcfun.shp_cylcenxtr(r=cbore_hole_head_d/2., h=cbore_hole_head_l, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=0, pos=pos_head) shp_cbore_hole = shp_hole.fuse(shp_hole_head) holes.append(shp_cbore_hole) shp_holes = shp_cenhole.multiFuse(holes) shp_plate = shp_box.cut(shp_holes) #doc.recompute() #fco_plate = doc.addObject("Part::Feature", name ) #fco_plate.Shape = shp_plate #return (fco_plate) return (shp_plate) # def BasePlace (self, position = (0,0,0)): # self.base_place = position # self.fco.Placement.Base = FreeCAD.Vector(position) def plate_lb2c ( fc_axis_h, fc_axis_l, cl=1, cw=1, ch=0, pos = V0, name = 'lb2c_plate'): shp_plate = plate_thruhole_hole8 ( side_l = kcomp_optic.LB2C_PLATE['L'], # 76.2, thick = kcomp_optic.LB2C_PLATE['thick'], thruhole_d = kcomp_optic.LB2C_PLATE['thruhole_d'], sym_hole_d = kcomp_optic.LB2C_PLATE['sym_hole_d'], sym_hole_sep = kcomp_optic.LB2C_PLATE['sym_hole_sep'], cbore_hole_d = kcomp_optic.LB2C_PLATE['cbore_hole_d'], cbore_hole_head_d = kcomp_optic.LB2C_PLATE['cbore_hole_head_d'], cbore_hole_head_l = kcomp_optic.LB2C_PLATE['cbore_hole_head_l'], cbore_hole_sep_l = kcomp_optic.LB2C_PLATE['cbore_hole_sep_l'], cbore_hole_sep_s = kcomp_optic.LB2C_PLATE['cbore_hole_sep_s'], fc_axis_h = fc_axis_h, fc_axis_l = fc_axis_l, cl=cl, cw=cw, ch=ch, pos = pos, name = name) return shp_plate #doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument #plate_lb2c (fc_axis_h = VZ, fc_axis_l = VX, cl=1, cw=1, ch=0, pos=V0, # name = 'lb2c_plate')
[docs]class Lb2cPlate (object): """ Same as plate_lb2c, but it creates an object. Parameters ---------- fc_axis_h: FreeCAD.Vector Direction of the vertical (thickness) fc_axis_l: FreeCAD.Vector Direction of the large distance of the counterbored asymetrical holes cl: int * 1: centered on the fc_axis_l direction cw: int * 1: centered on the axis_small direction (perpendicular to fc_axis_l and fc_axis_h) ch: int * 1: centered on the vertical direction (thickness) pos: FreeCAD.Vector Position of the center. The center is on the center of the plate, but on the axis_h can be in either side depending on ref_in name: str Name """ def __init__(self, fc_axis_h, fc_axis_l, cl=1, cw=1, ch=0, pos = V0, name = 'lb2c_plate'): doc = FreeCAD.ActiveDocument self.base_place = (0,0,0) shp_plate = plate_thruhole_hole8 ( side_l = kcomp_optic.LB2C_PLATE['L'], # 76.2, thick = kcomp_optic.LB2C_PLATE['thick'], thruhole_d = kcomp_optic.LB2C_PLATE['thruhole_d'], sym_hole_d = kcomp_optic.LB2C_PLATE['sym_hole_d'], sym_hole_sep = kcomp_optic.LB2C_PLATE['sym_hole_sep'], cbore_hole_d = kcomp_optic.LB2C_PLATE['cbore_hole_d'], cbore_hole_head_d = kcomp_optic.LB2C_PLATE['cbore_hole_head_d'], cbore_hole_head_l = kcomp_optic.LB2C_PLATE['cbore_hole_head_l'], cbore_hole_sep_l = kcomp_optic.LB2C_PLATE['cbore_hole_sep_l'], cbore_hole_sep_s = kcomp_optic.LB2C_PLATE['cbore_hole_sep_s'], fc_axis_h = fc_axis_h, fc_axis_l = fc_axis_l, cl=cl, cw=cw, ch=ch, pos = pos, name = name) self.side_l = kcomp_optic.LB2C_PLATE['L'] # 76.2 self.thick = kcomp_optic.LB2C_PLATE['thick'] self.thruhole_d = kcomp_optic.LB2C_PLATE['thruhole_d'] self.sym_hole_d = kcomp_optic.LB2C_PLATE['sym_hole_d'] self.sym_hole_sep = kcomp_optic.LB2C_PLATE['sym_hole_sep'] self.cbore_hole_d = kcomp_optic.LB2C_PLATE['cbore_hole_d'] self.cbore_hole_head_d = kcomp_optic.LB2C_PLATE['cbore_hole_head_d'] self.cbore_hole_head_l = kcomp_optic.LB2C_PLATE['cbore_hole_head_l'] self.cbore_hole_sep_l = kcomp_optic.LB2C_PLATE['cbore_hole_sep_l'] self.cbore_hole_sep_s = kcomp_optic.LB2C_PLATE['cbore_hole_sep_s'] self.fc_axis_h = fc_axis_h self.fc_axis_l = fc_axis_l self.cl=cl self.cw=cw self.ch=ch self.pos = pos self.name = name doc.recompute() fco_plate = doc.addObject("Part::Feature", name ) fco_plate.Shape = shp_plate self.fco = fco_plate def BasePlace (self, position = (0,0,0)): self.base_place = position self.fco.Placement.Base = FreeCAD.Vector(position) def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
#doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument #Lb2cPlate (fc_axis_h = VZ, fc_axis_l = VX, cl=1, cw=1, ch=0, pos=V0, # name = 'lb2c_plate') class PlateThruholeMhole (object): """ Draws a square plate, with a thru-hole in the center. * 1 hole on the side to mount it * 4 sets of holes in symetrical positions for screws * 4 sets of holes for cap-screws if any of these holes are zero, they will not be made :: fc_axis_m: axis on the mounting hole : : :-- sy_hole_sep -: : : :cbore_hole_sep_s: : : : : _______________________ | O O | ------------------- | 0 .... 0 | .... : | / \ | : : 6 | 2 | | : : | | | | +sym_hole_sep + cbore_hole_sep_l | \ .... / | : : | 0 0 | .... : | O ... O | ------------------- 5_________:1:__________| mounting hole / \ : fc_axis_m /\ fc_axis_h : ___________:____________.... | | : | 4 | : thick |___________3___________|....: mounting hole (4) Parameters ---------- side_l: float Length of the plate (two sides) thick: float Thickness (height of the plate) thruhole_d: float Diamenter of the central hole. If 0: no hole mhole_d:float Diameter of the mounting hole mhole_l: Length (depth) of the mounting hole. If 0: no hole sym_hole_d: Diamenter of the symetrical holes. If 0: no hole sym_hole_sep: float Distance between the centers of the symetrical holes cbore_hole_d: float Diameter of the shank of the counter bored hole. If 0: no hole cbore_hole_head_d: float Diameter of the cap of the counterbored screw cbore_hole_head_l: float Length of the cap (head) of the counterbored screw cbore_hole_sep_l: float Large separation of the counterbored holes cbore_hole_sep_s: float Small separation of the counterbored holes cbore_hole_sep_l_axis_m: float if the long separation of the cbore holes are in the direction of the axis_m or not * 1: like the drawing * 0: switchin cbore_hole_sep_l for cbore_hole_sep_s in the drawing chmf_r: float If >0 vertical edges are chamfered fc_axis_h: FreeCAD.Vector Direction of the vertical (thickness) from the inside of the plate fc_axis_m: FreeCAD.Vector Direction of the mounting hole goes in the mounting hole fc_axis_p: FreeCAD.Vector perpendicular direction of axis_h and axis_m, only used if not centered on this axis cm: int * 0: it will be on the mounting hole (point 1) * 1: centered on the fc_axis_m direction (point 2) cp: int * 0: points 5 (cm==0) or 6 (cm==1) * 1: centered on the perpendicular direction of fc_axis_m and fc_axis_h), if 0, fc_axis_p needs to be defined ch: int * 1: centered on the vertical direction (thickness) pos: FreeCAD.Vector Position of the center. name: str Name of the object :: _______________________ | O O | ------------------- | 0 .... 0 | .... : | / \ | : : | | | | : : | | | | +sym_hole_sep + cbore_hole_sep_l | \ .... / | : : | 0 0 | .... : | O ... O | ------------------- |_________:1:__________| : V fc_axis_m: axis on the mounting hole, goes outside ________________________.... |___________O___________|....: thick """ def __init__(self, side_l, thick, thruhole_d, mhole_d, mhole_l, sym_hole_d, sym_hole_sep, cbore_hole_d, cbore_hole_head_d, cbore_hole_head_l, cbore_hole_sep_l, cbore_hole_sep_s, cbore_hole_sep_l_axis_m =1, chmf_r = 0, fc_axis_h = VZ, fc_axis_m =VX, fc_axis_p = V0, cm=1, cp=1, ch=1, pos = V0, wfco=1, name = 'plate'): doc = FreeCAD.ActiveDocument self.sym_hole_d = sym_hole_d self.sym_hole_sep = sym_hole_sep # normalize de axis axis_h = DraftVecUtils.scaleTo(fc_axis_h,1) axis_m = DraftVecUtils.scaleTo(fc_axis_m,1) axis_m_n = axis_m.negative() if cp == 0: axis_p = DraftVecUtils.scaleTo(fc_axis_p,1) else: # no need to use fc_axis_p axis_p = axis_m.cross(axis_h) if cbore_hole_d > 0: if cbore_hole_sep_l_axis_m == 1: # long axis on axis_m axis_l = axis_m axis_s = axis_p else: axis_l = axis_p axis_s = axis_m else: axis_l = V0 axis_s = V0 self.h = thick self.l = side_l self.axis_h = axis_h self.axis_m = axis_m self.axis_p = axis_p self.axis_l = axis_l self.axis_s = axis_s self.pos = pos shp_box = fcfun.shp_box_dir(box_w=side_l, box_d = side_l, box_h= thick, fc_axis_h = axis_h, fc_axis_d= axis_m, cw = cp, cd = cm, ch = ch, pos = pos) if chmf_r > 0: shp_box = fcfun.shp_filletchamfer_dir(shp_box, axis_h, fillet = 0, radius = chmf_r) doc.recompute() # getting the offset of the center coordinates if cm == 1: m_0 = V0 # already centered m_mhole = DraftVecUtils.scaleTo(axis_m, -side_l/2.) else: m_0 = DraftVecUtils.scaleTo(axis_m, side_l/2.) m_mhole = V0 if cp == 1: p_0 = V0 else: p_0 = DraftVecUtils.scaleTo(axis_p, side_l/2.) if ch == 1: # for the height, we want the lower side h_0 = DraftVecUtils.scaleTo(axis_h, -thick/2.) h_cen = V0 h_top = DraftVecUtils.scaleTo(axis_h, thick/2.) else: h_0 = V0 h_cen = DraftVecUtils.scaleTo(axis_h, thick/2.) h_top = DraftVecUtils.scaleTo(axis_h, thick) # reference positions: # vector from the reference (pos) to the center fc_ref2center = m_0 + p_0 + h_cen # vector from the reference (pos) to the center at the bottom fc_ref2botcen = m_0 + p_0 + h_0 # vector from the reference (pos) to the center at the bottom fc_ref2topcen = m_0 + p_0 + h_top # vector from the reference (pos) to the mounting hole fc_ref2mhole = m_mhole + p_0 + h_0 self.fc_ref2center = fc_ref2center self.fc_ref2botcen = fc_ref2botcen self.fc_ref2topcen = fc_ref2topcen self.fc_ref2mhole = fc_ref2mhole # position at the center, except for axis_h: at its lower point botcen_pos = pos + fc_ref2botcen # m_0 + p_0 + h_0 topcen_pos = pos + fc_ref2topcen # m_0 + p_0 + h_top # position at the center center_pos = pos + fc_ref2center # m_0 + p_0 + h_cen # it doesnt matter if there is no mounting hole mount_pos = pos + fc_ref2mhole self.botcen_pos = botcen_pos self.topcen_pos = topcen_pos self.center_pos = center_pos self.mount_pos = mount_pos holes = [] # central hole if thruhole_d > 0: shp_cenhole = fcfun.shp_cylcenxtr(r=thruhole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=botcen_pos) holes.append(shp_cenhole) # mounting hole if mhole_d > 0: shp_mhole = fcfun.shp_cylcenxtr(r=mhole_d/2., h=mhole_l, normal=axis_m, ch = 0, xtr_top=0, xtr_bot=1., pos=mount_pos) holes.append(shp_mhole) # symetrical holes if sym_hole_d > 0: for add_m in (DraftVecUtils.scaleTo(axis_m, sym_hole_sep/2), DraftVecUtils.scaleTo(axis_m, - sym_hole_sep/2)) : for add_p in (DraftVecUtils.scaleTo(axis_p, sym_hole_sep/2), DraftVecUtils.scaleTo(axis_p, - sym_hole_sep/2)) : pos_hole = botcen_pos + add_m + add_p shp_hole = fcfun.shp_cylcenxtr(r=sym_hole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_hole) holes.append(shp_hole) # asymetrical holes if cbore_hole_d > 0: for add_l in (DraftVecUtils.scaleTo(axis_l, cbore_hole_sep_l/2), DraftVecUtils.scaleTo(axis_l, - cbore_hole_sep_l/2)) : for add_s in (DraftVecUtils.scaleTo(axis_s, cbore_hole_sep_s/2), DraftVecUtils.scaleTo(axis_s, - cbore_hole_sep_s/2)) : pos_hole = botcen_pos + add_l + add_s shp_hole = fcfun.shp_cylcenxtr(r=cbore_hole_d/2., h=thick, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_hole) pos_head = ( pos_hole + DraftVecUtils.scaleTo(axis_h, thick-cbore_hole_head_l)) shp_hole_head = fcfun.shp_cylcenxtr(r=cbore_hole_head_d/2., h=cbore_hole_head_l, normal=axis_h, ch = 0, xtr_top=1., xtr_bot=0, pos=pos_head) shp_cbore_hole = shp_hole.fuse(shp_hole_head) holes.append(shp_cbore_hole) shp_holes = fcfun.fuseshplist(holes) shp_plate = shp_box.cut(shp_holes) self.shp = shp_plate self.wfco = wfco if wfco == 1: # a freeCAD object is created fco_plate = doc.addObject("Part::Feature", name ) fco_plate.Shape = shp_plate self.fco = fco_plate def color (self, color = (1,1,1)): if self.wfco == 1: self.fco.ViewObject.ShapeColor = color else: logger.debug("Plate object with no fco") # exports the shape into stl format def export_stl (self, name = ""): #filepath = os.getcwd() if not name: name = self.name stlPath = filepath + "/freecad/stl/" stlFileName = stlPath + name + ".stl" # exportStl is not working well with FreeCAD 0.17 #self.shp.exportStl(stlFileName) mesh_shp = MeshPart.meshFromShape(self.shp, LinearDeflection=kparts.LIN_DEFL, AngularDeflection=kparts.ANG_DEFL) mesh_shp.write(stlFileName) del mesh_shp
[docs]def lcp01m_plate (d_lcp01m_plate = kcomp_optic.LCP01M_PLATE, fc_axis_h = VZ, fc_axis_m = VX, fc_axis_p = V0, cm=1, cp=1, ch=1, pos = V0, wfco= 1, name = 'LCP01M_PLATE' ): """ Creates a lcp01m_plate side. It creates from a dictionary Parameters ---------- d_lcp01m_plate: dict Dictionary with the dimensions of the plate defined in kcomp_optic.py fc_axis_h: FreeCAD.Vector Direction of the vertical (thickness) from the inside of the plate fc_axis_m: FreeCAD.Vector Direction of the mounting hole goes in the mounting hole fc_axis_p: FreeCAD.Vector Perpendicular direction of axis_h and axis_m, only used if not centered on this axis cm: int * 1: centered on the fc_axis_m direction (point 2) * 0: it will be on the mounting hole (point 1) cp: int * 1: centered on the perpendicular direction of fc_axis_m and fc_axis_h), if 0, fc_axis_p needs to be defined * 0: points 5 (cm==0) or 6 (cm==1) ch: int * 1: centered on the vertical direction (thickness) pos: FreeCAD.Vector Position of the center. wfco: int * 1: a FreeCAD object is created * 0: only de shape is created name: str name of the freecad object (if created) """ h_plate = PlateThruholeMhole( side_l = d_lcp01m_plate['L'], thick = d_lcp01m_plate['thick'], thruhole_d = d_lcp01m_plate['thruhole_d'], mhole_d = d_lcp01m_plate['mhole_d'], mhole_l = d_lcp01m_plate['mhole_depth'], sym_hole_d = d_lcp01m_plate['sym_hole_d'], sym_hole_sep = d_lcp01m_plate['sym_hole_sep'], cbore_hole_d = 0, cbore_hole_head_d = 0, cbore_hole_head_l = 0, cbore_hole_sep_l = 0, cbore_hole_sep_s = 0, cbore_hole_sep_l_axis_m =1, chmf_r = d_lcp01m_plate['chamfer_r'] , fc_axis_h = fc_axis_h, fc_axis_m = fc_axis_m, fc_axis_p = fc_axis_p, cm=cm, cp=cp, ch=ch, pos = pos, wfco=wfco, name = name) return h_plate
#doc = FreeCAD.newDocument() #lcp01m_plate ( # fc_axis_h = VX, # fc_axis_m = VY, # fc_axis_p = VZN, # cm=0, cp=0, ch=0, # pos = V0, # wfco= 1, # name = 'LCP01M_PLATE') # -------------------------- LCPB1M Cage Mounting Base for 60mm class Lcpb1mBase (object): """ Creates a mounting base, Thorlabs LCPB1_M :: fc_axis_h : ___________:____________ .... _......... |________________________|...:h_lip ..| |___ : | | h_sup+ | | + h_tot ______| |______... : |_____| : |_|__|____________________________|__|_|.:h_slot :.|_____|...:..>fc_axis_d s_mholes_dist (small mounting holes) .....+...... : : ___________:____________:_____________....................... fc_axis_w | |________________________| |...: d_lip :d_mount : | /\ | o (O) o | /\ |-----------: + d_tot |_| |_|________________________|_| |_|.....................: : : : l_mhole : : : : : : : : : : : : : : : : : :........ w_sup .........: : : : : : : : :........... slot_dist ..........: : : : :............... w_tot ................: ref_h ________________________ _ |___________2____________| | |__2 | | | | ______| |______ |____| 3_|2_|_____________1______________|__|_| 1_2__3 ref_d ref_w ref_d __________________1___________________ | |________________________| | | /\ | o (2) o | /\ | |_| |_|___________3____________|_| |_| """ def __init__(self, w_tot, d_tot, h_tot, h_slot, slot_dist, d_mount, slot_d, w_sup, h_sup, d_lip, s_mholes_dist, s_mholes_d, l_mbolt_d, fc_axis_d = VX, fc_axis_w = V0, fc_axis_h = VZ, ref_d = 1, ref_w = 1, ref_h = 1, pos = V0, wfco = 1, toprint= 0, name = 'Lcpb1mBase'): self.wfco = wfco self.name = name self.h_tot = h_tot, doc = FreeCAD.ActiveDocument # normalize the 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() self.axis_h = axis_h self.axis_d = axis_d self.axis_w = axis_w # best axis to print, to be pointing up: self.axis_print = axis_h self.ref_d = ref_d self.ref_w = ref_w self.ref_h = ref_h self.slot_dist = slot_dist # central large mounting bolt hole d_lmbolt = kcomp.D912[int(l_mbolt_d)] lmbolt_head_r = d_lmbolt['head_r'] lmbolt_shank_r_tol = d_lmbolt['shank_r_tol'] lmbolt_head_r_tol = d_lmbolt['head_r_tol'] lmbolt_head_l = d_lmbolt['head_l'] # ------- Reference to point w=1, d=1, h=1 # ----------- DISTANCES ON AXIS W fc_1_2_w = DraftVecUtils.scale(axis_w, slot_dist/2.) fc_1_3_w = DraftVecUtils.scale(axis_w, w_tot/2.) fc_1_2_d = DraftVecUtils.scale(axis_d, d_mount) fc_1_3_d = DraftVecUtils.scale(axis_d, d_tot) fc_1_2_h = DraftVecUtils.scale(axis_h, h_sup) if ref_w == 1: refto_1_w = V0 elif ref_w == 2: refto_1_w == fc_1_2_w.negative() elif ref_w == 3: refto_1_w = fc_1_3_w.negative() else: logger.error('wrong reference point') if ref_d == 1: refto_1_d = V0 elif ref_d == 2: refto_1_d = fc_1_2_d.negative() elif ref_d == 3: refto_1_d = fc_1_3_d.negative() else: logger.error('wrong reference point') if ref_h == 1: refto_1_h = V0 elif ref_h == 2: refto_1_h = fc_1_2_h.negative() else: logger.error('wrong reference point') self.refto_1_w = refto_1_w self.refto_1_d = refto_1_d self.refto_1_h = refto_1_h self.fc_1_2_w = fc_1_2_w self.fc_1_3_w = fc_1_3_w self.fc_1_2_d = fc_1_2_d self.fc_1_3_d = fc_1_3_d self.fc_1_2_h = fc_1_2_h # absolute position of point on w=1, d=1, h=1 w1_d1_h1_pos = pos + refto_1_w + refto_1_d + refto_1_h w1_d2_h1_pos = w1_d1_h1_pos + fc_1_2_d # Draw the 3 boxes: base_list = [] shp_lip_box = fcfun.shp_box_dir (box_w = w_sup, box_d = d_lip, box_h = h_tot, fc_axis_h = axis_h, fc_axis_d = axis_d, cw = 1, cd = 0, ch = 0, pos = w1_d1_h1_pos) base_list.append(shp_lip_box) shp_sup_box = fcfun.shp_box_dir (box_w = w_sup, box_d = d_tot, box_h = h_sup, fc_axis_h = axis_h, fc_axis_d = axis_d, cw = 1, cd = 0, ch = 0, pos = w1_d1_h1_pos) base_list.append(shp_sup_box) shp_slot_box = fcfun.shp_box_dir (box_w = w_tot, box_d = d_tot, box_h = h_slot, fc_axis_h = axis_h, fc_axis_d = axis_d, cw = 1, cd = 0, ch = 0, pos = w1_d1_h1_pos) base_list.append(shp_slot_box) shp_base = fcfun.fuseshplist(base_list) shp_base = shp_base.removeSplitter() holes = [] # slot holes are in w=2 for pos_wi in [fc_1_2_w, fc_1_2_w.negative()]: slot_pos = w1_d2_h1_pos + pos_wi # longer length, it doesnt matter shp_slot_hole = fcfun.shp_stadium_dir(length = d_tot, radius = slot_d/2. + kcomp.TOL, height = h_slot, fc_axis_h = axis_h, fc_axis_l = axis_d, ref_l = 2, ref_h=2, xtr_h = 1, xtr_nh = 1, pos = slot_pos) holes.append(shp_slot_hole) shp_lmbolt_hole = fcfun.shp_bolt_dir(r_shank = lmbolt_shank_r_tol, l_bolt = h_sup, # it seems that the head is larger: +1 r_head = lmbolt_head_r_tol + 1, l_head = lmbolt_head_l + kcomp.TOL, xtr_head = 1, xtr_shank = 1, support = toprint, fc_normal = axis_h, fc_verx1 = axis_w, pos = w1_d2_h1_pos) holes.append(shp_lmbolt_hole) fc_1_to_smholes = DraftVecUtils.scale(axis_w, s_mholes_dist/2.) for pos_wi in [fc_1_to_smholes.negative(), fc_1_to_smholes]: mshole_pos = w1_d2_h1_pos + pos_wi # longer length, it doesnt matter shp_smhole = fcfun.shp_cylcenxtr( r = s_mholes_d/2., h = h_sup, normal = axis_h, ch = 0, xtr_top = 1, xtr_bot = 1, pos = mshole_pos) holes.append(shp_smhole) shp_holes = fcfun.fuseshplist(holes) shp_base = shp_base.cut(shp_holes) if wfco == 1: # a freeCAD object is created fco_base = doc.addObject("Part::Feature", name ) fco_base.Shape = shp_base self.fco = fco_base def color (self, color = (1,1,1)): if self.wfco == 1: self.fco.ViewObject.ShapeColor = color else: logger.debug("Plate object with no fco") # exports the shape into stl format def export_stl (self, name = ""): #filepath = os.getcwd() if not name: name = self.name stlPath = filepath + "/freecad/stl/" stlFileName = stlPath + name + ".stl" # exportStl is not working well with FreeCAD 0.17 #self.shp.exportStl(stlFileName) mesh_shp = MeshPart.meshFromShape(self.shp, LinearDeflection=kparts.LIN_DEFL, AngularDeflection=kparts.ANG_DEFL) mesh_shp.write(stlFileName) del mesh_shp
[docs]def lcpb1m_base (d_lcpb1m_base = kcomp_optic.LCPB1M_BASE, fc_axis_d = VX, fc_axis_w = V0, fc_axis_h = VZ, ref_d = 1, ref_w = 1, ref_h = 1, pos = V0, wfco = 1, toprint= 0, name = 'Lcpb1mBase'): """ Creates a lcpb1m_base for plates side, it creates from a dictionary Parameters ---------- d_lcpb1m_base: dict Dictionary with the dimensions fc_axis_d: FreeCAD.Vector Direction of the deep fc_axis_w: FreeCAD.Vector Direction of the width fc_axis_h: FreeCAD.Vector Direction of the height ref_d: int Position in the fc_axis_d: * 1: top side * 2: center * 3: lower side ref_w: int Postion in the fc_axis_w: * 1: center * 2: center in left slot * 3: left side ref_h: int Positionin the fc_axis_h: * 1: base * 2: top pos: FreeCAD.Vector Position of the center. wfco: int * 1: a FreeCAD object is created * 0: only de shape is created toprint: int 1 if you want to include a triangle between the shank and the head to support the shank and not building the head on the air using kcomp.LAYER3D_H name: str Name of the freecad object (if created) """ h_baseplate = Lcpb1mBase( w_tot = d_lcpb1m_base['w_tot'], d_tot = d_lcpb1m_base['d_tot'], h_tot = d_lcpb1m_base['h_tot'], h_slot = d_lcpb1m_base['h_slot'], slot_dist = d_lcpb1m_base['slot_dist'], d_mount = d_lcpb1m_base['d_mount'], slot_d = d_lcpb1m_base['slot_d'], w_sup = d_lcpb1m_base['w_sup'], h_sup = d_lcpb1m_base['h_sup'], d_lip = d_lcpb1m_base['d_lip'], s_mholes_dist = d_lcpb1m_base['s_mholes_dist'], s_mholes_d = d_lcpb1m_base['s_mholes_d'], l_mbolt_d = d_lcpb1m_base['l_mbolt_d'], fc_axis_d = fc_axis_d, fc_axis_w = fc_axis_w, fc_axis_h = fc_axis_h, ref_d=ref_d, ref_w=ref_w, ref_h=ref_h, pos = pos, wfco=wfco, toprint= toprint, name = name) return h_baseplate
#doc = FreeCAD.newDocument() #lcpb1m_base (d_lcpb1m_base = kcomp_optic.LCPB1M_BASE, # fc_axis_d = VX, # fc_axis_w = V0, # fc_axis_h = VZ, # ref_d = 3, ref_w = 1, ref_h = 1, # pos = FreeCAD.Vector(3,4,8), # wfco = 1, toprint= 0, name = 'Lcpb1mBase') # ---------------------- Sm1TubelensSm2 --------------------------
[docs]class SM1TubelensSm2 (object): """ Creates a componente formed by joining: the lens tube SM1LXX + SM1A2 + SM2T2, so we have: * on one side a SM1 external thread * on the other side a SM2 external thread And inside we have a SM1 tube lens Since there are threads, they may be inserted differently, so size may vary. Therefore, size are approximate, and also, details are not drawn, such as threads, or even the part that contains the thread is not drawn: :: ......................... lens tube _HH ........... : ||..| : : LED SM1LXX || | : : _____ ..... ______________|| | : : __| : _|..............|| | : : | : | : : || | : : | 30.5+ | : SM1 : || | +55.9 + 57.2 | : | : : || | :SM2_TLENS_D : |__ : |_:............:.|| | : : _____| :....|______________|| | : : : : || | : : :3: Lext ||..| : : ||__|..........: : SM1_TLENS_D=30.5 HH ........................: 0.7: 5.6 So it will be: lens tube _HH ||..| SM1LXX || | ______________|| | |..............|| | | || | | SM1 || | | || | |..............|| | |______________|| | || | Lext ||..| ||__| HH The 3mm thread on the left is not drawn Parameters ---------- sm1l_size: float Length of the side of the cube (then it will be halved) fc_axis: FreeCAD.Vector Direction of the tube lens: FreeCAD.Vector axis_2: FreeCAD.Vector Direction big the other right side: ref_sm1: int * 1: if the position is referred to the sm1 end * 0: if the position is referred to the ring end pos: FreeCAD.Vector Position of the object ring: int * 1: if there is ring * 0: there is no ring, so just the thread, at it is not drawn name: str Name of the freecad object """ def __init__ (self, sm1l_size, fc_axis = VX, ref_sm1 = 1, pos = V0, ring = 1, name = 'tubelens_sm1_sm2'): doc = FreeCAD.ActiveDocument # dictionary with the dimensions d_sm1l_sm2 = kcomp_optic.SM1L_2_SM2 self.base_place = (0,0,0) self.sm1l_size = sm1l_size self.sm_dict = d_sm1l_sm2 self.sm1_d = d_sm1l_sm2['sm1_d'] self.sm1_l = d_sm1l_sm2['sm1_l'][sm1l_size] self.sm2_d = d_sm1l_sm2['sm2_d'] self.sm2_l = d_sm1l_sm2['sm2_l'] if ring == 1: self.ring_d = d_sm1l_sm2['ring_d'] self.ring_l = d_sm1l_sm2['ring_l'] self.ring = 1 else: self.ring_d = 0 self.ring_l = 0 self.ring = 0 self.thick = d_sm1l_sm2['thick'] self.fc_axis = fc_axis self.ref_sm1 = ref_sm1 self.pos = pos if ref_sm1 == 1: r1 = self.sm1_d/2. h1 = self.sm1_l r2 = self.sm2_d/2. h2 = self.sm2_l else: r1 = self.sm2_d/2. h1 = self.sm2_l r2 = self.sm1_d/2. h2 = self.sm1_l self.length = self.sm1_l + self.sm2_l + self.ring_l if ring == 1: shp_sm1_tube_sm2 = fcfun.add3CylsHole (r1, h1, r2, h2, rring = self.ring_d/2, hring = self.ring_l, thick = self.thick, normal = fc_axis, pos = pos) else: shp_sm1_tube_sm2 = fcfun.add2CylsHole (r1, h1, r2, h2, thick = self.thick, normal = fc_axis, pos = pos) doc.recompute() fco_sm1_tube_sm2 = doc.addObject("Part::Feature", name ) fco_sm1_tube_sm2.Shape = shp_sm1_tube_sm2 self.fco = fco_sm1_tube_sm2 def BasePlace (self, position = (0,0,0)): self.base_place = position self.fco.Placement.Base = FreeCAD.Vector(position) def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
# ---------------------- ThLed30 --------------------------
[docs]class ThLed30 (object): """ Creates the shape of a Thorlabs Led with 30.5 mm Heat Sink diameter The drawing is very rough :: :....35...: : : : : : Cable : | | diam ? : | | : ____|_|________:.................. ......__| | | | | | : : | : | | | | | : : | : | | | | | : <- ? + C| 0 | | | | | + 30.5 fc_axis : | | | | | | : :....|__ | | | | | : : |_______________|.................: : : : : :......50.......: : : :........60.4.......: : : : : : heatsinks_totl The reference is marked with a 0 in the drawing Parameters ---------- fc_axis: FreeCAD.Vector axis on the direction of the led fc_axis_cable: FreeCAD.Vector axis on the direction of the cable pos: FreeCAD.Vector Placement of the object name: str Object name """ def __init__ (self, fc_axis = VY, fc_axis_cable = VZN, pos = V0, name = 'thled30'): self.fc_axis = fc_axis self.fc_axis_cable = fc_axis_cable self.pos = pos doc = FreeCAD.ActiveDocument # normalize the axis and negate to build the cylinders n_axis = DraftVecUtils.scaleTo(fc_axis,-1) # dictionary with the dimensions d_led = kcomp_optic.THLED30 # length of the part of the heat sinks (very approximate) heatsinks_totl = d_led['cable_dist'] - d_led['cable_d'] # the main part, without the heat sink shp_cyl_body = fcfun.shp_cyl( r = d_led['ext_d']/2., h = d_led['ext_l'] - heatsinks_totl, normal = n_axis, pos = pos) # the solid part under the heat sinks shp_cyl_solid = fcfun.shp_cyl( r = d_led['ext_d']/6, #approximate h = d_led['ext_l'], normal = n_axis, pos = pos) fuse_list = [] fuse_list.append(shp_cyl_solid) # the part where the Led is, very approximate, simplified drawing shp_cyl_led = fcfun.shp_cylcenxtr( r = d_led['int_d']/2., h = d_led['tot_l'] - d_led['ext_l'], normal = DraftVecUtils.neg(n_axis), #on the other direction ch = 0, xtr_top=0, xtr_bot =1., pos = pos) fuse_list.append(shp_cyl_led) # Just a few heat sinks (4). Just to see them in the drawing heatsink_w = heatsinks_totl / 8. pos_heatsink = ( pos + DraftVecUtils.scaleTo(n_axis, d_led['ext_l'] - heatsinks_totl + heatsink_w)) pos_heatsink_add = DraftVecUtils.scaleTo(n_axis, 2* heatsink_w) for i in range(4): #0, 1, 2, 3 shp_heatsink = fcfun.shp_cyl( r = d_led['ext_d']/2., h = heatsink_w, normal = n_axis, pos = pos_heatsink) fuse_list.append(shp_heatsink) pos_heatsink = pos_heatsink + pos_heatsink_add # Cable poscable = ( pos + DraftVecUtils.scaleTo(n_axis, d_led['ext_l'] - d_led['cable_dist'])) shp_cable = fcfun.shp_cyl (r = d_led['cable_d']/2., h = d_led['ext_d'], normal = fc_axis_cable, pos = poscable) fuse_list.append(shp_cable) shp_led = shp_cyl_body.multiFuse(fuse_list) doc.recompute() fco_led = doc.addObject("Part::Feature", name ) fco_led.Shape = shp_led self.fco = fco_led def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
#doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument #ThLed30 ( # fc_axis = VY, # fc_axis_cable = VZN, # pos = V0, # name = 'thled30') # ---------------------- PrizLed --------------------------
[docs]class PrizLed (object): """ Creates the shape of a Prizmatix UHP-T-Led The drawing is very rough, and the original drawing lacks many dimensions :: ...22.... ........50......... : : : : ........:________________ vtl:_________________:vtr..... : 10.5+ | | |___________ | | : : : :.| O M6 | | | | ____ | +25 : : | | | | | / \ | : : +39.5 | | | Fan | | | SM1 | |...: : :.......| O | | | | \____ / | : | | | | | | + 90 | | |___________| | KEEP | : | | | | CLEAR | : | | | | | | | : | | | | V V | : | | | |_________________| : \_____________|_| |_________________|.......: : :15: : : : V :__:__________________________ fc_axis_clear | | | | | O | | | fc_axis_led| | | | <--- | | | | | | | | | | | | | O M6 | | | |______________|_|___________| : : :...........98.75............: Parameters ---------- fc_axis_led: FreeCAD.Vector Direction of the led fc_axis_clear: FreeCAD.Vector Direction of the arrows indicating to keep clear pos: FreeCAD.Vector Position of the LED, on the center of the SM1 thread name: str Object name """ def __init__ (self, fc_axis_led = VX, fc_axis_clear = VZN, pos = V0, name = 'prizmatix_led'): self.fc_axis_led = fc_axis_led self.fc_axis_clear = fc_axis_clear self.pos = pos self.d_led = kcomp_optic.PRIZ_UHP_LED # the dictionary doc = FreeCAD.ActiveDocument doc.recompute() d_led = kcomp_optic.PRIZ_UHP_LED # normalize axis: nnorm_led = DraftVecUtils.scaleTo(fc_axis_led,1) # negated to have the direction to build the shapes nnorm_ledn = DraftVecUtils.neg(nnorm_led) nnorm_clear = DraftVecUtils.scaleTo(fc_axis_clear,1) # get the 3rd perpendicular vector: nnorm_perp = nnorm_led.cross(nnorm_clear) nnorm_perpn = DraftVecUtils.neg(nnorm_perp) # check if they are perpendicular nperp = nnorm_led.dot(nnorm_clear) if nperp != 0: logger.error('axis are not perpendicular') # the center of the block will be on the half of the height:90. # pos is on 25., so 20. down the fc_axis_clear axis # use scale and not scale to because nnorm_clear length is 1 pos_center_block = pos + DraftVecUtils.scale(nnorm_clear, d_led['H']/2. - d_led['led_hole_dist']) shp_block = fcfun.shp_box_dir(box_w = d_led['width'], box_d = d_led['depth_block'], box_h = d_led['H'], fc_axis_h = nnorm_clear, fc_axis_d = nnorm_ledn, cw = 1, cd = 0, ch = 1, pos = pos_center_block) # chamfer the edge on these vertexes: chmf_v0 = ( pos_center_block + DraftVecUtils.scale(nnorm_clear, d_led['H']/2.) + DraftVecUtils.scale(nnorm_perp, d_led['width']/2.)) chmf_v1 = ( pos_center_block + DraftVecUtils.scale(nnorm_clear, d_led['H']/2.) + DraftVecUtils.scale(nnorm_perp, - d_led['width']/2.)) for edge in shp_block.Edges: edge_v0 = edge.Vertexes[0].Point #Point to get the FreeCAD.Vector edge_v1 = edge.Vertexes[1].Point if ((DraftVecUtils.equals(edge_v0, chmf_v0) and DraftVecUtils.equals(edge_v1, chmf_v1)) or (DraftVecUtils.equals(edge_v0, chmf_v1) and DraftVecUtils.equals(edge_v1, chmf_v0))): shp_block = shp_block.makeChamfer(d_led['chmf_r'],[edge]) break # adding the box of the fan: pos_fan = pos + DraftVecUtils.scale(nnorm_clear,10) shp_fan = fcfun.shp_box_dir(box_w = d_led['width'], box_d = d_led['depth_t'], box_h = d_led['width'], fc_axis_h = nnorm_clear, fc_axis_d = nnorm_ledn, cw = 1, cd = 0, ch = 1, pos = pos_fan) shp_block = shp_block.fuse(shp_fan) shp_block = shp_block.removeSplitter() # make a hole for the SM1 thread, doesnt say how deep it is shp_cyl_sm1 = fcfun.shp_cylcenxtr(r = d_led['led_hole_d']/2., h = d_led['led_hole_depth'], normal = nnorm_ledn, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos) # M6 mounting threads # top center point vtc = pos + DraftVecUtils.scale(nnorm_clear, - d_led['led_hole_dist']) # top corner right point: vtr = vtc + DraftVecUtils.scale(nnorm_perp, d_led['width']/2.) vtl = vtc + DraftVecUtils.scale(nnorm_perp, - d_led['width']/2.) # vector from the corner to top of the side hole corner2topsidehole = DraftVecUtils.scale(nnorm_ledn, d_led['side_thread_depth']) pos_sideholetopr = (vtr + corner2topsidehole + DraftVecUtils.scale(nnorm_clear,d_led['side_thread1_h'])) shp_sideholetopr = fcfun.shp_cylcenxtr(r = d_led['mthread_d']/2., h = d_led['mthread_h'], normal = nnorm_perpn, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos_sideholetopr) threadholes_list = [shp_sideholetopr] pos_sideholebotr = (vtr + corner2topsidehole + DraftVecUtils.scale(nnorm_clear,d_led['side_thread2_h'])) shp_sideholebotr = fcfun.shp_cylcenxtr(r = d_led['mthread_d']/2., h = d_led['mthread_h'], normal = nnorm_perpn, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos_sideholebotr) threadholes_list.append(shp_sideholebotr) pos_sideholetopl = (vtl + corner2topsidehole + DraftVecUtils.scale(nnorm_clear,d_led['side_thread1_h'])) shp_sideholetopl = fcfun.shp_cylcenxtr(r = d_led['mthread_d']/2., h = d_led['mthread_h'], normal = nnorm_perp, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos_sideholetopl) threadholes_list.append(shp_sideholetopl) pos_sideholebotl = (vtl + corner2topsidehole + DraftVecUtils.scale(nnorm_clear,d_led['side_thread2_h'])) shp_sideholebotl = fcfun.shp_cylcenxtr(r = d_led['mthread_d']/2., h = d_led['mthread_h'], normal = nnorm_perp, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos_sideholebotl) threadholes_list.append(shp_sideholebotl) corner2toptophole = DraftVecUtils.scale(nnorm_ledn, d_led['top_thread_depth']) pos_topholer = ( vtr + corner2toptophole + DraftVecUtils.scale(nnorm_perp, -(d_led['width']-d_led['top_thread_sep'])/2.)) shp_topholer = fcfun.shp_cylcenxtr(r=d_led['mthread_d']/2., h = d_led['mthread_h'], normal = nnorm_clear, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos_topholer) threadholes_list.append(shp_topholer) pos_topholel = ( vtl + corner2toptophole + DraftVecUtils.scale(nnorm_perp, (d_led['width']-d_led['top_thread_sep'])/2.)) shp_topholel = fcfun.shp_cylcenxtr(r=d_led['mthread_d']/2., h = d_led['mthread_h'], normal = nnorm_clear, ch = 0, xtr_top = 0, xtr_bot = 1, pos = pos_topholel) threadholes_list.append(shp_topholel) shp_holes = shp_cyl_sm1.multiFuse(threadholes_list) shp_block = shp_block.cut(shp_holes) doc.recompute() fco_prizled = doc.addObject("Part::Feature", name) fco_prizled.Shape = shp_block self.fco = fco_prizled def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
#doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument #PrizLed ( # fc_axis_led = VY, # fc_axis_clear = VZN, # pos = V0, # name = 'prizled') class BreadBoard (object): def __init__ (self, length, width, thick, hole_d, hole_sep, hole_sep_edge, cbored_hole_d, cbored_hole_sep, cbored_head_d, cbored_head_l, central_cbore = 0, cl= 1, cw = 1, ch = 0, fc_dir_h = VZ, fc_dir_w = VY, pos = V0, name = 'breadboard'): doc = FreeCAD.ActiveDocument shp_box = fcfun.shp_box_dir(box_w = length, box_d = width, box_h = thick, fc_axis_h = fc_dir_h, fc_axis_d = fc_dir_w, cw=cl, cd=cw, ch=ch, pos = pos) # normalize the axis, just in case: axis_h = DraftVecUtils.scaleTo(fc_dir_h,1) axis_w = DraftVecUtils.scaleTo(fc_dir_w,1) axis_l = axis_w.cross(axis_h) # getting the corner coordinates if cl == 1: l_0 = DraftVecUtils.scaleTo(axis_l, -length/2.) else: l_0 = V0 if cw == 1: w_0 = DraftVecUtils.scaleTo(axis_w, -width/2.) else: w_0 = V0 if ch == 1: h_0 = DraftVecUtils.scaleTo(axis_h, -thick/2.) else: h_0 = V0 # the point on the edge pos_corner = pos + l_0 + w_0 + h_0 #Counterbored holes pos_1cbored = ( pos_corner + DraftVecUtils.scaleTo(axis_l, cbored_hole_sep) + DraftVecUtils.scaleTo(axis_w, cbored_hole_sep)) pos_2cbored = ( pos_corner + DraftVecUtils.scaleTo(axis_l, length - cbored_hole_sep) + DraftVecUtils.scaleTo(axis_w, cbored_hole_sep)) pos_3cbored = ( pos_corner + DraftVecUtils.scaleTo(axis_l, length - cbored_hole_sep) + DraftVecUtils.scaleTo(axis_w, width - cbored_hole_sep)) pos_4cbored = ( pos_corner + DraftVecUtils.scaleTo(axis_l, cbored_hole_sep) + DraftVecUtils.scaleTo(axis_w, width - cbored_hole_sep)) extra_headcbore = DraftVecUtils.scaleTo(axis_h, thick-cbored_head_l) cbshank1 = fcfun.shp_cylcenxtr(r=cbored_hole_d/2., h=thick, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_1cbored) cbholehead1 = fcfun.shp_cylcenxtr(r=cbored_head_d/2., h=cbored_head_l, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=0., pos=pos_1cbored +extra_headcbore) cbore1 = cbshank1.fuse(cbholehead1) cbshank2 = fcfun.shp_cylcenxtr(r=cbored_hole_d/2., h=thick, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_2cbored) cbholehead2 = fcfun.shp_cylcenxtr(r=cbored_head_d/2., h=cbored_head_l, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=0., pos=pos_2cbored +extra_headcbore) cbore2 = cbshank2.fuse(cbholehead2) cbshank3 = fcfun.shp_cylcenxtr(r=cbored_hole_d/2., h=thick, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_3cbored) cbholehead3 = fcfun.shp_cylcenxtr(r=cbored_head_d/2., h=cbored_head_l, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=0., pos=pos_3cbored +extra_headcbore) cbore3 = cbshank3.fuse(cbholehead3) cbshank4 = fcfun.shp_cylcenxtr(r=cbored_hole_d/2., h=thick, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_4cbored) cbholehead4 = fcfun.shp_cylcenxtr(r=cbored_head_d/2., h=cbored_head_l, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=0., pos=pos_4cbored +extra_headcbore) cbore4 = cbshank4.fuse(cbholehead4) cboreholes_list = [cbore2, cbore3, cbore4] if central_cbore == 1: poscentral = ( pos_corner + DraftVecUtils.scaleTo(axis_l, length/2.) + DraftVecUtils.scaleTo(axis_w, width/2.)) cbshankcentral = fcfun.shp_cylcenxtr(r=cbored_hole_d/2., h=thick, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=1., pos=poscentral) cbholeheadcentral = fcfun.shp_cylcenxtr(r=cbored_head_d/2., h=cbored_head_l, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=0., pos=poscentral +extra_headcbore) cbholecentral = cbshankcentral.fuse(cbholeheadcentral) cboreholes_list.append(cbholecentral) cboresholes = cbore1.multiFuse(cboreholes_list) pos_1st_tap = ( pos_corner + DraftVecUtils.scaleTo(axis_l, hole_sep_edge) + DraftVecUtils.scaleTo(axis_w, hole_sep_edge) ) tapholes = [] for li in range (int(length)//int(hole_sep)): for wi in range (int(width)//int(hole_sep)): # if 50/25 -> range 0,1, will make on 12,5 and 37,5 pos_tap = ( pos_1st_tap + DraftVecUtils.scaleTo(axis_l, li * hole_sep) + DraftVecUtils.scaleTo(axis_w, wi * hole_sep)) hole = fcfun.shp_cylcenxtr(r=hole_d/2., h=thick, normal=fc_dir_h, ch = 0, xtr_top=1., xtr_bot=1., pos=pos_tap) tapholes.append(hole) allholes = cboresholes.multiFuse(tapholes) shp_breadboard = shp_box.cut(allholes) doc.recompute() fco_breadboard = doc.addObject("Part::Feature", name ) fco_breadboard.Shape = shp_breadboard self.fco = fco_breadboard def color (self, color = (1,1,1)): self.fco.ViewObject.ShapeColor = color
[docs]def f_breadboard (d_breadboard, length, width, cl = 1, cw = 1, ch = 1, fc_dir_h = VZ, fc_dir_w = VY, pos = V0, name = 'breadboard' ): """ Parameters ---------- d_breadboard: dict Dictionary with the values length: float width: float cl : int * 1: the length dimension is centered * 0: it is not centered cw : int * 1: the width dimension is centered * 0: it is not centered ch : int * 1: the height dimension is centered * 0: it is not centered fc_dir_h: FreeCAD.Vector Vector with the direction of the height fc_dir_w: FreeCAD.Vector Vector with the direction of the width pos: FreeCAD.Vector Placement of the model name: str object name Returns -------- FreeCAD Object Object with the sape of a BreadBoard """ if max(length,width) >= d_breadboard['minw_cencbore']: central_cbore = 1 else: central_cbore = 0 breadboard = BreadBoard( length = length, width = width, thick = d_breadboard['thick'], hole_d = d_breadboard['hole_d'], hole_sep = d_breadboard['hole_sep'], hole_sep_edge = d_breadboard['hole_sep_edge'], cbored_hole_d = d_breadboard['cbored_hole_d'], cbored_hole_sep = d_breadboard['cbored_hole_sep'], cbored_head_d = d_breadboard['cbore_head_d'], cbored_head_l = d_breadboard['cbore_head_l'], central_cbore = central_cbore, cl= cl, cw = cw, ch = ch, fc_dir_h = fc_dir_h, fc_dir_w = fc_dir_w, pos = pos, name = 'breadboard') return breadboard
#doc = FreeCAD.newDocument() #doc = FreeCAD.ActiveDocument #f_breadboard (kcomp_optic.BREAD_BOARD_M, # length = 200., # width = 500., # cl = 1, # cw = 1, # ch = 1, # fc_dir_h = VZ, # fc_dir_w = VY, # pos = V0, # name = 'breadboard' # )