zoukankan      html  css  js  c++  java
  • OpenCASCADE Chamfer 2D

    OpenCASCADE Chamfer 2D

    eryar@163.com

     二维的倒角Chamfer功能可以将两个不平行的曲线进行倒角。如下图所示为QCAD中进行倒角的效果图:选择要倒角的两个边,及设置两个边上的倒角距离。

     

    OpenCASCADE中也提供了这个二维曲线倒角功能,使用Tcl脚本在DRAW中显示如下:

    polyline p 0 0 0 10 0 0 10 10 0

    chamfer2d r p 3 5

    vdisplay r

      

    在源文件BRepTest_Fillet2DCommands.cxx中找到命令chamfer2d的实现: 

    //=======================================================================
    //function : chamfer2d
    //purpose  : Chamfer 2d.
    //usage    : chamfer2d result wire (or edge1 edge2) length1 length2
    //=======================================================================
    static Standard_Integer chamfer2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
    {
      if (n != 5 && n != 6) 
      {
        di << "Usage : chamfer2d result wire (or edge1 edge2) length1 length2";
        return 1;
      }
    
      TopoDS_Shape W;
      TopoDS_Shape E1, E2;
      if (n == 6)
      {
        // Get the edges.
        E1 = DBRep::Get(a[2], TopAbs_EDGE, Standard_True);
        E2 = DBRep::Get(a[3], TopAbs_EDGE, Standard_True);
      }
      else 
      {
        W = DBRep::Get(a[2], TopAbs_WIRE, Standard_True);
      }
    
      // Get the lengths.
      const Standard_Real length1 = (n == 6) ? Atof(a[4]) : Atof(a[3]);
      const Standard_Real length2 = (n == 6) ? Atof(a[5]) : Atof(a[4]);
    
      // Algo.
      ChFi2d_ChamferAPI algo;
      if (n == 6)
      {
        const TopoDS_Edge& e1 = TopoDS::Edge(E1);
        const TopoDS_Edge& e2 = TopoDS::Edge(E2);
        algo.Init(e1, e2);
      }
      else
      {
        const TopoDS_Wire& w = TopoDS::Wire(W);
        algo.Init(w);
      }
    
      // Prepare the chamfer.
      algo.Perform();
    
      // Get the result.
      TopoDS_Edge M1, M2; // modified E1 and E2
      TopoDS_Edge chamfer = algo.Result(M1, M2, length1, length2);
      if (chamfer.IsNull())
      {
        di << "Error: the algrithm produced no result.";
        return 1;
      }
    
      if (n == 6)
      {
        // Set result for DRAW.
        DBRep::Set(a[1], chamfer);
        
        // Update neighbour edges in DRAW.
        DBRep::Set(a[2], M1);
        DBRep::Set(a[3], M2);
      }
      else // recreate the wire using the chamfer
      {
        BRepBuilderAPI_MakeWire mkWire(M1, chamfer, M2);
        if (mkWire.IsDone())
          DBRep::Set(a[1], mkWire.Wire());
        else
          DBRep::Set(a[1], chamfer);
      }
    
      return 0;
    }

    从上述源码可以看出,二维曲线倒角功能主要是由类ChFi2d_ChamferAPI实现。OpenCASCADE中的算法类的大致套路就是:

    Init():初始化:数据输入。给定几种条件的初始化函数,对应几种情况的数据输入。

    Perform():执行计算。根据输入数据,计算出结果;

    Result()/Get():得到计算结果。

    二维曲线的倒角功能是相对简单的功能,所以找到类ChFi2d_ChamferAPI中源码看看实现过程:

    // Constructs a chamfer edge.
    // Returns true if the edge is constructed.
    Standard_Boolean ChFi2d_ChamferAPI::Perform()
    {
      myCurve1 = BRep_Tool::Curve(myEdge1, myStart1, myEnd1);
      myCurve2 = BRep_Tool::Curve(myEdge2, myStart2, myEnd2);
      // searching for common points
      if (myCurve1->Value(myStart1).IsEqual(myCurve2->Value(myEnd2), Precision::Confusion())) 
      {
        myCommonStart1 = true;
        myCommonStart2 = false;
      } 
      else 
      {
        if (myCurve1->Value(myEnd1).IsEqual(myCurve2->Value(myStart2), Precision::Confusion())) 
        {
          myCommonStart1 = false;
          myCommonStart2 = true;
        } 
        else
        {
          if (myCurve1->Value(myEnd1).IsEqual(myCurve2->Value(myEnd2), Precision::Confusion())) 
          {
            myCommonStart1 = false;
            myCommonStart2 = false;
          } 
          else 
          {
            myCommonStart1 = true;
            myCommonStart2 = true;
          }
        }
      }
      return Standard_True;
    }

    执行计算函数Perform中,根据边EDGE中的曲线数据,判断两个曲线的端点处是不是相连接的,并记录下连接状态:是首首连接、首尾连接等。这里面判断两个点是不是相等使用的gp_PntIsEqual()函数,这个是根据两个点之间的距离来判断的,需要计算出两个点之间的距离。这里可以使用距离的平方来判断SquareDistance来判断两个点是不是相等,可以提高性能。因为计算距离需要要开方,开方比较耗时。关于开方的数值算法,还有个传奇故事:一个Sqrt函数引发的血案 https://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html

    // Returns the result (chamfer edge, modified edge1, modified edge2).
    TopoDS_Edge ChFi2d_ChamferAPI::Result(TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2,
                                          const Standard_Real theLength1, const Standard_Real theLength2) 
    {
      TopoDS_Edge aResult;
      if (Abs(myEnd1 - myStart1) < theLength1) 
        return aResult;
      if (Abs(myEnd2 - myStart2) < theLength2) 
        return aResult;
    
      Standard_Real aCommon1 = (myCommonStart1?myStart1:myEnd1) + (((myStart1 > myEnd1)^myCommonStart1)?theLength1:-theLength1);
      Standard_Real aCommon2 = (myCommonStart2?myStart2:myEnd2) + (((myStart2 > myEnd2)^myCommonStart2)?theLength2:-theLength2);
    
      // make chamfer edge
      GC_MakeLine aML(myCurve1->Value(aCommon1), myCurve2->Value(aCommon2));
      BRepBuilderAPI_MakeEdge aBuilder(aML.Value(), myCurve1->Value(aCommon1), myCurve2->Value(aCommon2));
      aResult = aBuilder.Edge();
      // divide first edge
      BRepBuilderAPI_MakeEdge aDivider1(myCurve1, aCommon1, (myCommonStart1?myEnd1:myStart1));
      theEdge1 = aDivider1.Edge();
      // divide second edge
      BRepBuilderAPI_MakeEdge aDivider2(myCurve2, aCommon2, (myCommonStart2?myEnd2:myStart2));
      theEdge2 = aDivider2.Edge();
    
      return aResult;
    }

    这个代码很好理解,根据Perform()函数中计算到的相连状态,再结合参数曲线计算出倒角得到的线aResult,及倒角后的两条边。

    二维曲线倒角算法相对简单,在理解二维曲线倒角的基础上再去深入理解三维倒角原理。

    因为OpenCASCADE的BREP结构中没有保存从Vertex到Edger的关系,所以查找两条边EDGE的相连关系时只能从几何点之间的距离来处理。

    对于距离的比较,能直接用平方距离比较的情况下尽量避免开方,可以提高性能。


    为了方便大家在移动端也能看到我的博文和讨论交流,现已注册微信公众号,欢迎大家扫描下方二维码关注。
    Shing Liu(eryar@163.com)
  • 相关阅读:
    LoadRunner脚本增强技巧之参数化(二)
    LoadRunner脚本增强技巧之参数化(一)
    LoadRunner脚本增强技巧之手动关联
    LoadRunner脚本增强技巧之自动关联
    LoadRunner录制用户操作
    Fiddler绕过前端直接和后台进行交互
    Android手机Fiddler真机抓包
    zabbix自定义监控项二
    zabbix自定义监控项一
    zabbix主机自动发现和监控
  • 原文地址:https://www.cnblogs.com/eryar/p/Chamfer2d.html
Copyright © 2011-2022 走看看