def transform_nonuniformal(brep, factors, vec=[0, 0, 0], copy=False): """Nonuniformly scale brep with respect to pnt by the x y z scaling factors provided in 'factors', and translate by vector 'vec' Parameters ---------- factors : List of factors [Fx, Fy, Fz] Scaling factors with respect to origin (0,0,0) vec : List of x,y,z or gp_Vec the translation vector (default is [0,0,0]) Notes ----- * Only tested on 3d shapes * Assumes factors are define with respect to the origin (0,0,0) """ assert (len(factors) == 3), \ ("factors should have [Fx, Fy, Fz] scaling factors: Found length ", len(factors)) M = np.diag(factors).flatten() trns_M = gp_Mat(*M) try: V = gp_XYZ(*vec) except NotImplementedError: V = gp_XYZ(vec.X(), vec.Y(), vec.Z()) trns = gp_GTrsf(trns_M, V) brep_trns = BRepBuilderAPI_GTransform(brep, trns, copy) brep_trns.Build() return brep_trns.Shape()
def transform_nonuniformal(brep, factors, vec=[0, 0, 0], copy=False): """Nonuniformly scale brep with respect to pnt by the x y z scaling factors provided in 'factors', and translate by vector 'vec' Parameters ---------- factors : List of factors [Fx, Fy, Fz] Scaling factors with respect to origin (0,0,0) vec : List of x,y,z or gp_Vec the translation vector (default is [0,0,0]) Notes ----- * Only tested on 3d shapes * Assumes factors are define with respect to the origin (0,0,0) """ assert(len(factors) == 3),\ ("factors should have [Fx, Fy, Fz] scaling factors: Found length ", len(factors)) M = np.diag(factors).flatten() trns_M = gp_Mat(*M) try: V = gp_XYZ(*vec) except NotImplementedError: V = gp_XYZ(vec.X(), vec.Y(), vec.Z()) trns = gp_GTrsf(trns_M, V) brep_trns = BRepBuilderAPI_GTransform(brep, trns, copy) brep_trns.Build() return brep_trns.Shape()
def uniform_scale(occtopology, tx, ty, tz, ref_pypt): """ This function uniformly scales an OCCtopology based on the reference point and tx,ty,tz factors. Parameters ---------- occtopology : OCCtopology The OCCtopology to be scaled. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex tx : float The scale factor in the X-axis. ty : float The scale factor in the Y-axis. tz : float The scale factor in the Z-axis. 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. """ moved_shape = move(ref_pypt, (0, 0, 0), occtopology) xform = gp_GTrsf() xform.SetVectorialPart(gp_Mat( tx, 0, 0, 0, ty, 0, 0, 0, tz, )) brep = BRepBuilderAPI_GTransform(xform) brep.Perform(moved_shape, True) trsfshape = brep.Shape() move_back_shp = move((0, 0, 0), ref_pypt, trsfshape) return move_back_shp
def uniform_scale(occshape, tx, ty, tz, ref_pypt): moved_shape = move(ref_pypt, (0, 0, 0), occshape) xform = gp_GTrsf() xform.SetVectorialPart(gp_Mat( tx, 0, 0, 0, ty, 0, 0, 0, tz, )) brep = BRepBuilderAPI_GTransform(xform) brep.Perform(moved_shape, True) trsfshape = brep.Shape() move_back_shp = move((0, 0, 0), ref_pypt, trsfshape) return move_back_shp
def uniform_scale(occtopology, tx, ty, tz, ref_pypt): """ This function uniformly scales an OCCtopology based on the reference point and tx,ty,tz factors. Parameters ---------- occtopology : OCCtopology The OCCtopology to be scaled. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex tx : float The scale factor in the X-axis. ty : float The scale factor in the Y-axis. tz : float The scale factor in the Z-axis. 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. """ moved_shape = move(ref_pypt, (0,0,0),occtopology) xform = gp_GTrsf() xform.SetVectorialPart(gp_Mat( tx, 0, 0, 0, ty, 0, 0, 0, tz, )) brep = BRepBuilderAPI_GTransform(xform) brep.Perform(moved_shape, True) trsfshape = brep.Shape() move_back_shp = move((0,0,0), ref_pypt,trsfshape) return move_back_shp
from OCC.gp import gp_Pnt, gp_XYZ, gp_Mat, gp_GTrsf from OCC.BRepPrimAPI import BRepPrimAPI_MakeSphere, BRepPrimAPI_MakeBox from OCC.BRepBuilderAPI import BRepBuilderAPI_GTransform from OCC.BRepAlgoAPI import BRepAlgoAPI_Common from OCC.Display.SimpleGui import init_display display, start_display, add_menu, add_function_to_menu = init_display() orig = gp_Pnt(0., 0., 0.) sphere = BRepPrimAPI_MakeSphere(orig, 50.).Solid() # be careful that the following scale numbers are "not too big", # otherwise boolean operations can be buggy # see isue a1 = 17.1 a2 = 17.1 a3 = 3.5 gTrsf = gp_GTrsf(gp_Mat(a1, 0, 0, 0, a2, 0, 0, 0, a3), gp_XYZ(0., 112.2, 0.)) ellipsoid = BRepBuilderAPI_GTransform(sphere, gTrsf).Shape() # then perform a boolean intersection with a box box = BRepPrimAPI_MakeBox(gp_Pnt(-1000, -1000, -1000), gp_Pnt(1000, 112.2, 1000)).Shape() common = BRepAlgoAPI_Common(box, ellipsoid).Shape() assert not common.IsNull() display.DisplayShape(box, color = "BLACK", transparency = 0.8) display.DisplayShape(ellipsoid, color = "BLACK", transparency = 0.8) display.DisplayShape(common, color = "BLACK", transparency = 0.8, update=True) start_display()
''' xform = gp_Trsf() xform.SetValues( 1.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, Precision_Angular(), Precision_Confusion() ); brep = BRepBuilderAPI_GTransform(shape, gp_GTrsf(xform), False) ''' # This options works as desired xform = gp_GTrsf() xform.SetVectorialPart(gp_Mat( 1.5, 0, 0, 0, 1, 0, 0, 0, 1, )) brep = BRepBuilderAPI_GTransform(shape, xform, False) brep.Build() shape = brep.Shape() stl_writer = StlAPI.StlAPI_Writer() stl_writer.Write(shape, 'scaled-cylinder.stl')
def align_mutiHoles(shp, matched_hole_pairs): # matching points pntsA = [i[0].projLocation for i in matched_hole_pairs] pntsB = [i[1].projLocation for i in matched_hole_pairs] normal = gp_Vec(matched_hole_pairs[0][1].direction) pntsA_noDuplicates = list(set(pntsA)) pntsB_noDuplicates = list(set(pntsB)) if len(pntsA_noDuplicates) != len(pntsA) or len(pntsB_noDuplicates) != len( pntsB): logging.warn( "[WARN] There are duplicated pairs(i.e. [A,B], [B, A]) in the given matched_hole_pairs" ) assert len(pntsA_noDuplicates) == len( pntsB_noDuplicates), "[Error] data are not pairwise" assert len(pntsA_noDuplicates) >= 2 or len( pntsB_noDuplicates ) >= 2, "[FATEL] input hole pairs should be more than 2" # Create the 3rd point on the project plane in the perpandicular diretion from the 1st to the 2nd point # [TODO] More test # Now 3rd point was added in the middle, so there will be sysmetry problem? if (len(pntsA_noDuplicates) == 2 and len(pntsB_noDuplicates) == 2): logging.warn( "[WARN] only 2 hole pairs found, add a dummpy pair to constrain rotating along the normal project plane" ) # distance between two points, which is used as a scale dist = pntsA_noDuplicates[0].Distance(pntsA_noDuplicates[1]) / 2.0 vecA = gp_Vec(pntsA_noDuplicates[0], pntsA_noDuplicates[1]) # Translation vector from orignal mid-points to the 3rd point(dummy points) translateVecA = vecA.Crossed(normal).Normalized().Scaled(dist) dummyPntA = centerOfMass_pnts(pntsA_noDuplicates).Translated( translateVecA) pntsA_noDuplicates.append(dummyPntA) vecB = gp_Vec(pntsB_noDuplicates[0], pntsB_noDuplicates[1]) translateVecB = vecB.Crossed(normal).Normalized().Scaled(dist) dummyPntB = centerOfMass_pnts(pntsB_noDuplicates).Translated( translateVecB) pntsB_noDuplicates.append(dummyPntB) # center of Mass cenA = centerOfMass_pnts(pntsA_noDuplicates) cenB = centerOfMass_pnts(pntsB_noDuplicates) # translation vector from centerOfMass to origin mvVecA2O = gp_Vec(cenA, gp_Pnt(0, 0, 0)) mvVecB2O = gp_Vec(cenB, gp_Pnt(0, 0, 0)) # translate all points, with rigid movement to move solid's center of Mass to origin newPntsA = [i.Translated(mvVecA2O) for i in pntsA_noDuplicates] newPntsB = [i.Translated(mvVecB2O) for i in pntsB_noDuplicates] if newPntsB[1].X() * newPntsA[1].X() < 0: ttmp = newPntsB[0] newPntsB[0] = newPntsB[1] newPntsB[1] = ttmp # matching 2 points set by SVD, transform from B to A npMatA = [gpVec2npMat((gp_Vec(gp_Pnt(0, 0, 0), i))) for i in newPntsA] npMatB = [gpVec2npMat(gp_Vec(gp_Pnt(0, 0, 0), i)) for i in newPntsB] varMat = np.asmatrix(np.zeros((3, 3))) for i in range(0, len(npMatA)): varMat += npMatB[i] * npMatA[i].transpose() linAlg = np.linalg U, s, Vh = linAlg.svd(varMat, full_matrices=True) R = Vh.transpose() * U.transpose() # if R has determinant -1, then R is a rotation plus a reflection if linAlg.det(R) < 0: # [ToDo] Don't know why third column or row should multiply -1 reverseMat = np.matrix([(1, 0, 0), (0, 1, 0), (0, 0, -1)]) logging.info('det(R) is < 0, change the sign of last column of Vh') R = reverseMat * (Vh.transpose()) * U.transpose() # q = quaternion_from_matrix(R) R = np.array(R) RgpMat = gp_Mat(R[0][0], R[0][1], R[0][2], R[1][0], R[1][1], R[1][2], R[2][0], R[2][1], R[2][2]) # RgpMat = gp_Mat(gp_XYZ(R[0][0], R[1][0], R[2][0]), gp_XYZ(R[0][1], R[1][1], R[2][1]), gp_XYZ(R[0][2], R[1][2], R[2][2])) q = gp_Quaternion(RgpMat) # gp_Extrinsic_XYZ = 2 # q.GetEulerAngles(2) # qq = gp_Quaternion() # qq.SetVectorAndAngle(gp_Vec(gp_Dir(gp_XYZ(0,0,1))), q.GetEulerAngles(2)[2]) trsf = gp_Trsf() trsf.SetTranslation(mvVecB2O) toploc = TopLoc_Location(trsf) shp.Move(toploc) trsf = gp_Trsf() trsf.SetRotation(q) toploc = TopLoc_Location(trsf) shp.Move(toploc) trsf = gp_Trsf() trsf.SetTranslation(mvVecA2O.Reversed()) toploc = TopLoc_Location(trsf) shp.Move(toploc)
from OCC import StlAPI shape = BRepPrimAPI_MakeCylinder(20,40).Shape() # This options creates unwanted polygons ''' xform = gp_Trsf() xform.SetValues( 1.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, Precision_Angular(), Precision_Confusion() ); brep = BRepBuilderAPI_GTransform(shape, gp_GTrsf(xform), False) ''' # This options works as desired xform = gp_GTrsf() xform.SetVectorialPart(gp_Mat( 1.5, 0, 0, 0, 1, 0, 0, 0, 1, )) brep = BRepBuilderAPI_GTransform(shape, xform, False) brep.Build() shape = brep.Shape() stl_writer = StlAPI.StlAPI_Writer() stl_writer.Write(shape, 'scaled-cylinder.stl')