0023106: BRepMesh_IncrementalMesh returns wrong status
authoroan <oan@opencascade.com>
Fri, 26 Sep 2014 12:31:27 +0000 (16:31 +0400)
committerbugmaster <bugmaster@opencascade.com>
Fri, 26 Sep 2014 12:32:25 +0000 (16:32 +0400)
Fix compilation errors on Linux platform

Squeeze compilation warnings on Linux

Fix regressions

Back RemoveFaceAttribute for further reasons

Fix retrieving of polygon by index

Fix applying of location

Test case for issue CR23106

Fix memory leak regression 'test bugs vis bug79' occurred due to incorrect memory cleaning of inherited objects by MMgtRaw::Free through BRepMesh_IEdgeTool;

Replace BRepMesh_PDiscretRoot by pure pointer to BRepMesh_DiscretRoot;

Fix IVtkOCC_ShapeMesher.

41 files changed:
adm/UDLIST
src/BRepMesh/BRepMesh.cdl
src/BRepMesh/BRepMesh_Collections.hxx
src/BRepMesh/BRepMesh_Delaun.cxx
src/BRepMesh/BRepMesh_Delaun.hxx
src/BRepMesh/BRepMesh_DiscretFactory.cxx
src/BRepMesh/BRepMesh_Edge.hxx
src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_EdgeTessellator.cxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_EdgeTessellator.hxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_FaceAttribute.cxx
src/BRepMesh/BRepMesh_FaceAttribute.hxx
src/BRepMesh/BRepMesh_FastDiscret.cxx
src/BRepMesh/BRepMesh_FastDiscret.hxx
src/BRepMesh/BRepMesh_FastDiscretFace.cxx
src/BRepMesh/BRepMesh_FastDiscretFace.hxx
src/BRepMesh/BRepMesh_IEdgeTool.cxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_IEdgeTool.hxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_IncrementalMesh.cxx
src/BRepMesh/BRepMesh_IncrementalMesh.hxx
src/BRepMesh/BRepMesh_PluginMacro.hxx
src/BRepMesh/BRepMesh_ShapeTool.cxx
src/BRepMesh/BRepMesh_ShapeTool.hxx
src/BRepMesh/BRepMesh_Vertex.hxx
src/BRepMesh/BRepMesh_WireChecker.cxx
src/BRepMesh/BRepMesh_WireChecker.hxx
src/BRepMesh/FILES
src/IVtkOCC/IVtkOCC_ShapeMesher.cxx
src/MeshTest/MeshTest.cxx
src/MeshTest/MeshTest_DrawableMesh.cxx
src/MeshTest/MeshTest_DrawableMesh.hxx
src/MeshTest/MeshTest_PluginCommands.cxx
src/XBRepMesh/FILES [new file with mode: 0644]
src/XBRepMesh/XBRepMesh.cdl [deleted file]
src/XBRepMesh/XBRepMesh.cxx
src/XBRepMesh/XBRepMesh.hxx [new file with mode: 0644]
src/XSDRAWSTLVRML/XSDRAWSTLVRML_ToVRML.cxx
tests/bugs/mesh/bug23106 [new file with mode: 0755]

index c0ca732..1e9c93a 100644 (file)
@@ -182,7 +182,7 @@ p TopOpeBRepBuild
 p TopOpeBRepDS
 p TopOpeBRepTool
 p TopTrans
-p XBRepMesh
+n XBRepMesh
 t TKBO
 t TKBool
 t TKFeat
index e53dbc9..0883511 100644 (file)
@@ -54,8 +54,6 @@ is
       imported Circle from BRepMesh;
       imported DiscretRoot from BRepMesh; 
       imported DiscretFactory from BRepMesh;
-      --
-      pointer PDiscretRoot to DiscretRoot from BRepMesh;
       
       imported ShapeTool from BRepMesh;
       imported Collections from BRepMesh;
@@ -66,6 +64,10 @@ is
       imported WireInterferenceChecker from BRepMesh;
       imported EdgeChecker from BRepMesh;
       imported FaceChecker from BRepMesh;
+      imported EdgeParameterProvider from BRepMesh;
+      imported IEdgeTool from BRepMesh;
+      imported EdgeTessellationExtractor from BRepMesh;
+      imported EdgeTessellator from BRepMesh;
 
       primitive PluginEntryType;
 
index eb613ca..13a818d 100644 (file)
@@ -40,6 +40,7 @@
 #include <BRepMesh_Circle.hxx>
 #include <TopTools_ShapeMapHasher.hxx>
 #include <Handle_Poly_Triangulation.hxx>
+#include <TopoDS_Face.hxx>
 
 #include <vector>
 
@@ -48,7 +49,6 @@ class TopoDS_Shape;
 class TopoDS_Face;
 class TopoDS_Edge;
 class TopoDS_Vertex;
-class BRepMesh_FaceAttribute;
 class Handle_BRepMesh_FaceAttribute;
 class BRepMesh_VertexInspector;
 class BRepMesh_CircleInspector;
@@ -132,6 +132,9 @@ namespace BRepMeshCol
 
   //! Handles
   typedef N_HANDLE<MapOfInteger>                                                HMapOfInteger;
+  typedef N_HANDLE<IMapOfInteger>                                               HIMapOfInteger;
+  typedef N_HANDLE<DMapOfShapePairOfPolygon>                                    HDMapOfShapePairOfPolygon;
+  typedef N_HANDLE<DMapOfIntegerPnt>                                            HDMapOfIntegerPnt;
   typedef N_HANDLE<BRepMesh_Classifier>                                         HClassifier;
   typedef N_HANDLE<BndBox2dTree>                                                HBndBox2dTree;
   typedef N_HANDLE<Array1OfSegments>                                            HArray1OfSegments;
index aa628f9..6547834 100644 (file)
@@ -75,10 +75,9 @@ namespace {
 //function : BRepMesh_Delaun
 //purpose  : Creates the triangulation with an empty Mesh data structure
 //=======================================================================
-BRepMesh_Delaun::BRepMesh_Delaun( BRepMeshCol::Array1OfVertexOfDelaun& theVertices,
-                                  const Standard_Boolean               isPositive )
-: myIsPositiveOrientation( isPositive ),
-  myCircles( theVertices.Length(), new NCollection_IncAllocator() )
+BRepMesh_Delaun::BRepMesh_Delaun(
+  BRepMeshCol::Array1OfVertexOfDelaun& theVertices)
+: myCircles( theVertices.Length(), new NCollection_IncAllocator() )
 {
   if ( theVertices.Length() > 2 )
   {
@@ -92,11 +91,10 @@ BRepMesh_Delaun::BRepMesh_Delaun( BRepMeshCol::Array1OfVertexOfDelaun& theVertic
 //function : BRepMesh_Delaun
 //purpose  : Creates the triangulation with and existent Mesh data structure
 //=======================================================================
-BRepMesh_Delaun::BRepMesh_Delaun( const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
-                                  BRepMeshCol::Array1OfVertexOfDelaun&            theVertices,
-                                  const Standard_Boolean                          isPositive )
- : myIsPositiveOrientation( isPositive ),
-   myCircles( theVertices.Length(), theOldMesh->Allocator() )
+BRepMesh_Delaun::BRepMesh_Delaun(
+  const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
+  BRepMeshCol::Array1OfVertexOfDelaun&            theVertices)
+ : myCircles( theVertices.Length(), theOldMesh->Allocator() )
 {
   myMeshData = theOldMesh;
   if ( theVertices.Length() > 2 )
@@ -107,11 +105,10 @@ BRepMesh_Delaun::BRepMesh_Delaun( const Handle( BRepMesh_DataStructureOfDelaun )
 //function : BRepMesh_Delaun
 //purpose  : Creates the triangulation with and existent Mesh data structure
 //=======================================================================
-BRepMesh_Delaun::BRepMesh_Delaun( const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, 
-                                  BRepMeshCol::Array1OfInteger&                   theVertexIndices,
-                                  const Standard_Boolean                          isPositive )
- : myIsPositiveOrientation( isPositive ),
-   myCircles( theVertexIndices.Length(), theOldMesh->Allocator() )
+BRepMesh_Delaun::BRepMesh_Delaun(
+  const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, 
+  BRepMeshCol::Array1OfInteger&                   theVertexIndices)
+ : myCircles( theVertexIndices.Length(), theOldMesh->Allocator() )
 {
   myMeshData = theOldMesh;
   if ( theVertexIndices.Length() > 2 )
@@ -199,14 +196,6 @@ void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox )
   mySupVert[2] = myMeshData->AddNode(
     BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
 
-  if ( !myIsPositiveOrientation )
-  {
-    Standard_Integer aTmp;
-    aTmp         = mySupVert[1];
-    mySupVert[1] = mySupVert[2];
-    mySupVert[2] = aTmp;
-  }
-
   Standard_Integer e[3];
   Standard_Boolean o[3];
   for (Standard_Integer aNodeId = 0; aNodeId < 3; ++aNodeId)
@@ -354,13 +343,6 @@ void BRepMesh_Delaun::createTriangles ( const Standard_Integer            theVer
       continue;
     }
 
-    Standard_Boolean isSensOK;
-    if ( myIsPositiveOrientation )
-      isSensOK = ( aDist12 > 0. && aDist23 > 0.);
-    else
-      isSensOK = ( aDist12 < 0. && aDist23 < 0.);
-    
-
     BRepMesh_Edge aFirstLink( aNodes[1], aNodes[0], BRepMesh_Free );
     BRepMesh_Edge aLastLink ( aNodes[2], aNodes[1], BRepMesh_Free );
 
@@ -369,7 +351,8 @@ void BRepMesh_Delaun::createTriangles ( const Standard_Integer            theVer
       isPositive ? anEdgeId : -anEdgeId,
       myMeshData->AddLink( aLastLink ) };
 
-    if ( isSensOK )
+    Standard_Boolean isSensOK = (aDist12 > 0. && aDist23 > 0.);
+    if (isSensOK)
     {
       Standard_Integer anEdges[3];
       Standard_Boolean anEdgesOri[3];
@@ -935,8 +918,7 @@ Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
 {
   // Find the next link having the greatest angle 
   // respect to a direction of a reference one
-  Standard_Real aMaxAngle = myIsPositiveOrientation ?
-    RealFirst() : RealLast();
+  Standard_Real aMaxAngle = RealFirst();
 
   Standard_Integer aNextLinkId = 0;
   BRepMeshCol::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
@@ -996,11 +978,8 @@ Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
       }
     }
 
-    if ( ( myIsPositiveOrientation && anAngle <= aMaxAngle ) ||
-         (!myIsPositiveOrientation && anAngle >= aMaxAngle ) )
-    {
+    if (anAngle <= aMaxAngle)
       continue;
-    }
 
     Standard_Boolean isCheckEndPoints = ( anOtherNode != theFirstNode );
 
@@ -1802,12 +1781,8 @@ void BRepMesh_Delaun::meshSimplePolygon( BRepMeshCol::SequenceOfInteger& thePoly
     Standard_Real aDist     = aRefEdgeDir ^ aDistanceDir;
     Standard_Real aAngle    = Abs( aRefEdgeDir.Angle(aDistanceDir) );
     Standard_Real anAbsDist = Abs( aDist );
-    if ( ( anAbsDist < Precision                 ) ||
-         ( myIsPositiveOrientation && aDist < 0. ) ||
-         (!myIsPositiveOrientation && aDist > 0. ) )
-    {
+    if (anAbsDist < Precision || aDist < 0.)
       continue;
-    }
 
     if ( ( anAbsDist >= aMinDist                             ) &&
          ( aAngle <= aOptAngle || aAngle > AngDeviation90Deg ) )
index ae6da81..e6484a1 100755 (executable)
@@ -40,18 +40,15 @@ public:
   DEFINE_STANDARD_ALLOC
 
   //! Creates the triangulation with an empty Mesh data structure.
-  Standard_EXPORT BRepMesh_Delaun (BRepMeshCol::Array1OfVertexOfDelaun& theVertices,
-                                   const Standard_Boolean               isPositive = Standard_True);
+  Standard_EXPORT BRepMesh_Delaun (BRepMeshCol::Array1OfVertexOfDelaun& theVertices);
 
   //! Creates the triangulation with an existent Mesh data structure.
   Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
-                                   BRepMeshCol::Array1OfVertexOfDelaun&          theVertices,
-                                   const Standard_Boolean                        isPositive = Standard_True);
+                                   BRepMeshCol::Array1OfVertexOfDelaun&          theVertices);
 
   //! Creates the triangulation with an existant Mesh data structure.
   Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
-                                   BRepMeshCol::Array1OfInteger&                 theVertexIndices,
-                                   const Standard_Boolean                        isPositive = Standard_True);
+                                   BRepMeshCol::Array1OfInteger&                 theVertexIndices);
 
   //! Initializes the triangulation with an array of vertices.
   Standard_EXPORT void Init (BRepMeshCol::Array1OfVertexOfDelaun& theVertices);
@@ -307,7 +304,6 @@ private:
 private:
 
   Handle(BRepMesh_DataStructureOfDelaun) myMeshData;
-  Standard_Boolean                       myIsPositiveOrientation;
   BRepMesh_CircleTool                    myCircles;
   Standard_Integer                       mySupVert[3];
   BRepMesh_Triangle                      mySupTrian;
index 8e727bd..bc4e7d7 100644 (file)
@@ -18,7 +18,7 @@
 #include <OSD_SharedLibrary.hxx>
 #include <OSD_Function.hxx>
 #include <BRepMesh_IncrementalMesh.hxx>
-#include <BRepMesh_PDiscretRoot.hxx>
+#include <BRepMesh_DiscretRoot.hxx>
 
 namespace
 {
@@ -145,7 +145,7 @@ Standard_Boolean BRepMesh_DiscretFactory::SetDefault(
   }
 
   // try to create dummy tool
-  BRepMesh_PDiscretRoot anInstancePtr = NULL;
+  BRepMesh_DiscretRoot* anInstancePtr = NULL;
   Standard_Integer anErr = aFunc (TopoDS_Shape(), 0.001, 0.1, anInstancePtr);
   if (anErr != 0 || anInstancePtr == NULL)
   {
@@ -174,7 +174,7 @@ Handle(BRepMesh_DiscretRoot) BRepMesh_DiscretFactory::Discret(
   const Standard_Real theAngle)
 {
   Handle(BRepMesh_DiscretRoot) aDiscretRoot;
-  BRepMesh_PDiscretRoot anInstancePtr = NULL;
+  BRepMesh_DiscretRoot* anInstancePtr = NULL;
   if (myPluginEntry != NULL)
   {
     // use plugin
index 603c4cc..5a46ebb 100644 (file)
 #include <Standard_Macro.hxx>
 #include <BRepMesh_DegreeOfFreedom.hxx>
 
-//! Light weighted structure representing link of the mesh.
-class BRepMesh_Edge
+//! Light weighted structure representing simple link.
+class BRepMesh_OrientedEdge
 {
 public:
 
   DEFINE_STANDARD_ALLOC
-  
+
   //! Default constructor.
-  Standard_EXPORT BRepMesh_Edge()
-    : myFirstNode (-1),
-      myLastNode  (-1),
-      myMovability(BRepMesh_Deleted)
+  Standard_EXPORT BRepMesh_OrientedEdge()
+    : myFirstNode(-1),
+      myLastNode(-1)
   {
   }
 
-  //! Contructs a link beetween two vertices.
-  Standard_EXPORT BRepMesh_Edge(const Standard_Integer         theFirstNode,
-                                const Standard_Integer         theLastNode,
-                                const BRepMesh_DegreeOfFreedom theMovability)
-    : myFirstNode (theFirstNode),
-      myLastNode  (theLastNode),
-      myMovability(theMovability)
+  //! Constructs a link between two vertices.
+  Standard_EXPORT BRepMesh_OrientedEdge(
+    const Standard_Integer         theFirstNode,
+    const Standard_Integer         theLastNode)
+    : myFirstNode(theFirstNode),
+      myLastNode(theLastNode)
   {
   }
 
@@ -55,49 +53,88 @@ public:
   {
     return myLastNode;
   }
-  
+
+  //! Returns hash code for this edge.
+  //! @param theUpper upper index in the container.
+  //! @return hash code.
+  Standard_EXPORT Standard_Integer HashCode(const Standard_Integer theUpper) const
+  {
+    return ::HashCode(myFirstNode + myLastNode, theUpper);
+  }
+
+  //! Checks this and other edge for equality.
+  //! @param theOther edge to be checked against this one.
+  //! @retrun TRUE if edges have the same orientation, FALSE if not.
+  inline Standard_Boolean IsEqual(const BRepMesh_OrientedEdge& theOther) const
+  {
+    return (myFirstNode == theOther.myFirstNode && myLastNode == theOther.myLastNode);
+  }
+
+  //! Alias for IsEqual.
+  Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const
+  {
+    return IsEqual(Other);
+  }
+
+private:
+
+  Standard_Integer myFirstNode;
+  Standard_Integer myLastNode;
+};
+
+//! Light weighted structure representing link of the mesh.
+class BRepMesh_Edge : public BRepMesh_OrientedEdge
+{
+public:
+
+    //! Default constructor.
+  Standard_EXPORT BRepMesh_Edge()
+    : BRepMesh_OrientedEdge(),
+      myMovability(BRepMesh_Deleted)
+  {
+  }
+
+  //! Constructs a link between two vertices.
+  Standard_EXPORT BRepMesh_Edge(
+    const Standard_Integer         theFirstNode,
+    const Standard_Integer         theLastNode,
+    const BRepMesh_DegreeOfFreedom theMovability)
+    : BRepMesh_OrientedEdge(theFirstNode, theLastNode),
+      myMovability(theMovability)
+  {
+  }
+
   //! Returns movability flag of the Link.
   inline BRepMesh_DegreeOfFreedom Movability() const
   {
     return myMovability;
   }
-  
+
   //! Sets movability flag of the Link.
   //! \param theMovability flag to be set.
   inline void SetMovability(const BRepMesh_DegreeOfFreedom theMovability)
   {
     myMovability = theMovability;
   }
-  
-  //! Returns hash code for this edge.
-  //! \param theUpper upper index in the container.
-  //! \return hash code.
-  Standard_EXPORT Standard_Integer HashCode(const Standard_Integer theUpper) const
-  {
-    return ::HashCode(myFirstNode + myLastNode, theUpper);
-  }
-  
+
   //! Checks if the given edge and this one have the same orientation.
   //! \param theOther edge to be checked against this one.
   //! \retrun TRUE if edges have the same orientation, FALSE if not.
   inline Standard_Boolean IsSameOrientation(const BRepMesh_Edge& theOther) const
   {
-    return (myFirstNode == theOther.myFirstNode && myLastNode == theOther.myLastNode);
+    return BRepMesh_OrientedEdge::IsEqual(theOther);
   }
-  
+
   //! Checks for equality with another edge.
   //! \param theOther edge to be checked against this one.
   //! \return TRUE if equal, FALSE if not.
   inline Standard_Boolean IsEqual(const BRepMesh_Edge& theOther) const
   {
-    if (myMovability          == BRepMesh_Deleted || 
-        theOther.myMovability == BRepMesh_Deleted)
-    {
+    if (myMovability == BRepMesh_Deleted || theOther.myMovability == BRepMesh_Deleted)
       return Standard_False;
-    }
 
-    return IsSameOrientation(theOther) || 
-      (myFirstNode == theOther.myLastNode && myLastNode == theOther.myFirstNode);
+    return IsSameOrientation(theOther) ||
+      (FirstNode() == theOther.LastNode() && LastNode() == theOther.FirstNode());
   }
 
   //! Alias for IsEqual.
@@ -108,11 +145,15 @@ public:
 
 private:
 
-  Standard_Integer          myFirstNode;
-  Standard_Integer          myLastNode;
   BRepMesh_DegreeOfFreedom  myMovability;
 };
 
+inline Standard_Integer HashCode(const BRepMesh_OrientedEdge&   theEdge,
+                                 const Standard_Integer         theUpper)
+{
+  return theEdge.HashCode(theUpper);
+}
+
 inline Standard_Integer HashCode(const BRepMesh_Edge&   theEdge,
                                  const Standard_Integer theUpper)
 {
diff --git a/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx b/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx
new file mode 100644 (file)
index 0000000..9277956
--- /dev/null
@@ -0,0 +1,89 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_EdgeParameterProvider.hxx>
+#include <gp_Pnt.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <Precision.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+BRepMesh_EdgeParameterProvider::BRepMesh_EdgeParameterProvider(
+  const TopoDS_Edge&                   theEdge,
+  const TopoDS_Face&                   theFace,
+  const Handle(TColStd_HArray1OfReal)& theParameters)
+  : myParameters(theParameters),
+    myIsSameParam(BRep_Tool::SameParameter(theEdge)),
+    myScale(1.)
+{
+  if (myIsSameParam)
+    return;
+
+  // Extract actual parametric values
+  Standard_Real aLastParam;
+  BRep_Tool::Range(theEdge, theFace, myFirstParam, aLastParam);
+
+  myFoundParam = myCurParam = myFirstParam;
+
+  // Extract parameters stored in polygon
+  myOldFirstParam =
+    myParameters->Value(myParameters->Lower());
+
+  const Standard_Real aOldLastParam =
+    myParameters->Value(myParameters->Upper());
+
+  // Calculate scale factor between actual and stored parameters
+  if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) &&
+    myOldFirstParam != aOldLastParam)
+  {
+    myScale = (aLastParam - myFirstParam) /
+      (aOldLastParam - myOldFirstParam);
+  }
+
+  BRepAdaptor_Curve aCOnS(theEdge, theFace);
+  myProjector.Initialize(aCOnS, aCOnS.FirstParameter(),
+    aCOnS.LastParameter(), Precision::PConfusion());
+}
+
+//=======================================================================
+//function : Parameter
+//purpose  : 
+//=======================================================================
+Standard_Real BRepMesh_EdgeParameterProvider::Parameter(
+  const Standard_Integer theIndex,
+  const gp_Pnt&          thePoint3d)
+{
+  if (myIsSameParam)
+    return myParameters->Value(theIndex);
+
+  // Use scaled
+  Standard_Real aPrevParam = myCurParam;
+  myCurParam = myFirstParam + myScale * 
+    (myParameters->Value(theIndex) - myOldFirstParam);
+
+  myFoundParam += (myCurParam - aPrevParam);
+
+  myProjector.Perform(thePoint3d, myFoundParam);
+  if (myProjector.IsDone())
+    myFoundParam = myProjector.Point().Parameter();
+
+  return myFoundParam;
+}
diff --git a/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx b/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx
new file mode 100644 (file)
index 0000000..1a250db
--- /dev/null
@@ -0,0 +1,69 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_EdgeParameterProvider_HeaderFile
+#define _BRepMesh_EdgeParameterProvider_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Extrema_LocateExtPC.hxx>
+#include <Handle_TColStd_HArray1OfReal.hxx>
+
+class gp_Pnt;
+class TopoDS_Edge;
+class TopoDS_Face;
+class TColStd_HArray1OfReal;
+
+//! Auxiliary class provides correct parameters 
+//! on curve regarding SameParameter flag.
+class BRepMesh_EdgeParameterProvider
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  //! Constructor.
+  //! @param theEdge edge which parameters should be processed.
+  //! @param theFace face the parametric values are defined for.
+  //! @param theParameters parameters corresponded to discretization points.
+  BRepMesh_EdgeParameterProvider(
+    const TopoDS_Edge&                   theEdge,
+    const TopoDS_Face&                   theFace,
+    const Handle(TColStd_HArray1OfReal)& theParameters);
+
+  //! Returns parameter according to SameParameter flag of the edge.
+  //! If SameParameter is TRUE returns value from parameters w/o changes,
+  //! elsewhere scales initial parameter and tries to determine resulting
+  //! value using projection of the corresponded 3D point on PCurve.
+  Standard_Real Parameter(const Standard_Integer theIndex,
+                          const gp_Pnt&          thePoint3d);
+
+private:
+
+  Handle(TColStd_HArray1OfReal) myParameters;
+
+  Standard_Boolean              myIsSameParam;
+  Standard_Real                 myFirstParam;
+
+  Standard_Real                 myOldFirstParam;
+  Standard_Real                 myScale;
+
+  Standard_Real                 myCurParam;
+  Standard_Real                 myFoundParam;
+
+  Extrema_LocateExtPC           myProjector;
+};
+
+#endif
diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx
new file mode 100644 (file)
index 0000000..89ab5dc
--- /dev/null
@@ -0,0 +1,59 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_EdgeTessellationExtractor.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
+#include <Poly_Triangulation.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool)
+IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool)
+
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor(
+  const TopoDS_Edge&                          theEdge,
+  const Handle(Geom2d_Curve)&                 thePCurve,
+  const TopoDS_Face&                          theFace,
+  const Handle(Poly_Triangulation)&           theTriangulation,
+  const Handle(Poly_PolygonOnTriangulation)&  thePolygon,
+  const TopLoc_Location&                      theLocation)
+  : myProvider(theEdge, theFace, thePolygon->Parameters()),
+    myPCurve(thePCurve),
+    myNodes(theTriangulation->Nodes()),
+    myIndices(thePolygon->Nodes()),
+    myLoc(theLocation)
+{
+}
+
+//=======================================================================
+//function : Value
+//purpose  : 
+//=======================================================================
+void BRepMesh_EdgeTessellationExtractor::Value(
+  const Standard_Integer theIndex,
+  Standard_Real&         theParameter,
+  gp_Pnt&                thePoint,
+  gp_Pnt2d&              theUV)
+{
+  const gp_Pnt& theRefPnt = myNodes(myIndices(theIndex));
+  thePoint = BRepMesh_ShapeTool::UseLocation(theRefPnt, myLoc);
+
+  theParameter = myProvider.Parameter(theIndex, thePoint);
+  theUV        = myPCurve->Value(theParameter);
+}
diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx
new file mode 100644 (file)
index 0000000..b150005
--- /dev/null
@@ -0,0 +1,87 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_EdgeTessellationExtractor_HeaderFile
+#define _BRepMesh_EdgeTessellationExtractor_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <BRepMesh_IEdgeTool.hxx>
+#include <BRepMesh_EdgeParameterProvider.hxx>
+#include <Handle_Geom2d_Curve.hxx>
+#include <Handle_Poly_PolygonOnTriangulation.hxx>
+#include <Handle_Poly_Triangulation.hxx>
+#include <TopLoc_Location.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+
+class Poly_Triangulation;
+class Poly_PolygonOnTriangulation;
+class TopoDS_Edge;
+class TopoDS_Face;
+
+//! Auxiliary class implements functionality retrieving tessellated
+//! representation of an edge stored in polygon.
+class BRepMesh_EdgeTessellationExtractor : public BRepMesh_IEdgeTool
+{
+public:
+
+  //! Constructor.
+  //! Initializes extractor.
+  BRepMesh_EdgeTessellationExtractor(
+    const TopoDS_Edge&                          theEdge,
+    const Handle(Geom2d_Curve)&                 thePCurve,
+    const TopoDS_Face&                          theFace,
+    const Handle(Poly_Triangulation)&           theTriangulation,
+    const Handle(Poly_PolygonOnTriangulation)&  thePolygon,
+    const TopLoc_Location&                      theLocation);
+
+  //! Returns number of dicretization points.
+  virtual Standard_Integer NbPoints() const
+  {
+    return myIndices.Length();
+  }
+
+  //! Returns parameters of solution with the given index.
+  //! @param theIndex index of tessellation point.
+  //! @param theParameter parameters on PCurve corresponded to the solution.
+  //! @param thePoint tessellation point.
+  //! @param theUV coordinates of tessellation point in parametric space of face.
+  virtual void Value(const Standard_Integer theIndex,
+                     Standard_Real&         theParameter,
+                     gp_Pnt&                thePoint,
+                     gp_Pnt2d&              theUV);
+
+  DEFINE_STANDARD_RTTI(BRepMesh_EdgeTessellationExtractor)
+
+private:
+
+  //! Assignment operator.
+  void operator =(const BRepMesh_EdgeTessellationExtractor& /*theOther*/)
+  {
+  }
+
+private:
+
+  BRepMesh_EdgeParameterProvider myProvider;
+  const Handle(Geom2d_Curve)&    myPCurve;
+  const TColgp_Array1OfPnt&      myNodes;
+  const TColStd_Array1OfInteger& myIndices;
+  const TopLoc_Location          myLoc;
+};
+
+DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool)
+
+#endif
diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.cxx b/src/BRepMesh/BRepMesh_EdgeTessellator.cxx
new file mode 100644 (file)
index 0000000..2347a28
--- /dev/null
@@ -0,0 +1,217 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_EdgeTessellator.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom2d_Curve.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopLoc_Location.hxx>
+#include <BRep_Tool.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TColStd_Array1OfReal.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
+IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
+
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
+  const TopoDS_Edge&                               theEdge,
+  const Handle(BRepMesh_FaceAttribute)&            theFaceAttribute,
+  const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
+  const Standard_Real                              theLinDeflection,
+  const Standard_Real                              theAngDeflection)
+  : mySurface(theFaceAttribute->Surface())
+{
+  Standard_Real aPreciseAngDef = 0.5 * theAngDeflection;
+  Standard_Real aPreciseLinDef = 0.5 * theLinDeflection;
+  if (theEdge.Orientation() == TopAbs_INTERNAL)
+    aPreciseLinDef *= 0.5;
+
+  mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
+
+  Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
+  if (isSameParam)
+    myCOnS.Initialize(theEdge);
+  else
+    myCOnS.Initialize(theEdge, theFaceAttribute->Face());
+
+  TopLoc_Location aLoc;
+  const GeomAbs_CurveType aCurveType = myCOnS.GetType();
+  Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287
+
+  // Get range on 2d curve
+  Standard_Real aFirstParam, aLastParam;
+  BRep_Tool::Range(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam);
+  myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam, 
+    aPreciseLinDef, aPreciseAngDef, aMinPntNb);
+
+  if (aCurveType == GeomAbs_BSplineCurve)
+  {
+    // TODO: remove this code block when #24959 is fixed
+    const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1);
+    if ( aNbInt > 0 )
+    {
+      TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 );
+      myCOnS.Intervals(anIntervals, GeomAbs_C1);
+      for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt)
+      {
+        const Standard_Real& aStartInt = anIntervals.Value( aIntIt );
+        const Standard_Real& anEndInt  = anIntervals.Value( aIntIt + 1 );
+
+        BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt,
+          aPreciseLinDef, aPreciseAngDef, aMinPntNb);
+
+        Standard_Integer aNbAddNodes = aDetalizator.NbPoints();
+        for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt )
+        {
+          Standard_Real aParam;
+          gp_Pnt        aPoint3d;
+          gp_Pnt2d      aPoint2d;
+          aDetalizator.Value( aNodeIt, mySurface, aParam, aPoint3d, aPoint2d );
+          myTool->AddPoint( aPoint3d, aParam, Standard_False );
+        }
+      }
+    }
+  }
+
+  // PTv, chl/922/G9, Take into account internal vertices
+  // it is necessary for internal edges, which do not split other edges, by their vertex
+  TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX);
+  for (; aVertexIt.More(); aVertexIt.Next())
+  {
+    const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current());
+    if (aVertex.Orientation() != TopAbs_INTERNAL)
+      continue;
+
+    myTool->AddPoint(BRep_Tool::Pnt(aVertex), 
+      BRep_Tool::Parameter(aVertex, theEdge), Standard_True);
+  }
+
+  Standard_Integer aNodesNb = myTool->NbPoints();
+  //Check deflection in 2d space for improvement of edge tesselation.
+  if( isSameParam && aNodesNb > 1)
+  {
+    const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge);
+    TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces);
+    for (; aFaceIt.More(); aFaceIt.Next())
+    {
+      TopLoc_Location aLoc;
+      const TopoDS_Face&   aFace = TopoDS::Face(aFaceIt.Value());
+      Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
+
+      if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
+        continue;
+
+      Standard_Real aF, aL;
+      Handle(Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL);
+      if ( Abs(aF - aFirstParam) > Precision::PConfusion() ||
+           Abs(aL - aLastParam ) > Precision::PConfusion() )
+      {
+        continue;
+      }
+
+      aNodesNb = myTool->NbPoints();
+      TColStd_Array1OfReal aParamArray(1, aNodesNb);
+      for (Standard_Integer i = 1; i <= aNodesNb; ++i)
+      {
+        gp_Pnt2d      aTmpUV;
+        gp_Pnt        aTmpPnt;
+        Standard_Real aParam;
+        myTool->Value(i, mySurface, aParam, aTmpPnt, aTmpUV);
+        aParamArray.SetValue(i, aParam);
+      }
+
+      for (Standard_Integer i = 1; i < aNodesNb; ++i)
+        splitSegment(aSurf, aCurve2d, aParamArray(i), aParamArray(i + 1), 1);
+    }
+  }
+}
+
+//=======================================================================
+//function : Value
+//purpose  : 
+//=======================================================================
+void BRepMesh_EdgeTessellator::Value(const Standard_Integer theIndex,
+                                     Standard_Real&         theParameter,
+                                     gp_Pnt&                thePoint,
+                                     gp_Pnt2d&              theUV)
+{
+  myTool->Value(theIndex, mySurface, theParameter, thePoint, theUV);
+}
+
+//=======================================================================
+//function : splitSegment
+//purpose  : 
+//=======================================================================
+void BRepMesh_EdgeTessellator::splitSegment(
+  const Handle(Geom_Surface)& theSurf,
+  const Handle(Geom2d_Curve)& theCurve2d,
+  const Standard_Real         theFirst,
+  const Standard_Real         theLast,
+  const Standard_Integer      theNbIter)
+{
+  // limit iteration depth
+  if(theNbIter > 10)
+    return;
+
+  gp_Pnt2d uvf, uvl, uvm;
+  gp_Pnt   P3dF, P3dL, midP3d, midP3dFromSurf;
+  Standard_Real midpar;
+  
+  if(Abs(theLast - theFirst) < 2 * Precision::PConfusion())
+    return;
+
+  theCurve2d->D0(theFirst, uvf);
+  theCurve2d->D0(theLast,  uvl);
+
+  P3dF = theSurf->Value(uvf.X(), uvf.Y());
+  P3dL = theSurf->Value(uvl.X(), uvl.Y());
+  
+  if(P3dF.SquareDistance(P3dL) < mySquareEdgeDef)
+    return;
+
+  uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5);
+  midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y());
+
+  gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ();
+  aVec.Normalize();
+
+  gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
+  Standard_Real aModulus = Vec1.Dot(aVec);
+  gp_XYZ aProj = aVec * aModulus;
+  gp_XYZ aDist = Vec1 - aProj;
+
+  if(aDist.SquareModulus() < mySquareEdgeDef)
+    return;
+
+  midpar = (theFirst + theLast) * 0.5;
+  myCOnS.D0(midpar, midP3d);
+  myTool->AddPoint(midP3d, midpar, Standard_False);
+
+  splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
+  splitSegment(theSurf, theCurve2d, midpar, theLast,  theNbIter + 1); 
+}
diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.hxx b/src/BRepMesh/BRepMesh_EdgeTessellator.hxx
new file mode 100644 (file)
index 0000000..d64bf67
--- /dev/null
@@ -0,0 +1,88 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_EdgeTessellator_HeaderFile
+#define _BRepMesh_EdgeTessellator_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <BRepMesh_Collections.hxx>
+#include <BRepMesh_IEdgeTool.hxx>
+#include <BRepMesh_GeomTool.hxx>
+#include <BRepMesh_FaceAttribute.hxx>
+#include <Handle_Geom_Surface.hxx>
+#include <Handle_Geom2d_Curve.hxx>
+#include <Handle_BRepAdaptor_HSurface.hxx>
+#include <BRepAdaptor_Curve.hxx>
+
+class Geom_Surface;
+class Geom2d_Curve;
+class TopoDS_Edge;
+class BRepAdaptor_HSurface;
+class TopTools_IndexedDataMapOfShapeListOfShape;
+
+//! Auxiliary class implements functionality producing tessellated
+//! representation of an edge based on edge geometry.
+class BRepMesh_EdgeTessellator : public BRepMesh_IEdgeTool
+{
+public:
+
+  //! Constructor.
+  //! Automatically performs tessellation of the edge according to the
+  //! given parameters.
+  BRepMesh_EdgeTessellator(
+    const TopoDS_Edge&                               theEdge,
+    const Handle(BRepMesh_FaceAttribute)&            theFaceAttribute,
+    const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
+    const Standard_Real                              theLinDeflection,
+    const Standard_Real                              theAngDeflection);
+
+  //! Returns number of dicretization points.
+  virtual Standard_Integer NbPoints() const
+  {
+    return myTool->NbPoints();
+  }
+
+  //! Returns parameters of solution with the given index.
+  //! @param theIndex index of tessellation point.
+  //! @param theParameter parameters on PCurve corresponded to the solution.
+  //! @param thePoint tessellation point.
+  //! @param theUV coordinates of tessellation point in parametric space of face.
+  virtual void Value(const Standard_Integer theIndex,
+                     Standard_Real&         theParameter,
+                     gp_Pnt&                thePoint,
+                     gp_Pnt2d&              theUV);
+
+  DEFINE_STANDARD_RTTI(BRepMesh_EdgeTessellator)
+
+private:
+
+  //! 
+  void splitSegment(const Handle(Geom_Surface)& theSurf,
+                    const Handle(Geom2d_Curve)& theCurve2d,
+                    const Standard_Real         theFirst,
+                    const Standard_Real         theLast,
+                    const Standard_Integer      theNbIter);
+
+private:
+  N_HANDLE<BRepMesh_GeomTool>  myTool;
+  Handle(BRepAdaptor_HSurface) mySurface;
+  BRepAdaptor_Curve            myCOnS;
+  Standard_Real                mySquareEdgeDef;
+};
+
+DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
+
+#endif
index 0ce1d9c..716f3e0 100644 (file)
 // commercial license or contractual agreement.
 
 #include <BRepMesh_FaceAttribute.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <BRepMesh_Classifier.hxx>
+#include <BRepTools.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (BRepMesh_FaceAttribute, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FaceAttribute, Standard_Transient)
 
 //=======================================================================
-//function : BRepMesh_FaceAttribute
+//function : Constructor
 //purpose  : 
 //=======================================================================
-BRepMesh_FaceAttribute::BRepMesh_FaceAttribute():
- mydefface(0.), myumin(0.), myumax(0.), myvmin(0.), myvmax(0.),
- mydeltaX(1.), mydeltaY(1.), myminX(0.), myminY(0.)
+BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(
+  const TopoDS_Face&                theFace,
+  BRepMeshCol::DMapOfVertexInteger& theBoundaryVertices,
+  BRepMeshCol::DMapOfIntegerPnt&    theBoundaryPoints)
+  : myDefFace         (0.),
+    myUMin            (0.),
+    myUMax            (0.),
+    myVMin            (0.),
+    myVMax            (0.),
+    myDeltaX          (1.),
+    myDeltaY          (1.),
+    myStatus          (BRepMesh_NoError),
+    myBoundaryVertices(theBoundaryVertices),
+    myBoundaryPoints  (theBoundaryPoints),
+    myAllocator       (new NCollection_IncAllocator(64000))
 {
+  myVertexEdgeMap = new BRepMeshCol::IMapOfInteger;
+  myInternalEdges = new BRepMeshCol::DMapOfShapePairOfPolygon;
+  mySurfacePoints = new BRepMeshCol::DMapOfIntegerPnt;
+  myClassifier    = new BRepMesh_Classifier;
+
+  myFace = theFace;
+  BRepTools::Update(myFace);
+  myFace.Orientation(TopAbs_FORWARD);
+
+  BRepAdaptor_Surface aSurfAdaptor(myFace, Standard_False);
+  mySurface = new BRepAdaptor_HSurface(aSurfAdaptor);
+
+  ResetStructure();
+}
+
+//=======================================================================
+//function : Destructor
+//purpose  : 
+//=======================================================================
+BRepMesh_FaceAttribute::~BRepMesh_FaceAttribute()
+{
+  clearLocal();
+
+  mySurfaceVertices.Clear();
+  mySurfacePoints->Clear();
+
+  myClassifier.Nullify();
+  myAllocator.Nullify();
+}
+
+//=======================================================================
+//function : clearLocal
+//purpose  : 
+//=======================================================================
+void BRepMesh_FaceAttribute::clearLocal()
+{
+  myStructure.Nullify();
+
+  myLocation2D.Clear();
+  myVertexEdgeMap->Clear();
+  myInternalEdges->Clear();
+
+  myAllocator->Reset(Standard_False);
+}
+
+//=======================================================================
+//function : ResetStructure
+//purpose  : 
+//=======================================================================
+Handle(BRepMesh_DataStructureOfDelaun)& BRepMesh_FaceAttribute::ResetStructure()
+{
+  clearLocal();
+  myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator);
+
+  BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
+  Standard_Real aTolU = ToleranceU();
+  Standard_Real aTolV = ToleranceV();
+
+  myStructure->Data().SetCellSize(14.0 * aTolU, 14.0 * aTolV);
+  myStructure->Data().SetTolerance(aTolU, aTolV);
+  return myStructure;
+}
+
+//=======================================================================
+//function : computeParametricTolerance
+//purpose  : 
+//=======================================================================
+Standard_Real BRepMesh_FaceAttribute::computeParametricTolerance(
+  const Standard_Real theFirstParam,
+  const Standard_Real theLastParam) const
+{
+  const Standard_Real aDeflectionUV = 1.e-05;
+  return Max(Precision::PConfusion(), (theLastParam - theFirstParam) * aDeflectionUV);
+}
+
+//=======================================================================
+//function : getVertexIndex
+//purpose  : 
+//=======================================================================
+Standard_Boolean BRepMesh_FaceAttribute::getVertexIndex(
+  const TopoDS_Vertex& theVertex,
+  Standard_Integer&    theVertexIndex) const
+{
+  if (myBoundaryVertices.IsBound(theVertex))
+    theVertexIndex = myBoundaryVertices.Find(theVertex);
+  else if (mySurfaceVertices.IsBound(theVertex))
+    theVertexIndex = mySurfaceVertices.Find(theVertex);
+  else
+    return Standard_False;
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : AddNode
+//purpose  : 
+//=======================================================================
+void BRepMesh_FaceAttribute::AddNode(
+  const Standard_Integer         theIndex,
+  const gp_XY&                   theUV,
+  const BRepMesh_DegreeOfFreedom theMovability,
+  Standard_Integer&              theNodeIndex,
+  Standard_Integer&              theNodeOnEdgeIndex)
+{
+  BRepMesh_Vertex aNode(theUV, theIndex, theMovability);
+  theNodeIndex = myStructure->AddNode(aNode);
+  theNodeOnEdgeIndex = myVertexEdgeMap->FindIndex(theNodeIndex);
+  if (theNodeOnEdgeIndex == 0)
+    theNodeOnEdgeIndex = myVertexEdgeMap->Add(theNodeIndex);
+}
+
+//=======================================================================
+//function : Scale
+//purpose  : 
+//=======================================================================
+gp_XY BRepMesh_FaceAttribute::Scale(const gp_XY&           thePoint2d,
+                                    const Standard_Boolean isToFaceBasis)
+{
+  return isToFaceBasis ?
+    gp_XY((thePoint2d.X() - myUMin) / myDeltaX, (thePoint2d.Y() - myVMin) / myDeltaY) :
+    gp_XY(thePoint2d.X() * myDeltaX + myUMin, thePoint2d.Y() * myDeltaY + myVMin);
 }
index bd856b3..94d9068 100644 (file)
 #define _BRepMesh_FaceAttribute_HeaderFile
 
 #include <Standard.hxx>
+#include <Standard_Transient.hxx>
 #include <Standard_DefineHandle.hxx>
+
+#include <BRepMesh_Status.hxx>
 #include <BRepMesh_Collections.hxx>
-#include <Standard_Transient.hxx>
+#include <BRepMesh_DataStructureOfDelaun.hxx>
+#include <Handle_BRepAdaptor_HSurface.hxx>
 
+class BRepAdaptor_HSurface;
 
-//! auxiliary class for FastDiscret and FastDiscretFace classes <br>
+//! Auxiliary class for FastDiscret and FastDiscretFace classes.
 class BRepMesh_FaceAttribute : public Standard_Transient
 {
 public:
 
-  Standard_EXPORT BRepMesh_FaceAttribute();
-  
-  inline Standard_Real& GetDefFace()
+  //! Constructor.
+  //! @param theFace face the attribute is created for. 
+  //! Used for default initialization. Attribute keeps reference 
+  //! to the source face with forward orientation.
+  //! @param theBoundaryVertices shared map of shape vertices.
+  //! @param theBoundaryPoints shared discretization points of shape boundaries.
+  Standard_EXPORT BRepMesh_FaceAttribute(
+    const TopoDS_Face&                  theFace,
+    BRepMeshCol::DMapOfVertexInteger&   theBoundaryVertices,
+    BRepMeshCol::DMapOfIntegerPnt&      theBoundaryPoints);
+
+  //! Destructor.
+  virtual ~BRepMesh_FaceAttribute();
+
+public: //! @name main geometrical properties.
+
+  //! Returns face's surface.
+  inline const Handle(BRepAdaptor_HSurface)& Surface() const
+  {
+    return mySurface;
+  }
+
+  //! Returns forward oriented face to be used for calculations.
+  inline const TopoDS_Face& Face() const
+  {
+    return myFace;
+  }
+
+  //! Returns U tolerance of face calculated regarding its parameters.
+  inline Standard_Real ToleranceU() const
+  {
+    return computeParametricTolerance(myUMin, myUMax);
+  }
+
+  //! Returns V tolerance of face calculated regarding its parameters.
+  inline Standard_Real ToleranceV() const
+  {
+    return computeParametricTolerance(myVMin, myVMax);
+  }
+
+  //! Gives face deflection parameter.
+  inline Standard_Real GetDefFace() const
+  {
+    return myDefFace;
+  }
+
+  //! Sets face deflection.
+  inline void SetDefFace(const Standard_Real theDefFace)
+  {
+    myDefFace = theDefFace;
+  }
+
+  //! Gives minimal value in U domain.
+  inline Standard_Real GetUMin() const
+  {
+    return myUMin;
+  }
+
+  //! Sets minimal value in U domain.
+  inline void SetUMin(const Standard_Real theUMin)
+  {
+    myUMin = theUMin;
+  }
+
+  //! Gives minimal value in V domain.
+  inline Standard_Real GetVMin() const
+  {
+    return myVMin;
+  }
+
+  //! Sets minimal value in V domain.
+  inline void SetVMin(const Standard_Real theVMin)
+  {
+    myVMin = theVMin;
+  }
+
+  //! Gives maximal value in U domain.
+  inline Standard_Real GetUMax() const
+  {
+    return myUMax;
+  }
+
+  //! Sets maximal value in U domain.
+  inline void SetUMax(const Standard_Real theUMax)
+  {
+    myUMax = theUMax;
+  }
+
+  //! Gives maximal value in V domain.
+  inline Standard_Real GetVMax() const
   {
-    return mydefface;
+    return myVMax;
   }
 
-  inline Standard_Real& GetUMin()
+  //! Sets maximal value in V domain.
+  inline void SetVMax(const Standard_Real theVMax)
   {
-    return myumin;
+    myVMax = theVMax;
   }
 
-  inline Standard_Real& GetVMin()
+  //! Gives value of step in U domain.
+  inline Standard_Real GetDeltaX() const
   {
-    return myvmin;
+    return myDeltaX;
   }
 
-  inline Standard_Real& GetUMax()
+  //! Sets value of step in U domain.
+  inline void SetDeltaX(const Standard_Real theDeltaX)
   {
-    return myumax;
+    myDeltaX = theDeltaX;
   }
 
-  inline Standard_Real& GetVMax()
+  //! Gives value of step in V domain.
+  inline Standard_Real GetDeltaY() const
   {
-    return myvmax;
+    return myDeltaY;
   }
 
-  inline Standard_Real& GetDeltaX()
+  //! Sets value of step in V domain.
+  inline void SetDeltaY(const Standard_Real theDeltaY)
   {
-    return mydeltaX;
+    myDeltaY = theDeltaY;
   }
 
-  inline Standard_Real& GetDeltaY()
+  //! Sets set of status flags for this face.
+  inline Standard_Integer GetStatus() const
   {
-    return mydeltaY;
+    return myStatus;
   }
 
-  inline Standard_Real& GetMinX()
+  //! Sets status flag for this face.
+  inline void SetStatus(const BRepMesh_Status theStatus)
   {
-    return myminX;
+    myStatus |= theStatus;
   }
 
-  inline Standard_Real& GetMinY()
+  //! Returns TRUE in case if computed data is valid.
+  inline Standard_Boolean IsValid() const
   {
-    return myminY;
+    return (myStatus == BRepMesh_NoError || myStatus == BRepMesh_ReMesh);
   }
 
-  inline BRepMeshCol::HClassifier& GetClassifier()
+public: //! @name auxiliary structures
+
+  //! Clear all face attribute.
+  Standard_EXPORT void Clear();
+
+  //! Resets mesh data structure.
+  //! @returns reset data structure.
+  Standard_EXPORT Handle(BRepMesh_DataStructureOfDelaun)& ResetStructure();
+
+  //! Gives reference to map of internal edges of face.
+  inline BRepMeshCol::HDMapOfShapePairOfPolygon& ChangeInternalEdges()
   {
-    return myclassifier;
+    return myInternalEdges;
   }
 
+  //! Gives reference to map of 2D points of discretization.
+  inline BRepMeshCol::DMapOfIntegerListOfXY& ChangeLocation2D()
+  {
+    return myLocation2D;
+  }
+
+  //! Gives reference to map of 3D points of discretization.
+  inline BRepMeshCol::HDMapOfIntegerPnt& ChangeSurfacePoints()
+  {
+    return mySurfacePoints;
+  }
+
+  //! Gives reference on map of (vertex, edge) pairs of face.
+  inline BRepMeshCol::HIMapOfInteger& ChangeVertexEdgeMap()
+  {
+    return myVertexEdgeMap;
+  }
+
+  //! Gives Delaunay data structure.
+  inline Handle(BRepMesh_DataStructureOfDelaun)& ChangeStructure()
+  {
+    return myStructure;
+  }
+
+  //! Returns classifier.
+  inline BRepMeshCol::HClassifier& ChangeClassifier()
+  {
+    return myClassifier;
+  }
+
+public: //! @name Point/Vertex/Node manipulators
+
+  //! Gives the number of different locations in 3D space.
+  inline Standard_Integer LastPointId() const
+  {
+    return myBoundaryPoints.Extent() + mySurfacePoints->Extent();
+  }
+
+  //! Gives the 3D location of the vertex.
+  inline const gp_Pnt& GetPoint(const BRepMesh_Vertex& theVertex) const
+  {
+    return GetPoint(theVertex.Location3d());
+  }
+
+  //! Gives the 3D location of the vertex.
+  inline const gp_Pnt& GetPoint(const Standard_Integer theIndex) const
+  {
+    if (theIndex > myBoundaryPoints.Extent())
+      return mySurfacePoints->Find(theIndex);
+
+    return myBoundaryPoints(theIndex);
+  }
+
+  //! Returns index of the given vertex if it exists in cache, 
+  //! elsewhere adds it to cache and returns cached index.
+  //! @param theVertexExplorer template parameter intended to transfer
+  //! parameters of vertex to method. Explorer class can implement different
+  //! approaches of extraction of target parameters.
+  //! @param isFillEdgeVertices if TRUE adds vertex to shared map of 
+  //! edges vertices, elsewhere adds it map of face vertices.
+  template<class HVertexExplorer>
+    Standard_Integer GetVertexIndex(
+      const HVertexExplorer& theVertexExplorer,
+      const Standard_Boolean isFillEdgeVertices = Standard_False)
+  {
+    const TopoDS_Vertex& aVertex = theVertexExplorer->Vertex();
+    Standard_Integer aNewVertexIndex = 0;
+    if (getVertexIndex(aVertex, aNewVertexIndex))
+      return aNewVertexIndex;
+
+    if (!theVertexExplorer->IsSameUV() ||
+        !getVertexIndex(theVertexExplorer->SameVertex(), aNewVertexIndex))
+    {
+      aNewVertexIndex = LastPointId() + 1;
+
+      BRepMeshCol::DMapOfIntegerPnt& aPointsMap = isFillEdgeVertices ?
+        myBoundaryPoints : *mySurfacePoints;
+
+      aPointsMap.Bind(aNewVertexIndex, theVertexExplorer->Point());
+    }
+
+    BRepMeshCol::DMapOfVertexInteger& aVertexMap = isFillEdgeVertices ?
+      myBoundaryVertices : mySurfaceVertices;
+
+    aVertexMap.Bind(aVertex, aNewVertexIndex);
+
+    return aNewVertexIndex;
+  }
+
+  //! Adds node with the given parameters to mesh.
+  //! @param theIndex index of 3D point corresponded to the node.
+  //! @param theUV node position.
+  //! @param theMovability movability of a node.
+  //! @param theNodeIndex index of vertex in mesh structure.
+  //! @param theNodeOnEdgeIndex ordered index of node on the boundary.
+  Standard_EXPORT void AddNode(const Standard_Integer         theIndex,
+                               const gp_XY&                   theUV,
+                               const BRepMesh_DegreeOfFreedom theMovability,
+                               Standard_Integer&              theNodeIndex,
+                               Standard_Integer&              theNodeOnEdgeIndex);
+
+public: //! @name Auxiliary methods
+  
+  //! Scales the given point from real parametric space 
+  //! to face basis and otherwise.
+  //! @param thePoint2d point to be scaled.
+  //! @param isToFaceBasis if TRUE converts point to face basis,
+  //! otherwise performs reverse conversion.
+  //! @return scaled point.
+  Standard_EXPORT gp_XY Scale(const gp_XY&           thePoint2d, 
+                              const Standard_Boolean isToFaceBasis);
 
   DEFINE_STANDARD_RTTI(BRepMesh_FaceAttribute)
 
-private: 
-
-  Standard_Real mydefface;
-  Standard_Real myumin;
-  Standard_Real myumax;
-  Standard_Real myvmin;
-  Standard_Real myvmax;
-  Standard_Real mydeltaX;
-  Standard_Real mydeltaY;
-  Standard_Real myminX;
-  Standard_Real myminY;
-  BRepMeshCol::HClassifier myclassifier;
+private:
+
+  //! Assignment operator.
+  void operator =(const BRepMesh_FaceAttribute& /*theOther*/)
+  {
+  }
+
+  //! Computes parametric tolerance of a face regarding the given limits.
+  Standard_Real computeParametricTolerance(
+    const Standard_Real theFirstParam,
+    const Standard_Real theLastParam) const;
+
+  //! Clears internal data structures local to face.
+  void clearLocal();
+
+  //! Returns index of the given vertex if it exists in cache.
+  //! @param theVertex vertex which index should be retrieved.
+  //! @param theVertexIndex index of the given vertex.
+  //! @return TRUE if cached value is found, FALSE elsewhere.
+  Standard_EXPORT Standard_Boolean getVertexIndex(
+    const TopoDS_Vertex& theVertex,
+    Standard_Integer&    theVertexIndex) const;
+
+private:
+
+  Standard_Real                           myDefFace;       //!< Restore face deflection
+  Standard_Real                           myUMin;          //!< Describes minimal value in U domain
+  Standard_Real                           myUMax;          //!< Describes maximal value in U domain
+  Standard_Real                           myVMin;          //!< Describes minimal value in V domain
+  Standard_Real                           myVMax;          //!< Describes maximal value in V domain
+  Standard_Real                           myDeltaX;
+  Standard_Real                           myDeltaY;
+  Standard_Integer                        myStatus;
+
+  BRepMeshCol::DMapOfVertexInteger&       myBoundaryVertices;
+  BRepMeshCol::DMapOfIntegerPnt&          myBoundaryPoints;
+
+  TopoDS_Face                             myFace;
+  Handle(BRepAdaptor_HSurface)            mySurface;
+  BRepMeshCol::DMapOfVertexInteger        mySurfaceVertices;
+  BRepMeshCol::HDMapOfIntegerPnt          mySurfacePoints;
+
+  BRepMeshCol::DMapOfIntegerListOfXY      myLocation2D;
+  BRepMeshCol::HIMapOfInteger             myVertexEdgeMap;
+  BRepMeshCol::HDMapOfShapePairOfPolygon  myInternalEdges;
+
+  Handle(BRepMesh_DataStructureOfDelaun)  myStructure;
+  BRepMeshCol::HClassifier                myClassifier;
+  BRepMeshCol::Allocator                  myAllocator;
 };
 
 DEFINE_STANDARD_HANDLE(BRepMesh_FaceAttribute, Standard_Transient)
index 87ca40a..ba76f40 100644 (file)
 #include <BRepMesh_GeomTool.hxx>
 #include <BRepMesh_PairOfPolygon.hxx>
 #include <BRepMesh_Classifier.hxx>
-#include <BRepMesh_ShapeTool.hxx>
+#include <BRepMesh_EdgeParameterProvider.hxx>
+#include <BRepMesh_IEdgeTool.hxx>
+#include <BRepMesh_EdgeTessellator.hxx>
+#include <BRepMesh_EdgeTessellationExtractor.hxx>
 
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
@@ -33,7 +36,6 @@
 #include <BRepTools.hxx>
 #include <BRepBndLib.hxx>
 #include <BndLib_Add3dCurve.hxx>
-#include <BRep_Tool.hxx>
 #include <Poly_Triangulation.hxx>
 #include <Poly_PolygonOnTriangulation.hxx>
 
@@ -46,7 +48,6 @@
 
 #include <TColStd_Array1OfInteger.hxx>
 #include <TColStd_HArray1OfReal.hxx>
-#include <TColgp_Array1OfPnt.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
 #include <TColGeom2d_SequenceOfCurve.hxx>
 #include <SortTools_ShellSortOfReal.hxx>
@@ -54,7 +55,6 @@
 
 #include <TopTools_SequenceOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 
 #include <TopAbs.hxx>
 #include <TopoDS.hxx>
@@ -85,25 +85,24 @@ IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret, Standard_Transient)
 //function : BRepMesh_FastDiscret
 //purpose  : 
 //=======================================================================
-BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real    theDefle,
-                                           const Standard_Real    theAngl,
-                                           const Bnd_Box&         theBox,
-                                           const Standard_Boolean theWithShare,
-                                           const Standard_Boolean theInshape,
-                                           const Standard_Boolean theRelative,
-                                           const Standard_Boolean theShapetrigu,
-                                           const Standard_Boolean isInParallel)
+BRepMesh_FastDiscret::BRepMesh_FastDiscret(
+  const Standard_Real                              theDefle,
+  const Standard_Real                              theAngl,
+  const Bnd_Box&                                   theBox,
+  const Standard_Boolean                           theWithShare,
+  const Standard_Boolean                           theInshape,
+  const Standard_Boolean                           theRelative,
+  const Standard_Boolean                           theShapetrigu,
+  const Standard_Boolean                           isInParallel)
 : myAngle (theAngl),
   myDeflection (theDefle),
   myWithShare (theWithShare),
   myInParallel (isInParallel),
-  myNbLocat (0),
   myRelative (theRelative),
   myShapetrigu (theShapetrigu), 
   myInshape (theInshape)
 {
-  myAllocator = new NCollection_IncAllocator(64000);
-  if(myRelative)
+  if ( myRelative )
     BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
 }
 
@@ -111,7 +110,6 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real    theDefle,
 //function : BRepMesh_FastDiscret
 //purpose  : 
 //=======================================================================
-
 BRepMesh_FastDiscret::BRepMesh_FastDiscret(const TopoDS_Shape&    theShape,
                                            const Standard_Real    theDefle,
                                            const Standard_Real    theAngl,
@@ -125,64 +123,53 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(const TopoDS_Shape&    theShape,
   myDeflection (theDefle),
   myWithShare (theWithShare),
   myInParallel (isInParallel),
-  myNbLocat (0),
   myRelative (theRelative),
   myShapetrigu (theShapetrigu),
   myInshape (theInshape)
 {
-  myAllocator = new NCollection_IncAllocator(64000);
-  if(myRelative)
+  if ( myRelative )
     BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
-  Perform(theShape);
-}
 
-//=======================================================================
-//function : SetParallel
-//purpose  :
-//=======================================================================
-void BRepMesh_FastDiscret::SetParallel (const Standard_Boolean theInParallel)
-{
-  myInParallel = theInParallel;
+  Perform(theShape);
 }
 
 //=======================================================================
-//function : IsParallel
-//purpose  :
+//function : InitSharedFaces
+//purpose  : 
 //=======================================================================
-Standard_Boolean BRepMesh_FastDiscret::IsParallel() const
+void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape)
 {
-  return myInParallel;
+  TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
 }
 
 //=======================================================================
 //function : Perform(shape)
 //purpose  : 
 //=======================================================================
-
 void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
 {
-  TopTools_IndexedDataMapOfShapeListOfShape anAncestors;
-  TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, anAncestors);
+  InitSharedFaces(theShape);
+
   std::vector<TopoDS_Face> aFaces;
-  for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) {
-    TopoDS_Face aF = TopoDS::Face(ex.Current());
-    Add(aF, anAncestors);
-    aFaces.push_back(aF);
+  TopExp_Explorer anExplorer(theShape, TopAbs_FACE);
+  for (; anExplorer.More(); anExplorer.Next())
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current());
+    Add(aFace);
+    aFaces.push_back(aFace);
   }
 
 #ifdef HAVE_TBB
-  if (myInParallel)
+  if ( myInParallel )
   {
-    CreateMutexesForSubShapes(theShape, TopAbs_EDGE);
-    // mesh faces in parallel threads using TBB
-    tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *this);
-    RemoveAllMutexes();
+    tbb::parallel_for_each(aFaces.begin(), aFaces.end(), *this);
   }
   else
   {
 #endif
-    for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
-      Process (*it);
+    std::vector<TopoDS_Face>::const_iterator anIt(aFaces.begin());
+    for (; anIt != aFaces.end(); anIt++)
+      Process(*anIt);
 #ifdef HAVE_TBB
   }
 #endif
@@ -193,1438 +180,798 @@ void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
 //function : Process
 //purpose  : 
 //=======================================================================
-
 void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
 {
-  //cout << "START face " << theFace.TShape().operator->() << endl << flush;
-  Handle(BRepMesh_FaceAttribute) fattribute;
-  if ( GetFaceAttribute (theFace, fattribute) ) 
+  Handle(BRepMesh_FaceAttribute) anAttribute;
+  if (GetFaceAttribute(theFace, anAttribute))
   {
-    BRepMesh_FastDiscretFace aTool (GetAngle(), WithShare());
-    aTool.Add (theFace, fattribute, GetMapOfDefEdge(), myMutexProvider);
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      BRepMesh_FastDiscretFace aTool(GetAngle(), WithShare());
+      aTool.Add(anAttribute);
+    }
+    catch (Standard_Failure)
+    {
+      anAttribute->SetStatus(BRepMesh_Failure);
+    }
   }
-  //cout << "END   face " << theFace.TShape().operator->() << endl << flush;
 }
 
 //=======================================================================
 //function : Add(face)
 //purpose  : 
 //=======================================================================
-
-#define MESH_FAILURE(theface)        \
-{                                    \
-  myFacestate = BRepMesh_Failure;    \
-  myNottriangulated.Append(theface); \
-  return;                            \
-}
-
-void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface,
-                               const TopTools_IndexedDataMapOfShapeListOfShape& theAncestors)
+Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace)
 {
-#ifndef DEB_MESH
   try
   {
     OCC_CATCH_SIGNALS
-#endif
-  TopoDS_Face face = theface;
-  BRepTools::Update(face);
-  face.Orientation(TopAbs_FORWARD);
-  myStructure.Nullify();
-  Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator);
-  anAlloc->Reset(Standard_False);  
-  myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc);
-
-  Standard_Real aUmin, aVmin, aUmax, aVmax;
-  BRepTools::UVBounds (theface, aUmin, aUmax, aVmin, aVmax);
-  Standard_Real aTolU = Max( Precision::PConfusion(), (aUmax - aUmin) * UVDEFLECTION );
-  Standard_Real aTolV = Max( Precision::PConfusion(), (aVmax - aVmin) * UVDEFLECTION );
-  myStructure->Data().SetCellSize ( 14 * aTolU, 14 * aTolV );
-  myStructure->Data().SetTolerance( aTolU, aTolV );
-
-  BRepAdaptor_Surface  BS(face, Standard_False);
-  Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
-  
-  GeomAbs_SurfaceType thetype;
-  thetype = BS.GetType();
-
-  gp_Pnt2d uvFirst, uvLast;
-
-  Handle(Poly_Triangulation) T;
-  TopLoc_Location loc;
-
-  if (!myWithShare) {          
-    myVertices.Clear();
-    myEdges.Clear();
-  }
 
-  myVemap.Clear();
-  myLocation2d.Clear();
-  myInternaledges.Clear();
+    // Initialize face attributes
+    myAttribute.Nullify();
+    GetFaceAttribute(theFace, myAttribute);
+    if (myAttribute.IsNull())
+    {
+      myAttribute = new BRepMesh_FaceAttribute(theFace,
+        myBoundaryVertices, myBoundaryPoints);
 
-  Standard_Integer i;
-  i = 1;
+      myAttributes.Bind(theFace, myAttribute);
+    }
 
-  Standard_Real defedge, defface;
-  Standard_Integer nbEdge = 0;
-  Standard_Real savangle = myAngle;
-  Standard_Real cdef;
-  Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theface);
-  defface = 0.;
+    myStructure     = myAttribute->ResetStructure();
+    myVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
+    myInternalEdges = myAttribute->ChangeInternalEdges();
 
-  if (!myRelative) defface = Max(myDeflection, maxdef);
+    if (!myWithShare)
+    {
+      myEdges.Clear();
+      myBoundaryVertices.Clear();
+      myBoundaryPoints.Clear();
+    }
 
-  BRepMeshCol::SequenceOfReal aFSeq, aLSeq;
-  TColGeom2d_SequenceOfCurve aCSeq;
-  TopTools_SequenceOfShape aShSeq;
+    Standard_Real defedge;
+    Standard_Integer nbEdge = 0;
+    Standard_Real savangle = myAngle;
+    Standard_Real cdef;
+    Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace);
 
-  TopoDS_Iterator exW(face);
+    Standard_Real defface = 0.;
+    if (!myRelative)
+      defface = Max(myDeflection, maxdef);
 
-  for (; exW.More(); exW.Next()) {
-    const TopoDS_Shape& aWire = exW.Value();
-    if (aWire.ShapeType() != TopAbs_WIRE)
-      continue;
-    TopoDS_Iterator ex(aWire);
-    for(; ex.More(); ex.Next()) {
-      const TopoDS_Edge& edge = TopoDS::Edge(ex.Value());
-      nbEdge++;
-      if (!myMapdefle.IsBound(edge)) {
-        if (myRelative) {
-          if (myEdges.IsBound(edge)) {
-            const BRepMesh_PairOfPolygon& pair = myEdges.Find(edge);
-            const Handle(Poly_PolygonOnTriangulation)& P = pair.First();
-            defedge = P->Deflection();
+    N_SEQUENCE<EdgePCurve>  aPCurves;
+    N_SEQUENCE<TopoDS_Edge> aFaceEdges;
+
+    const TopoDS_Face&                  aFace = myAttribute->Face();
+    const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
+    TopExp_Explorer aWireIt(aFace, TopAbs_WIRE);
+    for (; aWireIt.More(); aWireIt.Next())
+    {
+      TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE);
+      for (; aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
+      {
+        const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
+        if (!myMapdefle.IsBound(aEdge))
+        {
+          if (myRelative)
+          {
+            if (myEdges.IsBound(aEdge))
+            {
+              const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
+              const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
+              defedge = aPolygon->Deflection();
+            }
+            else
+            {
+              defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(
+                aEdge, myDeflection, myDtotale, cdef);
+
+              myAngle = savangle * cdef;
+            }
+
+            defface += defedge;
+            defface = Max(maxdef, defface);
+          }
+          else
+          {
+            defedge = myDeflection;
           }
-          else {
-            defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(edge, 
-              myDeflection, myDtotale, cdef);
 
-            myAngle = savangle * cdef;
+          defedge = Max(maxdef, defedge);
+          defedge = Max(UVDEFLECTION, defedge);
+          myMapdefle.Bind(aEdge, defedge);
+        }
+        else
+        {
+          defedge = myMapdefle(aEdge);
+          if ( myRelative )
+          {
+            defface += defedge;
+            defface = Max(maxdef, defface);
           }
-          defface = defface + defedge;
-          defface = Max(maxdef, defface);
         }
-        else defedge = myDeflection;
-    
-        defedge = Max(maxdef, defedge);
-        defedge = Max(UVDEFLECTION , defedge);
-        myMapdefle.Bind(edge, defedge);
-      }
-      else{
-        defedge = myMapdefle(edge);
-        if (myRelative) {defface = defface + defedge; defface = Max(maxdef, defface);}
+
+        Standard_Real aFirstParam, aLastParam;
+        Handle(Geom2d_Curve) aCurve2d = 
+          BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam);
+
+        if (aCurve2d.IsNull())
+          continue;
+
+        EdgePCurve aPCurve = { aCurve2d, aFirstParam, aLastParam };
+        aPCurves.Append(aPCurve);
+        aFaceEdges.Append(aEdge);
+
+        add(aEdge, aPCurve, defedge);
+        myAngle = savangle;
       }
-      Standard_Real f1,l1;
-      Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(edge, face, f1, l1);
-      if (C.IsNull()) continue;
-
-      aFSeq.Append(f1);
-      aLSeq.Append(l1);
-      aCSeq.Append(C);
-      aShSeq.Append(edge);
-      Add(edge, face, gFace, C, theAncestors, defedge, f1, l1);
-      myAngle = savangle;
     }
-  }
 
-  if (nbEdge == 0 || myVemap.Extent() < 3)
-  {
-      MESH_FAILURE(theface);
-  }
+    if ( nbEdge == 0 || myVertexEdgeMap->Extent() < 3 )
+    {
+      myAttribute->SetStatus(BRepMesh_Failure);
+      return myAttribute->GetStatus();
+    }
 
-  if (myRelative ) defface = defface / nbEdge;
-  else             defface = myDeflection;
-
-  if (myWithShare) defface = Max(maxdef, defface);
-  
-  T = BRep_Tool::Triangulation(face, loc);
-
-  if (!myShapetrigu || T.IsNull()) {
-    
-    Standard_Real xCur, yCur;
-    Standard_Real maxX, minX, maxY, minY;
-    minX=minY=1.e100;
-    maxX=maxY=-1.e100;
-    
-    Standard_Integer ipn = 0;
-    Standard_Integer i1 =1;
-    for (i1 = 1; i1 <= myVemap.Extent(); i1++) {
-      const BRepMesh_Vertex& aV = myStructure->GetNode(myVemap.FindKey(i1));
-      ipn++;
-      xCur=aV.Coord().X();
-      yCur=aV.Coord().Y();
-      minX=Min(xCur, minX);
-      maxX=Max(xCur, maxX);
-      minY=Min(yCur, minY);
-      maxY=Max(yCur, maxY);
+    if ( myRelative )
+    {
+      defface = defface / nbEdge;
     }
-    Standard_Real myumin = minX;
-    Standard_Real myumax = maxX;
-    Standard_Real myvmin = minY;
-    Standard_Real myvmax = maxY;
-    
-    const Standard_Real umin = BS.FirstUParameter();
-    const Standard_Real umax = BS.LastUParameter();
-    const Standard_Real vmin = BS.FirstVParameter();
-    const Standard_Real vmax = BS.LastVParameter();
-
-    if (myumin < umin || myumax > umax)
+    else
+    {
+      defface = myDeflection;
+    }
+
+    if ( myWithShare )
+      defface = Max(maxdef, defface);
+
+    TopLoc_Location aLoc;
+    Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
+
+    if (!myShapetrigu || aTriangulation.IsNull())
     {
-      if (BS.IsUPeriodic())
+      Standard_Real xCur, yCur;
+      Standard_Real maxX, minX, maxY, minY;
+
+      minX = minY = 1.e100;
+      maxX = maxY =-1.e100;
+
+      Standard_Integer ipn = 0;
+      Standard_Integer i1 = 1;
+      for ( i1 = 1; i1 <= myVertexEdgeMap->Extent(); ++i1 )
       {
-        if ((myumax - myumin) > (umax - umin))
-        {
-          myumax = myumin + (umax - umin);
-        }
+        const BRepMesh_Vertex& aVertex = myStructure->GetNode(myVertexEdgeMap->FindKey(i1));
+
+        ++ipn;
+
+        xCur = aVertex.Coord().X();
+        yCur = aVertex.Coord().Y();
+
+        minX = Min(xCur, minX);
+        maxX = Max(xCur, maxX);
+        minY = Min(yCur, minY);
+        maxY = Max(yCur, maxY);
       }
-      else
+
+      Standard_Real myumin = minX;
+      Standard_Real myumax = maxX;
+      Standard_Real myvmin = minY;
+      Standard_Real myvmax = maxY;
+
+      const Standard_Real umin = gFace->FirstUParameter();
+      const Standard_Real umax = gFace->LastUParameter();
+      const Standard_Real vmin = gFace->FirstVParameter();
+      const Standard_Real vmax = gFace->LastVParameter();
+
+      if (myumin < umin || myumax > umax)
       {
-        if (umin > myumin) myumin = umin;
-        if (umax < myumax) myumax = umax;
+        if (gFace->IsUPeriodic())
+        {
+          if ((myumax - myumin) > (umax - umin))
+            myumax = myumin + (umax - umin);
+        }
+        else
+        {
+          if (umin > myumin)
+            myumin = umin;
+
+          if (umax < myumax)
+            myumax = umax;
+        }
       }
-    }
 
-    if (myvmin < vmin || myvmax > vmax)
-    {
-      if (BS.IsVPeriodic())
+      if (myvmin < vmin || myvmax > vmax)
       {
-        if ((myvmax - myvmin) > (vmax - vmin))
+        if (gFace->IsVPeriodic())
+        {
+          if ((myvmax - myvmin) > (vmax - vmin))
+            myvmax = myvmin + (vmax - vmin);
+        }
+        else
         {
-          myvmax = myvmin + (vmax - vmin);
+          if ( vmin > myvmin )
+            myvmin = vmin;
+
+          if (vmax < myvmax)
+            myvmax = vmax;
         }
       }
-      else
+
+      GeomAbs_SurfaceType aSurfType = gFace->GetType();
+      // Fast verification of the validity of calculated limits.
+      // If wrong, sure a problem of pcurve.
+      if (aSurfType == GeomAbs_BezierSurface &&
+         (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) )
       {
-        if (vmin > myvmin) myvmin = vmin;
-        if (vmax < myvmax) myvmax = vmax;
+        myAttribute->SetStatus(BRepMesh_Failure);
+        return myAttribute->GetStatus();
       }
-    }
 
-    // fast verification of the validity of calculated limits. If wrong, 
-    // sure a problem of pcurve.
-    if (thetype == GeomAbs_BezierSurface &&
-        (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5))
-    {
-      MESH_FAILURE(theface);
-    }
-    //define parameters for correct parametrics
-    
-    Standard_Real deltaX = 1.0;
-    Standard_Real deltaY = 1.0;
-    Standard_Integer nbVertices = myVemap.Extent();
-    const Standard_Real tolclass = Precision::PConfusion(); //0.03*Max(myumax-myumin, myvmax-myvmin);
-    
-    BRepMeshCol::HClassifier classifier = new BRepMesh_Classifier;
-    {
-      BRepMesh_WireChecker aDFaceChecker(face, 
-        tolclass, myInternaledges, myVemap, myStructure, 
-        myumin, myumax, myvmin, myvmax, myInParallel);
-      aDFaceChecker.ReCompute(classifier);
-    
-      myFacestate = aDFaceChecker.Status();
-      if (myFacestate == BRepMesh_SelfIntersectingWire)
+      //define parameters for correct parametrics
+      Standard_Real deltaX = 1.0;
+      Standard_Real deltaY = 1.0;
+
       {
-        Standard_Integer nbmaill = 0;
-        Standard_Real eps = Precision::Confusion();
-        while (nbmaill < 5 && myFacestate != BRepMesh_ReMesh)
+        BRepMeshCol::HClassifier& aClassifier = myAttribute->ChangeClassifier();
+        BRepMesh_WireChecker aDFaceChecker(aFace, Precision::PConfusion(),
+          myInternalEdges, myVertexEdgeMap, myStructure,
+          myumin, myumax, myvmin, myvmax, myInParallel );
+
+        aDFaceChecker.ReCompute(aClassifier);
+        BRepMesh_Status aCheckStatus = aDFaceChecker.Status();
+
+        if (aCheckStatus == BRepMesh_SelfIntersectingWire)
         {
-          nbmaill++;
-          
-          //clear the structure of links
-          myStructure.Nullify();
-          myStructure = new BRepMesh_DataStructureOfDelaun(anAlloc);
-          
-          myVemap.Clear();
-          myLocation2d.Clear();
-          myInternaledges.Clear();
-
-          Standard_Integer j1;
-          for(j1 = 1; j1 <= aShSeq.Length(); j1++)
+          Standard_Integer nbmaill = 0;
+          Standard_Real eps = Precision::Confusion();
+          while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh)
           {
-            const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
-            if (myEdges.IsBound(edge))
+            ++nbmaill;
+
+            // Clear the structure of links
+            myStructure = myAttribute->ResetStructure();
+
+            
+            for (Standard_Integer j = 1; j <= aFaceEdges.Length(); ++j)
             {
-              myEdges.UnBind(edge);
-              myInternaledges.UnBind(edge);
+              const TopoDS_Edge& anEdge = aFaceEdges(j);
+              if (myEdges.IsBound(anEdge))
+                myEdges.UnBind(anEdge);
+
+              defedge = Max(myMapdefle(anEdge) / 3.0, eps);
+              myMapdefle.Bind(anEdge, defedge);
+
+              add(anEdge, aPCurves(j), defedge);
             }
-          }
-          
-          
-          for( j1 = 1; j1 <= aShSeq.Length(); j1++)
-          {
-            const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
-            defedge = myMapdefle(edge) / 3.;
-            defedge = Max(defedge, eps);
-            myMapdefle.Bind(edge, defedge);
-            const Handle(Geom2d_Curve)& C = aCSeq.Value(j1);
-            Add(edge, face, gFace, C, theAncestors, defedge, aFSeq.Value(j1), aLSeq.Value(j1));
-          }
 
-          aDFaceChecker.ReCompute(classifier);
-          if (aDFaceChecker.Status() == BRepMesh_NoError)
-          {
-            myFacestate = BRepMesh_ReMesh;
+            aDFaceChecker.ReCompute(aClassifier);
+            if (aDFaceChecker.Status() == BRepMesh_NoError)
+              aCheckStatus = BRepMesh_ReMesh;
           }
-          nbVertices = myVemap.Extent();
         }
+
+        myAttribute->SetStatus(aCheckStatus);
+        if (!myAttribute->IsValid())
+          //RemoveFaceAttribute(theFace);
+          return myAttribute->GetStatus();
       }
-    }
-    
-    if (myFacestate != BRepMesh_NoError && myFacestate != BRepMesh_ReMesh)
-    {
-      myNottriangulated.Append(face);
-      classifier.Nullify();
-      return;
-    }
-    
-    // try to find the real length:
-    // akm (bug OCC16) : We must calculate these measures in non-singular
-    //     parts of face. Let's try to compute average value of three
-    //     (umin, (umin+umax)/2, umax), and respectively for v.
-    //                 vvvvv
-    Standard_Real longu = 0.0, longv = 0.0; //, last , first;
-    gp_Pnt P11, P12, P21, P22, P31, P32;
-    
-    Standard_Real du = (myumax-myumin)/20;
-    Standard_Real dv = (myvmax-myvmin)/20;
-    Standard_Real dfuave=(myumin+myumax)/2, dfucur;
-    Standard_Real dfvave=(myvmin+myvmax)/2, dfvcur;
-    // U loop
-    BS.D0 (myumin, myvmin, P11);
-    BS.D0 (myumin, dfvave, P21);
-    BS.D0 (myumin, myvmax, P31);
-    for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du)  {
-      BS.D0 (dfucur, myvmin, P12);
-      BS.D0 (dfucur, dfvave, P22);
-      BS.D0 (dfucur, myvmax, P32);
-      longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
-      P11 = P12;
-      P21 = P22;
-      P31 = P32;
-    }
-    // V loop
-    BS.D0(myumin, myvmin, P11);
-    BS.D0(dfuave, myvmin, P21);
-    BS.D0(myumax, myvmin, P31);
-    for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv) {    
-      BS.D0 (myumin, dfvcur, P12);
-      BS.D0 (dfuave, dfvcur, P22);
-      BS.D0 (myumax, dfvcur, P32);
-      longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
-      P11 = P12;
-      P21 = P22;
-      P31 = P32;
-    }
-    longu /= 3.;
-    longv /= 3.;
-    // akm (bug OCC16) ^^^^^
-    
-    if (longu <= 1.e-16 || longv <= 1.e-16) {
-      //yes, it is seen!!
-#ifdef DEB_MESH_CHRONO
-      chMaillEdges.Stop();
-      MESH_CHRONO_TSTOP(thetype);
-#endif
-      MESH_FAILURE(theface);
-    }
 
+      // try to find the real length:
+      // akm (bug OCC16) : We must calculate these measures in non-singular
+      //     parts of face. Let's try to compute average value of three
+      //     (umin, (umin+umax)/2, umax), and respectively for v.
+      //                 vvvvv
+      Standard_Real longu = 0.0, longv = 0.0; //, last , first;
+      gp_Pnt P11, P12, P21, P22, P31, P32;
+
+      Standard_Real du = 0.05 * ( myumax - myumin );
+      Standard_Real dv = 0.05 * ( myvmax - myvmin );
+      Standard_Real dfuave = 0.5 * ( myumin + myumax );
+      Standard_Real dfvave = 0.5 * ( myvmin + myvmax );
+      Standard_Real dfucur, dfvcur;
+
+      // U loop
+      gFace->D0(myumin, myvmin, P11);
+      gFace->D0(myumin, dfvave, P21);
+      gFace->D0(myumin, myvmax, P31);
+      for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du)
+      {
+        gFace->D0(dfucur, myvmin, P12);
+        gFace->D0(dfucur, dfvave, P22);
+        gFace->D0(dfucur, myvmax, P32);
+        longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
+        P11 = P12;
+        P21 = P22;
+        P31 = P32;
+      }
 
-    if (thetype == GeomAbs_Torus)  {
-      gp_Torus Tor = BS.Torus();
-      Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
-      Standard_Real Du, Dv;//, pasu, pasv;
-      
-      Dv = Max(1.0e0 - (defface/r),0.0e0) ;
-      Standard_Real oldDv = 2.0 * ACos (Dv);
-      oldDv = Min(oldDv, myAngle);
-      Dv  =  0.9*oldDv; //TWOTHIRD * oldDv;
-      Dv = oldDv;
-      
-      Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
-      Dv = (myvmax-myvmin)/(nbV+1);
-      
-      Standard_Real ru = R + r;
-      if (ru > 1.e-16) {
-        Du = Max(1.0e0 - (defface/ru),0.0e0);
-        Du  = (2.0 * ACos (Du));
-        Du = Min(Du, myAngle);
-        Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
-        if(aa < gp::Resolution())
-          return; 
-
-        Du = Du * Min(oldDv, Du) / aa;
+      // V loop
+      gFace->D0(myumin, myvmin, P11);
+      gFace->D0(dfuave, myvmin, P21);
+      gFace->D0(myumax, myvmin, P31);
+      for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv)
+      {
+        gFace->D0(myumin, dfvcur, P12);
+        gFace->D0(dfuave, dfvcur, P22);
+        gFace->D0(myumax, dfvcur, P32);
+        longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
+        P11 = P12;
+        P21 = P22;
+        P31 = P32;
       }
-      else Du = Dv;     
-  
-      Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
-      nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
+
+      longu /= 3.;
+      longv /= 3.;
+      // akm (bug OCC16) ^^^^^
+
+      if (longu <= 1.e-16 || longv <= 1.e-16)
+      {
+        //yes, it is seen!!
+        myAttribute->SetStatus(BRepMesh_Failure);
+        return myAttribute->GetStatus();
+      }
+
+
+      if (aSurfType == GeomAbs_Torus)
+      {
+        gp_Torus Tor = gFace->Torus();
+        Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
+        Standard_Real Du, Dv;//, pasu, pasv;
+
+        Dv = Max(1.0e0 - (defface/r),0.0e0) ;
+        Standard_Real oldDv = 2.0 * ACos (Dv);
+        oldDv = Min(oldDv, myAngle);
+        Dv  =  0.9*oldDv; //TWOTHIRD * oldDv;
+        Dv = oldDv;
+
+        Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
+        Dv = (myvmax-myvmin)/(nbV+1);
+
+        Standard_Real ru = R + r;
+        if ( ru > 1.e-16 )
+        {
+          Du = Max(1.0e0 - (defface/ru),0.0e0);
+          Du  = (2.0 * ACos (Du));
+          Du = Min(Du, myAngle);
+          Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
+
+          if (aa < gp::Resolution())
+            return myAttribute->GetStatus();
+
+          Du = Du * Min(oldDv, Du) / aa;
+        }
+        else
+        {
+          Du = Dv;
+        }
+
+        Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
+        nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
       
-      Du = (myumax-myumin)/(nbU+1);
-      //-- DeltaX and DeltaY are chosen so that to avoid "jumping" 
-      //-- of points on the grid
-      deltaX = Du;
-      deltaY = Dv;
-    }
-    else if (thetype == GeomAbs_Cylinder) {
-      /*Standard_Real aMax = Max(myumax,myvmax);
-      deltaX = 0.01;  //1./aMax; //0.01;
-      deltaY = 1.0;*/
-      gp_Cylinder Cyl = BS.Cylinder();
-      Standard_Real R = Cyl.Radius();
-      // Calculate parameters for iteration in U direction
-      Standard_Real Du = 1.0 - (defface/R);
-      if (Du < 0.0) Du = 0.0;
-      Du = 2.0 * ACos (Du);
-      if (Du > GetAngle()) Du = GetAngle();
-      deltaX = Du/longv;
-      deltaY = 1.;
-    }
-    else {
-      deltaX = (myumax-myumin)/longu;
-      deltaY = (myvmax-myvmin)/longv;
-    }    
+        Du = (myumax-myumin)/(nbU+1);
+        //-- DeltaX and DeltaY are chosen so that to avoid "jumping" 
+        //-- of points on the grid
+        deltaX = Du;
+        deltaY = Dv;
+      }
+      else if (aSurfType == GeomAbs_Cylinder)
+      {
+        gp_Cylinder Cyl = gFace->Cylinder();
+        Standard_Real R = Cyl.Radius();
 
-    if(!myMapattrib.IsBound(theface))
-    {
-      Handle(BRepMesh_FaceAttribute) aFA = new BRepMesh_FaceAttribute();
-      aFA->GetDefFace() = defface;
-      aFA->GetUMax() = myumax;
-      aFA->GetVMax() = myvmax;
-      aFA->GetUMin() = myumin;
-      aFA->GetVMin() = myvmin;
-      aFA->GetDeltaX() = deltaX;
-      aFA->GetDeltaY() = deltaY;
-      aFA->GetMinX() = minX;
-      aFA->GetMinY() = minY;
-      aFA->GetClassifier() = classifier;
-      myMapattrib.Bind(theface, aFA);
-    }
+        // Calculate parameters for iteration in U direction
+        Standard_Real Du = 1.0 - (defface/R);
+        if (Du < 0.0)
+          Du = 0.0;
 
-    //Standard_Integer nbVertices = myVemap.Extent();
-    T = new Poly_Triangulation(nbVertices, 1, Standard_True);
-    TColgp_Array1OfPnt&  Nodes = T->ChangeNodes();
-    TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes();
-    
-    Standard_Integer index;
-    for (i = 1; i <= nbVertices; i++) {
-      index = myVemap.FindKey(i);
-      Nodes(i) = Pnt(index);
-      Nodes2d(i).SetXY(Vertex(index).Coord());
-    }
-    BRepMesh_ShapeTool::AddInFace(face, T);
+        Du = 2.0 * ACos (Du);
+        if (Du > GetAngle())
+          Du = GetAngle();
 
-    BRepMeshCol::DMapOfShapePairOfPolygon::Iterator It(myInternaledges);
-    for (; It.More(); It.Next())
-    {
-      const TopoDS_Edge& aEdge = TopoDS::Edge(It.Key());
-      const BRepMesh_PairOfPolygon& pair = It.Value();
-      const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First();
-      const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last();
-      if ( NOD1 == NOD2 )
-        BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, T, loc);
+        deltaX = Du / longv;
+        deltaY = 1.;
+      }
       else
-        BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, NOD2, T, loc);
-    }
-  }
+      {
+        deltaX = (myumax-myumin)/longu;
+        deltaY = (myvmax-myvmin)/longv;
+      }
 
-#ifndef DEB_MESH
+      // Restore face attribute
+      myAttribute->SetDefFace(defface);
+      myAttribute->SetUMax(myumax);
+      myAttribute->SetVMax(myvmax);
+      myAttribute->SetUMin(myumin);
+      myAttribute->SetVMin(myvmin);
+      myAttribute->SetDeltaX(deltaX);
+      myAttribute->SetDeltaY(deltaY);
+    }
   }
   catch(Standard_Failure)
   {
-    MESH_FAILURE(theface);
+    myAttribute->SetStatus(BRepMesh_Failure);
   }
-#endif // DEB_MESH
-  myStructure.Nullify();
+
+  return myAttribute->GetStatus();
 }
 
 //=======================================================================
-//function : splitSegment
+//function : addLinkToMesh
 //purpose  :
 //=======================================================================
-static void splitSegment( BRepMesh_GeomTool&    theGT, 
-                          const Handle(Geom_Surface)& theSurf, 
-                          const Handle(Geom2d_Curve)& theCurve2d,
-                          const BRepAdaptor_Curve&    theBAC,
-                          const Standard_Real         theSquareEDef,
-                          const Standard_Real         theFirst,
-                          const Standard_Real         theLast,
-                          const Standard_Integer      theNbIter)
+void BRepMesh_FastDiscret::addLinkToMesh(
+  const Standard_Integer   theFirstNodeId,
+  const Standard_Integer   theLastNodeId,
+  const TopAbs_Orientation theOrientation)
 {
-  //limit ineration depth
-  if(theNbIter > 10)
-    return;
-  gp_Pnt2d uvf, uvl, uvm;
-  gp_Pnt   P3dF, P3dL, midP3d, midP3dFromSurf;
-  Standard_Real midpar;
-  
-  if(Abs(theLast - theFirst) < 2*Precision::PConfusion())
-    return;
-
-  theCurve2d->D0(theFirst, uvf);
-  theCurve2d->D0(theLast, uvl);
-
-  P3dF = theSurf->Value(uvf.X(), uvf.Y());
-  P3dL = theSurf->Value(uvl.X(), uvl.Y());
-  
-  if(P3dF.SquareDistance(P3dL) < theSquareEDef)
-    return;
-
-  uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5);
-  midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y());
-
-  gp_XYZ aVec = P3dL.XYZ()-P3dF.XYZ();
-  aVec.Normalize();
-
-  gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
-  Standard_Real aModulus = Vec1.Dot(aVec);
-  gp_XYZ aProj = aVec*aModulus;
-  gp_XYZ aDist = Vec1 - aProj;
-    
-  if(aDist.SquareModulus() < theSquareEDef)
-    return;
-
-  midpar = (theFirst + theLast) * 0.5;
-  theBAC.D0(midpar, midP3d);
-  theGT.AddPoint(midP3d, midpar, Standard_False);
-
-  splitSegment(theGT, theSurf, theCurve2d, theBAC, theSquareEDef, theFirst, midpar, theNbIter+1);
-  splitSegment(theGT, theSurf, theCurve2d, theBAC, theSquareEDef, midpar, theLast,  theNbIter+1); 
+  if (theOrientation == TopAbs_FORWARD)
+    myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier));
+  else if (theOrientation == TopAbs_REVERSED)
+    myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier));
+  else if (theOrientation == TopAbs_INTERNAL)
+    myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed));
 }
 
 //=======================================================================
-//function : Add
-//purpose  : 
+//function : getEdgeAttributes
+//purpose  :
 //=======================================================================
-void BRepMesh_FastDiscret::Add( const TopoDS_Edge&                  theEdge, 
-                                const TopoDS_Face&                  theFace, 
-                                const Handle(BRepAdaptor_HSurface)& theGFace,
-                                const Handle(Geom2d_Curve)&         theC2d,
-                                const TopTools_IndexedDataMapOfShapeListOfShape& theAncestors,
-                                const Standard_Real                 theDefEdge,
-                                const Standard_Real                 theFirst,
-                                const Standard_Real                 theLast)
+Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes(
+  const TopoDS_Edge&                      theEdge,
+  const BRepMesh_FastDiscret::EdgePCurve& thePCurve,
+  const Standard_Real                     theDefEdge,
+  BRepMesh_FastDiscret::EdgeAttributes&   theAttributes) const
 {
-  const TopAbs_Orientation orEdge = theEdge.Orientation();
-  if (orEdge == TopAbs_EXTERNAL) return;
-
-  const Standard_Boolean isEdgeBound = myEdges.IsBound(theEdge);
-
-  if (!isEdgeBound)
-  {
-    if (Update(theEdge, theFace, theC2d, theDefEdge, theFirst, theLast))
-    {
-      return;
-    }
-  }
-
-  TopoDS_Vertex pBegin, pEnd;
-  TopExp::Vertices(theEdge, pBegin, pEnd);
-  if (pBegin.IsNull() || pEnd.IsNull())
-  {
-    return;
-  }
-
-  Standard_Real wFirst, wLast;
-  BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
+  EdgeAttributes& aEAttr = theAttributes;
 
-  gp_Pnt2d uvFirst, uvLast;
-  BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
+  // Get vertices
+  TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex);
+  if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull())
+    return Standard_False;
 
-  const Standard_Boolean sameUV = uvFirst.IsEqual(uvLast, Precision::PConfusion());
+  // Get range on 2d curve
+  const TopoDS_Face& aFace = myAttribute->Face();
+  BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam);
 
-  //Control vertexes tolerances
-  gp_Pnt pFirst = theGFace->Value(uvFirst.X(), uvFirst.Y());
-  gp_Pnt pLast  = theGFace->Value(uvLast.X(), uvLast.Y());
+  // Get end points on 2d curve
+  BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV);
 
-  Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)), 
-                                    pLast.Distance(BRep_Tool::Pnt(pEnd)));
+  aEAttr.IsSameUV =
+    aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
 
-  if(mindist < BRep_Tool::Tolerance(pBegin) ||
-     mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
+  //Control tolerance of vertices
+  const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
+  gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
+  gp_Pnt pLast  = gFace->Value(aEAttr.LastUV.X(),  aEAttr.LastUV.Y());
 
-  // control of degenerated non-coded edges.
+  aEAttr.MinDist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(aEAttr.FirstVertex)),
+                             pLast .Distance(BRep_Tool::Pnt(aEAttr.LastVertex)));
 
-  Standard_Boolean degener = BRep_Tool::Degenerated(theEdge);
-
-  if (!degener)
+  if (aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.FirstVertex) ||
+      aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.LastVertex))
   {
-    if (pBegin.IsSame(pEnd))
-    {
-      // calculation of the length of the edge in 3D
-      Standard_Real longueur = 0.0;
-      Standard_Real du = (wLast-wFirst)/20;
-      gp_Pnt P1, P2;
-      BRepAdaptor_Curve BC(theEdge);
-      BC.D0(wFirst, P1);
-      Standard_Real tolV = BRep_Tool::Tolerance(pBegin);
-      Standard_Real tolV2 = 1.2*tolV;
-      for (Standard_Integer l = 1; l <= 20; l++) {
-        BC.D0(wFirst + l*du, P2);
-        longueur += P1.Distance(P2);
-        if (longueur > tolV2) break;
-        P1 = P2;
-      }
-
-      if (longueur < tolV2)
-      {
-        degener = Standard_True;
-      }
-    }
+    aEAttr.MinDist = theDefEdge;
   }
 
-  // Correct UV points
-  if (sameUV)
+  if (aEAttr.IsSameUV)
   {
     // 1. is it really sameUV without being degenerated
     gp_Pnt2d uvF, uvL;
-    theC2d->D0(theFirst, uvF);
-    theC2d->D0(theLast, uvL);
-    if (!uvFirst.IsEqual(uvF, Precision::PConfusion()))
-    {
-      uvFirst = uvF;
-    }
-    if (!uvLast.IsEqual(uvL, Precision::PConfusion()))
-    {
-      uvLast = uvL;
-    }
+    thePCurve.Curve2d->D0(thePCurve.FirstParam, uvF);
+    thePCurve.Curve2d->D0(thePCurve.LastParam,  uvL);
+
+    if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion()))
+      aEAttr.FirstUV = uvF;
+
+    if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion()))
+      aEAttr.LastUV = uvL;
   }
 
-  gp_XY theUV;
+  return Standard_True;
+}
 
-  // Process first vertex
-  Standard_Integer ipf;
-  if (myVertices.IsBound(pBegin))
+//=======================================================================
+//function : registerEdgeVertices
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscret::registerEdgeVertices(
+  BRepMesh_FastDiscret::EdgeAttributes& theAttributes,
+  Standard_Integer&                     ipf,
+  Standard_Integer&                     ivf,
+  Standard_Integer&                     isvf,
+  Standard_Integer&                     ipl,
+  Standard_Integer&                     ivl,
+  Standard_Integer&                     isvl)
+{
+  EdgeAttributes& aEAttr = theAttributes;
+  if (aEAttr.FirstVExtractor.IsNull())
   {
-    ipf = myVertices.Find(pBegin);
+    // Use edge geometry to produce tesselation.
+    aEAttr.FirstVExtractor = 
+      new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex);
   }
-  else
+
+  if (aEAttr.LastVExtractor.IsNull())
   {
-    if (sameUV && myVertices.IsBound(pEnd))
-    {
-      ipf = myVertices.Find(pEnd);
-    }
-    else
-    {
-      myNbLocat++;
-      ipf = myNbLocat;
-      myLocation3d.Bind(ipf, BRep_Tool::Pnt(pBegin));
-    }
-    myVertices.Bind(pBegin, ipf);
+    // Use edge geometry to produce tesselation.
+    aEAttr.LastVExtractor = 
+      new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex);
   }
 
-  Handle(BRepMesh_FaceAttribute) aFaceAttribute;
-  GetFaceAttribute ( theFace, aFaceAttribute );
-  theUV = BRepMesh_ShapeTool::FindUV(ipf, uvFirst, 
-    pBegin, mindist, aFaceAttribute, theGFace, myLocation2d);
+  gp_XY aTmpUV;
+  // Process first vertex
+  ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True);
+  aTmpUV = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aEAttr.FirstVertex, 
+    aEAttr.MinDist, myAttribute);
 
-  BRepMesh_Vertex vf(theUV, ipf, BRepMesh_Frontier);
-  Standard_Integer ivf = myStructure->AddNode(vf);
+  myAttribute->AddNode(ipf, aTmpUV, BRepMesh_Frontier, ivf, isvf);
 
   // Process last vertex
-  Standard_Integer ipl;
-  if (pEnd.IsSame(pBegin))
-  {
-    ipl = ipf;
-  }
-  else
+  ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf :
+    myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True);
+  aTmpUV = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aEAttr.LastVertex, 
+    aEAttr.MinDist, myAttribute);
+
+  myAttribute->AddNode(ipl, aTmpUV, BRepMesh_Frontier, ivl, isvl);
+}
+
+//=======================================================================
+//function : add
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscret::add(
+  const TopoDS_Edge&                      theEdge,
+  const BRepMesh_FastDiscret::EdgePCurve& thePCurve,
+  const Standard_Real                     theDefEdge)
+{
+  const TopAbs_Orientation orEdge = theEdge.Orientation();
+  if (orEdge == TopAbs_EXTERNAL)
+    return;
+
+  EdgeAttributes aEAttr;
+  if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr))
+    return;
+
+  if (!myEdges.IsBound(theEdge))
   {
-    if (myVertices.IsBound(pEnd))
-    {
-      ipl = myVertices.Find(pEnd);
-    }
-    else
-    {
-      if (sameUV)
-      {
-        ipl = ipf;
-      }
-      else
-      {
-        myNbLocat++;
-        ipl = myNbLocat;
-        myLocation3d.Bind(ipl, BRep_Tool::Pnt(pEnd));
-      }
-      myVertices.Bind(pEnd,ipl);
-    }
+    update(theEdge, thePCurve.Curve2d, theDefEdge, aEAttr);
+    return;
   }
 
-  theUV = BRepMesh_ShapeTool::FindUV(ipl, uvLast,
-    pEnd, mindist, aFaceAttribute, theGFace, myLocation2d);
+  Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
+  registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
 
-  BRepMesh_Vertex vl(theUV, ipl, BRepMesh_Frontier);
-  Standard_Integer ivl= myStructure->AddNode(vl);
+  // If this Edge has been already checked and it is not degenerated, 
+  // the points of the polygon calculated at the first check are retrieved :
 
-  Standard_Integer isvf = myVemap.FindIndex(ivf);
-  if (isvf == 0) isvf = myVemap.Add(ivf);
-  Standard_Integer isvl = myVemap.FindIndex(ivl);
-  if (isvl == 0) isvl = myVemap.Add(ivl);
-  
-  Standard_Real otherdefedge = 0.5*theDefEdge;
-  gp_Pnt2d uv;
-  BRepMesh_Vertex v2;
-  gp_Pnt   P3d;
+  // retrieve the polygone:
+  const BRepMesh_PairOfPolygon&              aPair    = myEdges.Find(theEdge);
+  const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
+  const TColStd_Array1OfInteger&             aNodes   = aPolygon->Nodes();
+  Handle(TColStd_HArray1OfReal)              aParams  = aPolygon->Parameters();
 
-  Handle(Poly_PolygonOnTriangulation) P1;
+  // creation anew:
+  const Standard_Integer  aNodesNb = aNodes.Length();
+  TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
+  TColStd_Array1OfReal    aNewParams(1, aNodesNb);
 
-  if (!isEdgeBound)
-  {
-    Handle(Poly_PolygonOnTriangulation) P2;
+  aNewNodes (1) = isvf;
+  aNewParams(1) = aEAttr.FirstParam;
 
-    if (degener)
-    {
-      // creation anew:
-      TColStd_Array1OfInteger Nodes(1, 2), NodInStruct(1, 2);
-      TColStd_Array1OfReal Param(1, 2);
-      
-      NodInStruct(1) = ipf;
-      Nodes(1) = isvf;
-      Param(1) = wFirst;
-      
-      NodInStruct(2) = ipl;
-      Nodes(2) = isvl;
-      Param(2) = wLast;
+  aNewNodes (aNodesNb) = isvl;
+  aNewParams(aNodesNb) = aEAttr.LastParam;
 
-      P1 = new Poly_PolygonOnTriangulation(Nodes, Param);
-      P2 = new Poly_PolygonOnTriangulation(NodInStruct, Param);
-    }
-    else
+  const TopoDS_Face& aFace = myAttribute->Face();
+  if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
+  {
+    BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams);
+    for (Standard_Integer i = 2; i < aNodesNb; ++i)
     {
-      if (orEdge == TopAbs_INTERNAL) otherdefedge *= 0.5;
-      
-      BRepAdaptor_Curve cons;
-      Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
-      if (isSameParam)
-      {
-        cons.Initialize(theEdge);
-      }
-      else
-      {
-        cons.Initialize(theEdge, theFace);
-      }
+      const Standard_Integer aPointId = aNodes(i);
+      gp_Pnt& aPnt = myBoundaryPoints(aPointId);
 
-      TopLoc_Location L;
-      Standard_Integer nbpmin = 2;
-      const GeomAbs_CurveType aCurveType = cons.GetType();
-      if ( aCurveType == GeomAbs_Circle )
-        nbpmin = 4; //OCC287
+      const Standard_Real aParam = aProvider.Parameter(i, aPnt);
+      gp_Pnt2d aUV = thePCurve.Curve2d->Value(aParam);
 
-      BRepMesh_GeomTool GT(cons, wFirst, wLast, otherdefedge, 0.5 * myAngle, nbpmin);
+      Standard_Integer iv2, isv;
+      myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv);
 
-      if ( aCurveType == GeomAbs_BSplineCurve )
-      {
-        const Standard_Integer aNbInt = cons.NbIntervals( GeomAbs_C1 );
-        if ( aNbInt > 0 )
-        {
-          TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 );
-          cons.Intervals( anIntervals, GeomAbs_C1 );
-          for ( Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt )
-          {
-            const Standard_Real& aStartInt = anIntervals.Value( aIntIt );
-            const Standard_Real& anEndInt  = anIntervals.Value( aIntIt + 1 );
+      aNewNodes (i) = isv;
+      aNewParams(i) = aParam;
 
-            BRepMesh_GeomTool aDetalizator( cons, aStartInt, anEndInt,
-              otherdefedge, 0.5 * myAngle, nbpmin );
+      addLinkToMesh(ivf, iv2, orEdge);
+      ivf = iv2;
+    }
 
-            Standard_Integer aNbAddNodes = aDetalizator.NbPoints();
-            for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt )
-            {
-              Standard_Real aParam;
-              gp_Pnt        aPoint3d;
-              gp_Pnt2d      aPoint2d;
-              aDetalizator.Value( aNodeIt, theGFace, aParam, aPoint3d, aPoint2d );
-              GT.AddPoint( aPoint3d, aParam, Standard_False );
-            }
-          }
-        }
-      }
+    // last point
+    if (ivf != ivl)
+      addLinkToMesh(ivf, ivl, orEdge);
+  }
 
-      // PTv, chl/922/G9, Take into account internal vertices
-      // it is necessary for internal edges, which do not split other edges, by their vertex
-      TopoDS_Iterator exV(theEdge);
-      for ( ; exV.More(); exV.Next() )
-      {
-        TopoDS_Vertex aIntV = TopoDS::Vertex(exV.Value());
-        if ( aIntV.Orientation() == TopAbs_INTERNAL )
-         GT.AddPoint(BRep_Tool::Pnt(aIntV),
-                     BRep_Tool::Parameter(aIntV, theEdge),
-                     Standard_True);
-      }
+  Handle(Poly_PolygonOnTriangulation) P1 = 
+    new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
 
-      Standard_Integer i; 
-      Standard_Integer nbnodes = GT.NbPoints();
-      //Check deflection in 2d space for improvement of edge tesselation.
-      if( isSameParam && nbnodes > 1)
-      {
-        Standard_Real aSquareEdgeDef = otherdefedge * otherdefedge;
-        const TopTools_ListOfShape& lf = theAncestors.FindFromKey(theEdge);
-        TopTools_ListIteratorOfListOfShape itl(lf);
-        for (; itl.More(); itl.Next()) {
-          const TopoDS_Face& aFace = TopoDS::Face (itl.Value());          
-
-          TopLoc_Location aLoc;
-          Standard_Real aF, aL;
-          Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
-          const Handle(Standard_Type)& aType = aSurf->DynamicType();
-          if(aType == STANDARD_TYPE(Geom_Plane))
-            continue;
-          Handle(Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL);
-          if(Abs(aF-wFirst)>Precision::PConfusion()||Abs(aL-wLast)>Precision::PConfusion())
-            continue;
-          
-          gp_Pnt2d uvf;
-          Standard_Real parf;
-          nbnodes = GT.NbPoints();
-          TColStd_Array1OfReal aParamArray(1, nbnodes);
-          for (i = 1; i <= nbnodes; i++)
-          {          
-            GT.Value(i, theGFace, parf, P3d, uvf);            
-            aParamArray.SetValue(i, parf);
-          }
-          for (i = 1; i < nbnodes; i++)
-          {
-            splitSegment(GT, aSurf, aCurve2d, cons, aSquareEdgeDef, aParamArray(i), aParamArray(i+1), 1);
-          }
-        }
-      }
+  storePolygon(theEdge, P1, theDefEdge);
+}
 
-      // Creation of polygons on triangulation:
-      Standard_Real puv;
-      nbnodes = GT.NbPoints();
+//=======================================================================
+//function : update(edge)
+//purpose  :
+//=======================================================================
+void BRepMesh_FastDiscret::update(
+  const TopoDS_Edge&                                theEdge,
+  const Handle(Geom2d_Curve)&                       theC2d,
+  const Standard_Real                               theDefEdge,
+  BRepMesh_FastDiscret::EdgeAttributes&             theAttributes)
+{
+  EdgeAttributes& aEAttr = theAttributes;
 
-      TColStd_Array1OfInteger Nodes(1, nbnodes);
-      TColStd_Array1OfInteger NodInStruct(1, nbnodes);
-      TColStd_Array1OfReal Param(1, nbnodes);
-      
-      // processing of the 1st point:
-      Nodes(1) = isvf;
-      NodInStruct(1) = ipf;
-      Param(1) = wFirst;
-      
-      // last point:
-      Nodes(nbnodes) = isvl;
-      NodInStruct(nbnodes) = ipl;
-      Param(nbnodes) = wLast;
+  const TopoDS_Face& aFace = myAttribute->Face();
+  Handle(BRepMesh_IEdgeTool) aEdgeTool;
+  // Try to find existing tessellation.
+  for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i)
+  {
+    TopLoc_Location aLoc;
+    Handle(Poly_Triangulation) aTriangulation;
+    Handle(Poly_PolygonOnTriangulation) aPolygon;
+    BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i);
 
-      if(nbnodes > 2)
-      {
-        Standard_Integer iv2;
-        for (i = 2; i < GT.NbPoints(); i++)
-        {
-          // Record 3d point
-          GT.Value(i, theGFace, puv, P3d, uv);
-          myNbLocat++;
-          myLocation3d.Bind(myNbLocat, P3d);
-          NodInStruct(i) = myNbLocat;
-          // Record 2d point
-          v2.Initialize(uv.Coord(), myNbLocat, BRepMesh_OnCurve);
-          iv2=myStructure->AddNode(v2);
-          
-          Standard_Integer isv = myVemap.FindIndex(iv2);
-          if (isv == 0) isv = myVemap.Add(iv2);
-          Nodes(i) = isv;
-          NodInStruct(i) = myNbLocat;
-          Param(i) = puv;
-    
-          if (orEdge == TopAbs_FORWARD)
-            myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier));
-          else if (orEdge == TopAbs_REVERSED)
-            myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier));
-          else if (orEdge == TopAbs_INTERNAL)
-            myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed));
-          ivf = iv2;
-        }
-      }
+    if (aPolygon.IsNull())
+      break;
 
-      P1 = new Poly_PolygonOnTriangulation(Nodes, Param);
-      P2 = new Poly_PolygonOnTriangulation(NodInStruct, Param);
-    }
+    if (aTriangulation.IsNull() || !aPolygon->HasParameters())
+      continue;
 
-    P2->Deflection(otherdefedge);
-    BRepMesh_PairOfPolygon pair;
-    pair.Append(P2);
-    myEdges.Bind(theEdge, pair);
-
-    if (ivf != ivl) {
-      if (orEdge == TopAbs_FORWARD)
-        myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Frontier));
-      else if (orEdge == TopAbs_REVERSED)
-        myStructure->AddLink(BRepMesh_Edge(ivl, ivf, BRepMesh_Frontier));
-      else if (orEdge == TopAbs_INTERNAL)
-        myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Fixed));
-    }
-      
+    if (aPolygon->Deflection() > 1.1 * theDefEdge)
+      continue;
 
-  }
-  // If this Edge has been already checked and it is not degenerated, 
-  // the points of the polygon calculated at the first check are retrieved :
-  else
-  {
-    if (degener)
-    {
-      // Create 2d polygon for degenerated edge
-      TColStd_Array1OfInteger Nodes(1, 2);
-      TColStd_Array1OfReal PPar(1, 2);
-      
-      Nodes(1) = isvf;
-      PPar(1) = wFirst;
-      
-      Nodes(2) = isvl;
-      PPar(2) = wLast;
-      
-      P1 = new Poly_PolygonOnTriangulation(Nodes, PPar);
-    }
-    else
-    {
-      // retrieve the polygone:
-      const BRepMesh_PairOfPolygon& pair = myEdges.Find(theEdge);
-      const Handle(Poly_PolygonOnTriangulation)& P = pair.First();
-      const TColStd_Array1OfInteger& NOD = P->Nodes();
-      Handle(TColStd_HArray1OfReal) Par = P->Parameters();
-
-      // creation anew:
-      const Standard_Integer nbnodes = NOD.Length();
-      TColStd_Array1OfInteger Nodes(1, nbnodes);
-      TColStd_Array1OfReal PPar(1, nbnodes);
-      Standard_Integer iv2;
-      
-      Nodes(1) = isvf;
-      PPar(1) = wFirst;
-      
-      Nodes(nbnodes) = isvl;
-      PPar(nbnodes) = wLast;
-      
-      if (nbnodes > 2)
-      {
-        Standard_Integer i;
-        if (BRep_Tool::SameParameter(theEdge))
-        {
-          for (i = 2; i < nbnodes; i++)
-          {
-            const Standard_Real puv = Par->Value(i);
-            theC2d->D0(puv, uv);
-            v2.Initialize(uv.Coord(), NOD(i), BRepMesh_OnCurve);
-            iv2 = myStructure->AddNode(v2);
-  
-            Standard_Integer isv = myVemap.FindIndex(iv2);
-            if (isv == 0) isv = myVemap.Add(iv2);
-            Nodes(i) = isv;
-            PPar(i) = puv;
-            
-            if (orEdge==TopAbs_FORWARD)
-              myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier));
-            else if (orEdge == TopAbs_REVERSED)
-              myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier));
-            else if (orEdge == TopAbs_INTERNAL)
-              myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed));
-    
-            ivf = iv2;
-          }
-        }
-        else
-        {
-          const Standard_Real wFold = Par->Value(Par->Lower());
-          const Standard_Real wLold = Par->Value(Par->Upper());
+    const TColgp_Array1OfPnt&      aNodes   = aTriangulation->Nodes();
+    const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes();
+    Handle(TColStd_HArray1OfReal)  aParams  = aPolygon->Parameters();
 
-          Standard_Real wKoef = 1.;
-          if ((wFold != wFirst || wLold != wLast) && wLold != wFold)
-          {
-            wKoef = (wLast - wFirst) / (wLold - wFold);
-          }
-          
-          BRepAdaptor_Curve cons(theEdge, theFace);
-          Extrema_LocateExtPC pcos;
-          pcos.Initialize(cons, cons.FirstParameter(), 
-              cons.LastParameter(), Precision::PConfusion());
-
-          Standard_Real wPrev;
-          Standard_Real wCur      = wFirst;
-          Standard_Real wCurFound = wFirst;
-          for (i = 2; i < nbnodes; i++)
-          {
-            P3d = myLocation3d(NOD(i));
-            // Record 2d point
-            wPrev = wCur;
-            wCur  = wFirst + wKoef*(Par->Value(i) - wFold);
-                  wCurFound += (wCur - wPrev);
-            pcos.Perform(P3d, wCurFound);
-            if (pcos.IsDone()) wCurFound = pcos.Point().Parameter();
-            theC2d->D0(wCurFound, uv);
-            v2.Initialize(uv.Coord(), NOD(i), BRepMesh_OnCurve);
-            iv2 = myStructure->AddNode(v2);
-                  
-            Standard_Integer isv = myVemap.FindIndex(iv2);
-            if (isv == 0) isv = myVemap.Add(iv2); 
-                  Nodes(i) = isv;
-            PPar(i) = wCurFound;
-                  
-            if (orEdge==TopAbs_FORWARD)
-              myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier));
-            else if (orEdge == TopAbs_REVERSED)
-              myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier));
-            else if (orEdge == TopAbs_INTERNAL)
-              myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed));
-    
-            ivf = iv2;
-          }
-        }
-      }
+    aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex, 
+      aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc);
 
-    P1 = new Poly_PolygonOnTriangulation(Nodes, PPar);
-    
-    if (ivf != ivl) {
-      if (orEdge == TopAbs_FORWARD) 
-        myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Frontier));
-      else if (orEdge == TopAbs_REVERSED)
-        myStructure->AddLink(BRepMesh_Edge(ivl, ivf, BRepMesh_Frontier));
-      else if (orEdge == TopAbs_INTERNAL)
-        myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Fixed));
-      }
-    }
-  }
+    aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex, 
+      aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc);
 
-  P1->Deflection(theDefEdge);
-  if (myInternaledges.IsBound(theEdge))
-  {
-    BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
-    if (orEdge == TopAbs_REVERSED)
-      pair.Append(P1);
-    else
-      pair.Prepend(P1);
+    aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d, 
+      aFace, aTriangulation, aPolygon, aLoc);
   }
-  else
+
+  if (aEdgeTool.IsNull())
   {
-    BRepMesh_PairOfPolygon pair1;
-    pair1.Append(P1);
-    myInternaledges.Bind(theEdge, pair1);
+    aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute, 
+      mySharedFaces, theDefEdge, myAngle);
   }
-}
 
+  Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
+  registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
 
-//=======================================================================
-//function : Update(edge)
-//purpose  :
-//=======================================================================
-Standard_Boolean BRepMesh_FastDiscret::Update(const TopoDS_Edge&          theEdge,
-                                              const TopoDS_Face&          theFace,
-                                              const Handle(Geom2d_Curve)& theC2d,
-                                              const Standard_Real         theDefEdge,
-                                              const Standard_Real         theFirst,
-                                              const Standard_Real         theLast)
-{
-  TopLoc_Location Loc;
-  Handle(Poly_Triangulation) T;
-  Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
-
-  Standard_Integer i = 1;
-  Standard_Boolean found = Standard_False;
-  do
+  TopAbs_Orientation orEdge = theEdge.Orientation();
+  Handle(Poly_PolygonOnTriangulation) P1, P2;
+  if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
   {
-    BRep_Tool::PolygonOnTriangulation(theEdge,Poly,T,Loc,i);
-    i++;
-    if (!found && !T.IsNull() && T->HasUVNodes() && 
-        !Poly.IsNull() && Poly->HasParameters())
-    {
-      if (Poly->Deflection() <= 1.1*theDefEdge)
-      {
-        // 2d vertex indices
-        TopAbs_Orientation orEdge = theEdge.Orientation();
-        Standard_Integer iv1, iv2, ivl;
-        Standard_Integer isv1, isv, isvl;
-        
-        // Get range on 2d curve
-        Standard_Real wFirst, wLast;
-        BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
-        
-        // Get end points on 2d curve
-        gp_Pnt2d uvFirst, uvLast;
-        BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
-
-        // Get vertices
-        TopoDS_Vertex pBegin, pEnd;
-        TopExp::Vertices(theEdge,pBegin,pEnd);
-        
-        const Standard_Boolean sameUV =
-          uvFirst.IsEqual(uvLast, Precision::PConfusion());
-        
-        //Controle vertice tolerances
-        BRepAdaptor_Surface  BS(theFace, Standard_False);
-        Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
-        
-
-        gp_Pnt pFirst = gFace->Value(uvFirst.X(), uvFirst.Y());
-        gp_Pnt pLast  = gFace->Value(uvLast.X(), uvLast.Y());
-        
-        Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)), 
-                                          pLast.Distance(BRep_Tool::Pnt(pEnd)));
-
-        if (mindist < BRep_Tool::Tolerance(pBegin) ||
-            mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
-        
-        if (sameUV)
-        {
-          // 1. is it really sameUV without being degenerated
-          gp_Pnt2d uvF, uvL;
-          theC2d->D0(theFirst, uvF);
-          theC2d->D0(theLast, uvL);
-          if (!uvFirst.IsEqual(uvF, Precision::PConfusion())) {
-            uvFirst = uvF;
-          }
-          if (!uvLast.IsEqual(uvL, Precision::PConfusion())) {
-            uvLast = uvL; 
-          }
-        }
+    const Standard_Integer  aNodesNb = 2;
+    TColStd_Array1OfInteger aNewNodes      (1, aNodesNb);
+    TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
+    TColStd_Array1OfReal    aNewParams     (1, aNodesNb);
 
-        const TColgp_Array1OfPnt&      Nodes   = T->Nodes();
-        const TColStd_Array1OfInteger& Indices = Poly->Nodes();
-        Handle(TColStd_HArray1OfReal)  Param   = Poly->Parameters();
-        
-        const Standard_Integer nbnodes = Indices.Length();
-        TColStd_Array1OfInteger NewNodes(1, nbnodes);
-        TColStd_Array1OfInteger NewNodInStruct(1, nbnodes);
-        
-        gp_Pnt P3d;
-        gp_XY theUV;
-        
-        // Process first vertex
-        Standard_Integer ipf;
-        if (myVertices.IsBound(pBegin))
-        {
-          ipf = myVertices.Find(pBegin);
-        }
-        else
-        {
-          if (sameUV && myVertices.IsBound(pEnd))
-          {
-              ipf = myVertices.Find(pEnd);
-          }
-          else
-          {
-            P3d = Nodes(Indices(1));
-            if (!Loc.IsIdentity())
-              P3d.Transform(Loc.Transformation());
-            myNbLocat++;
-            myLocation3d.Bind(myNbLocat,P3d);
-            ipf = myNbLocat;
-          }
-          myVertices.Bind(pBegin,ipf);
-        }
-        NewNodInStruct(1) = ipf;
-
-        Handle(BRepMesh_FaceAttribute) aFaceAttribute;
-        GetFaceAttribute ( theFace, aFaceAttribute );
-        theUV = BRepMesh_ShapeTool::FindUV(ipf, uvFirst,
-          pBegin, mindist, aFaceAttribute, gFace, myLocation2d);
-
-        BRepMesh_Vertex vf(theUV,ipf,BRepMesh_Frontier);
-        iv1 = myStructure->AddNode(vf);
-        isv1 = myVemap.FindIndex(iv1);
-        if (isv1 == 0) isv1 = myVemap.Add(iv1);
-        NewNodes(1) = isv1;
-        
-        // Process last vertex
-        Standard_Integer ipl;
-        if (pEnd.IsSame(pBegin))
-        {
-          ipl = ipf;
-        }
-        else
-        {
-          if (myVertices.IsBound(pEnd))
-          {
-            ipl = myVertices.Find(pEnd);
-          }
-          else
-          {
-            if (sameUV)
-            {
-              ipl = ipf;
-              ivl = iv1;
-            }
-            else
-            {
-              myNbLocat++;
-              myLocation3d.Bind(myNbLocat,Nodes(Indices(nbnodes)).Transformed(Loc.Transformation()));
-              ipl = myNbLocat;
-            }
-            myVertices.Bind(pEnd,ipl);
-          }
-        }
-        NewNodInStruct(nbnodes) = ipl;
-        theUV = BRepMesh_ShapeTool::FindUV(ipl, uvLast,
-          pEnd, mindist, aFaceAttribute, gFace, myLocation2d);
-
-        BRepMesh_Vertex vl(theUV,ipl,BRepMesh_Frontier);
-        
-        ivl = myStructure->AddNode(vl);
-        isvl = myVemap.FindIndex(ivl);
-        if (isvl == 0) isvl = myVemap.Add(ivl);
-        
-        NewNodes(nbnodes) = isvl;
-  
-        gp_Pnt2d uv;
-        BRepMesh_Vertex v;
-  
-        if (BRep_Tool::SameParameter(theEdge))
-        {
-          for (i = 2; i < Indices.Length(); i++)
-          {
-            // Record 3d point
-            P3d = Nodes(Indices(i));
-            if (!Loc.IsIdentity())
-              P3d.Transform(Loc.Transformation());
-            myNbLocat++;
-            myLocation3d.Bind(myNbLocat, P3d);
-            NewNodInStruct(i) = myNbLocat;
-            // Record 2d point
-            uv = theC2d->Value(Param->Value(i));
-            v.Initialize(uv.Coord(), myNbLocat, BRepMesh_Frontier);
-            iv2 = myStructure->AddNode(v);
-            isv = myVemap.FindIndex(iv2);
-            if (isv == 0) isv = myVemap.Add(iv2);
-            NewNodes(i) = isv;
-            
-            //add links
-            if (orEdge == TopAbs_FORWARD)
-              myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_REVERSED)
-              myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_INTERNAL)
-              myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
-            iv1 = iv2;  
-          }
-          
-          // last point
-          if (iv1 != ivl) {
-            if (orEdge == TopAbs_FORWARD)
-              myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_REVERSED)
-              myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_INTERNAL)
-              myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
-          }
-          
-          
-        }
-        else
-        {
-          const Standard_Real wFold = Param->Value(Param->Lower());
-          const Standard_Real wLold = Param->Value(Param->Upper());
-          
-          Standard_Real wKoef = 1.;
-          if ((wFold != wFirst || wLold != wLast) && wLold != wFold)
-          {
-            wKoef = (wLast - wFirst) / (wLold - wFold);
-          }
-    
-          BRepAdaptor_Curve cons(theEdge, theFace);
-          Extrema_LocateExtPC pcos;
-          pcos.Initialize(cons, cons.FirstParameter(), 
-                          cons.LastParameter(), Precision::PConfusion());
-          
-          Standard_Real wPrev;
-          Standard_Real wCur      = wFirst;
-          Standard_Real wCurFound = wFirst;
-          for (i = 2; i < Indices.Length(); i++)
-          {
-            // Record 3d point
-            P3d = Nodes(Indices(i));
-            if (!Loc.IsIdentity())
-              P3d.Transform(Loc.Transformation());
-            myNbLocat++;
-            myLocation3d.Bind(myNbLocat, P3d);
-            NewNodInStruct(i) = myNbLocat;
-            // Record 2d point
-            wPrev = wCur;
-            wCur  = wFirst + wKoef*(Param->Value(i) - wFold);
-            wCurFound += (wCur - wPrev);
-            pcos.Perform(P3d, wCurFound);
-            if (pcos.IsDone()) wCurFound = pcos.Point().Parameter();
-            theC2d->D0(wCurFound, uv);
-            v.Initialize(uv.Coord(), myNbLocat, BRepMesh_Frontier);
-            iv2 = myStructure->AddNode(v);
-            isv = myVemap.FindIndex(iv2);
-            if (isv == 0) isv = myVemap.Add(iv2);
-            NewNodes(i) = isv;
+    aNewNodInStruct(1) = ipf;
+    aNewNodes      (1) = isvf;
+    aNewParams     (1) = aEAttr.FirstParam;
 
-            
-            //add links
-            if (orEdge == TopAbs_FORWARD)
-              myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_REVERSED)
-              myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_INTERNAL)
-              myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
-            iv1 = iv2;              
-          }
-          
-          // last point
-          if (iv1 != ivl) {
-            if (orEdge == TopAbs_FORWARD)
-              myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_REVERSED)
-              myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
-            else if (orEdge == TopAbs_INTERNAL)
-              myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
-          }
-        }
-        
-        Handle(Poly_PolygonOnTriangulation) P1 =
-          new Poly_PolygonOnTriangulation(NewNodes, Param->Array1());
-        P1->Deflection(theDefEdge);
-        if (myInternaledges.IsBound(theEdge))
-        {
-          BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
-          if (theEdge.Orientation() == TopAbs_REVERSED)
-            pair.Append(P1);
-          else
-            pair.Prepend(P1);
-        }
-        else
-        {
-          BRepMesh_PairOfPolygon pair1;
-          pair1.Append(P1);
-          myInternaledges.Bind(theEdge, pair1);
-        }
-        
-        Handle(Poly_PolygonOnTriangulation) P2 =
-          new Poly_PolygonOnTriangulation(NewNodInStruct, Param->Array1());
-        P2->Deflection(theDefEdge);
-        BRepMesh_PairOfPolygon pair;
-        pair.Append(P2);
-        myEdges.Bind(theEdge, pair);
-        
-        found = Standard_True;
-      }
-      else
-      {
-        BRepMesh_ShapeTool::NullifyEdge(theEdge, T, Loc);
-        BRepMesh_ShapeTool::NullifyFace(theFace);
-      }
-    }
-    else if (!T.IsNull() && !T->HasUVNodes())
-    {
-      BRepMesh_ShapeTool::NullifyEdge(theEdge, T, Loc);
-      BRepMesh_ShapeTool::NullifyFace(theFace);
-    }
-  }
-  while (!Poly.IsNull());
+    aNewNodInStruct(aNodesNb) = ipl;
+    aNewNodes      (aNodesNb) = isvl;
+    aNewParams     (aNodesNb) = aEAttr.LastParam;
 
-  return found;
-}
+    P1 = new Poly_PolygonOnTriangulation(aNewNodes,       aNewParams);
+    P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
+  }
+  else
+  {
+    const Standard_Integer  aNodesNb = aEdgeTool->NbPoints();
+    TColStd_Array1OfInteger aNewNodes      (1, aNodesNb);
+    TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
+    TColStd_Array1OfReal    aNewParams     (1, aNodesNb);
 
-//=======================================================================
-//function : output
-//purpose  : 
-//=======================================================================
-Standard_Integer BRepMesh_FastDiscret::NbTriangles() const
-{
-  return myStructure->NbElements();
-}
+    aNewNodInStruct(1) = ipf;
+    aNewNodes      (1) = isvf;
+    aNewParams     (1) = aEAttr.FirstParam;
 
-//=======================================================================
-//function : Triangle
-//purpose  : 
-//=======================================================================
+    aNewNodInStruct(aNodesNb) = ipl;
+    aNewNodes      (aNodesNb) = isvl;
+    aNewParams     (aNodesNb) = aEAttr.LastParam;
 
-const BRepMesh_Triangle& BRepMesh_FastDiscret::Triangle
-  (const Standard_Integer Index) const
-{
-  return myStructure->GetElement(Index);
-}
+    Standard_Integer aLastPointId = myAttribute->LastPointId();
+    for (Standard_Integer i = 2; i < aNodesNb; ++i)
+    {
+      gp_Pnt        aPnt;
+      gp_Pnt2d      aUV;
+      Standard_Real aParam;
+      aEdgeTool->Value(i, aParam, aPnt, aUV);
+      myBoundaryPoints.Bind(++aLastPointId, aPnt);
 
-//=======================================================================
-//function : NbEdges
-//purpose  : 
-//=======================================================================
+      Standard_Integer iv2, isv;
+      myAttribute->AddNode(aLastPointId, aUV.Coord(), BRepMesh_Frontier, iv2, isv);
 
-Standard_Integer BRepMesh_FastDiscret::NbEdges() const
-{
-  return myStructure->NbLinks();
-}
+      aNewNodInStruct(i) = aLastPointId;
+      aNewNodes      (i) = isv;
+      aNewParams     (i) = aParam;
 
-//=======================================================================
-//function : Edge
-//purpose  : 
-//=======================================================================
+      addLinkToMesh(ivf, iv2, orEdge);
+      ivf = iv2;
+    }
 
-const BRepMesh_Edge& BRepMesh_FastDiscret::Edge(const Standard_Integer Index) const
-{
-  return myStructure->GetLink(Index);
-}
+    P1 = new Poly_PolygonOnTriangulation(aNewNodes,       aNewParams);
+    P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
+  }
 
-//=======================================================================
-//function : NbVertices
-//purpose  : 
-//=======================================================================
+  // last point
+  if (ivf != ivl)
+    addLinkToMesh(ivf, ivl, orEdge);
 
-Standard_Integer BRepMesh_FastDiscret::NbVertices() const
-{
-  return myStructure->NbNodes();
+  storePolygon(theEdge, P1, theDefEdge);
+  storePolygonSharedData(theEdge, P2, theDefEdge);
 }
 
 //=======================================================================
-//function : Vertex
+//function : storeInternalPolygon
 //purpose  : 
 //=======================================================================
-
-const BRepMesh_Vertex& BRepMesh_FastDiscret::Vertex
-  (const Standard_Integer Index) const
+void BRepMesh_FastDiscret::storePolygon(
+  const TopoDS_Edge&                         theEdge,
+  Handle(Poly_PolygonOnTriangulation)&       thePolygon,
+  const Standard_Real                        theDeflection)
 {
-  return myStructure->GetNode(Index);
-}
+  thePolygon->Deflection(theDeflection);
+  if (myInternalEdges->IsBound(theEdge))
+  {
+    BRepMesh_PairOfPolygon& aPair = myInternalEdges->ChangeFind(theEdge);
+    if (theEdge.Orientation() == TopAbs_REVERSED)
+      aPair.Append(thePolygon);
+    else
+      aPair.Prepend(thePolygon);
 
-//=======================================================================
-//function : Pnt
-//purpose  : 
-//=======================================================================
+    return;
+  }
 
-const gp_Pnt& BRepMesh_FastDiscret::Pnt(const Standard_Integer Index) const
-{
-  return myLocation3d(myStructure->GetNode(Index).Location3d());
+  BRepMesh_PairOfPolygon aPair;
+  aPair.Append(thePolygon);
+  myInternalEdges->Bind(theEdge, aPair);
 }
 
 //=======================================================================
-//function : VerticesOfDomain
+//function : storePolygonSharedData
 //purpose  : 
 //=======================================================================
-
-void BRepMesh_FastDiscret::VerticesOfDomain(BRepMeshCol::MapOfInteger&  Indices) const 
-{ 
-  Indices.Clear();
-  
-  // recuperate from the map of edges.
-  const BRepMeshCol::MapOfInteger& edmap = myStructure->LinksOfDomain();
-
-  // iterator on edges.
-  BRepMeshCol::MapOfInteger::Iterator iter(edmap);
-  
-  Standard_Integer ind_edge;
-  for (iter.Reset(); iter.More(); iter.Next()) {
-    ind_edge = iter.Key();
-    const BRepMesh_Edge& Ed = Edge(ind_edge);
-    Indices.Add(Ed.FirstNode());
-    Indices.Add(Ed.LastNode());
-  }
-}
-
-BRepMesh_Status BRepMesh_FastDiscret::CurrentFaceStatus() const
+void BRepMesh_FastDiscret::storePolygonSharedData(
+  const TopoDS_Edge&                         theEdge,
+  Handle(Poly_PolygonOnTriangulation)&       thePolygon,
+  const Standard_Real                        theDeflection)
 {
-  return myFacestate;
+  thePolygon->Deflection(theDeflection);
+  BRepMesh_PairOfPolygon aPair;
+  aPair.Append(thePolygon);
+  myEdges.Bind(theEdge, aPair);
 }
 
 //=======================================================================
 //function : GetFaceAttribute
 //purpose  : 
 //=======================================================================
-
-Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(const TopoDS_Face&              theFace,
-                                                        Handle(BRepMesh_FaceAttribute)& theFattrib) const
+Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(
+  const TopoDS_Face&              theFace,
+  Handle(BRepMesh_FaceAttribute)& theAttribute ) const
 {
-  if(myMapattrib.IsBound(theFace))
+  if (myAttributes.IsBound(theFace))
   {
-    theFattrib = myMapattrib(theFace);
+    theAttribute = myAttributes(theFace);
     return Standard_True;
   }
+
   return Standard_False;
 }
 
@@ -1632,28 +979,8 @@ Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(const TopoDS_Face&
 //function : RemoveFaceAttribute
 //purpose  : 
 //=======================================================================
-
 void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace)
 {
-  if(myMapattrib.IsBound(theFace))
-    myMapattrib.UnBind(theFace);
-}
-
-//=======================================================================
-//function : CreateMutexesForSubShapes
-//purpose  : 
-//=======================================================================
-void BRepMesh_FastDiscret::CreateMutexesForSubShapes(const TopoDS_Shape& theShape,
-                                                     const TopAbs_ShapeEnum theType)
-{
-  myMutexProvider.CreateMutexesForSubShapes(theShape, theType);
-}
-
-//=======================================================================
-//function : RemoveAllMutexes
-//purpose  : 
-//=======================================================================
-void BRepMesh_FastDiscret::RemoveAllMutexes()
-{
-  myMutexProvider.RemoveAllMutexes();
+  if (myAttributes.IsBound(theFace))
+    myAttributes.UnBind(theFace);
 }
index 245fa60..35b02f6 100644 (file)
 #include <BRepMesh_Triangle.hxx>
 #include <BRepMesh_FaceAttribute.hxx>
 #include <BRepMesh_Collections.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 
 class BRepMesh_DataStructureOfDelaun;
 class Bnd_Box;
 class TopoDS_Shape;
 class TopoDS_Face;
-class TopTools_IndexedDataMapOfShapeListOfShape;
 class TopoDS_Edge;
 class BRepAdaptor_HSurface;
 class Geom2d_Curve;
-class TopoDS_Vertex;
 class BRepMesh_Edge;
 class BRepMesh_Vertex;
 class gp_Pnt;
@@ -86,16 +89,17 @@ public:
                                        const Standard_Boolean shapetrigu = Standard_False,
                                        const Standard_Boolean isInParallel = Standard_False);
 
-  //! Build triangulation on the whole shape <br>
+  //! Build triangulation on the whole shape.
   Standard_EXPORT void Perform(const TopoDS_Shape& shape);
 
-  //! Record a face for further processing. <br>
-  Standard_EXPORT void Add(const TopoDS_Face& face,
-                           const TopTools_IndexedDataMapOfShapeListOfShape& ancestor) ;
+  //! Record a face for further processing.
+  //! @return status flags collected during discretization 
+  //! of boundaries of the given face.
+  Standard_EXPORT Standard_Integer Add(const TopoDS_Face& face);
 
-  //! Triangulate a face previously recorded for <br>
-  //! processing by call to Add(). Can be executed in <br>
-  //! parallel threads. <br>
+  //! Triangulate a face previously recorded for 
+  //! processing by call to Add(). Can be executed in 
+  //! parallel threads.
   Standard_EXPORT void Process(const TopoDS_Face& face) const;
 
   void operator ()(const TopoDS_Face& face) const
@@ -103,82 +107,22 @@ public:
     Process(face);
   }
   
-  Standard_EXPORT BRepMesh_Status CurrentFaceStatus() const;
-  
   //! Request algorithm to launch in multiple threads <br>
   //! to improve performance (should be supported by plugin). <br>
-  Standard_EXPORT void SetParallel(const Standard_Boolean theInParallel);
+  inline void SetParallel(const Standard_Boolean theInParallel)
+  {
+    myInParallel = theInParallel;
+  }
   
   //! Returns the multi-threading usage flag. <br>
-  Standard_EXPORT Standard_Boolean IsParallel() const;
-  
-  //! Creates mutexes for each sub-shape of type theType in theShape. <br>
-  //! Used to avoid data races. <br>
-  Standard_EXPORT void CreateMutexesForSubShapes(const TopoDS_Shape& theShape,
-                                                 const TopAbs_ShapeEnum theType);
-  
-  //! Removes all created mutexes <br>
-  Standard_EXPORT void RemoveAllMutexes();
-
-  //! Gives the number of built triangles. <br>
-  Standard_EXPORT Standard_Integer NbTriangles() const;
-
-  //! Gives the triangle of <Index>. <br>
-  Standard_EXPORT const BRepMesh_Triangle& Triangle(const Standard_Integer Index) const;
-
-  //! Gives the number of built Edges <br>
-  Standard_EXPORT Standard_Integer NbEdges() const;
-
-  //! Gives the edge of index <Index>. <br>
-  Standard_EXPORT const BRepMesh_Edge& Edge(const Standard_Integer Index) const;
-
-  //! Gives the number of built Vertices. <br>
-  Standard_EXPORT Standard_Integer NbVertices() const;
-
-  //! Gives the vertex of <Index>. <br>
-  Standard_EXPORT const BRepMesh_Vertex& Vertex(const Standard_Integer Index) const;
-
-  //! Gives the nodes of triangle with the given index.
-  Standard_EXPORT void TriangleNodes(const Standard_Integer theIndex,
-                                     Standard_Integer       (&theNodes)[3]) const
+  inline Standard_Boolean IsParallel() const
   {
-    myStructure->ElementNodes(Triangle(theIndex), theNodes);
+    return myInParallel;
   }
-
-  //! Gives the location3d of the vertex of <Index>. <br>
-  Standard_EXPORT const gp_Pnt& Pnt(const Standard_Integer Index) const;
-
+  
   //! Gives the list of indices of the vertices <br>
   Standard_EXPORT void VerticesOfDomain(BRepMeshCol::MapOfInteger& Indices) const;
 
-  //! Gives the list of indices of the edges <br>
-  inline void EdgesOfDomain(BRepMeshCol::MapOfInteger& Indices) const
-  { 
-    Indices = myStructure->LinksOfDomain();
-  }
-
-  //! Gives the list of indices of the triangles <br>
-  inline void TrianglesOfDomain(BRepMeshCol::MapOfInteger& Indices) const
-  { 
-    Indices = myStructure->ElementsOfDomain();
-  }
-
-  //! Gives the number of different location in 3d space.  
-  //! It is different of the number of vertices if there 
-  //! is more than one surface. <br>
-  //! Even for one surface, the number can be different
-  //! if an edge is shared. <br>
-  inline Standard_Integer NbPoint3d() const
-  {
-    return myNbLocat;
-  }
-
-  //! Gives the 3d space location of the vertex <Index>. <br>
-  inline const gp_Pnt& Point3d(const Standard_Integer Index) const
-  {
-    return myLocation3d(Index);
-  }
-
   //! returns the deflection value. <br>
   inline Standard_Real GetDeflection() const
   {
@@ -206,82 +150,227 @@ public:
     return myShapetrigu;
   }
 
-  //! returns the face deflection value. <br>
-  Standard_EXPORT Standard_Boolean GetFaceAttribute(const TopoDS_Face& face,Handle(BRepMesh_FaceAttribute)& fattrib) const;
+  Standard_EXPORT void InitSharedFaces(const TopoDS_Shape& theShape);
 
-  //! remove face attribute as useless to free locate memory <br>
-  Standard_EXPORT void RemoveFaceAttribute(const TopoDS_Face& face);
-  
-  inline const TopTools_DataMapOfShapeReal& GetMapOfDefEdge() const
+  inline const TopTools_IndexedDataMapOfShapeListOfShape& SharedFaces() const
   {
-    return myMapdefle;
+    return mySharedFaces;
   }
 
+  //! Gives face attribute.
+  Standard_EXPORT Standard_Boolean GetFaceAttribute
+    ( const TopoDS_Face& theFace, Handle(BRepMesh_FaceAttribute)& theAttribute ) const;
+
+  //! Remove face attribute as useless to free locate memory.
+  Standard_EXPORT void RemoveFaceAttribute( const TopoDS_Face& theFace );
+
+  //! Returns number of boundary 3d points.
+  inline Standard_Integer NbBoundaryPoints() const
+  {
+    return myBoundaryPoints.Extent();
+  }
 
   DEFINE_STANDARD_RTTI(BRepMesh_FastDiscret)
 
-private: 
-  
-  void Add(const TopoDS_Edge& edge,
-           const TopoDS_Face& face,
-           const Handle(BRepAdaptor_HSurface)& S,
-           const Handle(Geom2d_Curve)& C,
-           const TopTools_IndexedDataMapOfShapeListOfShape& ancestor,
-           const Standard_Real defedge,
-           const Standard_Real first,
-           const Standard_Real last);
-  
-  void Add(const TopoDS_Vertex& theVert,
-           const TopoDS_Face& face,
-           const Handle(BRepAdaptor_HSurface)& S);
-  
-  Standard_Boolean Update(const TopoDS_Edge& Edge,
-                          const TopoDS_Face& Face,
-                          const Handle(Geom2d_Curve)& C,
-                          const Standard_Real defedge,
-                          const Standard_Real first,
-                          const Standard_Real last);
-  
-  void InternalVertices(const Handle(BRepAdaptor_HSurface)& caro,
-                        BRepMeshCol::ListOfVertex& inter,
-                        const Standard_Real defedge,
-                        const BRepMeshCol::HClassifier& classifier);
-  
-  Standard_Real Control(const Handle(BRepAdaptor_HSurface)& caro,
-                        const Standard_Real defface,
-                        BRepMeshCol::ListOfVertex& inter,
-                        BRepMeshCol::ListOfInteger& badTri,
-                        BRepMeshCol::ListOfInteger& nulTri,
-                        BRepMesh_Delaun& trigu,
-                        const Standard_Boolean isfirst);
-  
-  void AddInShape(const TopoDS_Face& face,
-                  const Standard_Real defedge);
+private:
+
+  //! Auxiliary class used to extract geometrical parameters of TopoDS_Vertex.
+  class TopoDSVExplorer
+  {
+  public:
+    TopoDSVExplorer(
+      const TopoDS_Vertex&   theVertex,
+      const Standard_Boolean isSameUV,
+      const TopoDS_Vertex&   theSameVertex)
+      : myVertex(theVertex),
+        myIsSameUV(isSameUV),
+        mySameVertex(theSameVertex)
+    {
+    }
+
+    const TopoDS_Vertex& Vertex() const
+    {
+      return myVertex;
+    }
+
+    Standard_Boolean IsSameUV() const
+    {
+      return myIsSameUV;
+    }
+
+    const TopoDS_Vertex& SameVertex() const
+    {
+      return mySameVertex;
+    }
+
+    virtual gp_Pnt Point() const
+    {
+      return BRep_Tool::Pnt(myVertex);
+    }
+
+  private:
+
+    void operator =(const TopoDSVExplorer& /*theOther*/)
+    {
+    }
+
+  private:
+    const TopoDS_Vertex& myVertex;
+    Standard_Boolean     myIsSameUV;
+    const TopoDS_Vertex& mySameVertex;
+  };
+
+
+  //! Auxiliary class used to extract polygonal parameters of TopoDS_Vertex.
+  class PolyVExplorer : public TopoDSVExplorer
+  {
+  public:
+    PolyVExplorer(
+      const TopoDS_Vertex&      theVertex,
+      const Standard_Boolean    isSameUV,
+      const TopoDS_Vertex&      theSameVertex,
+      const Standard_Integer    theVertexIndex,
+      const TColgp_Array1OfPnt& thePolygon,
+      const TopLoc_Location&    theLoc)
+      : TopoDSVExplorer(theVertex, isSameUV, theSameVertex),
+        myVertexIndex(theVertexIndex),
+        myPolygon(thePolygon),
+        myLoc(theLoc)
+    {
+    }
+
+    virtual gp_Pnt Point() const
+    {
+      return BRepMesh_ShapeTool::UseLocation(myPolygon(myVertexIndex), myLoc);
+    }
+
+  private:
+
+    void operator =(const PolyVExplorer& /*theOther*/)
+    {
+    }
+
+  private:
+    Standard_Integer          myVertexIndex;
+    const TColgp_Array1OfPnt& myPolygon;
+    const TopLoc_Location     myLoc;
+  };
+
+  //! Structure keeps common parameters of edge
+  //! used for tessellation.
+  struct EdgeAttributes
+  {
+    TopoDS_Vertex              FirstVertex;
+    TopoDS_Vertex              LastVertex;
+
+    Standard_Real              FirstParam;
+    Standard_Real              LastParam;
+
+    gp_Pnt2d                   FirstUV;
+    gp_Pnt2d                   LastUV;
+
+    Standard_Boolean           IsSameUV;
+    Standard_Real              MinDist;
+
+    N_HANDLE<TopoDSVExplorer>  FirstVExtractor;
+    N_HANDLE<TopoDSVExplorer>  LastVExtractor;
+  };
+
+  //! Structure keeps geometrical parameters of edge's PCurve.
+  //! Used for caching.
+  struct EdgePCurve
+  {
+    Handle(Geom2d_Curve) Curve2d;
+    Standard_Real        FirstParam;
+    Standard_Real        LastParam;
+  };
+
+  //! Fills structure of by attributes of the given edge.
+  //! @return TRUE on success, FALSE elsewhere.
+  Standard_Boolean getEdgeAttributes(
+    const TopoDS_Edge&  theEdge,
+    const EdgePCurve&   thePCurve,
+    const Standard_Real theDefEdge,
+    EdgeAttributes&     theAttributes) const;
+
+  //! Registers end vertices of the edge in mesh data 
+  //! structure of currently processed face.
+  void registerEdgeVertices(
+    EdgeAttributes&   theAttributes,
+    Standard_Integer& ipf,
+    Standard_Integer& ivf, 
+    Standard_Integer& isvf,
+    Standard_Integer& ipl,
+    Standard_Integer& ivl,
+    Standard_Integer& isvl);
+
+  //! Adds tessellated representation of the given edge to
+  //! mesh data structure of currently processed face.
+  void add(const TopoDS_Edge&  theEdge,
+           const EdgePCurve&   theCurve2D,
+           const Standard_Real theEdgeDeflection);
+
+  //! Updates tessellated representation of the given edge.
+  //! If edge already has a polygon which deflection satisfies
+  //! the given value, retrieves tessellation from polygon.
+  //! Computes tessellation using edge's geometry elsewhere.
+  void update(
+    const TopoDS_Edge&          theEdge,
+    const Handle(Geom2d_Curve)& theCurve2D,
+    const Standard_Real         theEdgeDeflection,
+    EdgeAttributes&             theAttributes);
+
+  //! Adds new link to the mesh data structure.
+  //! Movability of the link and order of nodes depend on orientation parameter.
+  void addLinkToMesh(const Standard_Integer   theFirstNodeId,
+                     const Standard_Integer   theLastNodeId,
+                     const TopAbs_Orientation theOrientation);
+
+  //! Stores polygonal model of the given edge.
+  //! @param theEdge edge which polygonal model is stored.
+  //! @param thePolygon polygonal model of the edge.
+  //! @param theDeflection deflection with which polygonalization is performed.
+  //! This value is stored inside the polygon.
+  void storePolygon(
+    const TopoDS_Edge&                         theEdge,
+    Handle(Poly_PolygonOnTriangulation)&       thePolygon,
+    const Standard_Real                        theDeflection);
+
+  //! Caches polygonal model of the given edge to be used in further.
+  //! @param theEdge edge which polygonal data is stored.
+  //! @param thePolygon shared polygonal data of the edge.
+  //! @param theDeflection deflection with which polygonalization is performed.
+  //! This value is stored inside the polygon.
+  void storePolygonSharedData(
+    const TopoDS_Edge&                         theEdge,
+    Handle(Poly_PolygonOnTriangulation)&       thePolygon,
+    const Standard_Real                        theDeflection);
 
 private:
 
-  Standard_Real                             myAngle;
-  Standard_Real                             myDeflection;
-  Standard_Real                             myDtotale;
-  Standard_Boolean                          myWithShare;
-  Standard_Boolean                          myInParallel;
-  BRepMeshCol::DMapOfVertexInteger          myVertices;
-  BRepMeshCol::DMapOfShapePairOfPolygon     myEdges;
-  BRepMeshCol::DMapOfShapePairOfPolygon     myInternaledges;
-  Standard_Integer                          myNbLocat;
-  BRepMeshCol::DMapOfIntegerPnt             myLocation3d;
-  Handle_BRepMesh_DataStructureOfDelaun     myStructure;
-  BRepMeshCol::DMapOfFaceAttribute          myMapattrib;
-  TColStd_IndexedMapOfInteger               myVemap;
-  BRepMeshCol::DMapOfIntegerListOfXY        myLocation2d;
-  Standard_Boolean                          myRelative;
-  Standard_Boolean                          myShapetrigu;
-  Standard_Boolean                          myInshape;
-  BRepMesh_Status                           myFacestate;
-  TopTools_DataMapOfShapeReal               myMapdefle;
-  TopTools_ListOfShape                      myNottriangulated;
-  BRepMeshCol::Allocator                    myAllocator;
-  TopTools_MutexForShapeProvider            myMutexProvider;
+  TopoDS_Face                                         myFace;
+  Standard_Real                                       myAngle;
+  Standard_Real                                       myDeflection;
+  Standard_Real                                       myDtotale;
+  Standard_Boolean                                    myWithShare;
+  Standard_Boolean                                    myInParallel;
+  BRepMeshCol::DMapOfShapePairOfPolygon               myEdges;
+  BRepMeshCol::DMapOfFaceAttribute                    myAttributes;
+  Standard_Boolean                                    myRelative;
+  Standard_Boolean                                    myShapetrigu;
+  Standard_Boolean                                    myInshape;
+  TopTools_DataMapOfShapeReal                         myMapdefle;
+
+  // Data shared for whole shape
+  BRepMeshCol::DMapOfVertexInteger                    myBoundaryVertices;
+  BRepMeshCol::DMapOfIntegerPnt                       myBoundaryPoints;
+
+  // Fast access to attributes of current face
+  Handle(BRepMesh_FaceAttribute)                      myAttribute;
+  Handle(BRepMesh_DataStructureOfDelaun)              myStructure;
+  BRepMeshCol::HIMapOfInteger                         myVertexEdgeMap;
+  BRepMeshCol::HDMapOfShapePairOfPolygon              myInternalEdges;
+  TopTools_IndexedDataMapOfShapeListOfShape           mySharedFaces;
 };
 
 DEFINE_STANDARD_HANDLE(BRepMesh_FastDiscret, Standard_Transient)
index b2e5f20..949f26a 100644 (file)
@@ -15,7 +15,6 @@
 #include <BRepMesh_FastDiscretFace.hxx>
 
 #include <BRepMesh_PairOfPolygon.hxx>
-#include <BRepMesh_Classifier.hxx>
 #include <BRepMesh_ShapeTool.hxx>
 #include <Poly_PolygonOnTriangulation.hxx>
 #include <Poly_Triangulation.hxx>
@@ -30,7 +29,6 @@
 #include <BRep_TVertex.hxx>
 #include <BRep_Tool.hxx>
 
-#include <ElSLib.hxx>
 #include <GeomLib.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_BSplineSurface.hxx>
@@ -56,7 +54,7 @@
 #include <NCollection_Map.hxx>
 #include <Bnd_Box2d.hxx>
 
-#define UVDEFLECTION 1.e-05
+#include <algorithm>
 
 IMPLEMENT_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace, Standard_Transient)
@@ -92,6 +90,52 @@ static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_
   return (n? (result / (Standard_Real) n) : -1.);
 }
 
+namespace {
+
+  //! Auxiliary class used to extract geometrical parameters of fixed TopoDS_Vertex.
+  class FixedVExplorer
+  {
+  public:
+
+    DEFINE_STANDARD_ALLOC
+
+    FixedVExplorer(const TopoDS_Vertex& theVertex)
+      : myVertex(theVertex)
+    {
+    }
+
+    const TopoDS_Vertex& Vertex() const
+    {
+      return myVertex;
+    }
+
+    Standard_Boolean IsSameUV() const
+    {
+      return Standard_False;
+    }
+
+    TopoDS_Vertex SameVertex() const
+    {
+      return TopoDS_Vertex();
+    }
+
+    virtual gp_Pnt Point() const
+    {
+      return BRep_Tool::Pnt(myVertex);
+    }
+
+  private:
+
+    void operator =(const FixedVExplorer& /*theOther*/)
+    {
+    }
+
+  private:
+    const TopoDS_Vertex& myVertex;
+  };
+}
+
+
 //=======================================================================
 //function : BRepMesh_FastDiscretFace
 //purpose  : 
@@ -99,7 +143,7 @@ static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_
 BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace
                           (const Standard_Real     theAngle,
                            const Standard_Boolean  theWithShare) : 
-  myAngle(theAngle), myWithShare(theWithShare), myNbLocat(0), 
+  myAngle(theAngle), myWithShare(theWithShare),
   myInternalVerticesMode(Standard_True)
 {
   myAllocator = new NCollection_IncAllocator(64000);
@@ -109,446 +153,188 @@ BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace
 //function : Add(face)
 //purpose  : 
 //=======================================================================
-
-void BRepMesh_FastDiscretFace::Add(const TopoDS_Face&                    theFace,
-                                   const Handle(BRepMesh_FaceAttribute)& theAttrib,
-                                   const TopTools_DataMapOfShapeReal&    theMapDefle,
-                                   const TopTools_MutexForShapeProvider& theMutexProvider)
+void BRepMesh_FastDiscretFace::Add(const Handle(BRepMesh_FaceAttribute)& theAttribute)
 {
-#ifndef DEB_MESH
-  try
-  {
-    OCC_CATCH_SIGNALS
-#endif
-    TopoDS_Face face = theFace;
-    TopLoc_Location loc;
-
-    const Handle(Poly_Triangulation)& aFaceTrigu = BRep_Tool::Triangulation(face, loc);
-    if ( aFaceTrigu.IsNull() )
-      return;
+  if (!theAttribute->IsValid())
+    return;
 
-    myAttrib = theAttrib;
-    face.Orientation(TopAbs_FORWARD);
-    myStructure.Nullify();
-    Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator);
-    anAlloc->Reset(Standard_False);  
-    myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc);
-    
-    Standard_Real umax   = myAttrib->GetUMax();
-    Standard_Real umin   = myAttrib->GetUMin();
-    Standard_Real vmax   = myAttrib->GetVMax();
-    Standard_Real vmin   = myAttrib->GetVMin();
+  myAttribute     = theAttribute;
+  myStructure     = myAttribute->ChangeStructure();
+  myVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
+  myClassifier    = myAttribute->ChangeClassifier();
+  mySurfacePoints = myAttribute->ChangeSurfacePoints();
 
-    Standard_Real aTolU = Max( Precision::PConfusion(), (umax - umin) * UVDEFLECTION );
-    Standard_Real aTolV = Max( Precision::PConfusion(), (vmax - vmin) * UVDEFLECTION );
-    Standard_Real uCellSize = 14 * aTolU;
-    Standard_Real vCellSize = 14 * aTolV;
+  Standard_Real aTolU = myAttribute->ToleranceU();
+  Standard_Real aTolV = myAttribute->ToleranceV();
+  Standard_Real uCellSize = 14.0 * aTolU;
+  Standard_Real vCellSize = 14.0 * aTolV;
 
-    myStructure->Data().SetCellSize ( uCellSize, vCellSize );
-    myStructure->Data().SetTolerance( aTolU, aTolV );
+  const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
+  GeomAbs_SurfaceType thetype = gFace->GetType();
 
+  Standard_Integer i = 1;
 
-    BRepAdaptor_Surface  BS(face, Standard_False);
-    Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
-    
-    GeomAbs_SurfaceType thetype;
-    thetype = BS.GetType();
-    
-    TopAbs_Orientation orFace = face.Orientation();
-
-    if (!myWithShare)        
-      myVertices.Clear();
-
-    myListver.Clear();
-    myVemap.Clear();
-    myLocation2d.Clear();
-    myInternaledges.Clear();
-
-    Standard_Integer i = 1;
-    Standard_Integer ipn = 0;
-    TopoDS_Iterator exW(face);
-    for (; exW.More(); exW.Next()) {
-      const TopoDS_Shape& aWire = exW.Value();
-      if (aWire.ShapeType() != TopAbs_WIRE)
-        continue;
-      TopoDS_Iterator ex(aWire);
-      for(; ex.More(); ex.Next()) {
-        const TopoDS_Edge& edge = TopoDS::Edge(ex.Value());
-        if(edge.IsNull())
-          continue;
-        RestoreStructureFromTriangulation(edge, face, gFace, aFaceTrigu, 
-          theMapDefle(edge), loc, theMutexProvider);
-      }
-    }
-    
-    //////////////////////////////////////////////////////////// 
-    //add internal vertices after self-intersection check
-    Standard_Integer nbVertices = 0;
-    if(myInternalVerticesMode) {
-      for(TopExp_Explorer ex(face,TopAbs_VERTEX ,TopAbs_EDGE); ex.More(); ex.Next()) {
-        const TopoDS_Vertex& aVert = TopoDS::Vertex(ex.Current());
-        Add(aVert,face,gFace);
-      }
-      nbVertices = myVemap.Extent();
-    }
-    
-    // essai de determination de la longueur vraie:
-    // akm (bug OCC16) : We must calculate these measures in non-singular
-    //     parts of face. Let`s try to compute average value of three
-    //     (umin, (umin+umax)/2, umax), and respectively for v.
-    //                 vvvvv
-    //Standard_Real longu = 0.0, longv = 0.0; //, last , first;
-    //gp_Pnt P11, P12, P21, P22, P31, P32;
-
-    Standard_Real deltaX = myAttrib->GetDeltaX();
-    Standard_Real deltaY = myAttrib->GetDeltaY();
-    
-    BRepMeshCol::Array1OfInteger tabvert_corr(1, nbVertices);
-    gp_Pnt2d p2d;
-    
-    // Check the necessity to fill the map of parameters
-    const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus ||
-                                         thetype == GeomAbs_BezierSurface ||
-                                         thetype == GeomAbs_BSplineSurface);
-    myUParam.Clear(); 
-    myVParam.Clear();
-  
-    BRepMesh_VertexTool aMoveNodes(myVemap.Extent(), myAllocator);
-    
-    aMoveNodes.SetCellSize ( uCellSize / deltaX, vCellSize / deltaY);
-    aMoveNodes.SetTolerance( aTolU     / deltaX, aTolV     / deltaY);
+  //////////////////////////////////////////////////////////// 
+  //add internal vertices after self-intersection check
+  Standard_Integer nbVertices = 0;
+  if ( myInternalVerticesMode )
+  {
+    TopExp_Explorer anExplorer(myAttribute->Face(), TopAbs_VERTEX, TopAbs_EDGE);
+    for ( ; anExplorer.More(); anExplorer.Next() )
+      add(TopoDS::Vertex(anExplorer.Current()));
+    nbVertices = myVertexEdgeMap->Extent();
+  }
 
-    for (i = 1; i <= myStructure->NbNodes(); i++)
-    {
-      const BRepMesh_Vertex& v = myStructure->GetNode(i);
-      p2d = v.Coord();
-      if (useUVParam) {
-        myUParam.Add(p2d.X());
-        myVParam.Add(p2d.Y());
-      }
-      gp_XY res;
-      res.SetCoord((p2d.X() - umin ) / deltaX,
-                   (p2d.Y() - vmin ) / deltaY);
-      BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability());
-      const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
-      aMoveNodes.Add(v_new, alist);
-      tabvert_corr(i) = i;
-    }
-    myStructure->ReplaceNodes(aMoveNodes);
-    
-    Standard_Boolean rajout;
-    
-    BRepMeshCol::HClassifier& classifier = theAttrib->GetClassifier();
+  // essai de determination de la longueur vraie:
+  // akm (bug OCC16) : We must calculate these measures in non-singular
+  //     parts of face. Let`s try to compute average value of three
+  //     (umin, (umin+umax)/2, umax), and respectively for v.
+  //                 vvvvv
+  //Standard_Real longu = 0.0, longv = 0.0; //, last , first;
+  //gp_Pnt P11, P12, P21, P22, P31, P32;
 
-    switch (thetype)
-    {
-    case GeomAbs_Sphere:
-    case GeomAbs_Torus:
-      rajout = Standard_True;
-      break;
-    default:
-      rajout = Standard_False;
-    }  
+  const Standard_Real deltaX = myAttribute->GetDeltaX();
+  const Standard_Real deltaY = myAttribute->GetDeltaY();
 
-    BRepMesh_Delaun trigu(myStructure, tabvert_corr, orFace==TopAbs_FORWARD);
-    
-    //removed all free edges from triangulation
-    Standard_Integer nbLinks = myStructure->NbLinks();
-    for( i = 1; i <= nbLinks; i++ ) 
-    {
-      if( myStructure->ElementsConnectedTo(i).Extent() < 1 )
-      {
-        BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i);
-        if ( anEdge.Movability() == BRepMesh_Deleted )
-          continue;
+  BRepMeshCol::Array1OfInteger tabvert_corr(1, nbVertices);
 
-        anEdge.SetMovability(BRepMesh_Free);
-        myStructure->RemoveLink(i);
-      }
-    }
+  // Check the necessity to fill the map of parameters
+  const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus         ||
+                                       thetype == GeomAbs_BezierSurface ||
+                                       thetype == GeomAbs_BSplineSurface);
+  myUParam.Clear(); 
+  myVParam.Clear();
 
-    Standard_Boolean isaline;
-    isaline = ((umax-umin) < UVDEFLECTION) || ((vmax-vmin) < UVDEFLECTION);
-    
-    Standard_Real aDef = -1;
-    if (!isaline && myStructure->ElementsOfDomain().Extent() > 0) {
-      BRepMeshCol::ListOfInteger badTri, nulTri;
-      
-      if(!rajout)
-      {
-        aDef = Control(gFace, theAttrib->GetDefFace(), myListver, badTri, nulTri, trigu, Standard_True);
-        if( aDef > theAttrib->GetDefFace() || aDef < 0.)
-          rajout = Standard_True;
-      }
+  BRepMesh_VertexTool aMoveNodes(nbVertices, myAllocator);
 
-      if(!rajout) {
-        if(useUVParam) {
-          if(BS.IsUClosed()) {
-            if(myVParam.Extent() > 2) {
-              rajout = Standard_True;
-            }
-          }
-          if(BS.IsVClosed()) {
-            if(myUParam.Extent() > 2) {
-              rajout = Standard_True;
-            }
-          }
-        }
-      }
+  aMoveNodes.SetCellSize ( uCellSize / deltaX, vCellSize / deltaY);
+  aMoveNodes.SetTolerance( aTolU     / deltaX, aTolV     / deltaY);
 
-      if(rajout){
-        InternalVertices(gFace, myListver, theAttrib->GetDefFace(), classifier);
-        
-        if (myListver.Extent() > 0) {
-          BRepMeshCol::Array1OfVertexOfDelaun verttab(1, myListver.Extent());
-          BRepMeshCol::ListOfVertex::Iterator itVer(myListver);
-          ipn = 1;
-          for (; itVer.More(); itVer.Next())
-            verttab(ipn++) = itVer.Value();
-          trigu.AddVertices(verttab);
-        }
-        //control internal points
-        BRepMeshCol::ListOfVertex vvlist;
-        aDef = Control(gFace, theAttrib->GetDefFace(), vvlist, badTri, nulTri, trigu, Standard_False);
-        myListver.Append(vvlist);
-      }
-    }
+  for ( i = 1; i <= myStructure->NbNodes(); ++i )
+  {
+    const BRepMesh_Vertex& v = myStructure->GetNode(i);
+    gp_XY aPnt2d = v.Coord();
 
-    //modify myStructure back
-    aMoveNodes.SetCellSize ( uCellSize, vCellSize );
-    aMoveNodes.SetTolerance( aTolU    , aTolV     );
-    for (i = 1; i <= myStructure->NbNodes(); i++)
+    if (useUVParam)
     {
-      const BRepMesh_Vertex& v = myStructure->GetNode(i);
-      p2d = v.Coord();
-      gp_XY res;
-      res.SetCoord(p2d.X() * deltaX + umin, p2d.Y() * deltaY + vmin);
-      BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability());
-      const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
-      aMoveNodes.Add(v_new, alist);
+      myUParam.Add(aPnt2d.X());
+      myVParam.Add(aPnt2d.Y());
     }
-    myStructure->ReplaceNodes(aMoveNodes);
-  
-    AddInShape(face, (aDef < 0.0)? theAttrib->GetDefFace() : aDef, theMutexProvider);
-#ifndef DEB_MESH
-  }
-  catch(Standard_Failure)
-  {
-    BRepMesh_ShapeTool::NullifyFace(theFace);
+
+    aPnt2d = myAttribute->Scale(aPnt2d, Standard_True);
+    BRepMesh_Vertex v_new(aPnt2d, v.Location3d(), v.Movability());
+    const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
+    aMoveNodes.Add(v_new, alist);
+    tabvert_corr(i) = i;
   }
-#endif // DEB_MESH
-  myStructure.Nullify();
-  myAttrib.Nullify();
-}
+  myStructure->ReplaceNodes(aMoveNodes);
 
-//=======================================================================
-//function : RestoreStructureFromTriangulation(edge)
-//purpose  : Restore structure of Delaun from triangulation on face
-//=======================================================================
-Standard_Boolean BRepMesh_FastDiscretFace::RestoreStructureFromTriangulation
-                               (const TopoDS_Edge&                  theEdge,
-                                const TopoDS_Face&                  theFace,
-                                const Handle(BRepAdaptor_HSurface)& theSurf,
-                                const Handle(Poly_Triangulation)&   theTrigu,
-                                const Standard_Real                 theDefEdge,
-                                const TopLoc_Location&              theLoc,
-                                const TopTools_MutexForShapeProvider& theMutexProvider)
-{
-  // 2d vertex indices
-  TopAbs_Orientation orEdge = theEdge.Orientation();
-  // Get end points on 2d curve
-  gp_Pnt2d uvFirst, uvLast;
-  // oan: changes for right restoring of triangulation data from face & edges
-  Handle(Poly_PolygonOnTriangulation) Poly;
+  Standard_Boolean rajout = 
+    (thetype == GeomAbs_Sphere || thetype == GeomAbs_Torus);
 
-  {
-    // lock mutex during querying data from edge curves to prevent parallel change of the same data
-    Standard_Mutex* aMutex = theMutexProvider.GetMutex(theEdge);
-    Standard_Mutex::Sentry aSentry (aMutex);
+  BRepMesh_Delaun trigu(myStructure, tabvert_corr);
 
-    Poly = BRep_Tool::PolygonOnTriangulation(theEdge, theTrigu, theLoc);
-    if (Poly.IsNull() || !Poly->HasParameters())
-      return Standard_False;
+  //removed all free edges from triangulation
+  const Standard_Integer nbLinks = myStructure->NbLinks();
+  for( i = 1; i <= nbLinks; i++ ) 
+  {
+    if( myStructure->ElementsConnectedTo(i).Extent() < 1 )
+    {
+      BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i);
+      if ( anEdge.Movability() == BRepMesh_Deleted )
+        continue;
 
-    BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
+      anEdge.SetMovability(BRepMesh_Free);
+      myStructure->RemoveLink(i);
+    }
   }
 
-  // Get vertices
-  TopoDS_Vertex pBegin, pEnd;
-  TopExp::Vertices(theEdge,pBegin,pEnd);
-
-  const Standard_Boolean sameUV =
-    uvFirst.IsEqual(uvLast, Precision::PConfusion());
+  const Standard_Real umax = myAttribute->GetUMax();
+  const Standard_Real umin = myAttribute->GetUMin();
+  const Standard_Real vmax = myAttribute->GetVMax();
+  const Standard_Real vmin = myAttribute->GetVMin();
 
-  const TColgp_Array1OfPnt2d&    UVNodes = theTrigu->UVNodes();
-  const TColgp_Array1OfPnt&      Nodes   = theTrigu->Nodes();
-  const TColStd_Array1OfInteger& Indices = Poly->Nodes();
-
-  const Standard_Integer nbnodes = Indices.Length();
-  TColStd_Array1OfInteger NewNodes(1, nbnodes);
-  
-  gp_Pnt  P3d;
-  gp_XY   anUV;
+  Standard_Boolean isaline = 
+    ((umax - umin) < Precision::PConfusion() || 
+     (vmax - vmin) < Precision::PConfusion());
 
-  // Process first vertex
-  Standard_Integer ipf;
-  if (myVertices.IsBound(pBegin))
+  Standard_Real aDef = -1;
+  if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 )
   {
-    ipf = myVertices.Find(pBegin);
-  }
-  else
-  {
-    if (sameUV && myVertices.IsBound(pEnd))
+    BRepMeshCol::ListOfVertex aNewVertices;
+    if ( !rajout )
     {
-      ipf = myVertices.Find(pEnd);
-    }
-    else
-    {
-      P3d = Nodes(Indices(1));
-      if (!theLoc.IsIdentity())
-        P3d.Transform(theLoc.Transformation());
-      myNbLocat++;
-      myLocation3d.Bind(myNbLocat, P3d);
-      ipf = myNbLocat;
-    }
-    myVertices.Bind(pBegin,ipf);
-  } 
-    
- //Controle vertice tolerances
-  gp_Pnt pFirst = theSurf->Value(uvFirst.X(), uvFirst.Y());
-  gp_Pnt pLast  = theSurf->Value(uvLast.X(), uvLast.Y());
-  
-  Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)), 
-                                    pLast.Distance(BRep_Tool::Pnt(pEnd)));
+      aDef = control(aNewVertices, trigu, Standard_True);
 
-  if (mindist < BRep_Tool::Tolerance(pBegin) ||
-      mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
-  
-  anUV = BRepMesh_ShapeTool::FindUV(ipf, uvFirst,
-    pBegin, mindist, myAttrib, theSurf, myLocation2d);
-
-  Standard_Integer iv1, isv1;
-  BRepMesh_Vertex vf(anUV, ipf, BRepMesh_Frontier);
-  iv1 = myStructure->AddNode(vf);
-  isv1 = myVemap.FindIndex(iv1);
-  if (isv1 == 0)
-    isv1 = myVemap.Add(iv1);
-  NewNodes(1) = isv1;
-
-  // Process last vertex
-  Standard_Integer ipl, ivl;
-  if (pEnd.IsSame(pBegin))
-  {
-    ipl = ipf;
-  }
-  else
-  {
-    if (myVertices.IsBound(pEnd))
-    {
-      ipl = myVertices.Find(pEnd);
+      if( aDef > myAttribute->GetDefFace() || aDef < 0.)
+        rajout = Standard_True;
     }
-    else
+
+    if ( !rajout && useUVParam )
     {
-      if (sameUV)
-      {
-        ipl = ipf;
-        ivl = iv1;
-      }
-      else
+      if ( myVParam.Extent() > 2 &&
+          (gFace->IsUClosed()    ||
+            gFace->IsVClosed()))
       {
-        P3d = Nodes(Indices(nbnodes));
-        if (!theLoc.IsIdentity())
-          P3d.Transform(theLoc.Transformation());
-        myNbLocat++;
-        myLocation3d.Bind(myNbLocat, P3d);
-        ipl = myNbLocat;
+        rajout = Standard_True;
       }
-      myVertices.Bind(pEnd,ipl);
     }
-  }
 
-  anUV = BRepMesh_ShapeTool::FindUV(ipl, uvLast,
-    pEnd, mindist, myAttrib, theSurf, myLocation2d);
+    if ( rajout )
+    {
+      insertInternalVertices(aNewVertices, trigu);
 
-  BRepMesh_Vertex vl(anUV, ipl, BRepMesh_Frontier);
-  
-  Standard_Integer isvl;
-  ivl = myStructure->AddNode(vl);
-  isvl = myVemap.FindIndex(ivl);
-  if (isvl == 0) 
-    isvl = myVemap.Add(ivl);
-  NewNodes(nbnodes) = isvl;
-      
-  BRepMesh_Vertex v;
-
-  Standard_Integer i;
-  for (i = 2; i < nbnodes; i++)
-  {
-    // Record 3d point
-    P3d = Nodes(Indices(i));
-    if (!theLoc.IsIdentity())
-      P3d.Transform(theLoc.Transformation());
-    myNbLocat++;
-    myLocation3d.Bind(myNbLocat, P3d);
-    
-    // Record 2d point
-    anUV = UVNodes(Indices(i)).Coord();
-
-    Standard_Integer iv2, isv;
-    v.Initialize(anUV, myNbLocat, BRepMesh_Frontier);
-    iv2 = myStructure->AddNode(v);
-    isv = myVemap.FindIndex(iv2);
-    if (isv == 0)
-      isv = myVemap.Add(iv2);
-    NewNodes(i) = isv;
-    
-    //add links
-    if (orEdge == TopAbs_FORWARD)
-      myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
-    else if (orEdge == TopAbs_REVERSED)
-      myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
-    else if (orEdge == TopAbs_INTERNAL)
-      myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
-    iv1 = iv2;  
-  }
-  
-  // last point
-  if (iv1 != ivl) {
-    if (orEdge == TopAbs_FORWARD)
-      myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
-    else if (orEdge == TopAbs_REVERSED)
-      myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
-    else if (orEdge == TopAbs_INTERNAL)
-      myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
-  }
-  
-  Handle(Poly_PolygonOnTriangulation) P1 =
-        new Poly_PolygonOnTriangulation(NewNodes, Poly->Parameters()->Array1());
-  P1->Deflection(theDefEdge);
-  if (myInternaledges.IsBound(theEdge))
-  {
-    BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
-    if (theEdge.Orientation() == TopAbs_REVERSED)
-      pair.Append(P1);
-    else
-      pair.Prepend(P1);
+      //control internal points
+      aDef = control(aNewVertices, trigu, Standard_False);
+    }
   }
-  else
+
+  //modify myStructure back
+  aMoveNodes.SetCellSize ( uCellSize, vCellSize );
+  aMoveNodes.SetTolerance( aTolU    , aTolV     );
+
+  for ( i = 1; i <= myStructure->NbNodes(); ++i )
   {
-    BRepMesh_PairOfPolygon pair1;
-    pair1.Append(P1);
-    myInternaledges.Bind(theEdge, pair1);
+    const BRepMesh_Vertex& v = myStructure->GetNode(i);
+    gp_XY aPnt2d = myAttribute->Scale(v.Coord(), Standard_False);
+    BRepMesh_Vertex v_new(aPnt2d, v.Location3d(), v.Movability());
+    const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
+    aMoveNodes.Add(v_new, alist);
+
+    // Register internal nodes used in triangulation
+    if (!alist.IsEmpty() && myVertexEdgeMap->FindIndex(i) == 0)
+      myVertexEdgeMap->Add(i);
   }
+  myStructure->ReplaceNodes(aMoveNodes);
 
-  return Standard_True;
+  if (!(aDef < 0.))
+    myAttribute->SetDefFace(aDef);
 }
 
 //=======================================================================
-//function : InternalVertices
+//function : addVerticesToMesh
 //purpose  : 
 //=======================================================================
+Standard_Boolean BRepMesh_FastDiscretFace::addVerticesToMesh(
+  const BRepMeshCol::ListOfVertex& theVertices,
+  BRepMesh_Delaun&                 theMeshBuilder)
+{
+  if (theVertices.IsEmpty())
+    return Standard_False;
+
+  BRepMeshCol::Array1OfVertexOfDelaun aArrayOfNewVertices(1, theVertices.Extent());
+  BRepMeshCol::ListOfVertex::Iterator aVertexIt(theVertices);
+  for (Standard_Integer aVertexId = 0; aVertexIt.More(); aVertexIt.Next())
+    aArrayOfNewVertices(++aVertexId) = aVertexIt.Value();
+
+  theMeshBuilder.AddVertices(aArrayOfNewVertices);
+  return Standard_True;
+}
 
+//=======================================================================
+//function : insertInternalVertices
+//purpose  : 
+//=======================================================================
 static void filterParameters(const BRepMeshCol::IMapOfReal& theParams,
                              const Standard_Real            theMinDist,
                              const Standard_Real            theFilterDist,
@@ -585,7 +371,7 @@ static void filterParameters(const BRepMeshCol::IMapOfReal& theParams,
   //add last point if required
   if(aParamArray(anInitLen)-theParams(aParamLength) > theMinDist)
   {
-    aParamTmp.Append(aParamArray(anInitLen));        
+    aParamTmp.Append(aParamArray(anInitLen));
     aParamLength++;
   }
   
@@ -643,1084 +429,784 @@ static void filterParameters(const BRepMeshCol::IMapOfReal& theParams,
   }
 }
 
-void BRepMesh_FastDiscretFace::InternalVertices(const Handle(BRepAdaptor_HSurface)& theCaro,
-                                                BRepMeshCol::ListOfVertex&          theInternalV,
-                                                const Standard_Real                 theDefFace,
-                                                const BRepMeshCol::HClassifier&       theClassifier)
+void BRepMesh_FastDiscretFace::insertInternalVertices(
+  BRepMeshCol::ListOfVertex&  theNewVertices,
+  BRepMesh_Delaun&            theMeshBuilder)
 {
-  BRepMesh_Vertex newV;
-  gp_Pnt2d p2d;
-  gp_Pnt p3d;
+  const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
+  switch (gFace->GetType())
+  {
+  case GeomAbs_Sphere:
+      insertInternalVerticesSphere(theNewVertices);
+      break;
+
+  case GeomAbs_Cylinder:
+      insertInternalVerticesCylinder(theNewVertices);
+      break;
+
+  case GeomAbs_Cone:
+    insertInternalVerticesCone(theNewVertices);
+    break;
+
+  case GeomAbs_Torus:
+    insertInternalVerticesTorus(theNewVertices);
+    break;
+
+  case GeomAbs_BezierSurface:
+  case GeomAbs_BSplineSurface:
+    insertInternalVerticesBSpline(theNewVertices);
+    break;
+
+  default:
+    insertInternalVerticesOther(theNewVertices);
+    break;
+  }
   
-  // work following the type of surface
-  const BRepAdaptor_Surface& BS = *(BRepAdaptor_Surface*)&(theCaro->Surface());
-  GeomAbs_SurfaceType thetype = theCaro->GetType();
-
-  Standard_Real umax = myAttrib->GetUMax();
-  Standard_Real umin = myAttrib->GetUMin();
-  Standard_Real vmax = myAttrib->GetVMax();
-  Standard_Real vmin = myAttrib->GetVMin();
-  Standard_Real deltaX = myAttrib->GetDeltaX();
-  Standard_Real deltaY = myAttrib->GetDeltaY();
-
-  if (thetype == GeomAbs_Sphere)
-  { 
-    gp_Sphere S = BS.Sphere(); 
-    const Standard_Real R = S.Radius();
-
-    // Calculate parameters for iteration in V direction
-    Standard_Real Dv = 1.0 - (theDefFace/R);
-    if (Dv < 0.0) Dv = 0.0;
-    Standard_Real oldDv = 2.0 * ACos (Dv);
-    Dv  =  .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs
-    const Standard_Real sv = vmax - vmin;
-    Dv = sv/((Standard_Integer)(sv/Dv) + 1);
-    const Standard_Real pasvmax = vmax-Dv*0.5;
-
-    //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v)
-    //here approximate relation r*Du = R*Dv is used
-    
-    Standard_Real Du, pasu, pasv; //, ru;
-    const Standard_Real su = umax-umin;
-    Standard_Boolean Shift = Standard_False;
-    for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
+  addVerticesToMesh(theNewVertices, theMeshBuilder);
+}
+
+//=======================================================================
+//function : insertInternalVerticesSphere
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscretFace::insertInternalVerticesSphere(
+  BRepMeshCol::ListOfVertex& theNewVertices)
+{
+  const Standard_Real umax = myAttribute->GetUMax();
+  const Standard_Real umin = myAttribute->GetUMin();
+  const Standard_Real vmax = myAttribute->GetVMax();
+  const Standard_Real vmin = myAttribute->GetVMin();
+
+  gp_Sphere S = myAttribute->Surface()->Sphere();
+  const Standard_Real R = S.Radius();
+
+  // Calculate parameters for iteration in V direction
+  Standard_Real Dv = 1.0 - (myAttribute->GetDefFace() / R);
+  if (Dv < 0.0) Dv = 0.0;
+  Standard_Real oldDv = 2.0 * ACos(Dv);
+  Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs
+  const Standard_Real sv = vmax - vmin;
+  Dv = sv / ((Standard_Integer)(sv / Dv) + 1);
+  const Standard_Real pasvmax = vmax - Dv*0.5;
+
+  //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v)
+  //here approximate relation r*Du = R*Dv is used
+
+  Standard_Real Du, pasu, pasv; //, ru;
+  const Standard_Real su = umax - umin;
+  Standard_Boolean Shift = Standard_False;
+  for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
+  {
+    // Calculate parameters for iteration in U direction
+    // 1.-.365*pasv*pasv is simple approximation of Cos(pasv)
+    // with condition that it gives ~.1 when pasv = pi/2
+    Du = Dv / (1. - .365*pasv*pasv);
+    Du = su / ((Standard_Integer)(su / Du) + 1);
+    Shift = !Shift;
+    const Standard_Real d = (Shift) ? Du*.5 : 0.;
+    const Standard_Real pasumax = umax - Du*0.5 + d;
+    for (pasu = umin + Du - d; pasu < pasumax; pasu += Du)
     {
-      // Calculate parameters for iteration in U direction
-      // 1.-.365*pasv*pasv is simple approximation of Cos(pasv)
-      // with condition that it gives ~.1 when pasv = pi/2
-      Du = Dv/(1.-.365*pasv*pasv);
-      Du = su/((Standard_Integer)(su/Du) + 1);
-      Shift = !Shift;
-      const Standard_Real d = (Shift)? Du*.5 : 0.;
-      const Standard_Real pasumax = umax-Du*0.5 + d;
-      for (pasu = umin + Du - d; pasu < pasumax; pasu += Du)
-      {
-        if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
-        {
-          // Record 3d point
-#ifdef DEB_MESH_CHRONO
-          D0Internal++;
-#endif
-          ElSLib::D0(pasu, pasv, S, p3d);
-          myNbLocat++;
-          myLocation3d.Bind(myNbLocat, p3d);
-          // Record 2d point
-          p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
-          newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
-          theInternalV.Append(newV);
-        }
-      }
+      tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices);
     }
   }
-  else if (thetype == GeomAbs_Cylinder)
-  {
-    gp_Cylinder S = BS.Cylinder();
-    const Standard_Real R = S.Radius();
+}
 
-    // Calculate parameters for iteration in U direction
-    Standard_Real Du = 1.0 - (theDefFace/R);
-    if (Du < 0.0) Du = 0.0;
-    Du = 2.0 * ACos (Du);
-    if (Du > myAngle) Du = myAngle;
-    const Standard_Real su = umax - umin;
-    const Standard_Integer nbU = (Standard_Integer)(su/Du);
-    Du = su/(nbU+1);
-
-    // Calculate parameters for iteration in V direction
-    const Standard_Real sv = vmax - vmin;
-    Standard_Integer nbV = (Standard_Integer)( nbU*sv/(su*R) );
-    nbV = Min(nbV, 100*nbU);
-    Standard_Real Dv = sv/(nbV+1);
-
-    Standard_Real pasu, pasv, pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5;
-    for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) {
-      for (pasu = umin + Du; pasu < pasumax; pasu += Du) {
-        if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
-        {
-          // Record 3d point
-          ElSLib::D0(pasu, pasv, S, p3d);
-          myNbLocat++;
-          myLocation3d.Bind(myNbLocat, p3d);
-          // Record 2d point
-          p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
-          newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
-          theInternalV.Append(newV);
-        }
-      }
+//=======================================================================
+//function : insertInternalVerticesCylinder
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder(
+  BRepMeshCol::ListOfVertex& theNewVertices)
+{
+  const Standard_Real umax = myAttribute->GetUMax();
+  const Standard_Real umin = myAttribute->GetUMin();
+  const Standard_Real vmax = myAttribute->GetVMax();
+  const Standard_Real vmin = myAttribute->GetVMin();
+
+  gp_Cylinder S = myAttribute->Surface()->Cylinder();
+  const Standard_Real R = S.Radius();
+
+  // Calculate parameters for iteration in U direction
+  Standard_Real Du = 1.0 - (myAttribute->GetDefFace() / R);
+  if (Du < 0.0) Du = 0.0;
+  Du = 2.0 * ACos(Du);
+  if (Du > myAngle) Du = myAngle;
+  const Standard_Real su = umax - umin;
+  const Standard_Integer nbU = (Standard_Integer)(su / Du);
+  Du = su / (nbU + 1);
+
+  // Calculate parameters for iteration in V direction
+  const Standard_Real sv = vmax - vmin;
+  Standard_Integer nbV = (Standard_Integer)(nbU*sv / (su*R));
+  nbV = Min(nbV, 100 * nbU);
+  Standard_Real Dv = sv / (nbV + 1);
+
+  Standard_Real pasu, pasv, pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5;
+  for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
+  {
+    for (pasu = umin + Du; pasu < pasumax; pasu += Du)
+    {
+      tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices);
     }
   }
-  else if (thetype == GeomAbs_Cone)
+}
+
+//=======================================================================
+//function : insertInternalVerticesCone
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscretFace::insertInternalVerticesCone(
+  BRepMeshCol::ListOfVertex& theNewVertices)
+{
+  const Standard_Real umax = myAttribute->GetUMax();
+  const Standard_Real umin = myAttribute->GetUMin();
+  const Standard_Real vmax = myAttribute->GetVMax();
+  const Standard_Real vmin = myAttribute->GetVMin();
+
+  Standard_Real R, RefR, SAng;
+  gp_Cone C = myAttribute->Surface()->Cone();
+  RefR = C.RefRadius();
+  SAng = C.SemiAngle();
+  R = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng)));
+  Standard_Real Du, Dv, pasu, pasv;
+  Du = Max(1.0e0 - (myAttribute->GetDefFace() / R), 0.0e0);
+  Du = (2.0 * ACos(Du));
+  Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du);
+  Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*R));
+  Du = (umax - umin) / (nbU + 1);
+  Dv = (vmax - vmin) / (nbV + 1);
+
+  Standard_Real pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5;
+  for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
   {
-    Standard_Real R, RefR, SAng;
-    gp_Cone C = BS.Cone();
-    RefR = C.RefRadius();
-    SAng = C.SemiAngle();
-    R = Max(Abs(RefR+vmin*Sin(SAng)), Abs(RefR+vmax*Sin(SAng)));
-    Standard_Real Du, Dv, pasu, pasv;
-    Du = Max(1.0e0 - (theDefFace/R),0.0e0);
-    Du  = (2.0 * ACos (Du));
-    Standard_Integer nbU = (Standard_Integer) ( (umax-umin)/Du );
-    Standard_Integer nbV = (Standard_Integer) ( nbU*(vmax-vmin)/((umax-umin)*R) );
-    Du = (umax-umin)/(nbU+1);
-    Dv = (vmax-vmin)/(nbV+1);
-
-    Standard_Real pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5;
-    for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) {
-      for (pasu = umin + Du; pasu < pasumax; pasu += Du) {
-        if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
-        {
-          // Record 3d point
-          ElSLib::D0(pasu, pasv, C, p3d);
-          myNbLocat++;
-          myLocation3d.Bind(myNbLocat, p3d);
-          // Record 2d point
-          p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
-          newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
-          theInternalV.Append(newV);
-        }
-      }
+    for (pasu = umin + Du; pasu < pasumax; pasu += Du)
+    {
+      tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), C, theNewVertices);
     }
   }
-  else if (thetype == GeomAbs_Torus)
+}
+
+//=======================================================================
+//function : insertInternalVerticesTorus
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscretFace::insertInternalVerticesTorus(
+  BRepMeshCol::ListOfVertex& theNewVertices)
+{
+  const Standard_Real umax     = myAttribute->GetUMax();
+  const Standard_Real umin     = myAttribute->GetUMin();
+  const Standard_Real vmax     = myAttribute->GetVMax();
+  const Standard_Real vmin     = myAttribute->GetVMin();
+  const Standard_Real deltaX   = myAttribute->GetDeltaX();
+  const Standard_Real deltaY   = myAttribute->GetDeltaY();
+  const Standard_Real aDefFace = myAttribute->GetDefFace();
+
+  gp_Torus T = myAttribute->Surface()->Torus();
+
+  Standard_Boolean insert;
+  Standard_Integer i, j, ParamULength, ParamVLength;
+  Standard_Real pp, pasu, pasv;
+  Standard_Real r = T.MinorRadius(), R = T.MajorRadius();
+
+  BRepMeshCol::SequenceOfReal ParamU, ParamV;
+
+  Standard_Real Du, Dv;//, pasu, pasv;
+  Dv = Max(1.0e0 - (aDefFace / r), 0.0e0);
+  Standard_Real oldDv = 2.0 * ACos(Dv);
+  oldDv = Min(oldDv, myAngle);
+  Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
+  Dv = oldDv;
+
+  Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2);
+  Dv = (vmax - vmin) / (nbV + 1);
+  Standard_Real ru = R + r;
+  if (ru > 1.e-16)
   {
-    gp_Torus T = BS.Torus();
+    Du = 2.0 * ACos(Max(1.0 - (aDefFace / ru), 0.0));
+    if (myAngle < Du) Du = myAngle;
+    Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
+    if (aa < gp::Resolution())
+      return;
+    Du *= Min(oldDv, Du) / aa;
+  }
+  else Du = Dv;
 
-    Standard_Boolean insert;
-    Standard_Integer i, j, ParamULength, ParamVLength;
-    Standard_Real pp, pasu, pasv;
-    Standard_Real r = T.MinorRadius(), R = T.MajorRadius();
+  Standard_Integer nbU = Max((Standard_Integer)((umax - umin) / Du), 2);
+  nbU = Max(nbU, (int)(nbV*(umax - umin)*R / ((vmax - vmin)*r) / 5.));
+  Du = (umax - umin) / (nbU + 1);
 
-    BRepMeshCol::SequenceOfReal ParamU, ParamV;
+  if (R < r)
+  {
+    // As the points of edges are returned.
+    // in this case, the points are not representative.
 
-    Standard_Real Du, Dv;//, pasu, pasv;
-    Dv = Max(1.0e0 - (theDefFace/r),0.0e0) ;
-    Standard_Real oldDv = 2.0 * ACos (Dv);
-    oldDv = Min(oldDv, myAngle);
-    Dv  =  0.9*oldDv; //TWOTHIRD * oldDv;
-    Dv = oldDv;
-    
-    Standard_Integer nbV = Max((Standard_Integer)((vmax-vmin)/Dv), 2);
-    Dv = (vmax-vmin)/(nbV+1);
-    Standard_Real ru = R + r;
-    if (ru > 1.e-16)
-    {
-      Du  = 2.0 * ACos(Max(1.0 - (theDefFace/ru),0.0));
-      if (myAngle < Du) Du = myAngle;
-      Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
-      if(aa < gp::Resolution())
-        return; 
-      Du *= Min(oldDv, Du) / aa;
-    }
-    else Du = Dv;     
-    
-    Standard_Integer nbU = Max((Standard_Integer)((umax-umin)/Du), 2);
-    nbU = Max(nbU , (int)(nbV*(umax-umin)*R/((vmax-vmin)*r)/5.));
-    Du = (umax-umin)/(nbU+1);
-    
-    if (R < r)
-    {
-      // As the points of edges are returned.
-      // in this case, the points are not representative.
-            
-      //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
-           for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du);
-    }//R<r
-    else //U if R > r
-    {
-      //--ofv: U
-      // Number of mapped U parameters
-      const Standard_Integer LenU = myUParam.Extent();
-      // Fill array of U parameters
-      TColStd_Array1OfReal Up(1,LenU);
-      for (j = 1; j <= LenU; j++) Up(j) = myUParam(j);
-      
-      // Calculate DU, leave array of parameters
-      Standard_Real aDU = FUN_CalcAverageDUV(Up,LenU);
-      aDU = Max(aDU, Abs(umax -  umin) / (Standard_Real) nbU / 2.);
-      Standard_Real dUstd = Abs(umax -  umin) / (Standard_Real) LenU;
-      if (aDU > dUstd) dUstd = aDU;
-      // Add U parameters
-      for (j = 1; j <= LenU; j++)
-      {
-        pp = Up(j);
-        insert = Standard_True;
-        ParamULength = ParamU.Length();
-        for (i = 1; i <= ParamULength && insert; i++)
-        {
-          insert = (Abs(ParamU.Value(i)-pp) > (0.5*dUstd));
-        }
-        if (insert) ParamU.Append(pp);
-      }
-    } 
-
-    //--ofv: V
-    // Number of mapped V parameters
-    const Standard_Integer LenV = myVParam.Extent();
-    // Fill array of V parameters
-    TColStd_Array1OfReal Vp(1,LenV);
-    for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j);
-    // Calculate DV, sort array of parameters
-    Standard_Real aDV = FUN_CalcAverageDUV(Vp,LenV);
-    aDV = Max(aDV, Abs(vmax -  vmin) / (Standard_Real) nbV / 2.);
-
-    Standard_Real dVstd = Abs(vmax -  vmin) / (Standard_Real) LenV;
-    if (aDV > dVstd) dVstd = aDV;
-    // Add V parameters
-    for (j = 1; j <= LenV; j++)
+    //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
+    for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du);
+  }//R<r
+  else //U if R > r
+  {
+    //--ofv: U
+    // Number of mapped U parameters
+    const Standard_Integer LenU = myUParam.Extent();
+    // Fill array of U parameters
+    TColStd_Array1OfReal Up(1, LenU);
+    for (j = 1; j <= LenU; j++) Up(j) = myUParam(j);
+
+    // Calculate DU, leave array of parameters
+    Standard_Real aDU = FUN_CalcAverageDUV(Up, LenU);
+    aDU = Max(aDU, Abs(umax - umin) / (Standard_Real)nbU / 2.);
+    Standard_Real dUstd = Abs(umax - umin) / (Standard_Real)LenU;
+    if (aDU > dUstd) dUstd = aDU;
+    // Add U parameters
+    for (j = 1; j <= LenU; j++)
     {
-      pp = Vp(j);
-
+      pp = Up(j);
       insert = Standard_True;
-      ParamVLength = ParamV.Length();
-      for (i = 1; i <= ParamVLength && insert; i++)
+      ParamULength = ParamU.Length();
+      for (i = 1; i <= ParamULength && insert; i++)
       {
-        insert = (Abs(ParamV.Value(i)-pp) > (dVstd*2./3.));
+        insert = (Abs(ParamU.Value(i) - pp) > (0.5*dUstd));
       }
-      if (insert) ParamV.Append(pp);
+      if (insert) ParamU.Append(pp);
     }
+  }
 
-    Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
-    Standard_Real uminnew = umin+deltaY*0.1;
-    Standard_Real vminnew = vmin+deltaX*0.1;
-    Standard_Real umaxnew = umax-deltaY*0.1;
-    Standard_Real vmaxnew = vmax-deltaX*0.1;
+  //--ofv: V
+  // Number of mapped V parameters
+  const Standard_Integer LenV = myVParam.Extent();
+  // Fill array of V parameters
+  TColStd_Array1OfReal Vp(1, LenV);
+  for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j);
+  // Calculate DV, sort array of parameters
+  Standard_Real aDV = FUN_CalcAverageDUV(Vp, LenV);
+  aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real)nbV / 2.);
+
+  Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real)LenV;
+  if (aDV > dVstd) dVstd = aDV;
+  // Add V parameters
+  for (j = 1; j <= LenV; j++)
+  {
+    pp = Vp(j);
 
-    for (i = 1; i <= Lu; i++)
+    insert = Standard_True;
+    ParamVLength = ParamV.Length();
+    for (i = 1; i <= ParamVLength && insert; i++)
     {
-      pasu = ParamU.Value(i);
-      if (pasu >= uminnew && pasu < umaxnew)
+      insert = (Abs(ParamV.Value(i) - pp) > (dVstd*2. / 3.));
+    }
+    if (insert) ParamV.Append(pp);
+  }
+
+  Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
+  Standard_Real uminnew = umin + deltaY*0.1;
+  Standard_Real vminnew = vmin + deltaX*0.1;
+  Standard_Real umaxnew = umax - deltaY*0.1;
+  Standard_Real vmaxnew = vmax - deltaX*0.1;
+
+  for (i = 1; i <= Lu; i++)
+  {
+    pasu = ParamU.Value(i);
+    if (pasu >= uminnew && pasu < umaxnew)
+    {
+      for (j = 1; j <= Lv; j++)
       {
-        for (j = 1; j <= Lv; j++)
+        pasv = ParamV.Value(j);
+        if (pasv >= vminnew && pasv < vmaxnew)
         {
-          pasv = ParamV.Value(j);
-          if (pasv >= vminnew && pasv < vmaxnew)
-          {
-            if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
-            {
-              // Record 3d point
-              ElSLib::D0(pasu, pasv, T, p3d);
-              myNbLocat++;
-              myLocation3d.Bind(myNbLocat, p3d);
-              // Record 2d point
-              p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
-              newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
-              theInternalV.Append(newV);
-            }
-          }
+          tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), T, theNewVertices);
         }
       }
     }
   }
-  else if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface)
+}
+
+//=======================================================================
+//function : insertInternalVerticesBSpline
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
+  BRepMeshCol::ListOfVertex& theNewVertices)
+{
+  const Standard_Real aRange[2][2] = {
+      { myAttribute->GetUMax(), myAttribute->GetUMin() },
+      { myAttribute->GetVMax(), myAttribute->GetVMin() }
+  };
+
+  const Standard_Real aDelta[2] = { 
+    myAttribute->GetDeltaX(),
+    myAttribute->GetDeltaY()
+  };
+
+  const Standard_Real                 aDefFace = myAttribute->GetDefFace();
+  const Handle(BRepAdaptor_HSurface)& gFace    = myAttribute->Surface();
+
+  BRepMeshCol::SequenceOfReal aParams[2];
+  for (Standard_Integer i = 0; i < 2; ++i)
   {
-    //define resolutions
-    Standard_Real uRes = BS.UResolution(theDefFace);
-    Standard_Real vRes = BS.VResolution(theDefFace);
+    Standard_Boolean isU = (i == 0);
+    Standard_Real aRes = isU ?
+      gFace->UResolution(aDefFace) :
+      gFace->VResolution(aDefFace);
 
     // Sort and filter sequence of parameters
-    Standard_Real aMinDu = Precision::PConfusion();
-    if(deltaX < 1.)
-      aMinDu/=deltaX;
-
-    Standard_Real aDuMaxLim = 0.1*(umax-umin);
-    Standard_Real ddu = Min(aDuMaxLim,Max(0.005*(umax-umin),2.*uRes));
-    BRepMeshCol::SequenceOfReal ParamU; 
-    filterParameters(myUParam,aMinDu,ddu,ParamU);
-    Standard_Integer ParamULength = ParamU.Length();
-   
-    Standard_Real aMinDv = Precision::PConfusion();
-    if(deltaY < 1)
-      aMinDv/=deltaY;
-
-    Standard_Real aDvMaxLim = 0.1*(vmax-vmin);
-    Standard_Real ddv = Min(aDvMaxLim,Max(0.005*(vmax-vmin),2.*vRes));
-    BRepMeshCol::SequenceOfReal ParamV; 
-    filterParameters(myVParam,aMinDv,ddv,ParamV);
-    Standard_Integer ParamVLength = ParamV.Length();
-
-    // check intermediate isolines
-    Handle(Geom_Surface) B;
-    if (thetype == GeomAbs_BezierSurface) {
-      B = BS.Bezier();
+    Standard_Real aMinDiff = Precision::PConfusion();
+    if (aDelta[i] < 1.)
+      aMinDiff /= aDelta[i];
+
+    Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1];
+    Standard_Real aDiffMaxLim = 0.1 * aRangeDiff;
+    Standard_Real aDiff = Min(aDiffMaxLim, Max(0.005 * aRangeDiff, 2. * aRes));
+    filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]);
+  }
+
+  // check intermediate isolines
+  Handle(Geom_Surface) aBSpline;
+  GeomAbs_SurfaceType  aSurfType = gFace->GetType();
+  if (aSurfType == GeomAbs_BezierSurface)
+    aBSpline = gFace->Bezier();
+  else if (aSurfType == GeomAbs_BSplineSurface)
+    aBSpline = gFace->BSpline();
+
+  // precision for compare square distances
+  const Standard_Real aPrecision   = Precision::Confusion();
+  const Standard_Real aSqPrecision = aPrecision * aPrecision;
+  for (Standard_Integer k = 0; k < 2; ++k)
+  {
+    BRepMeshCol::SequenceOfReal& aParams1 = aParams[k];
+    BRepMeshCol::SequenceOfReal& aParams2 = aParams[(k + 1) % 2];
+    const Standard_Boolean isU = (k == 0);
+    Standard_Integer aStartIndex, aEndIndex; 
+    if (isU)
+    {
+      aStartIndex = 1;
+      aEndIndex   = aParams1.Length();
     }
-    else {
-      B = BS.BSpline();
+    else
+    {
+      aStartIndex = 2;
+      aEndIndex   = aParams1.Length() - 1;
     }
 
-    gp_Pnt P1, P2, PControl;
-    Standard_Real u, v, dist;
-
-    // precision for compare square distances
-    double dPreci = Precision::SquareConfusion();
-
-    // Insert V parameters by deflection criterion
-    Standard_Integer i,j;
-    Standard_Real V1, V2, U1, U2;
-    for (i = 1; i <= ParamULength; i++) {
-      Handle(Geom_Curve) IsoU = B->UIso(ParamU.Value(i));
-      V1 = ParamV.Value(1);
-      P1 = IsoU->Value(V1);
-      for (j = 2; j <= ParamVLength;) {
-        V2 = ParamV.Value(j);
-        P2 = IsoU->Value(V2);
-        v = 0.5*(V1+V2);
-        PControl = IsoU->Value(v);
+    for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i)
+    {
+      const Standard_Real aParam1 = aParams1(i);
+      Handle(Geom_Curve) aIso = isU ?
+        aBSpline->UIso(aParam1) : aBSpline->VIso(aParam1);
+
+      Standard_Real aPrevParam2 = aParams2(1);
+      gp_Pnt aPrevPnt2 = aIso->Value(aPrevParam2);
+      for (Standard_Integer j = 2; j <= aParams2.Length();)
+      {
+        Standard_Real aParam2 = aParams2(j);
+        gp_Pnt aPnt2 = aIso->Value(aParam2);
+        Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2);
+        gp_Pnt aMidPnt = aIso->Value(aMidParam);
+
         // 23.03.2010 skl for OCC21645 - change precision for comparison
-        if( P1.SquareDistance(P2) > dPreci ) {
-          gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2)));
-          dist = L.Distance(PControl);
-        }
-        else {
-          dist = P1.Distance(PControl);
+        Standard_Real aDist;
+        if (aPrevPnt2.SquareDistance(aPnt2) > aSqPrecision)
+        {
+          gp_Lin aLin(aPrevPnt2, gp_Dir(gp_Vec(aPrevPnt2, aPnt2)));
+          aDist = aLin.Distance(aMidPnt);
         }
-        if (dist > theDefFace) {
+        else
+          aDist = aPrevPnt2.Distance(aMidPnt);
+
+        if (aDist > aDefFace)
+        {
           // insertion 
-          ParamV.InsertBefore(j, v);
-          ParamVLength++;
+          aParams2.InsertBefore(j, aMidParam);
         }
-        else {
+        else
+        {
           //put regular grig for normals
-          gp_Dir N1(0,0,1),N2(0,0,1);
-          Standard_Boolean aSt1 = GeomLib::NormEstim(B, gp_Pnt2d(ParamU.Value(i),V1), Precision::Confusion(), N1);
-          Standard_Boolean aSt2 = GeomLib::NormEstim(B, gp_Pnt2d(ParamU.Value(i),v), Precision::Confusion(), N2);
-
-          Standard_Real anAngle1 = N2.Angle(N1);
-         if(aSt1 < 1 && aSt2 < 1 && anAngle1 > myAngle ) {
-            // insertion 
-            ParamV.InsertBefore(j, v);
-            ParamVLength++;
+          gp_Pnt2d aStPnt1, aStPnt2;
+          if (isU)
+          {
+            aStPnt1 = gp_Pnt2d(aParam1, aPrevParam2);
+            aStPnt2 = gp_Pnt2d(aParam1, aMidParam);
           }
-          else {
-            V1 = V2;
-            P1 = P2;
-            j++;
+          else
+          {
+            aStPnt1 = gp_Pnt2d(aPrevParam2, aParam1);
+            aStPnt2 = gp_Pnt2d(aMidParam,   aParam1);
           }
-        }
-      }
-    }
 
-    for (i = 2; i < ParamVLength; i++) {
-      v = ParamV.Value(i);
-      Handle(Geom_Curve) IsoV = B->VIso(v);
-      U1 = ParamU.Value(1);
-      P1 = IsoV->Value(U1);
-      for (j = 2; j <= ParamULength;) {
-        U2 = ParamU.Value(j);
-        P2 = IsoV->Value(U2);
-        u = 0.5*(U1+U2);
-        PControl = IsoV->Value(u);
-        // 23.03.2010 skl for OCC21645 - change precision for comparison
-        if( P1.SquareDistance(P2) > dPreci ) {
-          gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2)));
-          dist = L.Distance(PControl);
-        }
-        else {
-          dist = P1.Distance(PControl);
-        }
-        if (dist > theDefFace) {
-          // insertion 
-          ParamU.InsertBefore(j, u);
-          ParamULength++;
-        }
-        else {
-          //check normal
-          //put regular grig for normals
-          gp_Dir N1(0,0,1),N2(0,0,1);
-          Standard_Boolean aSt1 = GeomLib::NormEstim(B, gp_Pnt2d(U1,v), Precision::Confusion(), N1);
-          Standard_Boolean aSt2 = GeomLib::NormEstim(B, gp_Pnt2d(u,v), Precision::Confusion(), N2);
-          
-          Standard_Real anAngle1 = N2.Angle(N1);
-               if(aSt1 < 1 && aSt2 < 1 && anAngle1 > myAngle) {
+          gp_Dir N1(0, 0, 1), N2(0, 0, 1);
+          Standard_Boolean aSt1 = GeomLib::NormEstim(aBSpline, aStPnt1, aPrecision, N1);
+          Standard_Boolean aSt2 = GeomLib::NormEstim(aBSpline, aStPnt2, aPrecision, N2);
+
+          Standard_Real aAngle = N2.Angle(N1);
+          if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle)
+          {
             // insertion 
-            ParamU.InsertBefore(j, u);
-            ParamULength++;
+            aParams2.InsertBefore(j, aMidParam);
           }
-          else {
-            U1 = U2;
-            P1 = P2;
-            if (j < ParamULength) {
+          else
+          {
+            aPrevParam2 = aParam2;
+            aPrevPnt2   = aPnt2;
+
+            if (!isU && j < aParams2.Length())
+            {
+              // Update point parameter.
+              aStPnt1.SetX(aPrevParam2);
+
               // Classify intersection point
-              if (theClassifier->Perform(gp_Pnt2d(U1, v)) == TopAbs_IN)
+              if (myClassifier->Perform(aStPnt1) == TopAbs_IN)
               {
-                // Record 3d point
-                myNbLocat++;
-                myLocation3d.Bind(myNbLocat, P1);
-                // Record 2d point
-                p2d.SetCoord((U1-umin)/deltaX, (v-vmin)/deltaY);
-                newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
-                theInternalV.Append(newV);
+                insertVertex(aPrevPnt2, aStPnt1.Coord(), theNewVertices);
               }
             }
-            j++;
+
+            ++j;
           }
         }
       }
     }
   }
-  else {
-    const Standard_Real anAngle = 0.35;
-
-    Standard_Integer i, j, nbpointsU = 10, nbpointsV = 10;
-    Adaptor3d_IsoCurve tabu[11], tabv[11];
-
-    BRepMeshCol::SequenceOfReal ParamU, ParamV;
-    Standard_Real u, v, du, dv;
-    Standard_Integer iu, iv;
-    Standard_Real f, l;
-
-    du = (umax-umin) / (nbpointsU+1); dv = (vmax-vmin) / (nbpointsV+1);
-
-    for (iu = 0; iu <= nbpointsU; iu++) {
-      u = umin + iu*du;
-      tabu[iu].Load(theCaro);
-      tabu[iu].Load(GeomAbs_IsoU, u);
-    }
-
-    for (iv = 0; iv <= nbpointsV; iv++) {
-      v = vmin + iv*dv;
-      tabv[iv].Load(theCaro);
-      tabv[iv].Load(GeomAbs_IsoV, v);
-    }
+}
 
-    Standard_Integer imax = 1, MaxV = 0;
-    
-    GCPnts_TangentialDeflection* tabGU = new GCPnts_TangentialDeflection[nbpointsU+1];
-
-    for (i = 0; i <= nbpointsU; i++) {
-      f = Max(vmin, tabu[i].FirstParameter());
-      l = Min(vmax, tabu[i].LastParameter());
-      GCPnts_TangentialDeflection theDeflection(tabu[i], f, l, anAngle, 0.7*theDefFace, 2);
-      tabGU[i] = theDeflection;
-      if (tabGU[i].NbPoints() > MaxV) {
-        MaxV = tabGU[i].NbPoints();
-        imax = i;
-      }
-    }
-    
-    // return table of parameters V:
-    Standard_Integer NV = tabGU[imax].NbPoints();
-    for (i = 1; i <= NV; i++) {
-      ParamV.Append(tabGU[imax].Parameter(i));
-    }
-    delete [] tabGU;
+//=======================================================================
+//function : insertInternalVerticesOther
+//purpose  : 
+//=======================================================================
+void BRepMesh_FastDiscretFace::insertInternalVerticesOther(
+  BRepMeshCol::ListOfVertex& theNewVertices)
+{
+  const Standard_Real aAngle = 0.35;
+  const Standard_Real aRange[2][2] = {
+      { myAttribute->GetUMax(), myAttribute->GetUMin() },
+      { myAttribute->GetVMax(), myAttribute->GetVMin() }
+  };
+
+  const Standard_Real                 aDefFace = myAttribute->GetDefFace();
+  const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
+
+  BRepMeshCol::SequenceOfReal aParams[2];
+  const Standard_Integer aIsoPointsNb = 11;
+  for (Standard_Integer k = 0; k < 2; ++k)
+  {
+    const Standard_Boolean isU = (k == 0);
+    const GeomAbs_IsoType  aIsoType = isU ? GeomAbs_IsoU : GeomAbs_IsoV;
+    const Standard_Integer aOtherParamsIndex = (k + 1) % 2;
+    const Standard_Real (&aRange1)[2] = aRange[k];
+    const Standard_Real (&aRange2)[2] = aRange[aOtherParamsIndex];
+
+    GCPnts_TangentialDeflection aDiscretIso[aIsoPointsNb];
+    const Standard_Real aStepWidth = (aRange1[0] - aRange1[1]) / aIsoPointsNb;
+
+    // Find the most curved Iso.
+    Standard_Integer aMaxIndex = 1, aMaxPointsNb = 0;
+    for (Standard_Integer aIsoIt = 0; aIsoIt < aIsoPointsNb; ++aIsoIt)
+    {
+      Standard_Real aParam = aRange1[1] + aIsoIt * aStepWidth;
+      Adaptor3d_IsoCurve aIso(gFace, aIsoType, aParam);
 
-    imax = 1;
-    Standard_Integer MaxU = 0;
+      Standard_Real aFirstParam = Max(aRange2[1], aIso.FirstParameter());
+      Standard_Real aLastParam  = Min(aRange2[0], aIso.LastParameter());
 
-    GCPnts_TangentialDeflection* tabGV = new GCPnts_TangentialDeflection[nbpointsV+1];
+      aDiscretIso[aIsoIt].Initialize(aIso, aFirstParam, aLastParam, 
+        aAngle, 0.7 * aDefFace, 2);
 
-    for (i = 0; i <= nbpointsV; i++) {
-      f = Max(umin, tabv[i].FirstParameter());
-      l = Min(umax, tabv[i].LastParameter());
-      GCPnts_TangentialDeflection thedeflection2(tabv[i], f, l, anAngle, 0.7*theDefFace, 2);
-      tabGV[i] = thedeflection2;
-      if (tabGV[i].NbPoints() > MaxU) {
-        MaxU = tabGV[i].NbPoints();
-        imax = i;
+      const Standard_Integer aPointsNb = aDiscretIso[aIsoIt].NbPoints();
+      if (aPointsNb > aMaxPointsNb)
+      {
+        aMaxPointsNb = aPointsNb;
+        aMaxIndex    = aIsoIt;
       }
     }
-    
-    // return table of parameters U:
-    Standard_Integer NU = tabGV[imax].NbPoints();
-    for (i = 1; i <= NU; i++) {
-      ParamU.Append(tabGV[imax].Parameter(i));
-    }
-    delete [] tabGV;
-    
-    if (ParamU.Length() == 2) {
-      ParamU.InsertAfter(1, (umax+umin)*0.5);
-    }
-    if (ParamV.Length() == 2) {
-      ParamV.InsertAfter(1, (vmax+vmin)*0.5);
-    }
-    
-    BRepMeshCol::SequenceOfReal InsertV, InsertU;
-    gp_Pnt P1;
 
-    Adaptor3d_IsoCurve IsoV;
-    IsoV.Load(theCaro);
+    BRepMeshCol::SequenceOfReal& aParams2 = aParams[aOtherParamsIndex];
+    GCPnts_TangentialDeflection& aDIso    = aDiscretIso[aMaxIndex];
+    for (Standard_Integer i = 1; i <= aMaxPointsNb; ++i)
+      aParams2.Append(aDIso.Parameter(i));
 
-    Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
-    
-    for (i = 2; i < Lv; i++) {
-      v = ParamV.Value(i);
-      IsoV.Load(GeomAbs_IsoV, v);
-      for (j = 2; j < Lu; j++) {
-        u = ParamU.Value(j);
-        if (theClassifier->Perform(gp_Pnt2d(u, v)) == TopAbs_IN)
-        {
-          // Record 3d point
-          P1 = IsoV.Value(u);
-          myNbLocat++;
-          myLocation3d.Bind(myNbLocat, P1);
-          // Record 2d point
-          p2d.SetCoord((u-umin)/deltaX, (v-vmin)/deltaY);
-          newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
-          theInternalV.Append(newV); 
-        }
-      }
-    } 
+    if (aParams2.Length() == 2)
+      aParams2.InsertAfter(1, 0.5 * (aRange2[1] + aRange2[0]));
   }
-#ifdef DEB_MESH_CHRONO
-  chInternal.Stop();
-#endif
-}
 
-/**
-*  Internal class Couple, moved from MeshData package
-*/
+  Adaptor3d_IsoCurve aIsoV;
+  aIsoV.Load(gFace);
 
-class BRepMesh_Couple
-{
- public:
-  BRepMesh_Couple() { myI1 = myI2 = 0; }
-  BRepMesh_Couple(const Standard_Integer I1,
-                  const Standard_Integer I2)
-  { myI1 = I1; myI2 = I2; }
-
-  Standard_Integer myI1;
-  Standard_Integer myI2;
-};
-
-inline Standard_Boolean IsEqual(const BRepMesh_Couple& one,
-                                const BRepMesh_Couple& other)
-{
-  if (one.myI1 == other.myI1 &&
-      one.myI2 == other.myI2) return Standard_True;
-  else return Standard_False;
-}
+  const Standard_Integer aUPointsNb = aParams[0].Length();
+  const Standard_Integer aVPointsNb = aParams[1].Length();
+  for (Standard_Integer i = 2; i < aVPointsNb; ++i)
+  {
+    const Standard_Real aV = aParams[1].Value(i);
+    aIsoV.Load(GeomAbs_IsoV, aV);
 
-inline Standard_Integer HashCode(const BRepMesh_Couple& one,
-                                 const Standard_Integer Upper)
-{
-  return ::HashCode((one.myI1+one.myI2), Upper);
-}
+    for (Standard_Integer j = 2; j < aUPointsNb; ++j)
+    {
+      const Standard_Real aU = aParams[0].Value(j);
 
-typedef NCollection_Map<BRepMesh_Couple> BRepMesh_MapOfCouple;
+      const gp_Pnt2d aNewPoint(aU, aV);
+      if (myClassifier->Perform(aNewPoint) == TopAbs_IN)
+        insertVertex(aIsoV.Value(aU), aNewPoint.Coord(), theNewVertices);
+    }
+  }
+}
 
 //=======================================================================
-//function : Control
+//function : control
 //purpose  : 
 //=======================================================================
-Standard_Real BRepMesh_FastDiscretFace::Control(const Handle(BRepAdaptor_HSurface)& theCaro,
-                                                const Standard_Real                 theDefFace,
-                                                BRepMeshCol::ListOfVertex&          theInternalV,
-                                                BRepMeshCol::ListOfInteger&         theBadTriangles,
-                                                BRepMeshCol::ListOfInteger&         theNulTriangles,
-                                                BRepMesh_Delaun&                    theTrigu,
-                                                const Standard_Boolean              theIsFirst)
+Standard_Real BRepMesh_FastDiscretFace::control(
+  BRepMeshCol::ListOfVertex&  theNewVertices,
+  BRepMesh_Delaun&            theTrigu,
+  const Standard_Boolean      theIsFirst)
+
+#define CHECK_DEF_AND_INSERT_CURRENT(isSkipped)                 \
+if (aSqDef > aMaxSqDef)                                         \
+  aMaxSqDef = aSqDef;                                           \
+                                                                \
+(isSkipped) = Standard_False;                                   \
+if (aSqDef > aSqDefFace)                                        \
+{                                                               \
+  (isSkipped) = theIsFirst;                                     \
+  if (!(isSkipped))                                             \
+    insertVertex(pDef, mi2d, theNewVertices);                   \
+}                                                               \
+
 {
+  Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent();
+  if (aTrianglesNb < 1)
+    return -1.0;
+
   //IMPORTANT: Constants used in calculations
-  const Standard_Real MinimalArea2d = 1.e-9;
+  const Standard_Real MinimalArea2d     = 1.e-9;
   const Standard_Real MinimalSqLength3d = 1.e-12;
+  const Standard_Real aSqDefFace = myAttribute->GetDefFace() * myAttribute->GetDefFace();
 
-  // Define the number of iterations
-  Standard_Integer myNbIterations = 11;
-  const Standard_Integer nbPasses = (theIsFirst? 1 : myNbIterations);
+  const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
 
-  // Initialize stop condition
-  Standard_Boolean allDegenerated = Standard_False;
-  Standard_Integer nbInserted = 1;
-
-  // Create map of links to skip already processed
-  Standard_Integer nbtriangles;
-
-  nbtriangles = myStructure->ElementsOfDomain().Extent();
-  if (nbtriangles <= 0) return -1.0;
-  BRepMesh_MapOfCouple theCouples(3*nbtriangles);
-
-  gp_XY mi2d;
-  gp_XYZ vecEd1, vecEd2, vecEd3;
-  gp_Pnt pDef;
-  Standard_Real dv = 0, defl = 0, maxdef = -1;
-  Standard_Integer pass = 1, nf = 0, nl = 0;
-  BRepMesh_Vertex InsVertex;
-  Standard_Boolean caninsert;
-
-  Standard_Real sqdefface = theDefFace * theDefFace;
-
-  GeomAbs_SurfaceType thetype = theCaro->GetType();
-  Handle(Geom_Surface) BSpl;
-  Standard_Boolean isSpline = Standard_False;
-  if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface)
-  {
-    isSpline = Standard_True;
-    if (thetype == GeomAbs_BezierSurface) 
-      BSpl = theCaro->Bezier();
-    else 
-      BSpl = theCaro->BSpline();
-  }
+  Handle(Geom_Surface) aBSpline;
+  GeomAbs_SurfaceType  aSurfType = gFace->GetType();
+  if (aSurfType == GeomAbs_BezierSurface)
+    aBSpline = gFace->Bezier();
+  else if (aSurfType == GeomAbs_BSplineSurface)
+    aBSpline = gFace->BSpline();
 
-  NCollection_DataMap<Standard_Integer,gp_Dir> aNorMap;
-  BRepMeshCol::MapOfIntegerInteger aStatMap;
+  NCollection_DataMap<Standard_Integer, gp_Dir> aNorMap;
+  BRepMeshCol::MapOfIntegerInteger              aStatMap;
+  NCollection_Map<BRepMesh_OrientedEdge>        aCouples(3 * aTrianglesNb);
 
   // Perform refinement passes
-  for (; pass <= nbPasses && nbInserted && !allDegenerated; pass++)
+  // Define the number of iterations
+  Standard_Integer       aIterationsNb = 11;
+  const Standard_Integer aPassesNb = (theIsFirst ? 1 : aIterationsNb);
+  // Initialize stop condition
+  Standard_Real aMaxSqDef = -1.;
+  Standard_Integer aPass = 1, aInsertedNb = 1;
+  Standard_Boolean isAllDegenerated = Standard_False;
+  for (; aPass <= aPassesNb && aInsertedNb && !isAllDegenerated; ++aPass)
   {
-    theInternalV.Clear();
-    theBadTriangles.Clear();
-    
-    // Reset stop condition
-    allDegenerated = Standard_True;
-    nbInserted = 0;
-    maxdef = -1.0;
+    theNewVertices.Clear();
 
-    // Do not insert nodes in last pass in non-SharedMode
-    caninsert = (myWithShare || pass < nbPasses);
+    // Reset stop condition
+    aInsertedNb      = 0;
+    aMaxSqDef        = -1.;
+    isAllDegenerated = Standard_True;
 
-    // Read mesh size
-    nbtriangles = myStructure->ElementsOfDomain().Extent();
-    if (nbtriangles <= 0) break;
+    aTrianglesNb = myStructure->ElementsOfDomain().Extent();
+    if (aTrianglesNb < 1)
+      break;
 
     // Iterate on current triangles
-    BRepMeshCol::MapOfInteger::Iterator triDom;
-    const BRepMeshCol::MapOfInteger& TriMap = myStructure->ElementsOfDomain();
-    triDom.Initialize(TriMap);
-    Standard_Integer aNbPnt = 0;
-    Standard_Real umin = myAttrib->GetUMin();
-    Standard_Real vmin = myAttrib->GetVMin();
-    Standard_Real deltaX = myAttrib->GetDeltaX();
-    Standard_Real deltaY = myAttrib->GetDeltaY();
-    for (; triDom.More(); triDom.Next())
+    const BRepMeshCol::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
+    BRepMeshCol::MapOfInteger::Iterator aTriangleIt(aTriangles);
+    for (; aTriangleIt.More(); aTriangleIt.Next())
     {
-      Standard_Integer TriId = triDom.Key();
-      const BRepMesh_Triangle& curTri=Triangle(TriId);
-      if (curTri.Movability()==BRepMesh_Deleted) continue;
-      
+      const Standard_Integer aTriangleId = aTriangleIt.Key();
+      const BRepMesh_Triangle& aCurrentTriangle = myStructure->GetElement(aTriangleId);
+
+      if (aCurrentTriangle.Movability() == BRepMesh_Deleted)
+        continue;
+
       Standard_Integer v[3];
-      myStructure->ElementNodes(curTri, v);
+      myStructure->ElementNodes(aCurrentTriangle, v);
 
       Standard_Integer e[3];
       Standard_Boolean o[3];
-      curTri.Edges(e, o);
-      
-      Standard_Boolean m1 = (Edge(e[0]).Movability() == BRepMesh_Frontier);
-      Standard_Boolean m2 = (Edge(e[1]).Movability() == BRepMesh_Frontier);
-      Standard_Boolean m3 = (Edge(e[2]).Movability() == BRepMesh_Frontier);
-
-      const BRepMesh_Vertex& vert1=Vertex(v[0]);
-      const BRepMesh_Vertex& vert2=Vertex(v[1]);
-      const BRepMesh_Vertex& vert3=Vertex(v[2]);
-
-      const gp_XYZ& p1=myLocation3d(vert1.Location3d()).Coord();
-      const gp_XYZ& p2=myLocation3d(vert2.Location3d()).Coord();
-      const gp_XYZ& p3=myLocation3d(vert3.Location3d()).Coord();
-
-      vecEd1 = p2 - p1;
-      vecEd2 = p3 - p2;
-      vecEd3 = p1 - p3;
-
-      // Check for degenerated triangle
-      if (vecEd1.SquareModulus() < MinimalSqLength3d ||
-          vecEd2.SquareModulus() < MinimalSqLength3d ||
-          vecEd3.SquareModulus() < MinimalSqLength3d) 
+      aCurrentTriangle.Edges(e, o);
+
+      gp_XY xy[3];
+      gp_XYZ p[3];
+      Standard_Boolean m[3];
+      for (Standard_Integer i = 0; i < 3; ++i)
       {
-        theNulTriangles.Append(TriId);
-        continue;
+        m[i] = (myStructure->GetLink(e[i]).Movability() == BRepMesh_Frontier);
+
+        const BRepMesh_Vertex& aVertex = myStructure->GetNode(v[i]);
+        xy[i] = myAttribute->Scale(aVertex.Coord(), Standard_False);
+        p [i] = myAttribute->GetPoint(aVertex).Coord();
       }
 
-      allDegenerated = Standard_False;
+      gp_XYZ aLinkVec[3];
+      Standard_Boolean isDegeneratedTri = Standard_False;
+      for (Standard_Integer i = 0; i < 3 && !isDegeneratedTri; ++i)
+      {
+        aLinkVec[i] = p[(i + 1) % 3] - p[i];
+        isDegeneratedTri = (aLinkVec[i].SquareModulus() < MinimalSqLength3d);
+      }
+
+      if (isDegeneratedTri) 
+        continue;
 
-      gp_XY xy1(vert1.Coord().X()*deltaX+umin,vert1.Coord().Y()*deltaY+vmin);
-      gp_XY xy2(vert2.Coord().X()*deltaX+umin,vert2.Coord().Y()*deltaY+vmin);
-      gp_XY xy3(vert3.Coord().X()*deltaX+umin,vert3.Coord().Y()*deltaY+vmin);
+      isAllDegenerated = Standard_False;
 
       // Check triangle area in 2d
-      if (Abs((xy2-xy1)^(xy3-xy1)) < MinimalArea2d)
-      {
-        theNulTriangles.Append(TriId);
+      if (Abs((xy[1]-xy[0])^(xy[2]-xy[1])) < MinimalArea2d)
         continue;
-      }
 
       // Check triangle normal
-      gp_XYZ normal(vecEd1^vecEd2);
-      dv = normal.Modulus();
-      if (dv < Precision::Confusion())
+      gp_Pnt pDef;
+      Standard_Real aSqDef = -1.;
+      Standard_Boolean isSkipped = Standard_False;
+      gp_XYZ normal(aLinkVec[0] ^ aLinkVec[1]);
+      try
       {
-        theNulTriangles.Append(TriId);
-        continue;
+        OCC_CATCH_SIGNALS
+
+        normal.Normalize();
+
+        // Check deflection on triangle
+        gp_XY mi2d = (xy[0] + xy[1] + xy[2]) / 3.0;
+        gFace->D0(mi2d.X(), mi2d.Y(), pDef);
+        aSqDef = Abs(normal * (pDef.XYZ() - p[0]));
+        aSqDef *= aSqDef;
+
+        CHECK_DEF_AND_INSERT_CURRENT(isSkipped);
+        if (isSkipped)
+          break;
       }
-      normal /= dv;
-
-      // Check deflection on triangle
-      mi2d = (xy1+xy2+xy3)/3.0;
-      theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
-      defl = Abs(normal*(pDef.XYZ()-p1));
-      defl = defl*defl;     
-      /*mi2d = (xy1+xy2+xy3)/3.0;
-      theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
-      defl = pDef.SquareDistance((p1+p2+p3)/3.);*/
-      if (defl > maxdef) maxdef = defl;
-      if (defl > sqdefface)
+      catch (Standard_Failure)
       {
-        if (theIsFirst) break;
-        if (caninsert)
-        {
-          // Record new vertex
-          aNbPnt++;
-          myNbLocat++;
-          myLocation3d.Bind(myNbLocat,pDef);
-          mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
-          InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
-          theInternalV.Append(InsVertex);
-        }
-        theBadTriangles.Append(TriId);
+        continue;
       }
-      
-      if (!m2) // Not a boundary
+
+      for (Standard_Integer i = 0; i < 3 && !isSkipped; ++i)
       {
+        if (m[i]) // is a boundary
+          continue;
+
+        Standard_Integer j = (i + 1) % 3;
         // Check if this link was already processed
-        if (v[1] < v[2]) { nf = v[1]; nl = v[2]; } else { nf = v[2]; nl = v[1]; }
-        if (theCouples.Add(BRepMesh_Couple(nf,nl)))
+        Standard_Integer aFirstVertex, aLastVertex;
+        if (v[i] < v[j])
+        { 
+          aFirstVertex = v[i];
+          aLastVertex = v[j];
+        }
+        else
         {
-          // Check deflection on edge 1
-          mi2d = (xy2+xy3)*0.5;
-          theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
-          gp_Lin L (p2, gp_Vec(p2, p3));
-          defl = L.SquareDistance(pDef);
-          if (defl > maxdef) maxdef = defl;
-          if (defl > sqdefface)
-          {
-            if (theIsFirst) break;
-            if (caninsert)
-            {
-              // Record new vertex
-              aNbPnt++;              
-              myNbLocat++;
-              myLocation3d.Bind(myNbLocat,pDef);
-              mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
-              InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
-              theInternalV.Append(InsVertex);
-            }
-            theBadTriangles.Append(TriId);
-          }
+          aFirstVertex = v[j];
+          aLastVertex = v[i];
         }
-      }
 
-      if (!m3) // Not a boundary
-      {
-        // Check if this link was already processed
-        if (v[0] < v[2]) { nf = v[0]; nl = v[2]; } else { nf = v[2]; nl = v[0]; }
-        if (theCouples.Add(BRepMesh_Couple(nf,nl)))
+        if (aCouples.Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex)))
         {
-          // Check deflection on edge 2
-          mi2d = (xy3+xy1)*0.5;
-          theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
-          gp_Lin L (p1, gp_Vec(p1, p3));
-          defl = L.SquareDistance(pDef);
-          if (defl > maxdef) maxdef = defl;
-          if (defl > sqdefface)
-          {
-            if (theIsFirst) break;
-            if (caninsert)
-            {
-              // Record new vertex
-              aNbPnt++;
-              myNbLocat++;
-              myLocation3d.Bind(myNbLocat,pDef);
-              mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
-              InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
-              theInternalV.Append(InsVertex);
-            }
-            theBadTriangles.Append(TriId);
-          }
+          // Check deflection on edge 1
+          gp_XY mi2d = (xy[i] + xy[j]) * 0.5;
+          gFace->D0(mi2d.X(), mi2d.Y(), pDef);
+          gp_Lin aLin(p[i], gp_Vec(p[i], p[j]));
+          aSqDef = aLin.SquareDistance(pDef);
+
+          CHECK_DEF_AND_INSERT_CURRENT(isSkipped);
         }
       }
 
-      if (!m1) // Not a boundary
+      if (isSkipped)
+        break;
+
+      //check normal on bsplines
+      if (theIsFirst && !aBSpline.IsNull())
       {
-        // Check if this link was already processed
-        if (v[0] < v[1]) { nf = v[0]; nl = v[1]; } else { nf = v[1]; nl = v[0]; }
-        if (theCouples.Add(BRepMesh_Couple(nf,nl)))
+        gp_Dir N[3] = { gp::DZ(), gp::DZ(), gp::DZ() };
+        Standard_Integer aSt[3];
+
+        for (Standard_Integer i = 0; i < 3; ++i)
         {
-          // Check deflection on edge 3
-          mi2d = (xy1+xy2)*0.5;
-          theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
-          gp_Lin L (p1, gp_Vec(p1, p2));
-          defl = L.SquareDistance(pDef);
-          if (defl > maxdef) maxdef = defl;
-          if (defl > sqdefface)
+          if (aNorMap.IsBound(v[i]))
           {
-            if (theIsFirst) break;
-            if (caninsert)
-            {
-              // Record new vertex
-              aNbPnt++;
-              myNbLocat++;
-              myLocation3d.Bind(myNbLocat,pDef);
-              mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);              
-              InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
-              theInternalV.Append(InsVertex);
-            }
-            theBadTriangles.Append(TriId);
+            aSt[i] = aStatMap.Find(v[i]);
+            N[i] = aNorMap.Find(v[i]);
+          }
+          else
+          {
+            aSt[i] = GeomLib::NormEstim(aBSpline, gp_Pnt2d(xy[i]), Precision::Confusion(), N[i]);
+            aStatMap.Bind(v[i], aSt[i]);
+            aNorMap.Bind(v[i], N[i]);
           }
-        }
-      }
-      
-      //check normal on bsplines
-      if(theIsFirst && isSpline && !BSpl.IsNull() )      
-      {
-        gp_Dir N1(0,0,1), N2(0,0,1), N3(0,0,1);
-        Standard_Integer aSt1, aSt2, aSt3;
-        if(aNorMap.IsBound(v[0])) {
-          aSt1 = aStatMap.Find(v[0]);
-          N1 =aNorMap.Find(v[0]);
-        }
-        else {
-          aSt1 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy1), Precision::Confusion(), N1);
-          aStatMap.Bind(v[0],aSt1);
-          aNorMap.Bind(v[0],N1);
         }
 
-        if(aNorMap.IsBound(v[1])) {
-          aSt2 = aStatMap.Find(v[1]);
-          N2 = aNorMap.Find(v[1]);
-        }
-        else {
-          aSt2 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy2), Precision::Confusion(), N2);
-          aStatMap.Bind(v[1],aSt2);
-          aNorMap.Bind(v[1],N2);
-        }
+        Standard_Real aAngle[3];
+        for (Standard_Integer i = 0; i < 3; ++i)
+          aAngle[i] = N[(i + 1) % 3].Angle(N[i]);
 
-        if(aNorMap.IsBound(v[2])) {
-          aSt3 = aStatMap.Find(v[2]);
-          N3 = aNorMap.Find(v[2]);
-        }
-        else {
-          aSt3 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy3), Precision::Confusion(), N3);
-          aStatMap.Bind(v[2],aSt3);
-          aNorMap.Bind(v[2],N3.XYZ());
-        }
-        
-        Standard_Real anAngle1 = N2.Angle(N1);
-        Standard_Real anAngle2 = N3.Angle(N2);
-        Standard_Real anAngle3 = N1.Angle(N3);
-        if(aSt1 < 1 && aSt2 < 1 && aSt3 < 1 && 
-            (anAngle1 > myAngle || anAngle2 > myAngle || anAngle3 > myAngle)) {
-
-            maxdef = -1;
+        if (aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1)
+        {
+          if (aAngle[0] > myAngle || aAngle[1] > myAngle || aAngle[2] > myAngle)
+          {
+            aMaxSqDef = -1.;
             break;
+          }
         }
       }
     }
-    
-    if (!theIsFirst && theInternalV.Extent() > 0) 
-    {
-      BRepMeshCol::Array1OfVertexOfDelaun verttab(1, theInternalV.Extent());
-      BRepMeshCol::ListOfVertex::Iterator itVer(theInternalV);
-      Standard_Integer ipn = 1;
-      for (; itVer.More(); itVer.Next())
-        verttab(ipn++) = itVer.Value();
-        
-      theTrigu.AddVertices(verttab);
-      nbInserted++;
-    }
-  }
-
-   if (maxdef < 0)
-    return maxdef;
-  return Sqrt(maxdef);
-}
-
-//=======================================================================
-//function : AddInShape
-//purpose  : 
-//=======================================================================
-void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face&  theFace,
-                                          const Standard_Real theDefFace,
-                                          const TopTools_MutexForShapeProvider& theMutexProvider)
-{
-  TopLoc_Location loc = theFace.Location();
-  Handle(Poly_Triangulation) TOld = BRep_Tool::Triangulation(theFace, loc);
-  Handle(Poly_PolygonOnTriangulation) NullPoly;
-
-  BRepMesh_ShapeTool::NullifyFace(theFace);
-
-  try{
-  BRepMeshCol::MapOfInteger::Iterator it;
-
-  Standard_Integer i, index;
-  TopAbs_Orientation orFace = theFace.Orientation();
-
-  const BRepMeshCol::MapOfInteger& TriMap = myStructure->ElementsOfDomain();
-  it.Initialize(TriMap);
-    
-  Standard_Integer nTri = TriMap.Extent();
-  if (nTri != 0) {
-    
-    Poly_Array1OfTriangle Tri(1, nTri);
-    
-    i = 1;
-    
-    for (; it.More(); it.Next())
-    {
-      const BRepMesh_Triangle& aCurElem = myStructure->GetElement(it.Key());
-
-      Standard_Integer v[3];
-      myStructure->ElementNodes(aCurElem, v);
-      
-      Standard_Integer iv1, iv2, iv3;
-      iv1 = myVemap.FindIndex(v[0]);
-      if (iv1 == 0) iv1 = myVemap.Add(v[0]);
-      iv2 = myVemap.FindIndex(v[1]);
-      if (iv2 == 0) iv2 = myVemap.Add(v[1]);
-      iv3 = myVemap.FindIndex(v[2]);
-      if (iv3 == 0) iv3 = myVemap.Add(v[2]);
-      
-      if (orFace == TopAbs_REVERSED) Tri(i++).Set(iv1, iv3, iv2);
-      else Tri(i++).Set(iv1, iv2, iv3);
-    }
-    
-    Standard_Integer nbVertices = myVemap.Extent();
-    Handle(Poly_Triangulation) T = new Poly_Triangulation(nbVertices, nTri, Standard_True);
-    Poly_Array1OfTriangle& Trian = T->ChangeTriangles();
-    Trian = Tri;
-    TColgp_Array1OfPnt&  Nodes = T->ChangeNodes();
-    TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes();
-    
-    for (i = 1; i <= nbVertices; i++) {
-      index = myVemap.FindKey(i);
-      Nodes(i) = Pnt(index);
-      Nodes2d(i).SetXY(Vertex(index).Coord());
-    }
-    
-    T->Deflection(theDefFace);
-    BRepMesh_ShapeTool::AddInFace(theFace, T);
-
-    // implement polygons on triangulation in the face:
-    BRepMeshCol::DMapOfShapePairOfPolygon::Iterator It(myInternaledges);
-
-    for (; It.More(); It.Next()) {
-      const TopoDS_Edge& aEdge = TopoDS::Edge(It.Key());
-      const BRepMesh_PairOfPolygon& pair = It.Value();
-      const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First();
-      const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last();
 
-      // lock mutex to prevent parallel change of the same data
-      Standard_Mutex* aMutex = theMutexProvider.GetMutex(It.Key());
-      Standard_Mutex::Sentry aSentry (aMutex);
+    if (theIsFirst)
+      continue;
 
-      if ( NOD1 == NOD2 ) {
-        BRepMesh_ShapeTool::NullifyEdge(aEdge, TOld, loc);
-        BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, T, loc);
-      }
-      else {
-        BRepMesh_ShapeTool::NullifyEdge(aEdge, TOld, loc);
-        BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, NOD2, T, loc);
-      }
-    }
+    if (addVerticesToMesh(theNewVertices, theTrigu))
+      ++aInsertedNb;
   }
- }
-
- catch(Standard_Failure)
- {
-   //   MESH_FAILURE(theFace);
- }
-}
-
-
-//=======================================================================
-//function : Triangle
-//purpose  : 
-//=======================================================================
 
-const BRepMesh_Triangle& BRepMesh_FastDiscretFace::Triangle(const Standard_Integer Index) const
-{
-  return myStructure->GetElement(Index);
+  return (aMaxSqDef < 0) ? aMaxSqDef : Sqrt(aMaxSqDef);
 }
 
 //=======================================================================
-//function : NbEdges
+//function : add
 //purpose  : 
 //=======================================================================
-
-/*Standard_Integer BRepMesh_FastDiscretFace::NbEdges() const
+void BRepMesh_FastDiscretFace::add(const TopoDS_Vertex& theVertex)
 {
-  return myStructure->NbLinks();
-}*/
-
-//=======================================================================
-//function : Edge
-//purpose  : 
-//=======================================================================
+  if (theVertex.Orientation() != TopAbs_INTERNAL)
+    return;
 
-const BRepMesh_Edge& BRepMesh_FastDiscretFace::Edge(const Standard_Integer Index) const
-{
-  return myStructure->GetLink(Index);
-}
+  try
+  {
+    OCC_CATCH_SIGNALS
 
+    gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, myAttribute->Face());
 
-//=======================================================================
-//function : Vertex
-//purpose  : 
-//=======================================================================
+    N_HANDLE<FixedVExplorer> aFixedVExplorer = new FixedVExplorer(theVertex);
+    Standard_Integer aIndex = myAttribute->GetVertexIndex(aFixedVExplorer);
+    gp_XY anUV = BRepMesh_ShapeTool::FindUV(aIndex, aPnt2d,
+      theVertex, BRep_Tool::Tolerance(theVertex), myAttribute);
 
-const BRepMesh_Vertex& BRepMesh_FastDiscretFace::Vertex(const Standard_Integer Index) const
-{
-  return myStructure->GetNode(Index);
+    Standard_Integer aTmpId1, aTmpId2;
+    myAttribute->AddNode(aIndex, anUV, BRepMesh_Fixed, aTmpId1, aTmpId2);
+  }
+  catch (Standard_Failure)
+  {
+  }
 }
 
 //=======================================================================
-//function : Pnt
+//function : insertVertex
 //purpose  : 
 //=======================================================================
-
-const gp_Pnt& BRepMesh_FastDiscretFace::Pnt(const Standard_Integer Index) const
+void BRepMesh_FastDiscretFace::insertVertex(
+  const gp_Pnt&              thePnt3d,
+  const gp_XY&               theUV,
+  BRepMeshCol::ListOfVertex& theVertices)
 {
-  return myLocation3d(myStructure->GetNode(Index).Location3d());
-}
+  Standard_Integer aNbLocat = myAttribute->LastPointId();
+  mySurfacePoints->Bind(++aNbLocat, thePnt3d);
 
-static Standard_Boolean GetVertexParameters(const TopoDS_Vertex& theVert, 
-                                            const TopoDS_Face& theFace,
-                                            gp_Pnt2d& thePoint)
-{
-  TopLoc_Location L;
-  const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,L);
-  L = L.Predivided(theVert.Location());
-  BRep_ListIteratorOfListOfPointRepresentation itpr =
-    ((*((Handle(BRep_TVertex)*) &theVert.TShape()))->Points());
-  // Check first if there are PointRepresentation (case non Manifold)
-
-  while (itpr.More()) {
-    if (itpr.Value()->IsPointOnSurface(S,L)) {
-      thePoint.SetCoord(itpr.Value()->Parameter(),
-                        itpr.Value()->Parameter2());
-      return Standard_True;
-    }
-    itpr.Next();
-  }
-  return Standard_False;
-}
-
-//=======================================================================
-//function : Add
-//purpose  : method intended to add internal myVertices in triangulation.
-//=======================================================================
-void BRepMesh_FastDiscretFace::Add(const TopoDS_Vertex&                theVert, 
-                                   const TopoDS_Face&                  theFace, 
-                                   const Handle(BRepAdaptor_HSurface)& thegFace)
-{
-  const TopAbs_Orientation anOrient = theVert.Orientation();
-  gp_Pnt2d uvXY;
-  if( anOrient != TopAbs_INTERNAL || !GetVertexParameters(theVert,theFace,uvXY))
-    return;
-  Standard_Integer indVert =0;
-  if (myVertices.IsBound(theVert))
-    indVert = myVertices.Find(theVert);
-  else
-  {
-    myNbLocat++;
-    myLocation3d.Bind(myNbLocat, BRep_Tool::Pnt(theVert));
-    indVert = myNbLocat;
-    myVertices.Bind(theVert, indVert);
-  }
-  Standard_Real mindist = BRep_Tool::Tolerance(theVert);
-  // gp_Pnt2d uvXY = BRep_Tool::Parameters(theVert,theFace);
-  gp_XY anUV = BRepMesh_ShapeTool::FindUV(indVert, uvXY,
-    theVert, mindist, myAttrib, thegFace, myLocation2d);
-
-  BRepMesh_Vertex vf(anUV, indVert, BRepMesh_Fixed);
-  Standard_Integer ivff = myStructure->AddNode(vf);
-  Standard_Integer isvf = myVemap.FindIndex(ivff);
-  if (isvf == 0) isvf = myVemap.Add(ivff);  
-}
+  gp_XY aPnt2d  = myAttribute->Scale(theUV, Standard_True);
+  BRepMesh_Vertex aVertex(aPnt2d, aNbLocat, BRepMesh_Free);
+  theVertices.Append(aVertex);
+}
\ No newline at end of file
index bb42352..74fdc90 100644 (file)
@@ -26,6 +26,8 @@
 #include <Handle_Poly_Triangulation.hxx>
 #include <BRepMesh_Delaun.hxx>
 #include <BRepMesh_Triangle.hxx>
+#include <BRepMesh_Classifier.hxx>
+#include <ElSLib.hxx>
 
 class BRepMesh_DataStructureOfDelaun;
 class BRepMesh_FaceAttribute;
@@ -43,83 +45,113 @@ class BRepMesh_Vertex;
 class gp_Pnt;
 
 //! Algorithm to mesh a face with respect of the frontier 
-//! the deflection and by option the shared components. <br>
+//! the deflection and by option the shared components.
 class BRepMesh_FastDiscretFace : public Standard_Transient 
 {
 public:
 
-  
+
   Standard_EXPORT BRepMesh_FastDiscretFace(const Standard_Real theAngle,
                                            const Standard_Boolean theWithShare = Standard_True);
-  
-  Standard_EXPORT void Add(const TopoDS_Face& theFace,
-                           const Handle(BRepMesh_FaceAttribute)& theAttrib,
-                           const TopTools_DataMapOfShapeReal& theMapDefle,
-                           const TopTools_MutexForShapeProvider& theMutexProvider);
-  
-  Standard_EXPORT Standard_Real Control(const Handle(BRepAdaptor_HSurface)& theCaro,
-                                        const Standard_Real theDefFace,
-                                        BRepMeshCol::ListOfVertex& theInternalV,
-                                        BRepMeshCol::ListOfInteger& theBadTriangles,
-                                        BRepMeshCol::ListOfInteger& theNulTriangles,
-                                        BRepMesh_Delaun& theTrigu,
-                                        const Standard_Boolean theIsFirst);
+
+  Standard_EXPORT void Add(const Handle(BRepMesh_FaceAttribute)& theAttribute);
 
   //! Gives the triangle of <Index>. <br>
   Standard_EXPORT const BRepMesh_Triangle& Triangle(const Standard_Integer theIndex) const;
 
-  //! Gives the edge of index <Index>. <br>
-  Standard_EXPORT const BRepMesh_Edge& Edge(const Standard_Integer theIndex) const;
+  DEFINE_STANDARD_RTTI(BRepMesh_FastDiscretFace)
 
-  //! Gives the vertex of <Index>. <br>
-  Standard_EXPORT const BRepMesh_Vertex& Vertex(const Standard_Integer theIndex) const;
+private:
 
-  //! Gives the location3d of the vertex of <Index>. <br>
-  Standard_EXPORT const gp_Pnt& Pnt(const Standard_Integer theIndex) const;
+  void add(const TopoDS_Vertex& theVertex);
 
-  DEFINE_STANDARD_RTTI(BRepMesh_FastDiscretFace)
+  Standard_Real control(BRepMeshCol::ListOfVertex&  theNewVertices,
+                        BRepMesh_Delaun&            theMeshBuilder,
+                        const Standard_Boolean      theIsFirst);
 
-protected:
-  Standard_Boolean RestoreStructureFromTriangulation(const TopoDS_Edge& theEdge,
-                                                     const TopoDS_Face& theFace,
-                                                     const Handle(BRepAdaptor_HSurface)& theSurf,
-                                                     const Handle(Poly_Triangulation)& theTrigu,
-                                                     const Standard_Real theDefEdge,
-                                                     const TopLoc_Location& theLoc,
-                                                     const TopTools_MutexForShapeProvider& theMutexProvider);
-
-private: 
-  
-  void Add(const TopoDS_Vertex& theVert,
-           const TopoDS_Face& theFace,
-           const Handle(BRepAdaptor_HSurface)& theSFace);
-  
-  void InternalVertices(const Handle(BRepAdaptor_HSurface)& theCaro,
-                        BRepMeshCol::ListOfVertex& theInternalV,
-                        const Standard_Real theDefFace,
-                        const BRepMeshCol::HClassifier& theClassifier);
+  //! Registers the given nodes in mesh data structure and
+  //! performs refinement of existing mesh.
+  //! @param theVertices nodes to be inserted.
+  //! @param theMeshBuilder initialized tool refining mesh 
+  //! in respect to inserting nodes.
+  //! @return TRUE if vertices were been inserted, FALSE elewhere.
+  Standard_Boolean addVerticesToMesh(
+    const BRepMeshCol::ListOfVertex& theVertices,
+    BRepMesh_Delaun&                 theMeshBuilder);
+
+  //! Calculates nodes lying on face's surface and inserts them to a mesh.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  //! @param theMeshBuilder initialized tool refining mesh 
+  //! in respect to inserting nodes.
+  void insertInternalVertices(BRepMeshCol::ListOfVertex&  theNewVertices,
+                              BRepMesh_Delaun&            theMeshBuilder);
+
+  //! Calculates nodes lying on spherical surface.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  void insertInternalVerticesSphere(BRepMeshCol::ListOfVertex& theNewVertices);
+
+  //! Calculates nodes lying on cylindrical surface.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  void insertInternalVerticesCylinder(BRepMeshCol::ListOfVertex& theNewVertices);
+
+  //! Calculates nodes lying on conical surface.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  void insertInternalVerticesCone(BRepMeshCol::ListOfVertex& theNewVertices);
+
+  //! Calculates nodes lying on toroidal surface.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  void insertInternalVerticesTorus(BRepMeshCol::ListOfVertex& theNewVertices);
+
+  //! Calculates nodes lying on Bezier/BSpline surface.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  void insertInternalVerticesBSpline(BRepMeshCol::ListOfVertex& theNewVertices);
+
+  //! Calculates nodes lying on custom-type surface.
+  //! @param theNewVertices list of vertices to be extended and added to mesh.
+  void insertInternalVerticesOther(BRepMeshCol::ListOfVertex& theNewVertices);
   
-  void AddInShape(const TopoDS_Face& theFace,
-                  const Standard_Real theDefFace,
-                  const TopTools_MutexForShapeProvider& theMutexProvider);
+  //! Template method trying to insert new internal vertex corresponded to
+  //! the given 2d point. Calculates 3d position analytically using the given
+  //! surface.
+  //! @param thePnt2d 2d point to be inserted to the list.
+  //! @param theAnalyticSurface analytic surface to calculate 3d point.
+  //! @param[out] theVertices list of vertices to be updated.
+  template<class AnalyticSurface>
+  void tryToInsertAnalyticVertex(const gp_Pnt2d&            thePnt2d,
+                                 const AnalyticSurface&     theAnalyticSurface,
+                                 BRepMeshCol::ListOfVertex& theVertices)
+  {
+    if (!myClassifier->Perform(thePnt2d) == TopAbs_IN)
+      return;
+
+    gp_Pnt aPnt;
+    ElSLib::D0(thePnt2d.X(), thePnt2d.Y(), theAnalyticSurface, aPnt);
+    insertVertex(aPnt, thePnt2d.Coord(), theVertices);
+  }
+
+  //! Creates new vertex with the given parameters.
+  //! @param thePnt3d 3d point corresponded to the vertex.
+  //! @param theUV UV point corresponded to the vertex.
+  //! @param[out] theVertices list of vertices to be updated.
+  void insertVertex(const gp_Pnt&              thePnt3d,
+                    const gp_XY&               theUV,
+                    BRepMeshCol::ListOfVertex& theVertices);
 
 private:
+
   Standard_Real                             myAngle;
   Standard_Boolean                          myWithShare;
-  BRepMeshCol::DMapOfVertexInteger          myVertices;
-  BRepMeshCol::DMapOfShapePairOfPolygon     myInternaledges;
-  Standard_Integer                          myNbLocat;
-  BRepMeshCol::DMapOfIntegerPnt             myLocation3d;
-  Handle_BRepMesh_DataStructureOfDelaun     myStructure;
-  BRepMeshCol::ListOfVertex                 myListver;
-  BRepMeshCol::IMapOfInteger                myVemap;
-  BRepMeshCol::DMapOfIntegerListOfXY        myLocation2d;
-  Handle_BRepMesh_FaceAttribute             myAttrib;
   Standard_Boolean                          myInternalVerticesMode;
   BRepMeshCol::IMapOfReal                   myUParam;
   BRepMeshCol::IMapOfReal                   myVParam;
   BRepMeshCol::Allocator                    myAllocator;
+
+  // Fast access to attributes of current face
+  Handle(BRepMesh_FaceAttribute)            myAttribute;
+  Handle(BRepMesh_DataStructureOfDelaun)    myStructure;
+  BRepMeshCol::HIMapOfInteger               myVertexEdgeMap;
+  BRepMeshCol::HClassifier                  myClassifier;
+  BRepMeshCol::HDMapOfIntegerPnt            mySurfacePoints;
 };
 
 DEFINE_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient)
diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.cxx b/src/BRepMesh/BRepMesh_IEdgeTool.cxx
new file mode 100644 (file)
index 0000000..c000b51
--- /dev/null
@@ -0,0 +1,19 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_IEdgeTool.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (BRepMesh_IEdgeTool, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IEdgeTool, Standard_Transient)
diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.hxx b/src/BRepMesh/BRepMesh_IEdgeTool.hxx
new file mode 100644 (file)
index 0000000..6d7624d
--- /dev/null
@@ -0,0 +1,46 @@
+// Created on: 2014-08-13
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_IEdgeTool_HeaderFile
+#define _BRepMesh_IEdgeTool_HeaderFile
+
+#include <Standard.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Pnt2d.hxx>
+#include <Standard_Transient.hxx>
+
+//! Interface class providing API for edge tessellation tools.
+class BRepMesh_IEdgeTool : public Standard_Transient
+{
+public:
+  //! Returns number of tessellation points.
+  virtual Standard_Integer NbPoints() const = 0;
+
+  //! Returns parameters of solution with the given index.
+  //! @param theIndex index of tessellation point.
+  //! @param theParameter parameters on PCurve corresponded to the solution.
+  //! @param thePoint tessellation point.
+  //! @param theUV coordinates of tessellation point in parametric space of face.
+  virtual void Value(const Standard_Integer theIndex,
+                     Standard_Real&         theParameter,
+                     gp_Pnt&                thePoint,
+                     gp_Pnt2d&              theUV) = 0;
+
+  DEFINE_STANDARD_RTTI(BRepMesh_IEdgeTool)
+};
+
+DEFINE_STANDARD_HANDLE(BRepMesh_IEdgeTool, Standard_Transient)
+
+#endif
index e313ce7..4fd3418 100644 (file)
@@ -17,7 +17,7 @@
 #include <BRepMesh_IncrementalMesh.hxx>
 
 #include <Precision.hxx>
-#include <Standard_Mutex.hxx>
+#include <Standard_ErrorHandler.hxx>
 
 #include <BRepMesh_FaceChecker.hxx>
 #include <BRepMesh_ShapeTool.hxx>
 #include <TopExp_Explorer.hxx>
 
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_MutexForShapeProvider.hxx>
 #include <TColgp_Array1OfPnt.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TopTools_HArray1OfShape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 
 #include <GCPnts_TangentialDeflection.hxx>
 
@@ -90,10 +91,10 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(
   : myRelative  (isRelative),
     myInParallel(isInParallel)
 {
-  myDeflection = theLinDeflection;
-  myAngle      = theAngDeflection;
-  myShape      = theShape;
-
+  myDeflection  = theLinDeflection;
+  myAngle       = theAngDeflection;
+  myShape       = theShape;
+  
   Perform();
 }
 
@@ -115,7 +116,6 @@ void BRepMesh_IncrementalMesh::init()
   myModified = Standard_False;
 
   myEdgeDeflection.Clear();
-  mySharedFaces.Clear();
   myFaces.clear();
 
   setDone();
@@ -129,15 +129,16 @@ void BRepMesh_IncrementalMesh::init()
   if (aBox.IsVoid())
   {
     // Nothing to mesh.
-    myMesher.Nullify();
+    myMesh.Nullify();
     return;
   }
 
   BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
-  TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
 
-  myMesher = new BRepMesh_FastDiscret(myDeflection, myAngle, aBox,
+  myMesh = new BRepMesh_FastDiscret(myDeflection, myAngle, aBox,
     Standard_True, Standard_True, myRelative, Standard_True, myInParallel);
+
+  myMesh->InitSharedFaces(myShape);
 }
 
 //=======================================================================
@@ -208,7 +209,7 @@ void BRepMesh_IncrementalMesh::Perform()
 {
   init();
 
-  if (myMesher.IsNull())
+  if (myMesh.IsNull())
     return;
 
   update();
@@ -240,20 +241,18 @@ void BRepMesh_IncrementalMesh::update()
 #ifdef HAVE_TBB
   if (myInParallel)
   {
-    myMesher->CreateMutexesForSubShapes(myShape, TopAbs_EDGE);
-    tbb::parallel_for_each(myFaces.begin(), myFaces.end(), *myMesher);
-    myMesher->RemoveAllMutexes();
+    tbb::parallel_for_each(myFaces.begin(), myFaces.end(), *myMesh);
   }
   else
   {
 #endif
     for (aFaceIt = myFaces.begin(); aFaceIt != myFaces.end(); aFaceIt++)
-      myMesher->Process(*aFaceIt);
+      myMesh->Process(*aFaceIt);
 #ifdef HAVE_TBB
   }
 #endif
 
-  discretizeFreeEdges();
+  commit();
 }
 
 //=======================================================================
@@ -361,8 +360,11 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
 
     if (!aTriangulation.IsNull() && !aPolygon.IsNull())
     {
-      if (aPolygon->Deflection() < 1.1 * aEdgeDeflection)
+      if (aPolygon->Deflection() < 1.1 * aEdgeDeflection &&
+          aPolygon->HasParameters())
+      {
         continue;
+      }
 
       myModified = Standard_True;
       BRepMesh_ShapeTool::NullifyEdge(theEdge, aTriangulation, aLoc);
@@ -371,7 +373,8 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
     if (!myEmptyEdges.IsBound(theEdge))
       myEmptyEdges.Bind(theEdge, BRepMeshCol::MapOfTriangulation());
 
-    myEmptyEdges(theEdge).Add(aTriangulation);
+    if (!aTriangulation.IsNull())
+      myEmptyEdges(theEdge).Add(aTriangulation);
   }
   while (!aPolygon.IsNull());
 }
@@ -404,7 +407,8 @@ Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed(
         if (!myEmptyEdges.IsBound(aEdge))
           continue;
 
-        isEdgesConsistent &= myEmptyEdges(aEdge).Contains(aTriangulation);
+        BRepMeshCol::MapOfTriangulation& aTriMap = myEmptyEdges(aEdge);
+        isEdgesConsistent &= !aTriMap.IsEmpty() && !aTriMap.Contains(aTriangulation);
       }
 
       if (isEdgesConsistent)
@@ -434,24 +438,26 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
     return;
 
   myModified = Standard_True;
-  myMesher->Add(theFace, mySharedFaces);
+  Standard_Integer aStatus = myMesh->Add(theFace);
 
-  BRepMesh_Status aStatus = myMesher->CurrentFaceStatus();
-  myStatus |= (Standard_Integer)aStatus;
+  myStatus |= aStatus;
   if (aStatus != BRepMesh_ReMesh)
     return;
 
   BRepMeshCol::MapOfShape aUsedFaces;
   aUsedFaces.Add(theFace);
 
+  const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces = 
+    myMesh->SharedFaces();
+
   TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
   for (; aEdgeIt.More(); aEdgeIt.Next())
   {
     const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
-    if (mySharedFaces.FindIndex(aEdge) == 0)
+    if (aMapOfSharedFaces.FindIndex(aEdge) == 0)
       continue;
      
-    const TopTools_ListOfShape& aSharedFaces = mySharedFaces.FindFromKey(aEdge);
+    const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge);
     TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
     for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
     {
@@ -462,9 +468,120 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
       aUsedFaces.Add(aFace);
       toBeMeshed(aFace, Standard_False);
 
-      myMesher->Add(aFace, mySharedFaces);
-      myStatus |= (Standard_Integer)myMesher->CurrentFaceStatus();
+      myStatus |= myMesh->Add(aFace);
+    }
+  }
+}
+
+//=======================================================================
+//function : commit
+//purpose  : 
+//=======================================================================
+void BRepMesh_IncrementalMesh::commit()
+{
+  std::vector<TopoDS_Face>::iterator aFaceIt(myFaces.begin());
+  for (; aFaceIt != myFaces.end(); aFaceIt++)
+    commitFace(*aFaceIt);
+
+  discretizeFreeEdges();
+}
+
+//=======================================================================
+//function : commitFace
+//purpose  : 
+//=======================================================================
+void BRepMesh_IncrementalMesh::commitFace(const TopoDS_Face& theFace)
+{
+  TopoDS_Face aFace = theFace;
+  aFace.Orientation(TopAbs_FORWARD);
+
+  Handle(BRepMesh_FaceAttribute) aFaceAttribute;
+  if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute))
+    return;
+
+  BRepMesh_ShapeTool::NullifyFace(aFace);
+
+  if (!aFaceAttribute->IsValid())
+  {
+    myStatus |= aFaceAttribute->GetStatus();
+    return;
+  }
+
+  TopLoc_Location            aLoc = aFace.Location();
+  Handle(Poly_Triangulation) aOldTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
+
+  try
+  {
+    OCC_CATCH_SIGNALS
+
+    Handle(BRepMesh_DataStructureOfDelaun)& aStructure = aFaceAttribute->ChangeStructure();
+    const BRepMeshCol::MapOfInteger&        aTriangles = aStructure->ElementsOfDomain();
+    if (aTriangles.IsEmpty())
+      return;
+
+    BRepMeshCol::HIMapOfInteger& aVetrexEdgeMap = aFaceAttribute->ChangeVertexEdgeMap();
+
+    // Store triangles
+    Standard_Integer aVerticesNb  = aVetrexEdgeMap->Extent();
+    Standard_Integer aTrianglesNb = aTriangles.Extent();
+    Handle(Poly_Triangulation) aNewTriangulation =
+      new Poly_Triangulation(aVerticesNb, aTrianglesNb, Standard_True);
+
+    Poly_Array1OfTriangle& aPolyTrianges = aNewTriangulation->ChangeTriangles();
+
+    Standard_Integer aTriangeId = 1;
+    BRepMeshCol::MapOfInteger::Iterator aTriIt(aTriangles);
+    for (; aTriIt.More(); aTriIt.Next())
+    {
+      const BRepMesh_Triangle& aCurElem = aStructure->GetElement(aTriIt.Key());
+
+      Standard_Integer aNode[3];
+      aStructure->ElementNodes(aCurElem, aNode);
+
+      Standard_Integer aNodeId[3];
+      for (Standard_Integer i = 0; i < 3; ++i)
+        aNodeId[i] = aVetrexEdgeMap->FindIndex(aNode[i]);
+
+      aPolyTrianges(aTriangeId++).Set(aNodeId[0], aNodeId[1], aNodeId[2]);
+    }
+
+    // Store mesh nodes
+    TColgp_Array1OfPnt&   aNodes   = aNewTriangulation->ChangeNodes();
+    TColgp_Array1OfPnt2d& aNodes2d = aNewTriangulation->ChangeUVNodes();
+
+    for (Standard_Integer i = 1; i <= aVerticesNb; ++i)
+    {
+      Standard_Integer       aVertexId = aVetrexEdgeMap->FindKey(i);
+      const BRepMesh_Vertex& aVertex   = aStructure->GetNode(aVertexId);
+      const gp_Pnt&          aPoint    = aFaceAttribute->GetPoint(aVertex);
+
+      aNodes(i)   = aPoint;
+      aNodes2d(i) = aVertex.Coord();
     }
+
+    aNewTriangulation->Deflection(aFaceAttribute->GetDefFace());
+    BRepMesh_ShapeTool::AddInFace(aFace, aNewTriangulation);
+
+    // Store discretization of edges
+    BRepMeshCol::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges();
+    BRepMeshCol::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges);
+    for (; aEdgeIt.More(); aEdgeIt.Next())
+    {
+      const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key());
+      const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value();
+      const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First();
+      const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last();
+
+      BRepMesh_ShapeTool::NullifyEdge(aEdge, aOldTriangulation, aLoc);
+      if (aPolygon1 == aPolygon2)
+        BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aNewTriangulation, aLoc);
+      else
+        BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aNewTriangulation, aLoc);
+    }
+  }
+  catch (Standard_Failure)
+  {
+    myStatus |= BRepMesh_Failure;
   }
 }
 
@@ -476,7 +593,7 @@ Standard_Integer BRepMesh_IncrementalMesh::Discret(
   const TopoDS_Shape&    theShape,
   const Standard_Real    theDeflection,
   const Standard_Real    theAngle,
-  BRepMesh_PDiscretRoot& theAlgo)
+  BRepMesh_DiscretRoot* &theAlgo)
 {
   BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
   anAlgo->SetDeflection(theDeflection);
index 83a044b..7e53483 100644 (file)
@@ -20,9 +20,7 @@
 #include <BRepMesh_FastDiscret.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopTools_DataMapOfShapeReal.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <BRepMesh_DiscretRoot.hxx>
-#include <BRepMesh_PDiscretRoot.hxx>
 #include <Handle_Poly_Triangulation.hxx>
 #include <BRepMesh_Collections.hxx>
 
@@ -116,7 +114,7 @@ public: //! \name plugin API
   Standard_EXPORT static Standard_Integer Discret(const TopoDS_Shape&    theShape,
                                                   const Standard_Real    theLinDeflection,
                                                   const Standard_Real    theAngDeflection,
-                                                  BRepMesh_PDiscretRoot& theAlgo);
+                                                  BRepMesh_DiscretRoot* &theAlgo);
   
   //! Returns multi-threading usage flag set by default in 
   //! Discret() static method (thus applied only to Mesh Factories).
@@ -126,6 +124,11 @@ public: //! \name plugin API
   //! Discret() static method (thus applied only to Mesh Factories).
   Standard_EXPORT static void SetParallelDefault(const Standard_Boolean isInParallel);
 
+  //! Returns mesh tool storing mesh data.
+  inline const Handle(BRepMesh_FastDiscret)& Mesh() const
+  {
+    return myMesh;
+  }
 
   DEFINE_STANDARD_RTTI(BRepMesh_IncrementalMesh)
 
@@ -183,18 +186,23 @@ private:
   Standard_Boolean toBeMeshed(const TopoDS_Face&     theFace,
                               const Standard_Boolean isWithCheck);
 
+  //! Stores mesh to the shape.
+  void commit();
+
+  //! Stores mesh to the face.
+  void commitFace(const TopoDS_Face& theFace);
+
 protected:
 
-  Standard_Boolean                            myRelative;
-  Standard_Boolean                            myInParallel;
-  BRepMeshCol::DMapOfEdgeListOfTriangulation  myEmptyEdges;
-  Handle(BRepMesh_FastDiscret)                myMesher;
-  Standard_Boolean                            myModified;
-  TopTools_DataMapOfShapeReal                 myEdgeDeflection;
-  TopTools_IndexedDataMapOfShapeListOfShape   mySharedFaces;
-  Standard_Real                               myMaxShapeSize;
-  Standard_Integer                            myStatus;
-  std::vector<TopoDS_Face>                    myFaces;
+  Standard_Boolean                                    myRelative;
+  Standard_Boolean                                    myInParallel;
+  BRepMeshCol::DMapOfEdgeListOfTriangulation          myEmptyEdges;
+  Handle(BRepMesh_FastDiscret)                        myMesh;
+  Standard_Boolean                                    myModified;
+  TopTools_DataMapOfShapeReal                         myEdgeDeflection;
+  Standard_Real                                       myMaxShapeSize;
+  Standard_Integer                                    myStatus;
+  std::vector<TopoDS_Face>                            myFaces;
 };
 
 DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
index 4da575e..c2769ee 100644 (file)
@@ -21,13 +21,13 @@ extern "C" {                                                              \
   Standard_EXPORT Standard_Integer DISCRETALGO(const TopoDS_Shape& ,      \
                                                const Standard_Real,       \
                                                const Standard_Real,       \
-                                               BRepMesh_PDiscretRoot& );  \
+                                               BRepMesh_DiscretRoot* &);  \
 }                                                                         \
                                                                           \
-Standard_Integer DISCRETALGO(const TopoDS_Shape&     theShape,            \
-                             const Standard_Real     theLinDeflection,    \
-                             const Standard_Real     theAngDeflection,    \
-                             BRepMesh_PDiscretRoot&  theAlgo)             \
+Standard_Integer DISCRETALGO(const TopoDS_Shape&    theShape,             \
+                             const Standard_Real    theLinDeflection,     \
+                             const Standard_Real    theAngDeflection,     \
+                             BRepMesh_DiscretRoot* &theAlgo)              \
 {                                                                         \
   return name::Discret(theShape, theLinDeflection,                        \
     theAngDeflection, theAlgo);                                           \
index 9a70db7..38cc71a 100644 (file)
@@ -24,6 +24,8 @@
 #include <TColgp_Array1OfPnt.hxx>
 #include <Poly_Triangulation.hxx>
 #include <BRep_Builder.hxx>
+#include <TopExp.hxx>
+#include <BRepAdaptor_Curve.hxx>
 
 namespace {
   //! Auxilary struct to take a tolerance of edge.
@@ -108,7 +110,7 @@ Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection(
     return aDefEdge;
 
   Bnd_Box aBox;
-  BRepBndLib::Add(theEdge, aBox);
+  BRepBndLib::Add(theEdge, aBox, Standard_False);
   BoxMaxDimension(aBox, aDefEdge);
             
   // Adjust resulting value in relation to the total size
@@ -126,25 +128,25 @@ Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection(
 //purpose  : 
 //=======================================================================
 gp_XY BRepMesh_ShapeTool::FindUV(
-    const Standard_Integer                theIndexOfPnt3d,
-    const gp_Pnt2d&                       thePnt2d,
-    const TopoDS_Vertex&                  theVertex,
-    const Standard_Real                   theMinDistance,
-    const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
-    const Handle(BRepAdaptor_HSurface)&   theSurface,
-    BRepMeshCol::DMapOfIntegerListOfXY&   theLocation2dMap)
+  const Standard_Integer                theIndexOfPnt3d,
+  const gp_Pnt2d&                       thePnt2d,
+  const TopoDS_Vertex&                  theVertex,
+  const Standard_Real                   theMinDistance,
+  const Handle(BRepMesh_FaceAttribute)& theFaceAttribute)
 {
   const gp_XY& aPnt2d = thePnt2d.Coord();
-  if (!theLocation2dMap.IsBound(theIndexOfPnt3d))
+  BRepMeshCol::DMapOfIntegerListOfXY& aLocation2D =
+    theFaceAttribute->ChangeLocation2D();
+
+  if (!aLocation2D.IsBound(theIndexOfPnt3d))
   {
     BRepMeshCol::ListOfXY aPoints2d;
     aPoints2d.Append(aPnt2d);
-    theLocation2dMap.Bind(theIndexOfPnt3d, aPoints2d);
+    aLocation2D.Bind(theIndexOfPnt3d, aPoints2d);
     return aPnt2d;
   }
 
-  BRepMeshCol::ListOfXY& aPoints2d = 
-    theLocation2dMap.ChangeFind(theIndexOfPnt3d);
+  BRepMeshCol::ListOfXY& aPoints2d = aLocation2D.ChangeFind(theIndexOfPnt3d);
 
   // Find the most closest 2d point to the given one.
   gp_XY aUV;
@@ -166,23 +168,15 @@ gp_XY BRepMesh_ShapeTool::FindUV(
     Min(2. * BRep_Tool::Tolerance(theVertex), theMinDistance);
 
   // Get face limits
-  Standard_Real aDiffU, aDiffV;
-  if (theFaceAttribute.IsNull())
-  {
-    aDiffU = theSurface->LastUParameter() - theSurface->FirstUParameter();
-    aDiffV = theSurface->LastVParameter() - theSurface->FirstVParameter();
-  }
-  else
-  {
-    aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin();
-    aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin();
-  }
+  Standard_Real aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin();
+  Standard_Real aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin();
 
   const Standard_Real Utol2d = .5 * aDiffU;
   const Standard_Real Vtol2d = .5 * aDiffV;
 
-  const gp_Pnt aPnt1 = theSurface->Value(   aUV.X(),    aUV.Y());
-  const gp_Pnt aPnt2 = theSurface->Value(aPnt2d.X(), aPnt2d.Y());
+  const Handle(BRepAdaptor_HSurface)& aSurface = theFaceAttribute->Surface();
+  const gp_Pnt aPnt1 = aSurface->Value(aUV.X(), aUV.Y());
+  const gp_Pnt aPnt2 = aSurface->Value(aPnt2d.X(), aPnt2d.Y());
 
   //! If selected point is too far from the given one in parametric space
   //! or their positions in 3d are different, add the given point as unique.
@@ -272,3 +266,65 @@ void BRepMesh_ShapeTool::UpdateEdge(
   aBuilder.UpdateEdge(theEdge, thePolygon1, thePolygon2, 
     theTriangulation, theLocation);
 }
+
+//=======================================================================
+//function : UseLocation
+//purpose  : 
+//=======================================================================
+gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt&          thePnt,
+                                       const TopLoc_Location& theLoc)
+{
+  if (theLoc.IsIdentity())
+    return thePnt;
+
+  return thePnt.Transformed(theLoc.Transformation());
+}
+
+//=======================================================================
+//function : IsDegenerated
+//purpose  : 
+//=======================================================================
+Standard_Boolean BRepMesh_ShapeTool::IsDegenerated(
+  const TopoDS_Edge& theEdge,
+  const TopoDS_Face& theFace)
+{
+  // Get vertices
+  TopoDS_Vertex pBegin, pEnd;
+  TopExp::Vertices(theEdge, pBegin, pEnd);
+  if (pBegin.IsNull() || pEnd.IsNull())
+    return Standard_True;
+
+  if (BRep_Tool::Degenerated(theEdge))
+    return Standard_True;
+
+  if (!pBegin.IsSame(pEnd))
+    return Standard_False;
+
+  Standard_Real wFirst, wLast;
+  BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
+
+  // calculation of the length of the edge in 3D
+  Standard_Real longueur = 0.0;
+  Standard_Real du = (wLast - wFirst) * 0.05;
+  gp_Pnt P1, P2;
+  BRepAdaptor_Curve BC(theEdge);
+  BC.D0(wFirst, P1);
+  Standard_Real tolV = BRep_Tool::Tolerance(pBegin);
+  Standard_Real tolV2 = 1.2 * tolV;
+
+  for (Standard_Integer l = 1; l <= 20; ++l)
+  {
+    BC.D0(wFirst + l * du, P2);
+    longueur += P1.Distance(P2);
+
+    if (longueur > tolV2)
+      break;
+
+    P1 = P2;
+  }
+
+  if (longueur < tolV2)
+    return Standard_True;
+
+  return Standard_False;
+}
index 5c94663..9486d21 100644 (file)
@@ -43,18 +43,18 @@ public:
 
   //! Gets the maximum dimension of the given bounding box.
   //! If the given bounding box is void leaves the resulting value unchanged.
-  //! \param theBox bounding box to be processed.
-  //! \param theMaxDimension maximum dimension of the given box.
+  //! @param theBox bounding box to be processed.
+  //! @param theMaxDimension maximum dimension of the given box.
   Standard_EXPORT static void BoxMaxDimension(const Bnd_Box& theBox,
                                               Standard_Real& theMaxDimension);
 
   //! Returns relative deflection for edge with respect to shape size.
-  //! \param theEdge edge for which relative deflection should be computed.
-  //! \param theDeflection absolute deflection.
-  //! \param theMaxShapeSize maximum size of a shape.
-  //! \param theAdjustmentCoefficient coefficient of adjustment between maximum 
+  //! @param theEdge edge for which relative deflection should be computed.
+  //! @param theDeflection absolute deflection.
+  //! @param theMaxShapeSize maximum size of a shape.
+  //! @param theAdjustmentCoefficient coefficient of adjustment between maximum 
   //! size of shape and calculated relative deflection.
-  //! \return relative deflection for the edge.
+  //! @return relative deflection for the edge.
   Standard_EXPORT static Standard_Real RelativeEdgeDeflection(
     const TopoDS_Edge&  theEdge,
     const Standard_Real theDeflection,
@@ -63,24 +63,21 @@ public:
 
   //! Checks 2d representations of 3d point with the 
   //! given index for equality to avoid duplications.
-  //! \param theIndexOfPnt3d index of 3d point with which 2d 
+  //! @param theIndexOfPnt3d index of 3d point with which 2d 
   //! representation should be associated.
-  //! \param thePnt2d 2d representation of the point with the 
+  //! @param thePnt2d 2d representation of the point with the 
   //! given index.
-  //! \param theVertex vertex corresponded to 3d point with the 
+  //! @param theVertex vertex corresponded to 3d point with the 
   //! given index. Used to extract vertex tolerance in 3d space.
-  //! \param theMinDistance minimum distance between vertices 
+  //! @param theMinDistance minimum distance between vertices 
   //! regarding which they could be treated as distinct ones.
   //! This value is defined by mesher using parameters given by
   //! user in connection with shape metrics.
-  //! \param theFaceAttribute attributes contining data calculated
+  //! @param theFaceAttribute attributes contining data calculated
   //! according to face geomtry and define limits of face in parametric 
   //! space. If defined, will be used instead of surface parameter.
-  //! \param theSurface surface within which parametric space 
-  //! the 2d point is defined. Supposed to be used in case if face
-  //! attributes are not defined by the moment of method invocation.
-  //! \param theLocation2dMap map of 2d representations of 3d points.
-  //! \return given 2d point in case if 3d poind does not alredy have 
+  //! @param theLocation2dMap map of 2d representations of 3d points.
+  //! @return given 2d point in case if 3d poind does not alredy have 
   //! the similar representation, otherwice 2d point corresponding to 
   //! existing representation will be returned.
   Standard_EXPORT static gp_XY FindUV(
@@ -88,35 +85,33 @@ public:
     const gp_Pnt2d&                       thePnt2d,
     const TopoDS_Vertex&                  theVertex,
     const Standard_Real                   theMinDistance,
-    const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
-    const Handle(BRepAdaptor_HSurface)&   theSurface,
-    BRepMeshCol::DMapOfIntegerListOfXY&   theLocation2dMap);
+    const Handle(BRepMesh_FaceAttribute)& theFaceAttribute);
 
   //! Stores the given triangulation into the given face.
-  //! \param theFace face to be updated by triangulation.
-  //! \param theTriangulation triangulation to be stored into the face.
+  //! @param theFace face to be updated by triangulation.
+  //! @param theTriangulation triangulation to be stored into the face.
   Standard_EXPORT static void AddInFace(
     const TopoDS_Face&          theFace,
     Handle(Poly_Triangulation)& theTriangulation);
 
   //! Nullifies triangulation stored in the face.
-  //! \param theFace face to be updated by null triangulation.
+  //! @param theFace face to be updated by null triangulation.
   Standard_EXPORT static void NullifyFace(const TopoDS_Face& theFace);
 
   //! Nullifies polygon on triangulation stored in the edge.
-  //! \param theEdge edge to be updated by null polygon.
-  //! \param theTriangulation triangulation the given edge is associated to.
-  //! \param theLocation face location.
+  //! @param theEdge edge to be updated by null polygon.
+  //! @param theTriangulation triangulation the given edge is associated to.
+  //! @param theLocation face location.
   Standard_EXPORT static void NullifyEdge(
     const TopoDS_Edge&                theEdge,
     const Handle(Poly_Triangulation)& theTriangulation,
     const TopLoc_Location&            theLocation);
 
   //! Updates the given edge by the given tessellated representation.
-  //! \param theEdge edge to be updated.
-  //! \param thePolygon tessellated representation of the edge to be stored.
-  //! \param theTriangulation triangulation the given edge is associated to.
-  //! \param theLocation face location.
+  //! @param theEdge edge to be updated.
+  //! @param thePolygon tessellated representation of the edge to be stored.
+  //! @param theTriangulation triangulation the given edge is associated to.
+  //! @param theLocation face location.
   Standard_EXPORT static void UpdateEdge(
     const TopoDS_Edge&                         theEdge,
     const Handle(Poly_PolygonOnTriangulation)& thePolygon,
@@ -124,19 +119,34 @@ public:
     const TopLoc_Location&                     theLocation);
 
   //! Updates the given seam edge by the given tessellated representations.
-  //! \param theEdge edge to be updated.
-  //! \param thePolygon1 tessellated representation corresponding to
+  //! @param theEdge edge to be updated.
+  //! @param thePolygon1 tessellated representation corresponding to
   //! forward direction of the seam edge.
-  //! \param thePolygon2 tessellated representation corresponding to
+  //! @param thePolygon2 tessellated representation corresponding to
   //! reversed direction of the seam edge.
-  //! \param theTriangulation triangulation the given edge is associated to.
-  //! \param theLocation face location.
+  //! @param theTriangulation triangulation the given edge is associated to.
+  //! @param theLocation face location.
   Standard_EXPORT static void UpdateEdge(
     const TopoDS_Edge&                         theEdge,
     const Handle(Poly_PolygonOnTriangulation)& thePolygon1,
     const Handle(Poly_PolygonOnTriangulation)& thePolygon2,
     const Handle(Poly_Triangulation)&          theTriangulation,
     const TopLoc_Location&                     theLocation);
+
+  //! Applies location to the given point and return result.
+  //! @param thePnt point to be transformed.
+  //! @param theLoc location to be applied.
+  Standard_EXPORT static gp_Pnt UseLocation(const gp_Pnt&          thePnt,
+                                            const TopLoc_Location& theLoc);
+
+  //! Checks is the given edge degenerated.
+  //! Checks geometrical parameters in case if IsDegenerated flag is not set.
+  //! @param theEdge edge to be checked.
+  //! @param theFace face within which parametric space edge will be checked
+  //! for geometrical degenerativity.
+  Standard_EXPORT static Standard_Boolean IsDegenerated(
+    const TopoDS_Edge& theEdge,
+    const TopoDS_Face& theFace);
 };
 
 #endif
index 8fc1400..b288b3d 100644 (file)
@@ -110,8 +110,8 @@ public:
   //! \return TRUE if equal, FALSE if not.
   Standard_EXPORT Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const
   {
-    if (myMovability          != BRepMesh_Deleted || 
-        theOther.myMovability != BRepMesh_Deleted)
+    if (myMovability          == BRepMesh_Deleted || 
+        theOther.myMovability == BRepMesh_Deleted)
     {
       return Standard_False;
     }
index e6d2366..e939050 100644 (file)
@@ -22,7 +22,7 @@
 #include <BRepTools_WireExplorer.hxx>
 #include <TopAbs_Orientation.hxx>
 #include <TopoDS.hxx>
-#include <TopoDS_Iterator.hxx>
+#include <TopExp_Explorer.hxx>
 #include <Poly_PolygonOnTriangulation.hxx>
 #include <BRepMesh_PairOfPolygon.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
@@ -129,8 +129,8 @@ Standard_Integer BRepMesh_WireChecker::BndBox2dTreeSelector::IndicesNb() const
 BRepMesh_WireChecker::BRepMesh_WireChecker(
   const TopoDS_Face&                            theFace,
   const Standard_Real                           theTolUV,
-  const BRepMeshCol::DMapOfShapePairOfPolygon&  theEdges,
-  const TColStd_IndexedMapOfInteger&            theVertexMap,
+  const BRepMeshCol::HDMapOfShapePairOfPolygon& theEdges,
+  const BRepMeshCol::HIMapOfInteger&            theVertexMap,
   const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
   const Standard_Real                           theUmin,
   const Standard_Real                           theUmax,
@@ -151,18 +151,16 @@ BRepMesh_WireChecker::BRepMesh_WireChecker(
   TopoDS_Face aFace = theFace;
   aFace.Orientation(TopAbs_FORWARD);
 
-  TopoDS_Iterator aFaceExplorer(aFace);
+  TopExp_Explorer aFaceExplorer(aFace, TopAbs_WIRE);
   for (; aFaceExplorer.More(); aFaceExplorer.Next())
   {
-    const TopoDS_Shape& aWire = aFaceExplorer.Value();
-    if (aWire.ShapeType() != TopAbs_WIRE)
-      continue;
+    const TopoDS_Wire& aWire = TopoDS::Wire(aFaceExplorer.Current());
 
     myWiresEdges.push_back(ListOfEdges());
     ListOfEdges& aEdges = myWiresEdges.back();
 
     // Start traversing the wires
-    BRepTools_WireExplorer aWireExplorer(TopoDS::Wire(aWire), aFace);
+    BRepTools_WireExplorer aWireExplorer(aWire, aFace);
     for (; aWireExplorer.More(); aWireExplorer.Next())
     {
       const TopoDS_Edge& aEdge   = aWireExplorer.Current();
@@ -264,13 +262,13 @@ Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires(
     {
       const TopoDS_Edge& aEdge   = aEdgeIt.Value();
       TopAbs_Orientation aOrient = aEdge.Orientation();
-      if (!myEdges.IsBound(aEdge))
+      if (!myEdges->IsBound(aEdge))
         continue;
 
       // Retrieve polygon
       // Define the direction for adding points to aSeqPnt2d
       Standard_Integer aStartId, aEndId, aIncrement;
-      const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
+      const BRepMesh_PairOfPolygon& aPair = myEdges->Find(aEdge);
       Handle(Poly_PolygonOnTriangulation) aNOD;
       if (aOrient == TopAbs_FORWARD)
       {
@@ -288,8 +286,8 @@ Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires(
       }
 
       const TColStd_Array1OfInteger& aIndices = aNOD->Nodes();
-      const Standard_Integer aFirstVertexId = myVertexMap.FindKey(aIndices(aStartId));
-      const Standard_Integer aLastVertexId  = myVertexMap.FindKey(aIndices(aEndId)  );
+      const Standard_Integer aFirstVertexId = myVertexMap->FindKey(aIndices(aStartId));
+      const Standard_Integer aLastVertexId  = myVertexMap->FindKey(aIndices(aEndId)  );
 
       if (aFirstVertexId == aLastVertexId && (aEndId - aStartId) == aIncrement)
       {
@@ -320,7 +318,7 @@ Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires(
       {
         Standard_Integer aIndex = ((i == aStartId) ? 
           aFirstVertexId : 
-          myVertexMap.FindKey(aIndices(i)));
+          myVertexMap->FindKey(aIndices(i)));
 
         aSeqPnt2d.Append(gp_Pnt2d(myStructure->GetNode(aIndex).Coord()));
       }
index 417be93..d492599 100644 (file)
@@ -87,8 +87,8 @@ public:
   Standard_EXPORT BRepMesh_WireChecker(
     const TopoDS_Face&                            theFace,
     const Standard_Real                           theTolUV,
-    const BRepMeshCol::DMapOfShapePairOfPolygon&  theEdges,
-    const TColStd_IndexedMapOfInteger&            theVertexMap,
+    const BRepMeshCol::HDMapOfShapePairOfPolygon& theEdges,
+    const BRepMeshCol::HIMapOfInteger&            theVertexMap,
     const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
     const Standard_Real                           theUmin,
     const Standard_Real                           theUmax,
@@ -129,8 +129,8 @@ private:
 private:
 
   const Standard_Real                           myTolUV;
-  const BRepMeshCol::DMapOfShapePairOfPolygon&  myEdges;
-  const TColStd_IndexedMapOfInteger&            myVertexMap;
+  const BRepMeshCol::HDMapOfShapePairOfPolygon& myEdges;
+  const BRepMeshCol::HIMapOfInteger&            myVertexMap;
   const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
   const Standard_Real                           myUmin;
   const Standard_Real                           myUmax;
index 7d36164..e7c3736 100755 (executable)
@@ -36,6 +36,14 @@ BRepMesh_EdgeChecker.hxx
 BRepMesh_FaceChecker.hxx
 BRepMesh_SelectorOfDataStructureOfDelaun.hxx
 BRepMesh_SelectorOfDataStructureOfDelaun.cxx
+BRepMesh_EdgeParameterProvider.hxx
+BRepMesh_EdgeParameterProvider.cxx
+BRepMesh_IEdgeTool.hxx
+BRepMesh_IEdgeTool.cxx
+BRepMesh_EdgeTessellationExtractor.hxx
+BRepMesh_EdgeTessellationExtractor.cxx
+BRepMesh_EdgeTessellator.hxx
+BRepMesh_EdgeTessellator.cxx
 BRepMesh_FastDiscretFace.hxx
 BRepMesh_FastDiscretFace.cxx
 BRepMesh_FastDiscret.hxx
index 112d406..737684b 100644 (file)
@@ -21,7 +21,6 @@
 #include <BRepBndLib.hxx>
 #include <BRepMesh_DiscretFactory.hxx>
 #include <BRepMesh_DiscretRoot.hxx>
-#include <BRepMesh_PDiscretRoot.hxx>
 #include <BRepTools.hxx>
 #include <Hatch_Hatcher.hxx>
 #include <GCPnts_QuasiUniformDeflection.hxx>
index db6db2e..9b92c29 100644 (file)
@@ -394,36 +394,30 @@ static void MeshStats(const TopoDS_Shape& theSape,
 
 static Standard_Integer triangule(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
 {
-  if (nbarg < 4) return 1;
-
-  Standard_Boolean save = Standard_False;
+  if (nbarg < 4)
+    return 1;
 
   const char *id1 = argv[2];
-  TopoDS_Shape S = DBRep::Get(id1);
-  if (S.IsNull()) return 1;
-  di << argv[1] << " ";
-  Standard_Real Deflect=Draw::Atof(argv[3]);
-  if (Deflect<=0.) {
-    di << " Donner la fleche !" << "\n";
+  TopoDS_Shape aShape = DBRep::Get(id1);
+  if (aShape.IsNull())
     return 1;
-  }
 
-  if (nbarg >4) {
-    save = (Draw::Atoi(argv[4])==1);
-  }
+  di << argv[1] << " ";
 
-  Standard_Boolean partage=Standard_True;
-  if (nbarg>5) {
-    partage=Draw::Atoi(argv[5])==1;
+  Standard_Real aDeflection = Draw::Atof(argv[3]);
+  if (aDeflection <= 0.)
+  {
+    di << " Incorrect value of deflection!" << "\n";
+    return 1;
   }
 
-  Handle(MeshTest_DrawableMesh) DM =
-    new MeshTest_DrawableMesh(S,Deflect,partage, save);
+  Handle(MeshTest_DrawableMesh) aDMesh = 
+    new MeshTest_DrawableMesh(aShape, aDeflection);
 
-  Draw::Set(argv[1],DM);
+  Draw::Set(argv[1], aDMesh);
 
   Standard_Integer nbn, nbl, nbe;
-  MeshStats(S, nbe, nbl, nbn);
+  MeshStats(aShape, nbe, nbl, nbn);
 
   di<<"(Resultat ("<<nbe<<" mailles) ("<<nbl<<" aretes) ("<<nbn<<" sommets))"<<"\n";
 
@@ -437,16 +431,36 @@ static Standard_Integer triangule(Draw_Interpretor& di, Standard_Integer nbarg,
   }
   }*/
 
-  Bnd_Box bobo;
 
-  for (Standard_Integer lepnt=1; lepnt<DM->Mesh()->NbPoint3d(); lepnt++) {
-    bobo.Add(DM->Mesh()->Point3d(lepnt));
+  Bnd_Box aBox;
+  const Handle(BRepMesh_FastDiscret)& aFastDiscret = aDMesh->Mesher()->Mesh();
+
+  TopExp_Explorer aFaceIt(aShape, TopAbs_FACE);
+  for (; aFaceIt.More(); aFaceIt.Next())
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+
+    Handle(BRepMesh_FaceAttribute) anAttribute;
+    if (aFastDiscret->GetFaceAttribute(aFace, anAttribute) && anAttribute->IsValid())
+    {
+      const Standard_Integer aNbPnts = anAttribute->LastPointId();
+      for (Standard_Integer i = 1; i < aNbPnts; ++i)
+        aBox.Add(anAttribute->GetPoint(i));
+    }
+  }
+
+  Standard_Real aDelta = 0.;
+  if (!aBox.IsVoid())
+  {
+    Standard_Real x, y, z, X, Y, Z;
+    aBox.Get(x, y, z, X, Y, Z);
+
+    aDelta = Max(X - x, Max(Y - y, Z - z));
+    if (aDelta > 0.0)
+      aDelta = aDeflection / aDelta;
   }
-  Standard_Real x,y,z,X,Y,Z;
-  bobo.Get(x,y,z,X,Y,Z);
-  Standard_Real delta=Max(X-x,Max(Y-y,Z-z));
-  if (delta>0) delta=Deflect/delta;
-  di << " Fleche de " << delta << " fois la taille de l''objet." << "\n";
+
+  di << " Ratio between deflection and total shape size is " << aDelta << "\n";
 
   return 0;
 }
@@ -546,36 +560,60 @@ return 0;
 //function : vertices
 //purpose  : 
 //=======================================================================
-
-static Standard_Integer vertices (Draw_Interpretor&, Standard_Integer n, const char** a)
+static Standard_Integer vertices(
+  Draw_Interpretor& /*di*/, 
+  Standard_Integer  /*argc*/, 
+  const char**      /*argv*/)
 {
-  if (n < 3) return 1;
-
-  Handle(MeshTest_DrawableMesh) D =
-    Handle(MeshTest_DrawableMesh)::DownCast(Draw::Get(a[1]));
-  if (D.IsNull()) return 1;
-  TopoDS_Shape S = DBRep::Get(a[2]);
-  if (S.IsNull()) return 1;
-
-  TopExp_Explorer ex;
-  TColStd_SequenceOfInteger& vseq = D->Vertices();
-  Handle(BRepMesh_FastDiscret) M = D->Mesh();
-
-  // the faces
-  for (ex.Init(S,TopAbs_FACE);ex.More();ex.Next()) {
-    BRepMeshCol::MapOfInteger vtx;
-    M->VerticesOfDomain(vtx);
-    for (BRepMeshCol::MapOfInteger::Iterator it(vtx); it.More(); it.Next())
-      vseq.Append(it.Key());
-  }
-
+  return 0;
 
-  // the edges
-  //for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE);ex.More();ex.Next()) {
+  // TODO: OAN re-implement this command according changes in BRepMesh
+  //if (argc < 3)
+  //  return 1;
+
+  //Handle(MeshTest_DrawableMesh) aDrawableMesh =
+  //  Handle(MeshTest_DrawableMesh)::DownCast(Draw::Get(argv[1]));
+  //if (aDrawableMesh.IsNull())
+  //  return 1;
+
+  //TopoDS_Shape aShape = DBRep::Get(argv[2]);
+  //if (aShape.IsNull())
+  //  return 1;
+
+  //TColStd_SequenceOfInteger&   aVertexSeq = aDrawableMesh->Vertices();
+  //Handle(BRepMesh_FastDiscret) aMesh      = aDrawableMesh->Mesh();
+
+  //TopExp_Explorer aFaceIt(aShape, TopAbs_FACE);
+  //for (; aFaceIt.More(); aFaceIt.Next())
+  //{
+  //  const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+
+  //  Handle(BRepMesh_FaceAttribute) aAttribute;
+  //  if (aMesh->GetFaceAttribute(aFace, aAttribute))
+  //  {
+  //    Handle(BRepMesh_DataStructureOfDelaun) aStructure = aAttribute->EditStructure();
+
+  //    // Recuperate from the map of edges.
+  //    const BRepMeshCol::MapOfInteger& aEdgeMap = aStructure->LinksOfDomain();
+
+  //    // Iterator on edges.
+  //    BRepMeshCol::MapOfInteger aVertices;
+  //    BRepMeshCol::MapOfInteger::Iterator aEdgeIt(aEdgeMap);
+  //    for (; aEdgeIt.More(); aEdgeIt.Next())
+  //    {
+  //      const BRepMesh_Edge& aEdge = aStructure->GetLink(aEdgeIt.Key());
+  //      aVertices.Add(aEdge.FirstNode());
+  //      aVertices.Add(aEdge.LastNode());
+  //    }
+
+  //    BRepMeshCol::MapOfInteger::Iterator anIt(vtx);
+  //    for ( ; anIt.More(); anIt.Next() )
+  //      aVertexSeq.Append(anIt.Key());
+  //  }
   //}
 
-  Draw::Repaint();
-  return 0;
+  //Draw::Repaint();
+  //return 0;
 }
 
 //=======================================================================
@@ -1504,7 +1542,7 @@ void  MeshTest::Commands(Draw_Interpretor& theCommands)
   theCommands.Add("incmesh","incmesh shape deflection [inParallel (0/1) : 0 by default]",__FILE__, incrementalmesh, g);
   theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g);
   theCommands.Add("fastdiscret","fastdiscret shape deflection [shared [nbiter]]",__FILE__, fastdiscret, g);
-  theCommands.Add("mesh","mesh result Shape deflection [save partage]",__FILE__, triangule, g);
+  theCommands.Add("mesh","mesh result Shape deflection",__FILE__, triangule, g);
   theCommands.Add("addshape","addshape meshname Shape [deflection]",__FILE__, addshape, g);
   //theCommands.Add("smooth","smooth meshname",__FILE__, smooth, g);
   //theCommands.Add("edges","edges mesh shape, highlight the edges",__FILE__,edges, g);
index 75f7ad8..68cd191 100644 (file)
@@ -26,8 +26,7 @@
 #include <BRepMesh_Vertex.hxx>
 #include <BRepMesh_Triangle.hxx>
 #include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <Bnd_Box.hxx>
-#include <BRepBndLib.hxx>
+#include <TopExp_Explorer.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (MeshTest_DrawableMesh, Draw_Drawable3D)
 IMPLEMENT_STANDARD_RTTIEXT(MeshTest_DrawableMesh, Draw_Drawable3D)
@@ -36,9 +35,8 @@ IMPLEMENT_STANDARD_RTTIEXT(MeshTest_DrawableMesh, Draw_Drawable3D)
 //function : MeshTest_DrawableMesh
 //purpose  : 
 //=======================================================================
-
-MeshTest_DrawableMesh::MeshTest_DrawableMesh() :
-myDeflection(1.), myinshape(Standard_False)
+MeshTest_DrawableMesh::MeshTest_DrawableMesh()
+  : myDeflection(1.)
 {
 }
 
@@ -46,56 +44,41 @@ myDeflection(1.), myinshape(Standard_False)
 //function : MeshTest_DrawableMesh
 //purpose  : 
 //=======================================================================
-
-MeshTest_DrawableMesh::MeshTest_DrawableMesh(const TopoDS_Shape&    S,
-                                             const Standard_Real    Deflect,
-                                             const Standard_Boolean Partage,
-                                             const Standard_Boolean inshape) :
-myDeflection(Deflect), myinshape(inshape)
+MeshTest_DrawableMesh::MeshTest_DrawableMesh(const TopoDS_Shape& theShape,
+                                             const Standard_Real theDeflection)
+  : myDeflection(theDeflection)
 {
-  Bnd_Box B;
-  BRepBndLib::Add(S, B);
-
-  myMesh = new BRepMesh_FastDiscret(S, Deflect, 0.5, B, Partage, inshape);
+  Add(theShape);
 }
 
-
 //=======================================================================
 //function : MeshTest_DrawableMesh
 //purpose  : 
 //=======================================================================
-
-MeshTest_DrawableMesh::MeshTest_DrawableMesh(const Handle(BRepMesh_FastDiscret)& Tr):
-myDeflection(1.0)
+MeshTest_DrawableMesh::MeshTest_DrawableMesh(
+  const Handle(BRepMesh_IncrementalMesh)& theMesher)
+  : myDeflection(1.)
 {
-  myMesh = Tr;
+  myMesher = theMesher;
+  if (!myMesher.IsNull())
+    myDeflection = myMesher->Deflection();
 }
 
-
 //=======================================================================
 //function : MeshTest_DrawableMesh
 //purpose  : 
 //=======================================================================
-
-void MeshTest_DrawableMesh::Add(const TopoDS_Shape& S)
-{
-  Bnd_Box B;
-  BRepBndLib::Add(S, B);
-
-  if (myMesh.IsNull())
-    myMesh=new BRepMesh_FastDiscret(S, myDeflection, 0.5, B, myinshape);
-  else
-    myMesh->Perform(S);
-}
-
-//=======================================================================
-//function : AddInShape
-//purpose  : 
-//=======================================================================
-
-void MeshTest_DrawableMesh::AddInShape(const Standard_Boolean inshape) 
+void MeshTest_DrawableMesh::Add(const TopoDS_Shape& theShape)
 {
-  myinshape = inshape;
+  if (myMesher.IsNull())
+  {
+    myMesher = new BRepMesh_IncrementalMesh;
+    myMesher->SetDeflection(myDeflection);
+    myMesher->SetAngle(0.5);
+  }
+  
+  myMesher->SetShape(theShape);
+  myMesher->Perform();
 }
 
 //=======================================================================
@@ -172,18 +155,15 @@ void MeshTest_DrawableMesh::DrawOn(Draw_Display& /*D*/) const
 //function : Copy
 //purpose  : 
 //=======================================================================
-
 Handle(Draw_Drawable3D) MeshTest_DrawableMesh::Copy() const 
 {
-  Handle(MeshTest_DrawableMesh) D = new MeshTest_DrawableMesh();
-  return  D;
+  return new MeshTest_DrawableMesh(myMesher);
 }
 
 //=======================================================================
 //function : Dump
 //purpose  : 
 //=======================================================================
-
 void MeshTest_DrawableMesh::Dump(Standard_OStream&) const 
 {
   // Should be reimplemented
@@ -239,24 +219,45 @@ void MeshTest_DrawableMesh::Dump(Standard_OStream&) const
 //function : Whatis
 //purpose  : 
 //=======================================================================
-
-void MeshTest_DrawableMesh::Whatis(Draw_Interpretor& S) const 
+void MeshTest_DrawableMesh::Whatis(Draw_Interpretor& theStream) const 
 {
-  S << " 3d mesh\n";
-  S << "    - Triangles : " << myMesh->NbTriangles() << "\n";
-  S << "    - Edges     : " << myMesh->NbEdges()     << "\n";
-  S << "    - Vertices  : " << myMesh->NbVertices()  << "\n";
-  S << "    - Point3d   : " << myMesh->NbPoint3d()   << "\n";
+  const Handle(BRepMesh_FastDiscret)& aMesh = myMesher->Mesh();
+  Standard_Integer aPointsNb    = aMesh->NbBoundaryPoints();
+  Standard_Integer aTrianglesNb = 0;
+  Standard_Integer aEdgesNb     = 0;
+
+  const TopoDS_Shape& aShape = myMesher->Shape();
+  TopExp_Explorer aFaceIt(aShape, TopAbs_FACE);
+  for (; aFaceIt.More(); aFaceIt.Next())
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+
+    Handle(BRepMesh_FaceAttribute) aAtrribure;
+    if (!aMesh->GetFaceAttribute(aFace, aAtrribure) || !aAtrribure->IsValid())
+      continue;
+
+    aPointsNb   += aAtrribure->ChangeSurfacePoints()->Extent();
+
+    Handle(BRepMesh_DataStructureOfDelaun)& aStructure =
+      aAtrribure->ChangeStructure();
+
+    aTrianglesNb += aStructure->ElementsOfDomain().Extent();
+    aEdgesNb     += aStructure->LinksOfDomain().Extent();
+  }
+
+  theStream << " 3d mesh\n";
+  theStream << "    - Triangles : " << aTrianglesNb << "\n";
+  theStream << "    - Edges     : " << aEdgesNb     << "\n";
+  theStream << "    - Point3d   : " << aPointsNb    << "\n";
 }
 
 //=======================================================================
-//function : Mesh
+//function : Mesher
 //purpose  : 
 //=======================================================================
-
-Handle(BRepMesh_FastDiscret) MeshTest_DrawableMesh::Mesh() const 
+const Handle(BRepMesh_IncrementalMesh)& MeshTest_DrawableMesh::Mesher() const 
 {
-  return myMesh;
+  return myMesher;
 }
 
 
@@ -264,7 +265,6 @@ Handle(BRepMesh_FastDiscret) MeshTest_DrawableMesh::Mesh() const
 //function : Edges
 //purpose  : 
 //=======================================================================
-
 TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Edges()
 {
   return myEdges;
@@ -275,7 +275,6 @@ TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Edges()
 //function : Vertices
 //purpose  : 
 //=======================================================================
-
 TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Vertices()
 {
   return myVertices;
@@ -285,7 +284,6 @@ TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Vertices()
 //function : Triangles
 //purpose  : 
 //=======================================================================
-
 TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Triangles()
 {
   return myTriangles;
index 85bb3ed..d190007 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <Standard.hxx>
 #include <Standard_DefineHandle.hxx>
-#include <BRepMesh_FastDiscret.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 #include <Draw_Drawable3D.hxx>
 #include <Handle_Draw_Drawable3D.hxx>
@@ -37,40 +37,38 @@ public:
   
   Standard_EXPORT MeshTest_DrawableMesh();
   
-  Standard_EXPORT MeshTest_DrawableMesh(const TopoDS_Shape& S,const Standard_Real Deflect,const Standard_Boolean Partage,const Standard_Boolean InShape = Standard_False);
+  Standard_EXPORT MeshTest_DrawableMesh(const TopoDS_Shape& theShape,
+                                        const Standard_Real theDeflection);
   
-  Standard_EXPORT MeshTest_DrawableMesh(const Handle(BRepMesh_FastDiscret)& Tr);
+  Standard_EXPORT MeshTest_DrawableMesh(const Handle(BRepMesh_IncrementalMesh)& theMesher);
   
-  Standard_EXPORT void AddInShape(const Standard_Boolean inshape) ;
+  Standard_EXPORT void Add(const TopoDS_Shape& theShape);
   
-  Standard_EXPORT void Add(const TopoDS_Shape& S) ;
+  Standard_EXPORT TColStd_SequenceOfInteger& Edges();
   
-  Standard_EXPORT TColStd_SequenceOfInteger& Edges() ;
+  Standard_EXPORT TColStd_SequenceOfInteger& Vertices();
   
-  Standard_EXPORT TColStd_SequenceOfInteger& Vertices() ;
+  Standard_EXPORT TColStd_SequenceOfInteger& Triangles();
   
-  Standard_EXPORT TColStd_SequenceOfInteger& Triangles() ;
+  Standard_EXPORT void DrawOn(Draw_Display& theDisplay) const;
   
-  Standard_EXPORT void DrawOn(Draw_Display& dis) const;
+  Standard_EXPORT virtual Handle_Draw_Drawable3D Copy() const;
   
-  Standard_EXPORT virtual  Handle_Draw_Drawable3D Copy() const;
+  Standard_EXPORT virtual void Dump(Standard_OStream& theStream) const;
   
-  Standard_EXPORT virtual  void Dump(Standard_OStream& S) const;
+  Standard_EXPORT virtual void Whatis(Draw_Interpretor& theDi) const;
   
-  Standard_EXPORT virtual  void Whatis(Draw_Interpretor& S) const;
-  
-  Standard_EXPORT Handle(BRepMesh_FastDiscret) Mesh() const;
+  Standard_EXPORT const Handle(BRepMesh_IncrementalMesh)& Mesher() const;
 
   DEFINE_STANDARD_RTTI(MeshTest_DrawableMesh)
 
 private: 
 
-  Handle(BRepMesh_FastDiscret) myMesh;
-  Standard_Real myDeflection;
-  TColStd_SequenceOfInteger myEdges;
-  TColStd_SequenceOfInteger myVertices;
-  TColStd_SequenceOfInteger myTriangles;
-  Standard_Boolean myinshape;
+  Handle(BRepMesh_IncrementalMesh) myMesher;
+  Standard_Real                    myDeflection;
+  TColStd_SequenceOfInteger        myEdges;
+  TColStd_SequenceOfInteger        myVertices;
+  TColStd_SequenceOfInteger        myTriangles;
 };
 
 DEFINE_STANDARD_HANDLE(MeshTest_DrawableMesh, Draw_Drawable3D)
index 1b95c95..99b0e08 100644 (file)
@@ -23,7 +23,7 @@
 #include <BRepMesh_DiscretRoot.hxx>
 #include <BRepMesh_IncrementalMesh.hxx>
 #include <Bnd_Box.hxx>
-#include <BRepMesh_PDiscretRoot.hxx>
+#include <BRepMesh_DiscretRoot.hxx>
 #include <Draw.hxx>
 #include <DBRep.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
diff --git a/src/XBRepMesh/FILES b/src/XBRepMesh/FILES
new file mode 100644 (file)
index 0000000..c120d50
--- /dev/null
@@ -0,0 +1,2 @@
+XBRepMesh.hxx
+XBRepMesh.cxx
diff --git a/src/XBRepMesh/XBRepMesh.cdl b/src/XBRepMesh/XBRepMesh.cdl
deleted file mode 100644 (file)
index 428d3d4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
--- Created on: 2008-04-11
--- Created by: Peter KURNEV
--- Copyright (c) 2008-2014 OPEN CASCADE SAS
---
--- This file is part of Open CASCADE Technology software library.
---
--- This library is free software; you can redistribute it and/or modify it under
--- the terms of the GNU Lesser General Public License version 2.1 as published
--- by the Free Software Foundation, with special exception defined in the file
--- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
--- distribution for complete text of the license and disclaimer of any warranty.
---
--- Alternatively, this file may be used under the terms of Open CASCADE
--- commercial license or contractual agreement.
-
-package XBRepMesh 
-
-       ---Purpose: 
-
-uses 
-    TopoDS,
-    BRepMesh
-
-is 
-    Discret(theShape      : Shape from TopoDS;  
-           theDeflection : Real from Standard; 
-           theAngle      : Real from Standard;
-           theAlgo:out PDiscretRoot from BRepMesh) 
-       returns Integer from Standard; 
-
-end XBRepMesh;
index 051ecb6..6f76378 100644 (file)
@@ -13,7 +13,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <XBRepMesh.ixx>
+#include <XBRepMesh.hxx>
 #include <BRepMesh_PluginMacro.hxx>
 #include <BRepMesh_IncrementalMesh.hxx>
 
 //function : Discret
 //purpose  : 
 //=======================================================================
-Standard_Integer XBRepMesh::Discret(const TopoDS_Shape& theShape,
-                                   const Standard_Real theDeflection,
-                                   const Standard_Real theAngle,
-                                   BRepMesh_PDiscretRoot& theAlgo)
+Standard_Integer XBRepMesh::Discret(
+  const TopoDS_Shape&   theShape,
+  const Standard_Real   theDeflection,
+  const Standard_Real   theAngle,
+  BRepMesh_DiscretRoot* &theAlgo)
 {
   Standard_Integer iErr;
   //
diff --git a/src/XBRepMesh/XBRepMesh.hxx b/src/XBRepMesh/XBRepMesh.hxx
new file mode 100644 (file)
index 0000000..28e32c6
--- /dev/null
@@ -0,0 +1,39 @@
+// Created on: 2008-04-11
+// Created by: Peter KURNEV
+// Copyright (c) 2008-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _XBRepMesh_HeaderFile
+#define _XBRepMesh_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Macro.hxx>
+#include <BRepMesh_DiscretRoot.hxx>
+
+class TopoDS_Shape;
+
+class XBRepMesh
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+  
+  Standard_EXPORT static Standard_Integer Discret(
+    const TopoDS_Shape&    theShape,
+    const Standard_Real    theDeflection,
+    const Standard_Real    theAngle,
+    BRepMesh_DiscretRoot* &theAlgo);
+};
+
+#endif
index 0f775e6..5aaa2f5 100644 (file)
@@ -19,6 +19,8 @@
 #include <BRepMesh_Edge.hxx>
 #include <Bnd_Box.hxx>
 #include <BRepBndLib.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
 
 #include <gp_Pnt.hxx> //ied_modif_for_compil_Nov-20-1998
 
@@ -63,103 +65,141 @@ Standard_Real&  XSDRAWSTLVRML_ToVRML::Deflection ()         {  return myDeflecti
 //=======================================================================
 
 Standard_Boolean  XSDRAWSTLVRML_ToVRML::Write
-  (const TopoDS_Shape& aShape, const Standard_CString filename) const
+  (const TopoDS_Shape& theShape, const Standard_CString theFileName) const
 {
-  filebuf thefile;
-  ostream TheFileOut(&thefile);
-
-  if (thefile.open(filename,ios::out))
-    {
-
-      // Creates facets from the shape
-//      Create (defle     : Real    from Standard;
-//         shape     : Shape   from TopoDS;
-//            angl      : Real    from Standard= 0.17;
-//            withShare : Boolean from Standard=Standard_True;
-//            inshape   : Boolean from Standard=Standard_False;
-//            relative  : Boolean from Standard=Standard_False;
-//            shapetrigu: Boolean from Standard=Standard_False)
-//      returns mutable Discret from BRepMesh;
-      Bnd_Box B;
-      BRepBndLib::Add(aShape, B);
-
-      Handle(BRepMesh_FastDiscret)   TheDiscret = 
-  new BRepMesh_FastDiscret(aShape,
-           myDeflection,
-           0.17,
-           B,
-           Standard_True,
-           Standard_False,
-           Standard_True,
-           Standard_True);
-
-      Standard_Integer i,j;
-
-      // header of the VRML file
-      TheFileOut << "#VRML V2.0 utf8" << endl;
-      TheFileOut << "Group {" << endl;
-      TheFileOut << " children [ " << endl;
-      TheFileOut << " NavigationInfo {" << endl;
-      TheFileOut << "       type \"EXAMINE\" " << endl;
-      TheFileOut << " }," << endl;
-      TheFileOut << "Shape {" << endl;
-
-      TheFileOut << "   appearance Appearance {" << endl;
-      TheFileOut << "     texture ImageTexture {" << endl;
-      TheFileOut << "         url " << myTexture.ToCString() << endl;
-      TheFileOut << "         }" << endl;
-      TheFileOut << "     material Material { " << endl;
-      TheFileOut << "  diffuseColor " << myDiffuseColorRed << " " << myDiffuseColorGreen << " " << myDiffuseColorBlue << " " << endl;
-      TheFileOut << " emissiveColor " << myEmissiveColorRed << " "
-  << myEmissiveColorGreen << " " << myEmissiveColorBlue << " " << endl;
-      TheFileOut << " transparency " << myTransparency << endl;
-      TheFileOut << " ambientIntensity " << myAmbientIntensity << " " << endl;
-      TheFileOut << " specularColor " << mySpecularColorRed << " " << mySpecularColorGreen << " " << mySpecularColorBlue << " " << endl;
-      TheFileOut << " shininess " <<myShininess << " " << endl;
-      TheFileOut << "         }" << endl;
-      TheFileOut << "     }" << endl;
-
-      TheFileOut << "   geometry IndexedFaceSet {" << endl;
-      TheFileOut << "     coord Coordinate {" << endl;
-      TheFileOut << "       point [" << endl;
-      
-      // puts the coordinates of all the vertices using the order
-      // given during the discretisation
-      for (i=1;i<=TheDiscret->NbVertices();i++)
+  filebuf aFile;
+  ostream anOut(&aFile);
+
+  if ( aFile.open(theFileName,ios::out) )
   {
-    gp_Pnt TheVertex=TheDiscret->Pnt(i);
-    TheFileOut << "          " 
-      <<  TheVertex.Coord().X() << " " 
-        << TheVertex.Coord().Y() <<  " " 
-    << TheVertex.Coord().Z() << "," << endl;
+    // Creates facets from the shape
+    // Create (defle     : Real    from Standard;
+    //         shape     : Shape   from TopoDS;
+    //         angl      : Real    from Standard = 0.17;
+    //         withShare : Boolean from Standard = Standard_True;
+    //         inshape   : Boolean from Standard = Standard_False;
+    //         relative  : Boolean from Standard = Standard_False;
+    //         shapetrigu: Boolean from Standard = Standard_False)
+    //         returns mutable Discret from BRepMesh;
+
+    Bnd_Box aBox;
+    BRepBndLib::Add(theShape, aBox);
+
+    Handle(BRepMesh_FastDiscret) aDiscret =
+      new BRepMesh_FastDiscret( theShape,
+                                myDeflection,
+                                0.17,
+                                aBox,
+                                Standard_True,
+                                Standard_False,
+                                Standard_True,
+                                Standard_True );
+
+      // Header of the VRML file
+      anOut << "#VRML V2.0 utf8" << endl;
+      anOut << "Group {" << endl;
+      anOut << "  children [ " << endl;
+      anOut << "    NavigationInfo {" << endl;
+      anOut << "      type \"EXAMINE\" " << endl;
+      anOut << "    }," << endl;
+      anOut << "    Shape {" << endl;
+
+      anOut << "      appearance Appearance {" << endl;
+      anOut << "        texture ImageTexture {" << endl;
+      anOut << "          url " << myTexture.ToCString() << endl;
+      anOut << "        }" << endl;
+      anOut << "        material Material {" << endl;
+      anOut << "          diffuseColor " << myDiffuseColorRed << " "
+                                         << myDiffuseColorGreen << " "
+                                         << myDiffuseColorBlue << " " << endl;
+      anOut << "          emissiveColor " << myEmissiveColorRed << " "
+                                          << myEmissiveColorGreen << " "
+                                          << myEmissiveColorBlue << " " << endl;
+      anOut << "          transparency " << myTransparency << endl;
+      anOut << "          ambientIntensity " << myAmbientIntensity << " " << endl;
+      anOut << "          specularColor " << mySpecularColorRed << " "
+                                          << mySpecularColorGreen << " "
+                                          << mySpecularColorBlue << " " << endl;
+      anOut << "          shininess " << myShininess << " " << endl;
+      anOut << "        }" << endl;
+      anOut << "      }" << endl;
+
+      anOut << "      geometry IndexedFaceSet {" << endl;
+      anOut << "        coord Coordinate {" << endl;
+      anOut << "          point [" << endl;
+
+      // Puts the coordinates of all the vertices using the order
+      // given during the discretisation
+      TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
+      for (; aFaceIt.More(); aFaceIt.Next())
+      {
+        Handle(BRepMesh_FaceAttribute) anAttribute;
+        const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+        if (!aDiscret->GetFaceAttribute(aFace, anAttribute) || !anAttribute->IsValid())
+          continue;
+
+        Handle(BRepMesh_DataStructureOfDelaun)& aStructure =
+          anAttribute->ChangeStructure();
+
+        const Standard_Integer aNbVertices = aStructure->NbNodes();
+        for (Standard_Integer i = 1; i <= aNbVertices; ++i)
+        {
+          const BRepMesh_Vertex& aVertex = aStructure->GetNode(i);
+          const gp_Pnt&          aPoint  = anAttribute->GetPoint(aVertex);
+
+          anOut << "          "
+            << aPoint.Coord().X() << " "
+            << aPoint.Coord().Y() << " "
+            << aPoint.Coord().Z() << "," << endl;
+        }
+      }
+
+      anOut << "          ]" << endl;
+      anOut << "        }" << endl;
+      anOut << "        coordIndex [" << endl;
+
+      // Retrieves all the triangles in order to draw the facets
+      for (aFaceIt.Init(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
+      {
+        Handle(BRepMesh_FaceAttribute) anAttribute;
+        const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+
+        if (!aDiscret->GetFaceAttribute(aFace, anAttribute) || !anAttribute->IsValid())
+          continue;
+
+        Handle(BRepMesh_DataStructureOfDelaun)& aStructure =
+          anAttribute->ChangeStructure();
+
+        const Standard_Integer aNbTriangles = aStructure->NbElements();
+        for ( Standard_Integer i = 1; i <= aNbTriangles; ++i )
+        {
+          const BRepMesh_Triangle& aTriangle = aStructure->GetElement(i);
+
+          Standard_Integer v[3];
+          aStructure->ElementNodes(aTriangle, v);
+
+          anOut << "          "
+                << v[0] - 1 << ", "
+                << v[1] - 1 << ", "
+                << v[2] - 1 << ", -1," << endl;
+        }
+      }
+
+      anOut << "        ]" << endl;
+      anOut << "        solid FALSE" << endl; // it is not a closed solid
+      anOut << "        creaseAngle " << myCreaseAngle << " " << endl; // for smooth shading
+      anOut << "      }" << endl;
+      anOut << "    }" << endl;
+      anOut << "  ]" << endl;
+      anOut << "}" << endl;
   }
-      TheFileOut << "       ]" << endl;
-      TheFileOut << "     }" << endl;
-      
-      TheFileOut << "     coordIndex [" << endl;
-      
-      // retrieves all the triangles in order to draw the facets
-      for (j=1; j <= TheDiscret->NbTriangles(); j++)
+  else
   {
-    Standard_Integer v[3];
-    TheDiscret->TriangleNodes(j, v);
-    
-    TheFileOut << "          " << v[0]-1  << ", " << v[1]-1 << ", "  << v[2]-1  << ", -1, " << endl;
+    // Failure when opening file
+    return Standard_False;
   }
-      
-      TheFileOut << "          ]" << endl;
-      TheFileOut << "     solid FALSE" << endl;      // it is not a closed solid
-      TheFileOut << " creaseAngle " << myCreaseAngle << " " << endl; // for smooth shading
-      TheFileOut << "     }" << endl;
-      TheFileOut << "   }" << endl;
-    TheFileOut << " ]" << endl;
-    TheFileOut << "} " << endl;
-      
-    }
-  else return Standard_False;  // failure when opening file
-
-  thefile.close();
 
+  aFile.close();
   return Standard_True;
 }
 
diff --git a/tests/bugs/mesh/bug23106 b/tests/bugs/mesh/bug23106
new file mode 100755 (executable)
index 0000000..b0b0a14
--- /dev/null
@@ -0,0 +1,29 @@
+puts "========"
+puts "OCC23106"
+puts "========"
+puts ""
+###########################################
+## BRepMesh_IncrementalMesh returns wrong status
+###########################################
+
+set BugNumber OCC23106
+
+restore [locate_data_file bug23106_face_0triangles.brep] result
+
+incmesh result 0.01
+triangles result 
+
+set tri 0
+set nod 0
+
+set tri_info [trinfo result]
+regexp { +([-0-9.+eE]+) +triangles} $tri_info full tri
+regexp { +([-0-9.+eE]+) +nodes} $tri_info full nod
+
+if { ${tri} > 0 && ${nod} > 0 } {
+    puts "${BugNumber} shading: OK"
+} else {
+    puts "${BugNumber} shading: Faulty"
+}
+
+set 3dviewer 1