def match_singleHole(solid_add, solid_base):

    cyls_sel_base, cyls_sel_add, projPln = selectCylinderFromClosestPln(
        solid_add, solid_base)
    pntList_base = []
    for i in cyls_sel_base:
        loc = BRepAdaptor_Surface(i).Cylinder().Location()
        pnt = gp_Pnt(loc.X(), loc.Y(), loc.Z())
        pntList_base.append(pnt)

    pntList_add = []
    for i in cyls_sel_add:
        loc = BRepAdaptor_Surface(i).Cylinder().Location()
        pnt = gp_Pnt(loc.X(), loc.Y(), loc.Z())
        pntList_add.append(pnt)

    pntList_base_proj = [
        ais_ProjectPointOnPlane(pnt, projPln) for pnt in pntList_base
    ]
    pntList_add_proj = [
        ais_ProjectPointOnPlane(pnt, projPln) for pnt in pntList_add
    ]

    mvVec = get_shortest_vec(pntList_add_proj, pntList_base_proj)
    trsf = gp_Trsf()
    trsf.SetTranslation(mvVec)
    solid_add.Move(TopLoc_Location(trsf))
def filter_cylinder_by_position(cylList_from_solidAdd, projPln, dist_tol=0.3):
    """Project all points of cylinders' axis into the projPln, and return the projected point on the projPln

    Arguments:
        cylList_from_solidAdd {[type]} -- [description]
        projPln {[type]} -- [description]

    Keyword Arguments:
        dist_tol {float} -- [description] (default: {0.3})

    Returns:
        [type] -- [description]
    """
    # project the first cylinder to get the point. Which is needed for the later distance calculation
    initPnt = ais_ProjectPointOnPlane(
        BRepAdaptor_Surface(cylList_from_solidAdd[0],
                            True).Cylinder().Location(), projPln)
    projPntList = [initPnt]
    for cyl in cylList_from_solidAdd:
        newPnt = ais_ProjectPointOnPlane(
            BRepAdaptor_Surface(cyl, True).Cylinder().Location(), projPln)
        isNewPnt = True
        # check whehter the projected point overlaps other points
        for pnt in projPntList:
            if newPnt.Distance(pnt) < dist_tol:
                isNewPnt = False
        if isNewPnt:
            projPntList.append(newPnt)
    return projPntList
def get_neighbor_vector(hole_cyl, cylList, projPln):
    vecList = []
    pnt_hole = BRepAdaptor_Surface(hole_cyl, True).Cylinder().Location()
    pnt_start = ais_ProjectPointOnPlane(pnt_hole, projPln)
    for cyl in cylList:
        pnt_cyl = BRepAdaptor_Surface(cyl, True).Cylinder().Location()
        pnt_end = ais_ProjectPointOnPlane(pnt_cyl, projPln)
        vecList.append(gp_Vec(pnt_start, pnt_end))
    return vecList
def get_closest_parallel_planePair(solid_add,
                                   solid_base=None,
                                   init_min_dist=1000.0,
                                   xyplane_z_inMM=1215.0):
    """
    Arguments:
        solid_add {TopoDS_Solid} -- The solid going to be added

    Keyword Arguments:
        solid_base {TopoDS_Solid} -- By default, solid_base will be xy-plane (default: {None})
        init_min_dist {float} -- [description] (default: {10.0})

    Returns:
        {dict} -- keyValues: miniDist, topoPair, geomPair, mvVec
    """
    min_dist = init_min_dist
    ang_list = find_closest_normal_pair(solid_add, solid_base)
    if solid_base is None:
        solid_base = gen_boxSolidAsTable(height=xyplane_z_inMM)
    axisGrp1 = group_planes_by_axis(solid_base)
    axisGrp2 = group_planes_by_axis(solid_add)
    axisPair = ang_list['minAxisKeyPair']
    for axKeyPair in axisPair:
        for topoPln1 in axisGrp1[axKeyPair[0]]:
            surf1 = BRepAdaptor_Surface(topoPln1, True)
            pln1 = surf1.Plane()
            # [ToDo] A better distance evaluation, how to select a correct point which is inside the wire or centerofmass of plane
            plnpnt1 = pln1.Location()
            for topoPln2 in axisGrp2[axKeyPair[1]]:
                surf2 = BRepAdaptor_Surface(topoPln2, True)
                pln2 = surf2.Plane()
                # rospy.logdebug('Distance:', pln2.Distance(plnpnt1))
                dist = pln2.Distance(plnpnt1)
                if dist < min_dist:
                    min_dist = dist
                    minDistTopoPair = [topoPln1, topoPln2]
                    minDistGeomPair = [pln1, pln2]
    p = gp_Pnt(0, 0, 0)
    p1 = ais_ProjectPointOnPlane(p, minDistGeomPair[0])
    p2 = ais_ProjectPointOnPlane(p, minDistGeomPair[1])
    # in order to remove small digits
    projPln = minDistGeomPair[0]
    mvVec = gp_Vec(p2, p1)
    projPlnNormal = gp_Vec(projPln.Axis().Direction())
    mag = np.sign(mvVec.Dot(projPlnNormal)) * mvVec.Magnitude()
    mvVec = projPlnNormal.Normalized().Multiplied(mag)
    return {
        'minDist': dist,
        'topoPair': minDistTopoPair,
        'geomPair': minDistGeomPair,
        'mvVec': mvVec
    }
 def setProjPln(self, gp_pln):
     self.projPln = gp_pln
     self.projLocation = ais_ProjectPointOnPlane(self.location,
                                                 self.projPln)
def cylinder_pnt2pln(cyl, pln):
    ais_ProjectPointOnPlane(cyl.Location(), pln)