0025039: Improvement of code structure of general and supporting tools implemented...
[occt.git] / src / BRepMesh / BRepMesh_GeomTool.cxx
index 53ccef5..ba95397 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <BRepMesh_GeomTool.ixx>
+#include <BRepMesh_GeomTool.hxx>
 
-#include <BRepMesh_ShapeTool.hxx>
 #include <TopAbs_Orientation.hxx>
-#include <GeomAbs_SurfaceType.hxx>
 #include <CSLib.hxx>
 #include <Precision.hxx>
 #include <Adaptor3d_IsoCurve.hxx>
 #include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <Geom2d_Curve.hxx>
+#include <BRep_Tool.hxx>
 
-BRepMesh_GeomTool::BRepMesh_GeomTool(BRepAdaptor_Curve& C,
-                                      const Standard_Real Ufirst,
-                                      const Standard_Real Ulast,
-                                      const Standard_Real AngDefl,
-                                      const Standard_Real Deflection,
-                                      const Standard_Integer nbpmin) :
-       pnts(C,Ufirst,Ulast,AngDefl,Deflection, nbpmin),
-//       pnts(C,Deflection,Ufirst,Ulast),
-       parametric(GeomAbs_NoneIso)
+//=======================================================================
+//function : Constructor
+//purpose  :
+//=======================================================================
+BRepMesh_GeomTool::BRepMesh_GeomTool(
+  const BRepAdaptor_Curve& theCurve,
+  const Standard_Real      theFirstParam,
+  const Standard_Real      theLastParam,
+  const Standard_Real      theLinDeflection,
+  const Standard_Real      theAngDeflection,
+  const Standard_Integer   theMinPointsNb)
+  : myEdge(&theCurve.Edge()),
+    myIsoType(GeomAbs_NoneIso)
 {
+  myDiscretTool.Initialize(theCurve, theFirstParam, theLastParam,
+    theAngDeflection, theLinDeflection, theMinPointsNb);
 }
-//
-BRepMesh_GeomTool::BRepMesh_GeomTool(const Handle(BRepAdaptor_HSurface)& S,
-                                      const Standard_Real ParamIso,
-                                      const GeomAbs_IsoType Type,
-                                      const Standard_Real Ufirst,
-                                      const Standard_Real Ulast,
-                                      const Standard_Real AngDefl,
-                                      const Standard_Real Deflection,
-                                      const Standard_Integer nbpmin) :
-       parametric(Type)
+
+//=======================================================================
+//function : Constructor
+//purpose  :
+//=======================================================================
+BRepMesh_GeomTool::BRepMesh_GeomTool(
+  const Handle(BRepAdaptor_HSurface)& theSurface,
+  const GeomAbs_IsoType               theIsoType,
+  const Standard_Real                 theParamIso,
+  const Standard_Real                 theFirstParam,
+  const Standard_Real                 theLastParam,
+  const Standard_Real                 theLinDeflection,
+  const Standard_Real                 theAngDeflection,
+  const Standard_Integer              theMinPointsNb)
+  : myEdge(NULL),
+    myIsoType(theIsoType)
 {
-  Adaptor3d_IsoCurve Iso(S, Type,ParamIso,Ufirst,Ulast);
-  pnts.Initialize(Iso,Ufirst,Ulast,AngDefl,Deflection, nbpmin);
-//  pnts.Initialize(Iso,Deflection,Ufirst,Ulast);
+  Adaptor3d_IsoCurve aIso(theSurface, theIsoType, theParamIso,
+    theFirstParam, theLastParam);
+
+  myDiscretTool.Initialize(aIso, theFirstParam, theLastParam,
+    theAngDeflection, theLinDeflection, theMinPointsNb);
 }
 
-Standard_Integer BRepMesh_GeomTool::AddPoint(const gp_Pnt& thePnt,
-                                            const Standard_Real theParam,
-                                            const Standard_Boolean theIsReplace)
+//=======================================================================
+//function : Value
+//purpose  :
+//=======================================================================
+Standard_Boolean BRepMesh_GeomTool::Value(
+  const Standard_Integer              theIndex,
+  const Handle(BRepAdaptor_HSurface)& theSurface,
+  Standard_Real&                      theParam,
+  gp_Pnt&                             thePoint,
+  gp_Pnt2d&                           theUV) const
 {
-  return pnts.AddPoint(thePnt, theParam, theIsReplace);
+  if (theIndex < 1 || theIndex > NbPoints())
+    return Standard_False;
+
+  if (myEdge == NULL)
+    return Standard_False;
+
+  thePoint = myDiscretTool.Value(theIndex);
+  theParam = myDiscretTool.Parameter(theIndex);
+
+  const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
+
+  Standard_Real aFirst, aLast;
+  Handle(Geom2d_Curve) aCurve = 
+    BRep_Tool::CurveOnSurface(*myEdge, aFace, aFirst, aLast);
+
+  aCurve->D0(theParam, theUV);
+
+  return Standard_True;
 }
 
-Standard_Integer BRepMesh_GeomTool::NbPoints() const {
-  return pnts.NbPoints();
+//=======================================================================
+//function : Value
+//purpose  :
+//=======================================================================
+Standard_Boolean BRepMesh_GeomTool::Value(const Standard_Integer theIndex,
+                                          const Standard_Real    theIsoParam,
+                                          Standard_Real&         theParam,
+                                          gp_Pnt&                thePoint,
+                                          gp_Pnt2d&              theUV) const
+{
+  if (theIndex < 1 || theIndex > NbPoints())
+    return Standard_False;
+
+  thePoint = myDiscretTool.Value(theIndex);
+  theParam = myDiscretTool.Parameter(theIndex);
+
+  if (myIsoType == GeomAbs_IsoU)
+    theUV.SetCoord(theIsoParam, theParam);
+  else
+    theUV.SetCoord(theParam, theIsoParam);
+
+  return Standard_True;
 }
 
-void BRepMesh_GeomTool::Value(const Standard_Real IsoParam,
-                              const Standard_Integer Index,
-                              Standard_Real& W, gp_Pnt& P, gp_Pnt2d& UV) const
+//=======================================================================
+//function : Normal
+//purpose  :
+//=======================================================================
+Standard_Boolean BRepMesh_GeomTool::Normal(
+  const Handle(BRepAdaptor_HSurface)& theSurface,
+  const Standard_Real                 theParamU,
+  const Standard_Real                 theParamV,
+  gp_Pnt&                             thePoint,
+  gp_Dir&                             theNormal)
 {
-  P = pnts.Value(Index);
-  W = pnts.Parameter(Index);
-  if (parametric == GeomAbs_IsoU) {
-    UV.SetCoord(IsoParam,W);
-  }
-  else {
-    UV.SetCoord(W,IsoParam);
+  Standard_Boolean isOK = Standard_True;
+  gp_Vec aD1U, aD1V;
+
+  theSurface->D1(theParamU, theParamV, thePoint, aD1U, aD1V);
+
+  CSLib_DerivativeStatus aStatus;
+  CSLib::Normal(aD1U, aD1V, Precision::Angular(), aStatus, theNormal);
+  if (aStatus != CSLib_Done)
+  {
+    gp_Vec aD2U,aD2V,aD2UV;
+    theSurface->D2(theParamU, theParamV, thePoint, aD1U, aD1V, aD2U, aD2V, aD2UV);
+    CSLib_NormalStatus aNormalStatus;
+    CSLib::Normal(aD1U, aD1V, aD2U, aD2V, aD2UV, Precision::Angular(), 
+      isOK, aNormalStatus, theNormal);
   }
+
+  if (!isOK)
+    return Standard_False;
+
+  const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
+  TopAbs_Orientation aOri = aFace.Orientation();
+  if (aOri == TopAbs_REVERSED)
+    theNormal.Reverse();
+
+  return Standard_True;
 }
 
-void BRepMesh_GeomTool::Value(const BRepAdaptor_Curve& C,
-                              const Handle(BRepAdaptor_HSurface)& S,
-                              const Standard_Integer Index,
-                              Standard_Real& W, gp_Pnt& P, gp_Pnt2d& UV) const
+//=============================================================================
+//function : IntLinLin
+//purpose  : 
+//=============================================================================
+BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntLinLin(
+  const gp_XY&  theStartPnt1,
+  const gp_XY&  theEndPnt1,
+  const gp_XY&  theStartPnt2,
+  const gp_XY&  theEndPnt2,
+  gp_XY&        theIntPnt,
+  Standard_Real (&theParamOnSegment)[2])
 {
-  P = pnts.Value(Index);
-  W = pnts.Parameter(Index);
-  BRepMesh_ShapeTool::Parameters(C.Edge(), ((BRepAdaptor_Surface*)&(S->Surface()))->Face(), W, UV);
+  gp_XY aVec1    = theEndPnt1   - theStartPnt1;
+  gp_XY aVec2    = theEndPnt2   - theStartPnt2;
+  gp_XY aVecO1O2 = theStartPnt2 - theStartPnt1;
+    
+  Standard_Real aCrossD1D2 = aVec1    ^ aVec2;
+  Standard_Real aCrossD1D3 = aVecO1O2 ^ aVec2;
+
+  const Standard_Real aPrec = gp::Resolution();
+  // Are edgegs codirectional
+  if ( Abs( aCrossD1D2 ) < aPrec )
+  {
+    // Just a parallel case?
+    if( Abs( aCrossD1D3 ) < aPrec )
+      return BRepMesh_GeomTool::Same;
+    else
+      return BRepMesh_GeomTool::NoIntersection;
+  }
+
+  theParamOnSegment[0] = aCrossD1D3 / aCrossD1D2;
+  theIntPnt = theStartPnt1 + theParamOnSegment[0] * aVec1;
+
+  Standard_Real aCrossD2D3 = aVecO1O2 ^ aVec1;
+  theParamOnSegment[1] = aCrossD2D3 / aCrossD1D2;
+
+  return BRepMesh_GeomTool::Cross;
 }
 
-void BRepMesh_GeomTool::D0(const Handle(BRepAdaptor_HSurface)& S,const Standard_Real U,
-                           const Standard_Real V,gp_Pnt& P) 
+//=============================================================================
+//function : IntSegSeg
+//purpose  : 
+//=============================================================================
+BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntSegSeg(
+  const gp_XY&           theStartPnt1,
+  const gp_XY&           theEndPnt1,
+  const gp_XY&           theStartPnt2,
+  const gp_XY&           theEndPnt2,
+  const Standard_Boolean isConsiderEndPointTouch,
+  const Standard_Boolean isConsiderPointOnSegment,
+  gp_Pnt2d&              theIntPnt)
 {
-  S->D0(U,V,P);
-}  
-
-Standard_Boolean BRepMesh_GeomTool::Normal(const Handle(BRepAdaptor_HSurface)& S,
-                                           const Standard_Real U,
-                                           const Standard_Real V, 
-                                           gp_Pnt& P,
-                                           gp_Dir& Nor) 
+  Standard_Integer aPointHash[] = {
+    classifyPoint(theStartPnt1, theEndPnt1, theStartPnt2),
+    classifyPoint(theStartPnt1, theEndPnt1, theEndPnt2  ),
+    classifyPoint(theStartPnt2, theEndPnt2, theStartPnt1),
+    classifyPoint(theStartPnt2, theEndPnt2, theEndPnt1  )
+  };
+
+  // Consider case when edges have shared vertex
+  if ( isConsiderEndPointTouch )
+  {
+    if ( aPointHash[0] < 0 || aPointHash[1] < 0 )
+      return BRepMesh_GeomTool::EndPointTouch;
+  }
+
+  Standard_Integer aPosHash = 
+    aPointHash[0] + aPointHash[1] + aPointHash[2] + aPointHash[3];
+
+  /*=========================================*/
+  /*  1) hash code == 1:
+
+                    0+
+                    /
+           0      1/         0
+           +======+==========+
+  
+      2) hash code == 2:
+
+           0    1        1   0
+        a) +----+========+---+
+
+           0       1   1     0
+        b) +-------+===+=====+
+
+                                             */
+  /*=========================================*/
+  if ( aPosHash == 1 )
+  {
+    if (isConsiderPointOnSegment)
+    {
+      if (aPointHash[0] == 1)
+        theIntPnt = theStartPnt1;
+      else if (aPointHash[1] == 1)
+        theIntPnt = theEndPnt1;
+      else if (aPointHash[2] == 1)
+        theIntPnt = theStartPnt2;
+      else
+        theIntPnt = theEndPnt2;
+
+      return BRepMesh_GeomTool::PointOnSegment;
+    }
+
+    return BRepMesh_GeomTool::NoIntersection;
+  }
+  else if ( aPosHash == 2 )
+    return BRepMesh_GeomTool::Glued;
+
+  Standard_Real aParam[2];
+  IntFlag aIntFlag = IntLinLin(theStartPnt1, theEndPnt1, 
+    theStartPnt2, theEndPnt2, theIntPnt.ChangeCoord(), aParam);
+
+  if (aIntFlag == BRepMesh_GeomTool::NoIntersection)
+    return BRepMesh_GeomTool::NoIntersection;
+
+  if (aIntFlag == BRepMesh_GeomTool::Same)
+  {
+    if ( aPosHash < -2 )
+      return BRepMesh_GeomTool::Same;
+    else if ( aPosHash == -1 )
+      return BRepMesh_GeomTool::Glued;
+
+    return BRepMesh_GeomTool::NoIntersection;
+  }
+
+  // Cross
+  // Intersection is out of segments ranges
+  const Standard_Real aPrec    = Precision::PConfusion();
+  const Standard_Real aEndPrec = 1 - aPrec;
+  for (Standard_Integer i = 0; i < 2; ++i)
+  {
+    if( aParam[i] < aPrec || aParam[i] > aEndPrec )
+      return BRepMesh_GeomTool::NoIntersection;
+  }
+  return BRepMesh_GeomTool::Cross;
+}
+
+//=============================================================================
+//function : classifyPoint
+//purpose  : 
+//=============================================================================
+Standard_Integer BRepMesh_GeomTool::classifyPoint(
+  const gp_XY& thePoint1,
+  const gp_XY& thePoint2,
+  const gp_XY& thePointToCheck)
 {
-  Standard_Boolean OK = Standard_True;
-  gp_Vec D1U,D1V;
-  CSLib_DerivativeStatus Status;
-  S->D1(U,V,P,D1U,D1V);
-  CSLib::Normal(D1U,D1V,Standard_Real(Precision::Angular()),Status,Nor);
-  if (Status!= CSLib_Done) {
-    gp_Vec D2U,D2V,D2UV;
-    S->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
-    CSLib_NormalStatus NStat;
-    CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor);
+  gp_XY aP1 = thePoint2       - thePoint1;
+  gp_XY aP2 = thePointToCheck - thePoint1;
+  
+  const Standard_Real aPrec   = Precision::PConfusion();
+  const Standard_Real aSqPrec = aPrec * aPrec;
+  Standard_Real aDist = Abs(aP1 ^ aP2);
+  if (aDist > aPrec)
+  {
+    aDist = (aDist * aDist) / aP1.SquareModulus();
+    if (aDist > aSqPrec)
+      return 0; //out
   }
-  if (OK) {
-    if (BRepMesh_ShapeTool::Orientation(((BRepAdaptor_Surface*)&(S->Surface()))->Face()) == TopAbs_REVERSED)  Nor.Reverse();
+    
+  gp_XY aMult = aP1.Multiplied(aP2);
+  if ( aMult.X() < 0.0 || aMult.Y() < 0.0 )
+    return 0; //out
+    
+  if (aP1.SquareModulus() < aP2.SquareModulus())
+    return 0; //out
+    
+  if (thePointToCheck.IsEqual(thePoint1, aPrec) || 
+      thePointToCheck.IsEqual(thePoint2, aPrec))
+  {
+    return -1; //coinsides with an end point
   }
-  return OK;
+    
+  return 1;
 }