欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OCCT中的偏移面 (Geom_OffsetSurface)

程序员文章站 2022-04-15 18:42:03
...

 三维空间中,偏移面的定义如下:

  •  基础面(偏移面与基础面平行)。
  •  偏移面与基础面的距离。

    通过将基础面上的点沿其法向移动特定距离得到偏移面上的点。法向通过叉积D1u ^ D1v 得到,D1u和D1v分别是在参数u和v方向上与基础面相切的向量。偏移值的符号决定了相对于基础面的哪个侧面做偏移。如果偏移为正,则沿法向做偏移,如果偏移为负,则沿法向的反向做偏移。如果isNotCheckC0 = TRUE,则尚未检查基础表面是否具有C0连续性。

  •  偏移表面是在基础面的一份拷贝上做偏移,因此,当基础面改变时,偏移平面不变。
  •  基础表面上的任何点都必须只定义一个法向量。这必须由用户验证,因为在构造时不进行检查以检测具有多个可能的法线方向的点。

    在OCCT中,偏移面的构造如下:

Geom_OffsetSurface::Geom_OffsetSurface (const Handle(Geom_Surface)& theSurf, 
                    const Standard_Real theOffset,
                    const Standard_Boolean isTheNotCheckC0) 
                    : offsetValue (theOffset) 
{

    SetBasisSurface(theSurf, isTheNotCheckC0);

}
void Geom_OffsetSurface::SetBasisSurface (const Handle(Surface)& S,
  const Standard_Boolean isNotCheckC0)
{
  Standard_Real aUf, aUl, aVf, aVl;
  S->Bounds(aUf, aUl, aVf, aVl);

  Handle(Surface) aCheckingSurf = Handle(Surface)::DownCast(S->Copy());
  Standard_Boolean isTrimmed = Standard_False;

  while(aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
    aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
  {
    if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
    {
      Handle(Geom_RectangularTrimmedSurface) aTrimS = 
        Handle(Geom_RectangularTrimmedSurface)::DownCast(aCheckingSurf);
      aCheckingSurf = aTrimS->BasisSurface();
      isTrimmed = Standard_True;
    }

    if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
    {
      Handle(Geom_OffsetSurface) aOS = 
        Handle(Geom_OffsetSurface)::DownCast(aCheckingSurf);
      aCheckingSurf = aOS->BasisSurface();
      offsetValue += aOS->Offset();
    }
  }


  myBasisSurfContinuity = aCheckingSurf->Continuity();

  Standard_Boolean isC0 = !isNotCheckC0 &&
    (myBasisSurfContinuity == GeomAbs_C0);

  // Basis surface must be at least C1
  if (isC0)
  {
    Handle(Geom_Curve) aCurve;

    if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)))
    {
      Handle(Geom_SurfaceOfRevolution) aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aCheckingSurf);
      aCurve = aRevSurf->BasisCurve();
    }
    else if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)))
    {
      Handle(Geom_SurfaceOfLinearExtrusion) aLESurf = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aCheckingSurf);
      aCurve = aLESurf->BasisCurve();
    }

    if(!aCurve.IsNull())
    {
      while(aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)) ||
        aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
      {
        if (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
        {
          Handle(Geom_TrimmedCurve) aTrimC = 
            Handle(Geom_TrimmedCurve)::DownCast(aCurve);
          aCurve = aTrimC->BasisCurve();
        }

        if (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
        {
          Handle(Geom_OffsetCurve) aOC = 
            Handle(Geom_OffsetCurve)::DownCast(aCurve);
          aCurve = aOC->BasisCurve();
        }
      }
    }

    Standard_Real aUIsoPar = (aUf + aUl)/2.0, aVIsoPar = (aVf + aVl)/2.0;
    Standard_Boolean isUG1 = Standard_False, isVG1 = Standard_False;
 
    const Handle(Geom_Curve) aCurv1 = aCurve.IsNull() ? aCheckingSurf->UIso(aUIsoPar) : aCurve;
    const Handle(Geom_Curve) aCurv2 = aCheckingSurf->VIso(aVIsoPar);
    isUG1 = !aCurv1->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
    isVG1 = !aCurv2->IsKind(STANDARD_TYPE(Geom_BSplineCurve));

    if(!isUG1)
    {
      Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv1);
      isUG1 = aBC->IsG1(aVf, aVl, MyAngularToleranceForG1);
    }
    //
    if(!isVG1)
    {
      Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv2);
      isVG1 = aBC->IsG1(aUf, aUl, MyAngularToleranceForG1);
    }
    //
    if(isUG1 && isVG1) 
    {
      myBasisSurfContinuity = GeomAbs_G1;
      isC0 = Standard_False;
    }

    // Raise exception if still C0
    if (isC0)
      Standard_ConstructionError::Raise("Offset with no C1 Surface");
  }

  if(isTrimmed)
  {
    basisSurf = 
      new Geom_RectangularTrimmedSurface(aCheckingSurf, aUf, aUl, aVf, aVl);
  }
  else
  {
    basisSurf = aCheckingSurf;
  }
  
  equivSurf = Surface();
  //
  // Tolerance en dur pour l'instant ,mais on devrait la proposer dans le constructeur
  // et la mettre en champ, on pourrait utiliser par exemple pour l'extraction d'iso 
  // et aussi pour les singularite. Pour les surfaces osculatrices, on l'utilise pour
  // detecter si une iso est degeneree.
  Standard_Real Tol = Precision::Confusion(); //0.0001;
  myOscSurf.Init(basisSurf,Tol);

}