def __group_coaxial_cylinders(cylinders, tol_ang=0.5, tol_lin=0.1, roundDigit=6): """According to cylinders' axis, categorize a list of cylinders into a dictionary by using its axis as a key. Arguments: cylinders {[TopoDS_Face,...]} -- list of TopoDS_Face tol_ang {float} -- [Unit - degree] the angle between these two axis below this value will be recognize as two parallel axis tol_lin Returns: {'string': [TopoDS_Face,...]} -- returns a dictionary, key is string of axis and location vector, value is list of TopoDS_Shape """ logging.debug('Entering group_coaxial') tol_rad = radians(tol_ang) skipList = [] cyl_ax_grp = {} for i in range(0, len(cylinders)): if i in skipList: continue cyl1 = BRepAdaptor_Surface(cylinders[i], True).Cylinder() axis1 = cyl1.Axis() location1 = cyl1.Location() axisDir1 = (round(axis1.Direction().X(), roundDigit), round(axis1.Direction().Y(), roundDigit), round(axis1.Direction().Z(), roundDigit)) cylLoc1 = (round(location1.X(), roundDigit), round(location1.Y(), roundDigit), round(location1.Z(), roundDigit)) key = (axisDir1, cylLoc1) if key not in cyl_ax_grp.keys(): cyl_ax_grp[key] = [cylinders[i]] else: logging.warning('Error !!! Please check the logic again !') for j in range(i + 1, len(cylinders)): # logging.debug('i = %d, j = %d' % (i, j)) if j in skipList: # logging.debug('skip !!') continue cyl2 = BRepAdaptor_Surface(cylinders[j]).Cylinder() axis2 = cyl2.Axis() if axis1.IsCoaxial(axis2, tol_rad, tol_lin) or axis1.IsCoaxial( axis2.Reversed(), tol_rad, tol_lin): # logging.debug('Coaxial !!') cyl_ax_grp[key].append(cylinders[j]) skipList.append(j) return cyl_ax_grp
def group_planes_by_axis(shape): """[summary] Extract all planes from shape, and group them according to their normal vector. Arguments: shape {TopoDS_Shape} -- [description] Returns: {dict} -- key: normal vector as string) value: list of TopoDS_Shape(Plane) """ if shape is None: logging.warn("Input shape is None") pln_dict = None else: planeList = RecognizeTopo(shape).planes() pln_dict = {} for pln in planeList: gp_pln = BRepAdaptor_Surface(pln).Plane() normal = gp_pln.Axis().Direction() key = '%.6f,%.6f,%.6f' % (round(normal.X(), 6), round( normal.Y(), 6), round(normal.Z(), 6)) key = tuple([float(i) for i in key.split(',')]) if key not in pln_dict.keys(): pln_dict[key] = [pln] else: pln_dict[key].append(pln) return pln_dict
def group_cylinders_byAxisDir(cylinders, anglTolDeg=5, roundDigit=6, groupParallelAx=True): logging.debug('Entering group_cylinders_byAxisDir') cyl_ax = {} for cylinder in cylinders: cyl = BRepAdaptor_Surface(cylinder, True).Cylinder() axis = cyl.Axis() key = (round(axis.Direction().X(), roundDigit), round(axis.Direction().Y(), roundDigit), round(axis.Direction().Z(), roundDigit)) if key in cyl_ax.keys(): cyl_ax[key].append(cylinder) else: cyl_ax[key] = [cylinder] for key in cyl_ax.keys(): listOflist = list(find_full_cylinder(cyl_ax[key]).values()) cyl_ax[key] = [k for i in listOflist for k in i] if groupParallelAx: axisKeyList = list(cyl_ax.keys()) combineList = [] j = 0 while len(axisKeyList) >= 1: ax1 = axisKeyList.pop(0) grp = [ax1] dir1 = gp_Dir(ax1[0], ax1[1], ax1[2]) while j < len(axisKeyList): ax2 = axisKeyList[j] dir2 = gp_Dir(ax2[0], ax2[1], ax2[2]) j += 1 if dir1.IsParallel(dir2, radians(anglTolDeg)): grp.append(ax2) j -= 1 axisKeyList.pop(j) combineList.append(grp) j = 0 cyl_grpByAx = {} for i in combineList: cyl_grpByAx[i[0]] = [] for j in i: cyl_grpByAx[i[0]] += cyl_ax[j] else: cyl_grpByAx = cyl_ax return cyl_grpByAx
def group_cyl_byPln(solid, distTol=0.5, angTolDeg=5.0): cylinders = RecognizeTopo(solid).cylinders() cyl_dirGrp = group_cylinders_byAxisDir(cylinders, anglTolDeg=angTolDeg, groupParallelAx=True) cyl_dirGrpKeys = list(cyl_dirGrp.keys()) # group cylinders by plane CylinderGrpsFromDiffPln = {} j = 0 for dirKey in cyl_dirGrpKeys: CylinderGrpsFromDiffPln[dirKey] = [] parallel_cyl_grps = cyl_dirGrp[dirKey].copy() grp_cylinderOnSamePln = {} while len(parallel_cyl_grps) >= 1: # take out the first element for creating plane, and search the other cylinders on the same plane firstCylinder = parallel_cyl_grps.pop(0) # fitting a geomety surface to TopoDS_Surface brepCylinder = BRepAdaptor_Surface(firstCylinder).Cylinder() dir1 = brepCylinder.Axis().Direction() # location of cylinder is usually the location of local coordinate system, which is on the axis of cylinder loc1 = brepCylinder.Location() # create gp_Pln pln = gp_Pln(loc1, dir1) grp_cylinderOnSamePln[pln] = [firstCylinder] # Search the cylinders on the same pln, if yes, extract from parallel_cyl_grps # loop all elements in parallel_cyl_grps while j < len(parallel_cyl_grps): brepCylinder2 = BRepAdaptor_Surface( parallel_cyl_grps[j]).Cylinder() loc2 = brepCylinder2.Location() if pln.Distance(gp_Pnt(loc2.X(), loc2.Y(), loc2.Z())) < distTol: grp_cylinderOnSamePln[pln].append(parallel_cyl_grps[j]) parallel_cyl_grps.pop(j) else: j += 1 j = 0 CylinderGrpsFromDiffPln[dirKey] = grp_cylinderOnSamePln return CylinderGrpsFromDiffPln