コード例 #1
0
ファイル: modify.py プロジェクト: yusheng-wang/py4design
def rotate(occtopology, rot_pypt, pyaxis, degree):
    """
    This function rotates an OCCtopology based on the rotation point, an axis and the rotation degree.
 
    Parameters
    ----------        
    occtopology : OCCtopology
        The OCCtopology to be rotated.
        OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex 
        
    rot_pypt : tuple of floats
        The OCCtopology will rotate in reference to this point.
        A pypt is a tuple that documents the xyz coordinates of a pt e.g. (x,y,z)
        
    pyaxis : tuple of floats
        The OCCtopology will rotate along this axis.
        A pyaxis is a tuple that documents the xyz of a direction e.g. (x,y,z)
        
    degree : float
       The degree of rotation.
        
    Returns
    -------
    rotated topology : OCCtopology (OCCshape)
        The rotated OCCtopology.
    """
    
    from math import radians
    gp_ax3 = gp_Ax1(gp_Pnt(rot_pypt[0], rot_pypt[1], rot_pypt[2]), gp_Dir(pyaxis[0], pyaxis[1], pyaxis[2]))
    aTrsf = gp_Trsf()
    aTrsf.SetRotation(gp_ax3, radians(degree))
    rot_brep = BRepBuilderAPI_Transform(aTrsf)
    rot_brep.Perform(occtopology, True)
    rot_shape = rot_brep.Shape()
    return rot_shape
コード例 #2
0
def translate_topods_from_vector(brep_or_iterable, vec, copy=False):
    '''
    Function Originally from pythonocc-utils, modified to work on objects

    translates a brep over a vector

    Parameters
    ----------
    brep : the Topo_DS to translate

    vec : the vector defining the translation

    copy : copies to brep if True
    '''
    trns = gp_Trsf()
    trns.SetTranslation(vec)
    if issubclass(brep_or_iterable.__class__, TopoDS_Shape):
        brep_trns = BRepBuilderAPI_Transform(brep_or_iterable, trns, copy)
        brep_trns.Build()
        return brep_trns.Shape()
    else:
        return [
            translate_topods_from_vector(brep_or_iterable, vec, copy)
            for i in brep_or_iterable
        ]
コード例 #3
0
def move(orig_pypt, location_pypt, occtopology):
    """
    This function moves an OCCtopology from the orig_pypt to the location_pypt.
 
    Parameters
    ----------        
    orig_pypt : tuple of floats
        The OCCtopology will move in reference to this point.
        A pypt is a tuple that documents the xyz coordinates of a pt e.g. (x,y,z)
        
    location_pypt : tuple of floats
        The destination of where the OCCtopology will be moved in relation to the orig_pypt.
        A pypt is a tuple that documents the xyz coordinates of a pt e.g. (x,y,z)
        
    occtopology : OCCtopology
        The OCCtopology to be moved.
        OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex 

    Returns
    -------
    moved topology : OCCtopology (OCCshape)
        The moved OCCtopology.
    """
    gp_ax31 = gp_Ax3(gp_Pnt(orig_pypt[0], orig_pypt[1], orig_pypt[2]), gp_DZ())
    gp_ax32 = gp_Ax3(
        gp_Pnt(location_pypt[0], location_pypt[1], location_pypt[2]), gp_DZ())
    aTrsf = gp_Trsf()
    aTrsf.SetTransformation(gp_ax32, gp_ax31)
    trsf_brep = BRepBuilderAPI_Transform(aTrsf)
    trsf_brep.Perform(occtopology, True)
    trsf_shp = trsf_brep.Shape()
    return trsf_shp
コード例 #4
0
def scale(occtopology, scale_factor, ref_pypt):
    """
    This function uniformly scales an OCCtopology based on the reference point and the scale factor.
 
    Parameters
    ----------        
    occtopology : OCCtopology
        The OCCtopology to be scaled.
        OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex 
        
    scale_factor : float
        The scale factor.
       
    ref_pypt : tuple of floats
        The OCCtopology will scale in reference to this point.
        A pypt is a tuple that documents the xyz coordinates of a pt e.g. (x,y,z)
        
    Returns
    -------
    scaled topology : OCCtopology (OCCshape)
        The scaled OCCtopology.
    """
    xform = gp_Trsf()
    gp_pnt = construct.make_gppnt(ref_pypt)
    xform.SetScale(gp_pnt, scale_factor)
    brep = BRepBuilderAPI_Transform(xform)
    brep.Perform(occtopology, True)
    trsfshape = brep.Shape()
    return trsfshape
コード例 #5
0
def clone_tooth(base_shape):
    clone = gp_Trsf()
    grouped_shape = base_shape

    # Find a divisor, between 1 and 8, for the number_of teeth
    multiplier = 1
    max_multiplier = 1
    for i in range(0, 8):
        if num_teeth % multiplier == 0:
            max_multiplier = i + 1

    multiplier = max_multiplier
    for i in range(1, multiplier):
        clone.SetRotation(gp_OZ(), -i * tooth_angle)
        rotated_shape = BRepBuilderAPI_Transform(base_shape, clone,
                                                 True).Shape()
        grouped_shape = BRepAlgoAPI_Fuse(grouped_shape, rotated_shape).Shape()

    # Rotate the basic tooth and fuse together
    aggregated_shape = grouped_shape
    for i in range(1, int(num_teeth / multiplier)):
        clone.SetRotation(gp_OZ(), -i * multiplier * tooth_angle)
        rotated_shape = BRepBuilderAPI_Transform(grouped_shape, clone,
                                                 True).Shape()
        aggregated_shape = BRepAlgoAPI_Fuse(aggregated_shape,
                                            rotated_shape).Shape()

    cylinder = BRepPrimAPI_MakeCylinder(gp_XOY(), top_radius - roller_diameter,
                                        thickness)
    aggregated_shape = BRepAlgoAPI_Fuse(aggregated_shape,
                                        cylinder.Shape()).Shape()

    return aggregated_shape
コード例 #6
0
def rotate(brep, axe, degree, copy=False):
    """Rotates the brep
    
    Originally from pythonocc-utils : might add dependency on this?

    Parameters
    ----------
    brep : shape to rotate
    
    axe : axis of rotation
    
    degree : Number of degrees to rotate through
    
    copy : bool (default=False)
    
    Returns
    -------
    BRepBuilderAPI_Transform.Shape : Shape handle
        The handle to the rotated shape
    """
    trns = gp_Trsf()
    trns.SetRotation(axe, np.radians(degree))
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    brep_trns.Build()
    return brep_trns.Shape()
コード例 #7
0
    def translate(self, target):
        transform = gp.gp_Trsf()
        transform.SetTranslation(gp.gp_Vec(*target))

        # FIXME: this needs some explanation... should it be here?
        needle_transform = BRepTransform(self.needle, transform, False)
        needle_transform.Build()
        self.needle = needle_transform.Shape()
コード例 #8
0
ファイル: manipulator.py プロジェクト: go-smart/goosefoot
    def translate(self, target):
        transform = gp.gp_Trsf()
        transform.SetTranslation(gp.gp_Vec(*target))

        for i, needle in enumerate(self.shapes):
            needle_transform = BRepTransform(needle, transform, False)
            needle_transform.Build()
            self.shapes[i] = needle_transform.Shape()
コード例 #9
0
def move(orig_pt, location_pt, occshape):
    gp_ax31 = gp_Ax3(gp_Pnt(orig_pt[0], orig_pt[1], orig_pt[2]), gp_DZ())
    gp_ax32 = gp_Ax3(gp_Pnt(location_pt[0], location_pt[1], location_pt[2]),
                     gp_DZ())
    aTrsf = gp_Trsf()
    aTrsf.SetTransformation(gp_ax32, gp_ax31)
    trsf_brep = BRepBuilderAPI_Transform(aTrsf)
    trsf_brep.Perform(occshape, True)
    trsf_shp = trsf_brep.Shape()
    return trsf_shp
コード例 #10
0
      def rotate(self,shape) :
          from OCC.Core.gp import gp_Trsf
          from OCC.BRepBuilderAPI import BRepBuilderAPI_Transform

          trns = gp_Trsf()
          trns.SetRotation(self.RevAxis,self.getStart())
          brep_trns = BRepBuilderAPI_Transform(shape, trns, False)
          brep_trns.Build()
          shape = brep_trns.Shape()
          return shape
コード例 #11
0
 def buildStringer(self):
     ms = MakeSlotShapedSolid()
     ms.ax2 = gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1), gp_Dir(1, 0, 0))
     ms.thickness = self.thickness
     ms.width = self.width
     ms.length = self.l_max
     solid = ms.Solid()
     trsf = gp_Trsf()
     trsf.SetTranslation(gp_Vec(0, 0, -self.thickness / 2.0))
     mt = BRepBuilderAPI_Transform(solid, trsf)
     self.shape = mt.Shape()
コード例 #12
0
def mirror_pnt_dir(brep, pnt, direction, copy=False):
    '''
    @param brep:
    @param line:
    '''
    trns = gp_Trsf()
    trns.SetMirror(gp_Ax1(pnt, direction))
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    with assert_isdone(brep_trns, 'could not produce mirror'):
        brep_trns.Build()
        return brep_trns.Shape()
コード例 #13
0
ファイル: manipulator.py プロジェクト: go-smart/goosefoot
    def scale(self, scaling):
        if scaling is None:
            scaling = 1.0

        transform = gp.gp_Trsf()
        transform.SetScale(self.origin, REFERENCE_SCALING / scaling)

        for i, needle in enumerate(self.shapes):
            needle_transform = BRepTransform(needle, transform, False)
            needle_transform.Build()
            self.shapes[i] = needle_transform.Shape()
コード例 #14
0
ファイル: Construct.py プロジェクト: psavine42/OCCUtilsExt
def mirror_axe2(brep, axe2, copy=False):
    """
    @param brep:
    @param line:
    """
    trns = gp_Trsf()
    trns.SetMirror(axe2)
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    with assert_isdone(brep_trns, 'could not produce mirror'):
        brep_trns.Build()
        return brep_trns.Shape()
コード例 #15
0
ファイル: Construct.py プロジェクト: psavine42/OCCUtilsExt
def rotate(brep, axe, degree, copy=False):
    """
    @param brep:
    @param axe:
    @param degree:
    """
    trns = gp_Trsf()
    trns.SetRotation(axe, radians(degree))
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    with assert_isdone(brep_trns, 'could not produce rotation'):
        brep_trns.Build()
        return ST(brep_trns.Shape())
コード例 #16
0
def translate_topods_from_vector(brep_or_iterable, vec, copy=False):
    '''
    translate a brep over a vector
    @param brep:    the Topo_DS to translate
    @param vec:     the vector defining the translation
    @param copy:    copies to brep if True
    '''
    trns = gp_Trsf()
    trns.SetTranslation(vec)
    brep_trns = BRepBuilderAPI_Transform(brep_or_iterable, trns, copy)
    brep_trns.Build()
    return brep_trns.Shape()
コード例 #17
0
ファイル: Construct.py プロジェクト: psavine42/OCCUtilsExt
def scale_uniformal(brep, pnt, factor, copy=False):
    """
    translate a brep over a vector
    @param brep:    the Topo_DS to translate
    @param pnt:     a gp_Pnt
    @param triple:  scaling factor
    @param copy:    copies to brep if True
    """
    trns = gp_Trsf()
    trns.SetScale(pnt, factor)
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    brep_trns.Build()
    return brep_trns.Shape()
コード例 #18
0
ファイル: cuboidbuilder.py プロジェクト: go-smart/goosefoot
    def make_reference(self, **parameters):
        l = parameters['length']
        w = parameters['width']
        h = parameters['height']
        box_shape = BRepPrimAPI_MakeBox(l, w, h)

        transform = gp.gp_Trsf()
        transform.SetTranslation(gp.gp_Vec(-l / 2, -w / 2, -h / 2))

        shape_transform = BRepTransform(box_shape.Shape(), transform, False)
        shape_transform.Build()
        shape = shape_transform.Shape()

        return shape
コード例 #19
0
    def Solid(self):

        mw = BRepBuilderAPI_MakeWire()
        points = []

        x = -self.length / 2.0
        y = -self.width / 2.0
        z = 0.0
        points.append(gp_Pnt(x, y, z))

        x = self.length / 2.0
        points.append(gp_Pnt(x, y, z))

        me = BRepBuilderAPI_MakeEdge(points[0], points[1])
        mw.Add(me.Edge())  # bottom edge

        ax = gp_Ax2(gp_Pnt(x, 0, 0), gp_Dir(0, 0, 1), gp_Dir(0, -1, 0))
        circ = gp_Circ(ax, self.width / 2.0)
        me = BRepBuilderAPI_MakeEdge(circ, 0, pi)
        mw.Add(me.Edge())

        points = []
        y = self.width / 2.0
        points.append(gp_Pnt(x, y, z))

        x = -self.length / 2.0
        points.append(gp_Pnt(x, y, z))
        me = BRepBuilderAPI_MakeEdge(points[0], points[1])
        mw.Add(me.Edge())  # top edge

        ax = gp_Ax2(gp_Pnt(x, 0, 0), gp_Dir(0, 0, 1), gp_Dir(0, 1, 0))
        circ = gp_Circ(ax, self.width / 2.0)
        me = BRepBuilderAPI_MakeEdge(circ, 0, pi)
        mw.Add(me.Edge())

        mf = BRepBuilderAPI_MakeFace(mw.Wire())
        mp = BRepPrimAPI_MakePrism(mf.Face(), gp_Vec(0, 0, self.thickness))

        shape = mp.Shape()

        #v_trans = gp_Vec(self.ax2.Location().XYZ())
        ax = gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1), gp_Dir(1, 0, 0))
        #mainRotationAngle = ax.Angle(self.ax2)

        trsf = gp_Trsf()
        trsf.SetTransformation(gp_Ax3(self.ax2), gp_Ax3(ax))

        mt = BRepBuilderAPI_Transform(shape, trsf)
        return mt.Shape()
コード例 #20
0
ファイル: Construct.py プロジェクト: psavine42/OCCUtilsExt
def mirror_pnt_dir(brep: TopoDS_Shape, pnt: gp_Pnt, direction, copy=False):
    """
    mirror 'brep' with the plane created by normal
    @param brep:
    @param pnt:
    @param normal:
    @param copy:
    """
    trns = gp_Trsf()
    # create Z axis from point and direction
    z = gp_Ax1(pnt, direction)
    trns.SetMirror(z)
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    with assert_isdone(brep_trns, 'could not produce mirror'):
        brep_trns.Build()
        return brep_trns.Shape()
コード例 #21
0
def shape_base_drain():
    '''
    output
        s: TopoDS_Shape
    '''
    wire = wire_circle()

    trsf = gp_Trsf()
    trsf.SetScale(DRAIN_RCS.Location(), DRAIN_R)
    bresp_trsf = BRepBuilderAPI_Transform(wire, trsf)
    wire = topods.Wire(bresp_trsf.Shape())

    base_face = BRepBuilderAPI_MakeFace(wire).Face()
    shape = BRepPrimAPI_MakePrism(base_face, gp_Vec(0, 0, DRAIN_T)).Shape()

    return shape
コード例 #22
0
ファイル: manipulator.py プロジェクト: go-smart/goosefoot
    def reorient(self, z_target_axis):
        # Note that needles are expected to lie along the z-axis with tip at the
        # origin.
        z_axis = [0, 0, 1]
        rot_axis = N.cross(z_axis, z_target_axis)
        if N.linalg.norm(rot_axis) > 1e-6:
            rotation_axis = gp.gp_Ax1(self.origin, gp.gp_Dir(*rot_axis))
            rotation_angle = N.arccos(N.dot(z_axis, z_target_axis) / (N.linalg.norm(z_axis) * N.linalg.norm(z_target_axis)))

            transform = gp.gp_Trsf()
            transform.SetRotation(rotation_axis, rotation_angle)

            for i, needle in enumerate(self.shapes):
                needle_transform = BRepTransform(needle, transform, False)
                needle_transform.Build()
                self.shapes[i] = needle_transform.Shape()
コード例 #23
0
def boolean_cut(base):
    # Create a cylinder
    cylinder_radius = 0.25
    cylinder_height = 2.0
    cylinder_origin = gp_Ax2(gp_Pnt(0.0, 0.0, -cylinder_height / 2.0),
                             gp_Dir(0.0, 0.0, 1.0))
    cylinder = BRepPrimAPI_MakeCylinder(cylinder_origin, cylinder_radius,
                                        cylinder_height)

    # Repeatedly move and subtract it from the input shape
    move = gp_Trsf()
    boolean_result = base
    clone_radius = 1.0

    for clone in range(8):
        angle = clone * pi / 4.0
        # Move the cylinder
        move.SetTranslation(
            gp_Vec(cos(angle) * clone_radius,
                   sin(angle) * clone_radius, 0.0))
        moved_cylinder = BRepBuilderAPI_Transform(cylinder.Shape(), move,
                                                  True).Shape()
        # Subtract the moved cylinder from the drilled sphere
        boolean_result = BRepAlgoAPI_Cut(boolean_result,
                                         moved_cylinder).Shape()
    return boolean_result
コード例 #24
0
def list_wire_random():
    '''
    output
        wires:      {TopoDS_Wire:string}
        wire_name:  ''
    '''
    wire_name = ''
    #    number of rings
    numr = int((DRAIN_R / 4 / DRAIN_S - 0.5))
    wires = {}

    for i in range(numr):
        #        radius of ith ring
        radius = 3 * DRAIN_S + i * 4 * DRAIN_S
        #        number of cells per ring
        nump = int(1.5 * pi + 2 * pi * i)
        #        print('np:',np)

        #        randomly choose the number of cells to combine
        combo_list = range(1, nump // 3 + 1)
        combo = random.choice(combo_list)
        #        angle between two adjacent cells
        ang = 2 * pi / nump
        #        randomly offset the start cell
        offset = random.gauss(ang / 2, ang / 2)
        if offset < 0.:
            offset = 0.
        if offset > ang:
            offset = ang
        wlist, combo_name = list_wire_combo(combo, ang, offset, radius)
        wires.update(wlist)
        wire_name += str(combo) + '(' + combo_name + ')'
        nump = nump // combo
        #        print('combo',combo,'repeat',np)

        ang = 2 * pi / nump
        for j in range(1, nump):
            trsf = gp_Trsf()
            trsf.SetRotation(
                gp_Ax1(DRAIN_RCS.Location(), DRAIN_RCS.Direction()), ang * j)
            for wire in wlist:
                wname = wlist[wire]
                bresp_trsf = BRepBuilderAPI_Transform(wire, trsf)
                wire = topods.Wire(bresp_trsf.Shape())
                wires[wire] = wname

    return wires, wire_name
コード例 #25
0
def mirror(brep, plane='xz', axe2=None, copy=False):
    """Originally from pythonocc-utils : might add dependency on this?
    Mirrors object

    Parameters
    ----------
    brep : OCC.TopoDS.TopoDS_Shape
        The shape to mirror

    plane : string (default = 'xz')
        The name of the plane in which to mirror objects. Acceptable inputs are
        any of 'xy', 'yx' , 'zy', 'yz', 'yz', 'zy'. Overwritten if axe2 is
        defined.

    axe2 : OCC.gp.gp_Ax2
        The axes through which to mirror (overwrites input 'plane')

    copy : bool
        
    Returns
    -------
    BRepBuilderAPI_Transform.Shape : TopoDS_Shape
        The reflected shape
    
    Notes
    -----
    Pchambers: Added a functionality here to specify a plane using a string so
    that users could avoid interacting with core occ objects"""
    if axe2:
        plane = None
    else:
        Orig = gp_Pnt(0., 0., 0.)
        if plane in ['xz', 'zx']:
            ydir = gp_Dir(0, 1, 0)
            axe2 = gp_Ax2(Orig, ydir)
        elif plane in ['yz', 'zy']:
            xdir = gp_Dir(1, 0, 0)
            axe2 = gp_Ax2(Orig, xdir)
        elif plane in ['xy', 'yx']:
            zdir = gp_Dir(0, 0, 1)
            axe2 = gp_Ax2(Orig, zdir)
        else:
            raise (ValueError, "Unknown mirror plane string,", plane)
    trns = gp_Trsf()
    trns.SetMirror(axe2)
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    return brep_trns.Shape()
コード例 #26
0
ファイル: Construct.py プロジェクト: psavine42/OCCUtilsExt
def translate_topods_from_vector(brep_or_iterable, vec, copy=False):
    """
    translate a brep over a vector
    @param brep:    the Topo_DS to translate
    @param vec:     the vector defining the translation
    @param copy:    copies to brep if True
    """
    st = ShapeToTopology()
    trns = gp_Trsf()
    trns.SetTranslation(vec)
    if issubclass(brep_or_iterable.__class__, TopoDS_Shape):
        brep_trns = BRepBuilderAPI_Transform(brep_or_iterable, trns, copy)
        brep_trns.Build()
        return st(brep_trns.Shape())
    else:
        return [
            translate_topods_from_vector(brep_or_iterable, vec, copy)
            for i in brep_or_iterable
        ]
コード例 #27
0
def scale_uniformal(brep, pnt, factor, copy=False):
    '''
    translate a brep over a vector : from pythonocc-utils
    Paramters
    ---------
    brep : TopoDS_Shape
        the TopoDS_Shape to scale
    pnt : gp_Pnt
        Origin of scaling
    factor : scalar
        Scaling factor
    copy : bool
        copies to brep if True
    '''
    trns = gp_Trsf()
    trns.SetScale(pnt, factor)
    brep_trns = BRepBuilderAPI_Transform(brep, trns, copy)
    brep_trns.Build()
    return brep_trns.Shape()
def rotate_shp_3_axis(shape, rx, ry, rz, unity="deg"):
    """ Rotate a shape around (O,x), (O,y) and (O,z).
    @param rx_degree : rotation around (O,x)
    @param ry_degree : rotation around (O,y)
    @param rz_degree : rotation around (O,z)
    @return : the rotated shape.
    """
    if unity == "deg":  # convert angle to radians
        rx = radians(rx)
        ry = radians(ry)
        rz = radians(rz)
    alpha = gp_Trsf()
    alpha.SetRotation(gp_OX(), rx)
    beta = gp_Trsf()
    beta.SetRotation(gp_OY(), ry)
    gamma = gp_Trsf()
    gamma.SetRotation(gp_OZ(), rz)
    brep_trns = BRepBuilderAPI_Transform(shape, alpha*beta*gamma, False)
    shp = brep_trns.Shape()
    return shp
コード例 #29
0
    def positionedShape(self):
        pnt_0, v_dir_0 = self.ball_0.D1()
        pnt_1, v_dir_1 = self.ball_1.D1()
        v_ball_0 = gp_Vec(pnt_0.XYZ())
        v_ball_1 = gp_Vec(pnt_1.XYZ())
        v_mid = (v_ball_0 + v_ball_1).Multiplied(0.5)
        v_ball_to_ball = gp_Vec(pnt_1.XYZ()) - gp_Vec(pnt_0.XYZ())

        v_0 = (v_ball_to_ball.Crossed(v_dir_0)).Normalized()
        v_1 = (v_ball_to_ball.Crossed(v_dir_1)).Normalized()
        v_y = (v_0 + v_1).Multiplied(0.5).Normalized()
        v_z = (v_ball_to_ball.Crossed(v_y)).Normalized()

        ax_final = gp_Ax3(gp_Pnt(v_mid.XYZ()), gp_Dir(v_z.XYZ()),
                          gp_Dir(v_ball_to_ball.XYZ()))

        trsf = gp_Trsf()
        trsf.SetTransformation(ax_final, gp_Ax3())

        mt = BRepBuilderAPI_Transform(self.shape, trsf)
        return mt.Shape()
コード例 #30
0
ファイル: shapes.py プロジェクト: fragmuffin/cadquery
    def transformShape(self, tMatrix):
        """
            tMatrix is a matrix object.
            returns a copy of the ojbect, transformed by the provided matrix,
            with all objects keeping their type
        """

        r = Shape.cast(
            BRepBuilderAPI_Transform(self.wrapped, tMatrix.wrapped).Shape())
        r.forConstruction = self.forConstruction

        return r