]> OCCT Git - occt-copy.git/commitdiff
0024265: Replacing vertices with tolerance that covers lacking edge by two new vertic...
authoribs <ibs@opencascade.com>
Thu, 17 Oct 2013 11:16:32 +0000 (15:16 +0400)
committeribs <ibs@opencascade.com>
Wed, 9 Apr 2014 12:18:19 +0000 (16:18 +0400)
ShapeFix_LackingEdgeRecover was introduced
"fixlackingedges" draw command waas introduced
don't process a vertex if it is shared by more than 2 edges placed on one face;

src/SWDRAW/SWDRAW_ShapeFix.cxx
src/ShapeFix/ShapeFix.cdl
src/ShapeFix/ShapeFix.cxx
src/ShapeFix/ShapeFix_LackingEdgeRecover.cdl [new file with mode: 0644]
src/ShapeFix/ShapeFix_LackingEdgeRecover.cxx [new file with mode: 0644]

index 8dc75e556c791e4ba6d5f1d92e251a2896ac4cc4..894701234091b2aec9f52f9192d7f3aad4ede5e6 100644 (file)
@@ -46,6 +46,7 @@
 #include <ShapeFix_Wireframe.hxx>
 #include <ShapeFix_Face.hxx>
 #include <ShapeFix_Shape.hxx>
+#include <ShapeFix_LackingEdgeRecover.hxx>
 #include <Precision.hxx>
 #include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
 #include <ShapeExtend_MsgRegistrator.hxx>
@@ -567,6 +568,52 @@ Standard_Integer fixsmall(Draw_Interpretor& di, Standard_Integer n, const char**
   return 0;
 }
 
+//=======================================================================
+//function : fixlackingedges
+//purpose  : 
+//=======================================================================
+
+static Standard_Integer fixlackingedges(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+  if( n < 3) 
+  {
+    di << "\nInvalid number of arguments\n";
+    return 1;
+  }
+  Standard_Integer aCurIndexOfArg = 1;
+  
+  // result shape
+  Standard_CString aNameOfModifiedShape = a[aCurIndexOfArg];
+
+  // source shape
+  aCurIndexOfArg++;
+  TopoDS_Shape aShape = DBRep::Get(a[aCurIndexOfArg]);
+  if (aShape.IsNull())
+  {
+    di << "\nthe shape is null\n";
+    return 1;
+  }
+
+  // max tolerance
+  Standard_Real aMaxTol = 0.01;
+  aCurIndexOfArg++;
+  if (aCurIndexOfArg < n)
+    aMaxTol = Draw::Atof(a[aCurIndexOfArg]);
+
+  Handle(ShapeFix_LackingEdgeRecover) aLackingEdgeTool = 
+    new ShapeFix_LackingEdgeRecover;
+
+  aLackingEdgeTool->SetMaxTolerance(aMaxTol);
+  aLackingEdgeTool->Init(aShape);
+  aLackingEdgeTool->Perform();
+
+  TopoDS_Shape aModifiedShape = aLackingEdgeTool->Shape();
+
+  DBRep::Set ( aNameOfModifiedShape, aModifiedShape );
+
+  return 0;
+}
+
 //=======================================================================
 //function : fixsmalledges
 //purpose  : 
@@ -775,8 +822,8 @@ static Standard_Integer connectedges(Draw_Interpretor& di, Standard_Integer n, c
                   __FILE__,reface,g);
   theCommands.Add ("fixshape","res shape [preci [maxpreci]] [{switches}]",
                   __FILE__,fixshape,g);
-//  theCommands.Add ("testfill","result edge1 edge2",
-//                __FILE__,XSHAPE_testfill,g);
+  theCommands.Add ("fixlackingedges","result shape [toler]",
+                  __FILE__,fixlackingedges,g);
   theCommands.Add ("fixwgaps","result shape [toler=0]",
                   __FILE__,fixgaps,g);
   theCommands.Add ("fixsmall","result shape [toler=1.]",
index 87e9f83ddd5574b3c6ed884e363c059cff148fea..fc971d97da8fb4983b20e60e4278828cb43a5b53 100644 (file)
@@ -33,6 +33,7 @@ uses
     GeomAbs,
     Adaptor3d,
     TCollection,
+    TColgp,
     TColStd,
     TopAbs,
     TopLoc,
@@ -103,8 +104,11 @@ is
        
     class IntersectionTool;
        ---Purpose: Tool for fixing selfintersecting wire
-      --          and intersecting wires
-       
+        --          and intersecting wires
+        
+    class LackingEdgeRecover;
+        ---Purpose: Tool for lacking edges recover
+      
     class SplitTool;
        ---Purpose: Tool for splitting and cutting edges; incudes methods
       --          used in OverlappingTool and IntersectionTool
@@ -142,6 +146,12 @@ is
       ---Purpose: Removes edges which are less than given tolerance from shape
       --          with help of ShapeFix_Wire::FixSmall()
 
+    RecoverLackingEdges (theShape: Shape from TopoDS; theMaxTolerance: Real; theContext: in out ReShape from ShapeBuild) 
+       returns Shape from TopoDS;
+      ---Purpose: Recovers lacking edges by replacing of vertices with tolerance
+      --          greater than max tolerance by couple of vertices with "normal"
+      --          tolerance and lacking edge between them
+
     FixVertexPosition(theshape: in out Shape from TopoDS;
                      theTolerance: Real; 
                      thecontext: ReShape from ShapeBuild) returns Boolean;
index 816ccc35208d116138090fe26f253cb9f8c64823..c48d4d5bad82045409f899d7a83c3e2e488e5835 100644 (file)
@@ -52,6 +52,7 @@
 #include <ShapeFix_Shape.hxx>
 #include <ShapeFix_Wire.hxx>
 #include <ShapeFix_Face.hxx>
+#include <ShapeFix_LackingEdgeRecover.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <GeomAdaptor_HSurface.hxx>
 #include <TopTools_MapOfShape.hxx>
@@ -712,3 +713,23 @@ Standard_Real ShapeFix::LeastEdgeSize(TopoDS_Shape& theShape)
   aRes = sqrt(aRes);
   return aRes;
 }
+
+//=======================================================================
+//function : RecoverLackingEdges
+//purpose  : 
+//=======================================================================
+
+TopoDS_Shape ShapeFix::RecoverLackingEdges(const TopoDS_Shape& theShape,
+                                           const Standard_Real theMaxTolerance,
+                                           Handle(ShapeBuild_ReShape)& theContext)
+{
+  Handle(ShapeFix_LackingEdgeRecover) aLackingEdgeTool = 
+    new ShapeFix_LackingEdgeRecover;
+
+  aLackingEdgeTool->SetContext(theContext);
+  aLackingEdgeTool->SetMaxTolerance(theMaxTolerance);
+  aLackingEdgeTool->Init(theShape);
+  aLackingEdgeTool->Perform();
+
+  return aLackingEdgeTool->Shape();
+}
diff --git a/src/ShapeFix/ShapeFix_LackingEdgeRecover.cdl b/src/ShapeFix/ShapeFix_LackingEdgeRecover.cdl
new file mode 100644 (file)
index 0000000..76e6bff
--- /dev/null
@@ -0,0 +1,113 @@
+-- Created on:   10.10.2013
+-- Created by:   Briginas Ivan
+
+class LackingEdgeRecover from ShapeFix inherits Root from ShapeFix
+
+---Purpose: Fixing lacking edge
+        
+uses
+
+    Shape               from TopoDS,
+    Face                from TopoDS,
+    Wire                from TopoDS,
+    Edge                from TopoDS,
+    Vertex              from TopoDS,
+    Pnt                 from gp,
+    Pnt2d               from gp,
+    BSplineCurve        from Geom2d,
+    Curve               from Geom2d,
+    WireData            from ShapeExtend,
+    Root                from ShapeFix,
+    SequenceOfPnt       from TColgp
+    
+is
+    
+    Create returns LackingEdgeRecover from ShapeFix;
+        ---Purpose: Default constructor set precision and status message
+        --          and drops all fixing statuses
+        
+    Create (theShape: Shape from TopoDS)
+    returns LackingEdgeRecover from ShapeFix;
+        ---Purpose: Constructor call Init method
+
+    Init (me: mutable; theShape: Shape from TopoDS);
+        ---Purpose: apply current context to the shape.
+
+    Perform (me: mutable);
+        ---Purpose: split vertices with big tolerance covering missed edge, 
+        --          into two new vertices and lacking edge
+
+    Shape (me) returns Shape from TopoDS;
+        ---Purpose: Returns resulting shape
+
+    ConvertLackingVerticesTo2D(me;
+                               theWire: Wire from TopoDS;
+                               theFace: Face from TopoDS;
+                               theFirstVertex:  Vertex from TopoDS;
+                               theSecondVertex: Vertex from TopoDS;
+                               theFirstPnt2D:  in out Pnt2d from gp;
+                               theSecondPnt2D: in out Pnt2d from gp);
+        ---Purpose: seek the ends of parametric curves of edges that share 
+        --          input vertices (first and second) update the first and
+        --          the second points by found results
+
+    MakeBSplineLackingCurve2D(me;
+                              theFirstPnt2D:  Pnt2d from gp;
+                              theSecondPnt2D: Pnt2d from gp) 
+    returns BSplineCurve from Geom2d;
+        ---Purpose: create and return b-spline in 2D space
+
+
+    IsWireStrip(me;
+                theWire: Wire from TopoDS;
+                theFace: Face from TopoDS;
+                theVertex: Vertex from TopoDS;
+                theFirstPnt: in out Pnt from gp;
+                theSecondPnt: in out Pnt from gp) returns Boolean;
+    ---Purpose: 1. build vector between the ends of the parametric curves (of
+    --             edges belonging to the wire) that share the vertex;
+    --          2. project the wire on the built vector
+    --          3. return TRUE if the length of the projection is less than
+    --             the length of the built vector which was multiplied by <br>
+    --          predefined (2) number
+
+    ReplaceVertex(me;
+                  theVertex: Vertex from TopoDS;
+                  theEdge: Edge from TopoDS;
+                  theFace: Face from TopoDS;
+                  theListOfFirstPnt: SequenceOfPnt from TColgp;
+                  theFirstVertex: Vertex from TopoDS;
+                  theSecondVertex: Vertex from TopoDS)
+    returns Edge from TopoDS;
+    ---Purpose: replace the vertex of the edge by the first or the second vertex
+    --          before replacing the method choose what vertex should be used for 
+    --          replacing return modified edge (with replaced vertex)
+
+    ConvertTo2D(me;
+                theEdge : Edge from TopoDS;
+                theVertex : Vertex from TopoDS;
+                theCurve2D : Curve from Geom2d;
+                thePFirst : Real;
+                thePSecond : Real)
+    returns Pnt2d from gp;
+    ---Purpose: calculate parametric representation the vertex on the curve 2d
+    --          return this representation
+
+    ProjectTo2DVector(me;
+                      theWireData : WireData from ShapeExtend;
+                      theFace : Face from TopoDS;
+                      thePntNbPerEdgeForProj : Real;
+                      thePFirst2D : Pnt2d from gp;
+                      thePSecond2D : Pnt2d from gp)
+    returns Real;
+    ---Purpose: 1. project the wire (equidistant point of it) on the vector
+    --             is formed by the first and second parametric points
+    --          2. calculate and RETURN length of the projection
+
+fields
+
+    myShape : Shape from TopoDS is protected;
+    myRecoveredShape : Shape from TopoDS is protected;
+    myStatus : Integer is protected;
+
+end LackingEdgeRecover;
diff --git a/src/ShapeFix/ShapeFix_LackingEdgeRecover.cxx b/src/ShapeFix/ShapeFix_LackingEdgeRecover.cxx
new file mode 100644 (file)
index 0000000..7878290
--- /dev/null
@@ -0,0 +1,795 @@
+// File:      ShapeFix_LackingEdgeRecover.cxx
+// Created:   10.10.2013
+// Author:    Briginas Ivan
+
+#include <ShapeFix_LackingEdgeRecover.hxx>
+
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+
+#include <Geom_Curve.hxx>
+#include <Geom_Surface.hxx>
+
+#include <BRepLib.hxx>
+
+#include <Geom2d_BSplineCurve.hxx>
+
+#include <gp_Pnt2d.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec2d.hxx>
+
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TColgp_SequenceOfPnt.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+
+#include <NCollection_List.hxx>
+#include <NCollection_Map.hxx>
+#include <NCollection_DataMap.hxx>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+
+#include <ShapeBuild_Edge.hxx>
+
+#include <ShapeExtend.hxx>
+#include <ShapeExtend_WireData.hxx>
+#include <ShapeBuild_ReShape.hxx>
+
+#include <ShapeFix_Edge.hxx>
+
+#include <Standard_Assert.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (ShapeFix_LackingEdgeRecover, ShapeFix_Root)
+IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_LackingEdgeRecover, ShapeFix_Root)
+
+inline Standard_Boolean IsEqual(const TopoDS_Edge& theEdge1,
+                                const TopoDS_Edge& theEdge2)
+{ 
+  return theEdge1.IsSame(theEdge2); 
+}
+
+inline Standard_Boolean IsEqual(const TopoDS_Face& theFace1,
+                                const TopoDS_Face& theFace2)
+{ 
+  return theFace1.IsEqual(theFace2); 
+}
+
+ShapeFix_LackingEdgeRecover::ShapeFix_LackingEdgeRecover()
+{
+  myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
+  SetPrecision(Precision::Confusion());
+}
+
+ShapeFix_LackingEdgeRecover::ShapeFix_LackingEdgeRecover(const TopoDS_Shape& theShape)
+{
+  this->Init(theShape);
+}
+
+TopoDS_Shape ShapeFix_LackingEdgeRecover::Shape() const
+{
+  return myRecoveredShape;
+}
+
+void ShapeFix_LackingEdgeRecover::Init(const TopoDS_Shape& theShape)
+{
+  myShape = theShape;
+  if ( Context().IsNull() ) 
+    SetContext ( new ShapeBuild_ReShape );
+
+  myRecoveredShape = theShape;
+}
+
+void ShapeFix_LackingEdgeRecover::Perform()
+{
+  myRecoveredShape = Context()->Apply(myShape);
+  
+  TopTools_IndexedDataMapOfShapeListOfShape aVertexEdgesMap, aVertexWiresMap,
+                                            anEdgeFacesMap,  aWireFacesMap;
+
+  TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_VERTEX, TopAbs_EDGE, aVertexEdgesMap);
+  TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_VERTEX, TopAbs_WIRE, aVertexWiresMap);
+  TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_EDGE,   TopAbs_FACE, anEdgeFacesMap);
+  TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_WIRE,   TopAbs_FACE, aWireFacesMap);
+
+  NCollection_List< std::pair<TopoDS_Vertex, TopoDS_Vertex> > aVerticesForLackingEdgesBuilding;
+  typedef NCollection_DataMap<TopoDS_Face, Standard_Integer> FaceDataMap;
+
+  // search vertices with tolerance greater than specified threshold (theMaxTol)
+  TopTools_IndexedMapOfShape aShapeVertexMap;
+  TopExp::MapShapes(myRecoveredShape, TopAbs_VERTEX, aShapeVertexMap);
+
+  Standard_Integer aVertIter = 1; // start from 1
+  for (; aVertIter <= aShapeVertexMap.Extent(); ++aVertIter)
+  {
+    TopoDS_Vertex aCurVertex = TopoDS::Vertex (aShapeVertexMap.FindKey(aVertIter));
+    Standard_Real aCurTol    = BRep_Tool::Tolerance (aCurVertex);
+
+    // skip vertices with tolerance lesser than theMaxTol
+    if (aCurTol < this->MaxTolerance())
+      continue;
+
+    const TopTools_ListOfShape& aSharingWiresOfCurVertex = aVertexWiresMap.FindFromKey (aCurVertex);
+
+    // process each edge
+    Standard_Boolean anIsVertexReplaced = Standard_False;
+    gp_Pnt aFirstNewPnt, aSecondNewPnt; // these points will replace vertex with big tolerance
+
+    TopTools_ListIteratorOfListOfShape anWireIter(aSharingWiresOfCurVertex);
+    for (;anWireIter.More() && !anIsVertexReplaced; anWireIter.Next())
+    {
+      const TopoDS_Wire& aCurWire = TopoDS::Wire(anWireIter.Value());
+
+      const TopTools_ListOfShape& aSharingFacesOfCurWire =
+        aWireFacesMap.FindFromKey (anWireIter.Value());
+
+      // (IMPORTANT) process just first found face
+      TopTools_ListIteratorOfListOfShape aSharingFacesOfCurWireIter(aSharingFacesOfCurWire);
+      for (; aSharingFacesOfCurWireIter.More() && !anIsVertexReplaced; aSharingFacesOfCurWireIter.Next())
+      {
+        // replace the vertex if sharing wire is strip
+        anIsVertexReplaced = IsWireStrip(aCurWire, TopoDS::Face(aSharingFacesOfCurWireIter.Value()),
+                                         aCurVertex, aFirstNewPnt, aSecondNewPnt);
+      }
+    }
+
+    //int todo_streach_degenerated_edge;
+
+    if (!anIsVertexReplaced)
+      continue;
+
+
+    const TopTools_ListOfShape& aSharingEdgesOfCurVertex =
+      aVertexEdgesMap.FindFromKey (aCurVertex);
+
+    FaceDataMap aSharingFacesMap;
+    Standard_Boolean anIsCurVertexSkipped = Standard_False;
+
+    // split sharing edges into two groups
+    TColgp_SequenceOfPnt aFirstPntList, aSecondPntList;
+    NCollection_Map<TopoDS_Edge> anEdgeMap;
+    TopTools_ListIteratorOfListOfShape aSharingEdgesOfCurVertexIter(aSharingEdgesOfCurVertex);
+    for (; aSharingEdgesOfCurVertexIter.More(); aSharingEdgesOfCurVertexIter.Next())
+    {
+      const TopoDS_Edge& aCurIntEdge = TopoDS::Edge(aSharingEdgesOfCurVertexIter.Value());
+
+      if (!anEdgeMap.Contains(aCurIntEdge))
+        anEdgeMap.Add(aCurIntEdge);
+      else
+        continue;
+
+      if (!anEdgeFacesMap.Contains(aCurIntEdge))
+        continue;
+      const TopTools_ListOfShape& aSharingFacesOfCurIntEdge = anEdgeFacesMap.FindFromKey (aCurIntEdge);
+
+      if (aSharingFacesOfCurIntEdge.IsEmpty())
+        continue;
+
+      // collect all sharing faces
+      TopTools_ListIteratorOfListOfShape aSharingFacesIter(aSharingFacesOfCurIntEdge);
+      for(; aSharingFacesIter.More(); aSharingFacesIter.Next())
+      {
+        const TopoDS_Face aCurShFace = TopoDS::Face(aSharingFacesIter.Value());
+
+        if (!aSharingFacesMap.IsBound(aCurShFace))
+          aSharingFacesMap.Bind(aCurShFace, 1);
+        else
+          aSharingFacesMap(aCurShFace)++;
+      }
+
+      // skip the case when a vertex is being shared by more 
+      // than 2 edges that belong to one face
+      Standard_Integer aMaxNbEdgesOnOneFace = 2;
+      for (FaceDataMap::Iterator anIt(aSharingFacesMap);
+           anIt.More() && !anIsCurVertexSkipped; anIt.Next())
+      {
+        if (anIt.Value() > aMaxNbEdgesOnOneFace)
+          anIsCurVertexSkipped = Standard_True;
+      }
+
+      // break processing of edges that share the cur vertex
+      if (anIsCurVertexSkipped)
+        break;
+
+      // take first sharing face
+      const TopoDS_Face& aCurIntFace = TopoDS::Face(aSharingFacesOfCurIntEdge.First());
+
+      TopLoc_Location aLocation;
+      Handle(Geom_Surface) aCurIntSurf = BRep_Tool::Surface (aCurIntFace, aLocation);
+
+      Standard_Real aPFirstParamOfCurIntEdge, aPLastParamOfCurIntEdge;
+      Handle(Geom2d_Curve) aPCurveOfCurIntEdge = 
+        BRep_Tool::CurveOnSurface (aCurIntEdge, aCurIntFace, 
+        aPFirstParamOfCurIntEdge, aPLastParamOfCurIntEdge);
+
+      // sort couple of vertices of the current internal edge
+      TopoDS_Iterator anVerticesIter(aCurIntEdge, TopAbs_VERTEX);
+      for (; anVerticesIter.More(); anVerticesIter.Next())
+      {
+        const TopoDS_Vertex& aCurInternalVertex = TopoDS::Vertex(anVerticesIter.Value());
+
+        if(!aCurInternalVertex.IsSame(aCurVertex))
+          continue;
+
+        gp_Pnt2d anAddingPnt2D = ConvertTo2D(aCurIntEdge, aCurInternalVertex, aPCurveOfCurIntEdge,
+          aPFirstParamOfCurIntEdge, aPLastParamOfCurIntEdge);
+
+        gp_Pnt anAddingPnt;
+        aCurIntSurf->D0(anAddingPnt2D.X(), anAddingPnt2D.Y(), anAddingPnt);
+
+        Standard_Real aDist2ToFirstNewPnt  = aFirstNewPnt.SquareDistance(anAddingPnt);
+        Standard_Real aDist2ToSecondNewPnt = aSecondNewPnt.SquareDistance(anAddingPnt);
+
+        if (aDist2ToFirstNewPnt < aDist2ToSecondNewPnt)
+          aFirstPntList.Append(anAddingPnt);
+        else
+          aSecondPntList.Append(anAddingPnt);
+      }
+    }
+
+    if (anIsCurVertexSkipped)
+      continue;
+
+    if (aFirstPntList.IsEmpty() || aSecondPntList.IsEmpty())
+      continue;
+
+    // === process FIRST group
+    // mean point of first group
+    gp_XYZ aTotalXYZ;
+    for (Standard_Integer aCurIndex = 1; aCurIndex <= aFirstPntList.Length(); aCurIndex++)
+      aTotalXYZ += aFirstPntList.Value(aCurIndex).XYZ();
+
+    gp_Pnt aMeanFirstNewPnt(aTotalXYZ/aFirstPntList.Length());
+    // === END process FIRST group
+
+    // === process SECOND group
+    // mean point of second group
+    aTotalXYZ = gp_XYZ();
+    for (Standard_Integer aCurIndex = 1; aCurIndex <= aSecondPntList.Length(); aCurIndex++)
+      aTotalXYZ += aSecondPntList.Value(aCurIndex).XYZ();
+
+    gp_Pnt aMeanSecondNewPnt(aTotalXYZ/aSecondPntList.Length());
+    // === END process SECOND group
+
+    // create new vertices
+    BRep_Builder aBuilder;
+    TopoDS_Vertex aFirstNewVertex, aSecondNewVertex;
+    // tolerance of vertices will be corrected during future edge replacement
+    aBuilder.MakeVertex (aFirstNewVertex, aMeanFirstNewPnt, Precision::Confusion());
+    aBuilder.MakeVertex (aSecondNewVertex, aMeanSecondNewPnt, Precision::Confusion());
+
+    // fill in for building lacking edges
+    aVerticesForLackingEdgesBuilding.Append(std::make_pair(aFirstNewVertex, aSecondNewVertex));
+
+    // tool for fixing of vertex tolerance
+    Handle(ShapeFix_Edge) anEdgeFixer = new ShapeFix_Edge;
+
+    // update the shape to replace vertex with big tolerance by two new vertices 
+    aSharingEdgesOfCurVertexIter.Initialize(aSharingEdgesOfCurVertex);
+    for (; aSharingEdgesOfCurVertexIter.More(); aSharingEdgesOfCurVertexIter.Next())
+    {
+      const TopoDS_Edge& aCurIntUnUpdatedEdge = TopoDS::Edge(aSharingEdgesOfCurVertexIter.Value());
+
+      // current updated edge
+      TopoDS_Edge aCurIntEdge  = TopoDS::Edge(Context()->Apply(aCurIntUnUpdatedEdge));
+
+      // the copy of the current internal updated edge
+      TopoDS_Edge aModifedEdge = TopoDS::Edge(Context()->Apply(aCurIntUnUpdatedEdge));
+
+      // take first sharing face
+      const TopTools_ListOfShape& aSharingFacesOfCurIntEdge = anEdgeFacesMap.FindFromKey (aCurIntUnUpdatedEdge);
+      const TopoDS_Face& aCurIntFace = TopoDS::Face(aSharingFacesOfCurIntEdge.First());
+
+      TopoDS_Iterator aVertIterOfCurIntEdge(aCurIntEdge);
+      for (; aVertIterOfCurIntEdge.More(); aVertIterOfCurIntEdge.Next())
+      {
+        const TopoDS_Vertex& aCurVertexOfCurIntEdge = TopoDS::Vertex(aVertIterOfCurIntEdge.Value());
+
+        if (!aCurVertexOfCurIntEdge.IsSame(aCurVertex))
+          continue;
+
+        // replace the current vertex of the current internal edge by couple of new vertices
+        aModifedEdge = ReplaceVertex(aCurVertexOfCurIntEdge, aModifedEdge, 
+          aCurIntFace, aFirstPntList,
+          aFirstNewVertex, aSecondNewVertex);
+
+        // increase tolerance of vertices of the modified 
+        // edge if the ones don't cover the tolerance 
+        // of the modified edge
+        anEdgeFixer->FixVertexTolerance(aModifedEdge);
+      }
+
+      // update the context
+      Context()->Replace(aCurIntEdge, aModifedEdge);
+    }
+  }
+
+  // apply the changes containing all replacements with vertices
+  myRecoveredShape = Context()->Apply(myRecoveredShape);
+
+  // add lacking edges into the modified shape (it doesn't contain vertices with big tolerance already)
+  TopTools_IndexedDataMapOfShapeListOfShape anUpdatedVertexWiresMap, anUpdatedWireFacesMap;
+  TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_VERTEX, TopAbs_WIRE, anUpdatedVertexWiresMap);
+  TopExp::MapShapesAndAncestors(myRecoveredShape, TopAbs_WIRE,   TopAbs_FACE, anUpdatedWireFacesMap);
+
+  NCollection_List< std::pair<TopoDS_Vertex, TopoDS_Vertex> >::Iterator
+    aVerticesForLackingEdgesIter(aVerticesForLackingEdgesBuilding);
+
+  // run through all pairs of new vertices to add lacking edge between them
+  for (; aVerticesForLackingEdgesIter.More(); aVerticesForLackingEdgesIter.Next())
+  {
+    const TopoDS_Vertex& aFirstNewVertex = aVerticesForLackingEdgesIter.Value().first;
+    const TopoDS_Vertex& aSecondNewVertex = aVerticesForLackingEdgesIter.Value().second;
+
+    // wires share the first new vertex
+    if (!anUpdatedVertexWiresMap.Contains(aFirstNewVertex))
+      continue;
+    const TopTools_ListOfShape& aSharingWiresOfFirstNewVertex =
+      anUpdatedVertexWiresMap.FindFromKey (aFirstNewVertex);
+
+    // wires share the second new vertex
+    if (!anUpdatedVertexWiresMap.Contains(aSecondNewVertex))
+      continue;
+    const TopTools_ListOfShape& aSharingWiresOfSecondNewVertex =
+      anUpdatedVertexWiresMap.FindFromKey (aSecondNewVertex);
+
+    // seek the intersection of two lists of sharing wires
+    TopTools_ListIteratorOfListOfShape anIterOfFirstWireList(aSharingWiresOfFirstNewVertex);
+
+    TopTools_ListOfShape anIntersectOfTwoLists;
+    for (; anIterOfFirstWireList.More(); anIterOfFirstWireList.Next())
+    {
+      TopTools_ListIteratorOfListOfShape anIterOfSecondWireList(aSharingWiresOfSecondNewVertex);
+      for (; anIterOfSecondWireList.More(); anIterOfSecondWireList.Next())
+      {
+        if (anIterOfFirstWireList.Value().IsSame(anIterOfSecondWireList.Value()))
+          anIntersectOfTwoLists.Append(anIterOfFirstWireList.Value());
+      }
+    }
+
+    // tool for fixing of vertex tolerance to cover edge tolerance that contains this vertex
+    Handle(ShapeFix_Edge) anEdgeFixer = new ShapeFix_Edge;
+    TopoDS_Edge aLackingEdge;
+    BRep_Builder aBuilder;
+
+    // add lacking edge to each intersected wire by replacing one their edge
+    TopTools_ListIteratorOfListOfShape anIterOfIntersetionList(anIntersectOfTwoLists);
+    for (; anIterOfIntersetionList.More(); anIterOfIntersetionList.Next())
+    {
+      const TopoDS_Wire& aCurWire = TopoDS::Wire(anIterOfIntersetionList.Value());
+
+      // faces of doesn't updated wire
+      const TopTools_ListOfShape& aSharingFacesOfCurWire =
+        anUpdatedWireFacesMap.FindFromKey (aCurWire);
+
+      if (aSharingFacesOfCurWire.Extent() == 0)
+        continue;
+
+      // _first_ found face containing the current wire
+      const TopoDS_Face& aCurFace = TopoDS::Face(aSharingFacesOfCurWire.First());
+
+      TopLoc_Location aLocation;
+      Handle(Geom_Surface) aCurSurf = BRep_Tool::Surface (aCurFace, aLocation);
+
+      TopoDS_Wire anUpdatedCurWire = TopoDS::Wire(Context()->Apply(aCurWire));
+
+      // seek 2d points (from doesn't updated wire) for 2d pcurve building
+      gp_Pnt2d aFirst2D, aSecond2D;
+      ConvertLackingVerticesTo2D(aCurWire, aCurFace, aFirstNewVertex, aSecondNewVertex, aFirst2D, aSecond2D);
+
+      // create 2d pcurve for lacking edge
+      const Handle(Geom2d_BSplineCurve)& aBSplineLackingCurve2D = 
+                                           MakeBSplineLackingCurve2D(aFirst2D, aSecond2D);
+
+      if (aLackingEdge.IsNull())
+        aLackingEdge = BRepBuilderAPI_MakeEdge(aBSplineLackingCurve2D, aCurSurf, aFirstNewVertex, aSecondNewVertex);
+
+      // add pcurve to the lacking edge
+      aBuilder.UpdateEdge(aLackingEdge, aBSplineLackingCurve2D, aCurSurf, aLocation, 
+                          BRep_Tool::Tolerance(aLackingEdge));
+
+      // set orientation of the lacking edge
+      TopAbs_Orientation anOrientOfLackingEdge = TopAbs_FORWARD;
+      for (TopoDS_Iterator anEdgeIter(aCurWire); anEdgeIter.More(); anEdgeIter.Next())
+      {
+        const TopoDS_Edge& aCurIntEdge = TopoDS::Edge(anEdgeIter.Value());
+
+        if (aFirstNewVertex.IsSame(TopExp::FirstVertex(aCurIntEdge)))
+        {
+          if (aCurIntEdge.Orientation() == TopAbs_FORWARD)
+            anOrientOfLackingEdge = TopAbs_REVERSED;
+          else
+            anOrientOfLackingEdge = TopAbs_FORWARD;
+
+          break;
+        }
+        else if (aFirstNewVertex.IsSame(TopExp::LastVertex(aCurIntEdge)))
+        {
+          if (aCurIntEdge.Orientation() == TopAbs_FORWARD)
+            anOrientOfLackingEdge = TopAbs_FORWARD;
+          else
+            anOrientOfLackingEdge = TopAbs_REVERSED;
+
+          break;
+        }
+      }
+
+      aLackingEdge = TopoDS::Edge(aLackingEdge.Oriented(anOrientOfLackingEdge));
+
+      // add lacking edge to current wire
+      anUpdatedCurWire.Free(Standard_True);
+      aBuilder.Add(anUpdatedCurWire, aLackingEdge);
+
+      Context()->Replace(aCurWire, anUpdatedCurWire);
+    }
+
+    BRepLib::BuildCurve3d(aLackingEdge);
+    BRepLib::SameParameter(aLackingEdge, 1.e-5, Standard_True);
+  }
+
+  myRecoveredShape = Context()->Apply(myRecoveredShape);
+  
+  myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
+}
+
+//=======================================================================
+//function : ReplaceVertex
+//purpose  : replace the input vertex by couple of new ones
+//=======================================================================
+TopoDS_Edge ShapeFix_LackingEdgeRecover::ReplaceVertex(const TopoDS_Vertex& theVert /*theBeingReplacedVertex*/,
+                                                       const TopoDS_Edge&   theEdge /*theBeingReplacedEdge  */,
+                                                       const TopoDS_Face&   theFace,
+                                                       const TColgp_SequenceOfPnt&
+                                                                            theListOfFirstPnt,
+                                                       const TopoDS_Vertex& theFirstVertex,
+                                                       const TopoDS_Vertex& theSecondVertex) const
+{
+  Standard_Real aPFirstParamOfEdge, aPLastParamOfEdge;
+  Handle(Geom2d_Curve) aPCurveOfCurIntEdge = 
+    BRep_Tool::CurveOnSurface (theEdge, theFace, aPFirstParamOfEdge, aPLastParamOfEdge);
+
+  TopAbs_Orientation anOrientOfVert = theVert.Orientation();
+
+  // seek the end of pcurve that shares the input vertex
+  gp_Pnt2d aBeingSoughtPnt2D = ConvertTo2D(theEdge, theVert, aPCurveOfCurIntEdge, 
+                                           aPFirstParamOfEdge, aPLastParamOfEdge);
+
+  TopLoc_Location aLocation;
+  Handle(Geom_Surface) aSurf = BRep_Tool::Surface (theFace, aLocation);
+
+  // convert the found end of pcurve to point in 3D space
+  gp_Pnt aBeingSoughtPnt;
+  aSurf->D0(aBeingSoughtPnt2D.X(), aBeingSoughtPnt2D.Y(), aBeingSoughtPnt);
+
+  // seek what list contains found 3D point
+  Standard_Boolean anIsBeingSoughtPntInFirstList = Standard_False;
+  Standard_Integer aCurIndex = 1;
+  for (; aCurIndex <= theListOfFirstPnt.Length() && !anIsBeingSoughtPntInFirstList; aCurIndex++)
+    if (aBeingSoughtPnt.Distance(theListOfFirstPnt.Value(aCurIndex)) <= Precision::Confusion())
+      anIsBeingSoughtPntInFirstList = Standard_True;
+
+  // choose what vertex in the edge will be replaced taking into account found 
+  // list containing this found 3d point
+  TopoDS_Vertex aBeingSoughtVertex;
+  if (anIsBeingSoughtPntInFirstList)
+    aBeingSoughtVertex = TopoDS::Vertex(theFirstVertex.Oriented(anOrientOfVert));
+  else
+    aBeingSoughtVertex = TopoDS::Vertex(theSecondVertex.Oriented(anOrientOfVert));
+
+  TopoDS_Edge aModifiedEdge;
+  ShapeBuild_Edge anEdgeBuilder;
+
+  // replace the vertex in the edge by chosen vertex
+  if (anOrientOfVert == TopAbs_FORWARD)
+    aModifiedEdge = anEdgeBuilder.CopyReplaceVertices(theEdge, aBeingSoughtVertex, TopoDS_Vertex());
+  else
+    aModifiedEdge = anEdgeBuilder.CopyReplaceVertices(theEdge, TopoDS_Vertex(), aBeingSoughtVertex);
+
+  return aModifiedEdge;
+}
+
+//=======================================================================
+//function : IsWireStrip
+//purpose  : find out wire is strip or not
+//=======================================================================
+Standard_Boolean ShapeFix_LackingEdgeRecover::IsWireStrip(const TopoDS_Wire& theWire,
+                                                          const TopoDS_Face& theFace,
+                                                          const TopoDS_Vertex& theVertex,
+                                                          gp_Pnt& theFirstPnt, gp_Pnt& theSecondPnt) const
+{
+  // if the wide of the wire projection in parametric space of the face
+  // on vector (which is formed by the first and second input points; theirs analogues in
+  // parametric space of the face) will be less than this parameter - aStripRation 
+  // then wire is detected as a strip
+  Standard_Real aStripRatio = 2.0; 
+  
+  // number of equidistant points on each edge for wire projection
+  // in parametric space on the vector that was described previously
+  Standard_Integer aPntNbPerEdgeForProj = 10; 
+
+  // the analogues of the first and second points in parametric space of the face
+  gp_Pnt2d aPFirst2D, aPSecond2D;
+
+  // the wire is explored by BRepTools_WireExplorer and it is 
+  // guaranteed that edges will be SEQUENCIALLY connected
+  Standard_Boolean isNOTExpByBRepTools_WireExplorer = Standard_False;
+  Handle(ShapeExtend_WireData) anEdgeExp = 
+    new ShapeExtend_WireData(theWire, isNOTExpByBRepTools_WireExplorer);
+
+  Standard_Integer aStartIndex = 1; // start index of ShapeExtend_WireData
+  Standard_Integer anEndIndex  = anEdgeExp->NbEdges();
+
+  if (anEndIndex == 0) // the WIRE IS EMPTY
+    return Standard_False;
+
+  // run through all edges and seek couple of edges which share the vertex
+  Standard_Integer anEdgeIndex, anEdgeIndex_Prev, anEdgeIndex_Next;
+  for (anEdgeIndex = aStartIndex; anEdgeIndex <= anEndIndex; anEdgeIndex++)
+  {
+    // index of previous edge
+    if (anEdgeIndex == aStartIndex) anEdgeIndex_Prev = anEndIndex;
+    else anEdgeIndex_Prev = anEdgeIndex-1;
+
+    // index of next element
+    if (anEdgeIndex == anEndIndex) anEdgeIndex_Next = aStartIndex;
+    else anEdgeIndex_Next = anEdgeIndex+1;
+
+    const TopoDS_Edge& aCurEdge = anEdgeExp->Edge(anEdgeIndex);
+
+    TopoDS_Vertex aCurFirstVertex = TopExp::FirstVertex(aCurEdge);
+    TopoDS_Vertex aCurLastVertex  = TopExp::LastVertex(aCurEdge);
+
+    Standard_Boolean anIsFirstBelong = theVertex.IsSame(aCurFirstVertex);
+    Standard_Boolean anIsLastBelong  = theVertex.IsSame(aCurLastVertex);
+
+    if (!anIsFirstBelong && !anIsLastBelong)
+      continue;
+
+    //int todo_investigate_degenerated_edge;
+
+    Standard_Real aPFirstParamOfCurEdge, aPLastParamOfCurEdge;
+    Handle(Geom2d_Curve) aPCurveOfCurEdge = 
+      BRep_Tool::CurveOnSurface (aCurEdge, theFace, aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
+
+    if (anIsFirstBelong && anIsLastBelong) // both ends of current edge belong to the vertex
+    {
+      aPCurveOfCurEdge->D0(aPFirstParamOfCurEdge, aPFirst2D);
+      aPCurveOfCurEdge->D0(aPLastParamOfCurEdge, aPSecond2D);
+    }
+    else
+    {
+      if (anIsFirstBelong) // first end of current edge
+        aPCurveOfCurEdge->D0(aPFirstParamOfCurEdge, aPFirst2D);
+      else if (anIsLastBelong) // last end of current edge
+        aPCurveOfCurEdge->D0(aPLastParamOfCurEdge, aPFirst2D);
+
+      // is second edge nether next edge in the sequence or previous?
+      TopAbs_Orientation aCurEdgeOrient = aCurEdge.Orientation();
+      Standard_Boolean anIsSecondANextEdge = 
+        (aCurEdgeOrient == TopAbs_FORWARD  && anIsLastBelong) ||
+        (aCurEdgeOrient == TopAbs_REVERSED && anIsFirstBelong);
+
+      Standard_Integer anIndexOfEdgeWithSecondPnt = 
+        (anIsSecondANextEdge ? anEdgeIndex_Next : anEdgeIndex_Prev);
+
+      //
+      const TopoDS_Edge& anEdgeWithSecondPnt = anEdgeExp->Edge(anIndexOfEdgeWithSecondPnt);
+      TopAbs_Orientation anOrientOfEdgeWithSecondPnt = anEdgeWithSecondPnt.Orientation();
+
+      Standard_Boolean isFirstVertexOfEdgeWithSecondPnt = Standard_True;
+      if (anIsSecondANextEdge) // next edge in the edge sequence
+      {
+        if (anOrientOfEdgeWithSecondPnt == TopAbs_FORWARD)
+          isFirstVertexOfEdgeWithSecondPnt = Standard_True;
+        else
+          isFirstVertexOfEdgeWithSecondPnt = Standard_False;
+      }
+      else // previous edge in sequence in the edge sequence
+      {
+        if (anOrientOfEdgeWithSecondPnt == TopAbs_FORWARD)
+          isFirstVertexOfEdgeWithSecondPnt = Standard_False;
+        else
+          isFirstVertexOfEdgeWithSecondPnt = Standard_True;
+      }
+
+      Standard_Real aFirstParamOfEdgeWithSecondPnt, aLastParamOfEdgeWithSecondPnt;
+      Handle(Geom2d_Curve) aPCurveOfEdgeWithSecondPnt =
+        BRep_Tool::CurveOnSurface (anEdgeWithSecondPnt, theFace,
+        aFirstParamOfEdgeWithSecondPnt,
+        aLastParamOfEdgeWithSecondPnt);
+
+      if (isFirstVertexOfEdgeWithSecondPnt)
+        aPCurveOfEdgeWithSecondPnt->D0(aFirstParamOfEdgeWithSecondPnt, aPSecond2D);
+      else
+        aPCurveOfEdgeWithSecondPnt->D0(aLastParamOfEdgeWithSecondPnt, aPSecond2D);
+    }
+
+    if (aPFirst2D.Distance(aPSecond2D) <= Precision::Confusion())
+      continue;
+
+    // project points of edges on aPVec2D
+    Standard_Real aProjLength = ProjectTo2DVector(anEdgeExp, theFace, aPntNbPerEdgeForProj, aPFirst2D, aPSecond2D);
+    
+    gp_Vec2d aPVec2D(aPFirst2D, aPSecond2D);
+    if (aProjLength <= aStripRatio*aPVec2D.Magnitude())
+    {
+      TopLoc_Location aLocation;
+      Handle(Geom_Surface) aSurf = BRep_Tool::Surface (theFace, aLocation);
+
+      aSurf->D0(aPFirst2D.X() , aPFirst2D.Y(),  theFirstPnt);
+      aSurf->D0(aPSecond2D.X(), aPSecond2D.Y(), theSecondPnt);
+
+      return Standard_True;
+    }
+  }
+
+  return Standard_False;
+}
+
+//=======================================================================
+//function : ConvertLackingVerticesTo2D
+//purpose  : 
+//=======================================================================
+void ShapeFix_LackingEdgeRecover::ConvertLackingVerticesTo2D(const TopoDS_Wire&   theWire, 
+                                                             const TopoDS_Face&   theFace, 
+                                                             const TopoDS_Vertex& theFirstVertex,
+                                                             const TopoDS_Vertex& theSecondVertex, 
+                                                             gp_Pnt2d&      theFirstPnt2D, 
+                                                             gp_Pnt2d&      theSecondPnt2D) const
+{
+  Standard_Boolean aHasFirstBeenFound  = Standard_False;
+  Standard_Boolean aHasSecondBeenFound = Standard_False;
+  TopoDS_Iterator anEdgeIter(theWire);
+  for (; anEdgeIter.More(); anEdgeIter.Next())
+  {
+    const TopoDS_Edge& aCurEdge = TopoDS::Edge(anEdgeIter.Value());
+
+    Standard_Real aPFirstParamOfCurEdge, aPLastParamOfCurEdge;
+    Handle(Geom2d_Curve) aCurCurve2D = 
+      BRep_Tool::CurveOnSurface(aCurEdge, theFace, aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
+
+    TopoDS_Iterator aVertexIter(aCurEdge);
+    for (; aVertexIter.More(); aVertexIter.Next())
+    {
+      const TopoDS_Vertex& aCurVertex = TopoDS::Vertex(aVertexIter.Value());
+      if (!aHasFirstBeenFound)
+      {
+        if (theFirstVertex.IsSame(aCurVertex))
+        {
+          aHasFirstBeenFound = Standard_True;
+          theFirstPnt2D = ConvertTo2D(aCurEdge, aCurVertex, aCurCurve2D, 
+                                      aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
+        }
+      }
+
+      if (!aHasSecondBeenFound)
+      {
+        if (theSecondVertex.IsSame(aCurVertex))
+        {
+          aHasSecondBeenFound = Standard_True;
+          theSecondPnt2D = ConvertTo2D(aCurEdge, aCurVertex, aCurCurve2D, 
+                                       aPFirstParamOfCurEdge, aPLastParamOfCurEdge);
+        }
+      }
+    }
+    
+    if (aHasFirstBeenFound && aHasSecondBeenFound)
+      break;
+  }
+}
+
+//=======================================================================
+//function : MakeBSplineLackingCurve2D
+//purpose  :
+//=======================================================================
+Handle(Geom2d_BSplineCurve) ShapeFix_LackingEdgeRecover::MakeBSplineLackingCurve2D(
+                                                                  const gp_Pnt2d& theFirstPnt2D,
+                                                                  const gp_Pnt2d& theSecondPnt2D) const
+{
+  TColgp_Array1OfPnt2d aPolesOfBSplineCurve (1, 2);
+  aPolesOfBSplineCurve(1).SetCoord(theFirstPnt2D.X(), theFirstPnt2D.Y());
+  aPolesOfBSplineCurve(2).SetCoord(theSecondPnt2D.X(), theSecondPnt2D.Y());
+
+  TColStd_Array1OfReal aKnotesOfBSplineCurve(1, 2);
+  aKnotesOfBSplineCurve(1) = 0.0;
+  aKnotesOfBSplineCurve(2) = 1.0;
+
+  TColStd_Array1OfInteger aMultiplicities (1, 2);
+  aMultiplicities(1) = 2;
+  aMultiplicities(2) = 2;
+
+  return new Geom2d_BSplineCurve(aPolesOfBSplineCurve, aKnotesOfBSplineCurve, aMultiplicities, 1, 0);
+}
+
+//=======================================================================
+//function : ConvertTo2D
+//purpose  :
+//=======================================================================
+gp_Pnt2d ShapeFix_LackingEdgeRecover::ConvertTo2D(const TopoDS_Edge& theEdge,
+                                                  const TopoDS_Vertex& theVertex,
+                                                  const Handle(Geom2d_Curve)& theCurve2D,
+                                                  const Standard_Real thePFirst,
+                                                  const Standard_Real thePLast) const
+{
+  gp_Pnt2d aPnt2d;
+  if (theEdge.Orientation() == TopAbs_FORWARD)
+  {
+    if (theVertex.Orientation() == TopAbs_FORWARD)
+      theCurve2D->D0(thePFirst, aPnt2d);
+    else
+      theCurve2D->D0(thePLast, aPnt2d);
+  }
+  else
+  {
+    if (theVertex.Orientation() == TopAbs_FORWARD)
+      theCurve2D->D0(thePLast, aPnt2d);
+    else
+      theCurve2D->D0(thePFirst, aPnt2d);
+  }
+
+  return aPnt2d;
+}
+
+//=======================================================================
+//function : ProjectTo2DVector
+//purpose  :
+//=======================================================================
+Standard_Real ShapeFix_LackingEdgeRecover::ProjectTo2DVector(const Handle(ShapeExtend_WireData)& theWireData,
+                                                             const TopoDS_Face& theFace,
+                                                             const Standard_Real thePntNbPerEdgeForProj,
+                                                             const gp_Pnt2d& thePFirst2D,
+                                                             const gp_Pnt2d& thePSecond2D) const
+{
+  gp_Vec2d aPVec2D(thePFirst2D, thePSecond2D);
+
+  Standard_Integer aStartIndex = 1; // start index of ShapeExtend_WireData
+  Standard_Integer anEndIndex  = theWireData->NbEdges();
+
+  // project points of edges on aPVec2D
+  Standard_Real aMaxWireValue = -Precision::Infinite();
+  Standard_Real aMinWireValue =  Precision::Infinite();
+
+  Standard_Integer aCurEdgeIndex = aStartIndex;
+  for (; aCurEdgeIndex <= anEndIndex; aCurEdgeIndex++)
+  {
+    Standard_Real aPFirstParamOfIntCurEdge, aPLastParamOfIntCurEdge;
+    Handle(Geom2d_Curve) aPCurveOfIntCurEdge = 
+      BRep_Tool::CurveOnSurface (theWireData->Edge(aCurEdgeIndex), theFace,
+      aPFirstParamOfIntCurEdge, aPLastParamOfIntCurEdge);
+
+    // split the curve of the current edge on aPntNbPerEdgeForProj parts
+    Standard_Integer aCurStep = 0;
+    Standard_Real  aPCurParam = aPFirstParamOfIntCurEdge;
+    Standard_Real   aStepSize = (aPLastParamOfIntCurEdge - aPFirstParamOfIntCurEdge)/thePntNbPerEdgeForProj;
+    while (aPCurParam <= aPLastParamOfIntCurEdge)
+    {
+      aPCurParam = aPFirstParamOfIntCurEdge + aCurStep*aStepSize;
+
+      gp_Pnt2d aPCur2D;
+      aPCurveOfIntCurEdge->D0(aPCurParam, aPCur2D);
+
+      // project current parametric point on the vector (by scalar product)
+      Standard_Real aStepFromPFirst2D = aPVec2D*gp_Vec2d(thePFirst2D, aPCur2D) / aPVec2D.Magnitude();
+
+      aMaxWireValue = Max(aMaxWireValue, aStepFromPFirst2D);
+      aMinWireValue = Min(aMinWireValue, aStepFromPFirst2D);
+
+      aCurStep++;
+    }
+  }
+
+  return Abs(aMaxWireValue - aMinWireValue);
+}
\ No newline at end of file