布尔数据 点的相交

发布时间 2023-09-25 19:35:37作者: opencascade

布尔数据 点的相交

eryar@163.com

1 Introduction

OpenCASCADE中将相交干涉分成两种类型,一种类型是边界表示数据中的点线面Vertex, Edge, Face包含几何和容差,在3D空间中距离在容差范围之内的BRep相交。包含几何数据的点线面就有6种类型的BRep相交(BRep interferences):

  • Vertex/Vertex
  • Vertex/Edge
  • Vertex/Face
  • Edge/Edge
  • Edge/Face
  • Face/Face

第二种类型是一个模型完全在一个Solid之内,这种相交称为非BRep的相交(Non-BRep interferences),有四种可能:

  • Vertex/Solid
  • Edge/Solid
  • Face/Solid
  • Solid/Solid

上面两种类型的相交总共为10种,在类BOPDS_DS中通过静态函数NbInterfTypes()返回。代码如下:

//=======================================================================
//function : NbInterfTypes
//purpose  : Returns the number of types of the interferences
//=======================================================================
inline Standard_Integer BOPDS_DS::NbInterfTypes()
{
  return 10;
}

在BOPDS_Tools中又重新对相交的类型进行编码。本文通过在DRAW中使用Tcl来对源码进行DEBUG,主要来探究一下对点Vertex的相交处理。

2 Vertex/Vertex interference

上图所示为文档中对点/点相交的描述,当两个点之间的距离在容差范围之内时,判定为相交。相交的结果会得到新的点Vertex,其坐标为考虑两个点的容差的一个球的中心,容差为球的半径。在DRAW中输入命令:

vertex v1 1 2 3
vertex v2 1 2 3
bop v1 v2

其中两点求交代码如下:

//=======================================================================
// function: ComputeVV
// purpose: 
//=======================================================================
Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1, 
                                               const TopoDS_Vertex& aV2,
                                               const Standard_Real aFuzz)
{
  Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
  gp_Pnt aP1, aP2;
  Standard_Real aFuzz1 = (aFuzz > Precision::Confusion() ? aFuzz : Precision::Confusion());
  //
  aTolV1=BRep_Tool::Tolerance(aV1);
  aTolV2=BRep_Tool::Tolerance(aV2);
  aTolSum=aTolV1+aTolV2+aFuzz1;
  aTolSum2=aTolSum*aTolSum;
  //
  aP1=BRep_Tool::Pnt(aV1);
  aP2=BRep_Tool::Pnt(aV2);
  //
  aD2=aP1.SquareDistance(aP2);
  if (aD2>aTolSum2) {
    return 1;
  }
  return 0;
}

从代码中可以看出OCC中布尔模糊容差Fuzzy Tolerance的最高精度为Precision::Confusion()。根据相交结果生成新的点代码如下:

//=======================================================================
// function: MakeVertex
// purpose : Makes the vertex in the middle of given vertices with
//           the tolerance covering all tolerance spheres of vertices.
//=======================================================================
void BOPTools_AlgoTools::MakeVertex(const TopTools_ListOfShape& aLV,
                                    TopoDS_Vertex& aVnew)
{
  Standard_Integer aNb = aLV.Extent();
  if (aNb == 1)
    aVnew=*((TopoDS_Vertex*)(&aLV.First()));
  else if (aNb > 1)
  {
    Standard_Real aNTol;
    gp_Pnt aNC;
    BRepLib::BoundingVertex(aLV, aNC, aNTol);
    BRep_Builder aBB;
    aBB.MakeVertex(aVnew, aNC, aNTol);
  }
}

算法实现与文档描述一致。相交结果除了新产生的点,还有这些产生这些结果的数据都保存到BOPDS_InterfVV中,代码如下:

if (theAddInterfs) {
    if (myDS->AddInterf(n1, n2))
    {
        BOPDS_InterfVV& aVV = aVVs.Appended();
        aVV.SetIndices(n1, n2);
        aVV.SetIndexNew(nV);
    }
}

其中BOPDS_InterfVV中保存了哪两个点相交的索引n1, n2及产生新的点的索引nV。

3 Vertex/Edge interference

对于点Vi和边Ej相交的条件为点Vi到边的投影距离小于点Tol(Vi),边Tol(Ej)的容差之和。在DRAW中输入命令如下:

vertex v1 0 0 0
vertex v2 6 0 0
vertex v 3 0 0
edge e v1 v2
bop e v

其中点与边相交的代码如下:

//=======================================================================
//function : ComputeVE
//purpose  : 
//=======================================================================
Standard_Integer IntTools_Context::ComputeVE
  (const TopoDS_Vertex& theV, 
   const TopoDS_Edge&   theE,
   Standard_Real& theT,
   Standard_Real& theTol,
   const Standard_Real theFuzz)
{
  if (BRep_Tool::Degenerated(theE)) {
    return -1;
  }
  if (!BRep_Tool::IsGeometric(theE)) { 
    return -2;
  }
  Standard_Real aDist, aTolV, aTolE, aTolSum;
  Standard_Integer aNbProj;
  gp_Pnt aP;
  //
  aP=BRep_Tool::Pnt(theV);
  //
  GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(theE);
  aProjector.Perform(aP);

  aNbProj=aProjector.NbPoints();
  if (!aNbProj) {
    return -3;
  }
  //
  aDist=aProjector.LowerDistance();
  //
  aTolV=BRep_Tool::Tolerance(theV);
  aTolE=BRep_Tool::Tolerance(theE);
  aTolSum = aTolV + aTolE + Max(theFuzz, Precision::Confusion());
  //
  theTol = aDist + aTolE;
  theT = aProjector.LowerDistanceParameter();
  if (aDist > aTolSum) {
    return -4;
  }
  return 0;
}

使用类GeomAPI_ProjectPointOnCurve来计算点到线的投影距离,当距离小于点Tol(V)和Tol(E)及模糊容差Fuzzy之和的认为是相交的。相交结果保存在BOPDS_InterfVE中,记录了点和边的索引及点在边上的参数。

这里面会引入两个新的概念:BOPDS_Pave和BOPDS_PaveBlock。其中PaveBlock中记录了边中所有的点的Pave,及边的索引。Pave中记录点的索引,在边上的参数。一个PaveBlock对应边上一小部分。

因为容差的原因还引入收缩范围Shrunk Range的概念,先记住这些概念看看后面如何使用这些数据。

4 Vertex/Face interference

点与面的相交也是通过点到面的投影距离来判定的。当然也可以用Tcl脚本来调试,这里留给同学们自己动手尝试一下。计算点与面相交的代码如下:

//=======================================================================
//function : ComputeVF
//purpose  : 
//=======================================================================
Standard_Integer IntTools_Context::ComputeVF
  (const TopoDS_Vertex& theVertex, 
   const TopoDS_Face&   theFace,
   Standard_Real& theU,
   Standard_Real& theV,
   Standard_Real& theTol,
   const Standard_Real theFuzz)
{
  Standard_Real aTolV, aTolF, aTolSum, aDist;
  gp_Pnt aP;

  aP = BRep_Tool::Pnt(theVertex);
  //
  // 1. Check if the point is projectable on the surface
  GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(theFace);
  aProjector.Perform(aP);
  //
  if (!aProjector.IsDone()) { // the point is not  projectable on the surface
    return -1;
  }
  //
  // 2. Check the distance between the projection point and 
  //    the original point
  aDist = aProjector.LowerDistance();
  //
  aTolV = BRep_Tool::Tolerance(theVertex);
  aTolF = BRep_Tool::Tolerance(theFace);
  //
  aTolSum = aTolV + aTolF + Max(theFuzz, Precision::Confusion());
  theTol = aDist + aTolF;
  aProjector.LowerDistanceParameters(theU, theV);
  //
  if (aDist > aTolSum) {
    // the distance is too large
    return -2;
  }
  //
  gp_Pnt2d aP2d(theU, theV);
  Standard_Boolean pri = IsPointInFace (theFace, aP2d);
  if (!pri) {//  the point lays on the surface but out of the face 
    return -3;
  }
  return 0;
}

使用类GeomAPI_ProjectPointOnSurf来计算点到面的投影距离,并使用定位器IntTools_FClass2d来判断点是否在有界的Face面上。将计算结果保存到BOPDS_InterfVF中,保存数据有点与面的索引和点在面的参数空间上的参数。还更新面的信息,将这些点的索引保存到VerticesIn中。

5 Conclusion

综上所述,在DRAW中使用脚本可以方便对相关代码进行DEBUG。通过点与点、边和面的相交代码实现可以看出在BOPDS中对于相交结果保存了哪些数据。及模糊容差Fuzzy Tolerance的作用和精度。通过引入Pave, PaveBlock, Shrunk Range来保存求交结果及容差处理。