]> OCCT Git - occt.git/commitdiff
0022707: Invalid shape translating a SAT file
authorSSV <>
Sat, 14 Jan 2012 09:06:48 +0000 (09:06 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:32:00 +0000 (19:32 +0400)
src/ShapeFix/ShapeFix_Face.cdl
src/ShapeFix/ShapeFix_Face.cxx

index a24de09a3c64510b3a4649e8b63d7facb1d3948a..c6151bea836e7e8b025ae05bddbaacc2d02a6e98 100755 (executable)
@@ -1,9 +1,7 @@
--- File:       ShapeFix_Face.cdl
--- Created:    Wed Jun  3 12:33:25 1998
--- Author:     data exchange team
---             <det@nnov.matra-dtv.fr>
----Copyright:   Matra Datavision 1998
-
+---File:      ShapeFix_Face.cdl
+---Created:   Wed Jun  3 12:33:25 1998
+---Author:    data exchange team
+---Copyright: Open CASCADE SAS 2011
 
 class Face from ShapeFix inherits Root from ShapeFix
 
@@ -37,7 +35,7 @@ is
         ---Purpose: Creates a tool and loads a face
 
     ClearModes (me: mutable) is virtual;
-       ---Purpose: Sets all modes to default
+        ---Purpose: Sets all modes to default
 
     Init (me: mutable; face: Face from TopoDS);
         ---Purpose: Loads a whole face already created, with its wires, sense and
@@ -54,147 +52,154 @@ is
         --          By default it will be FORWARD, or REVERSED if <fwd> is False
 
     SetMsgRegistrator (me: mutable; msgreg: BasicMsgRegistrator from ShapeExtend) is redefined;
-       ---Purpose: Sets message registrator
+        ---Purpose: Sets message registrator
 
     SetPrecision (me: mutable; preci: Real) is redefined;
-       ---Purpose: Sets basic precision value (also to FixWireTool)
+        ---Purpose: Sets basic precision value (also to FixWireTool)
 
     SetMinTolerance (me: mutable; mintol: Real) is redefined;
-       ---Purpose: Sets minimal allowed tolerance (also to FixWireTool)
+        ---Purpose: Sets minimal allowed tolerance (also to FixWireTool)
 
     SetMaxTolerance (me: mutable; maxtol: Real) is redefined;
-       ---Purpose: Sets maximal allowed tolerance (also to FixWireTool)
+        ---Purpose: Sets maximal allowed tolerance (also to FixWireTool)
 
     FixWireMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the mode for applying fixes of 
         --          ShapeFix_Wire, by default True. 
 
     FixOrientationMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the fix orientation mode, by default
         --          True. If True, wires oriented to border limited square.
 
     FixAddNaturalBoundMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the add natural bound mode.
-       --          If true, natural boundary is added on faces that miss them.
+        --          If true, natural boundary is added on faces that miss them.
         --          Default is False for faces with single wire (they are
         --          handled by FixOrientation in that case) and True for others.
 
     FixMissingSeamMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the fix missing seam mode, by default
         --          True. If True, tries to insert seam is missed.
 
     FixSmallAreaWireMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the fix small area wire mode, by default
         --          False. If True, drops small wires.
     FixIntersectingWiresMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the fix intersecting wires mode
         --          by default True.
        
     FixLoopWiresMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the fix loop wires mode
         --          by default True.
        
     FixSplitFaceMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the fix split face mode
         --          by default True.
        
     AutoCorrectPrecisionMode (me: mutable) returns Integer;
-       ---C++: return &
-       ---C++: inline
+        ---C++: return &
+        ---C++: inline
         ---Purpose: Returns (modifiable) the auto-correct precision mode
         --          by default False.
+        
+    FixPeriodicDegeneratedMode (me: mutable) returns Integer;
+        ---C++: return &
+        ---C++: inline
+        ---Purpose: Returns (modifiable) the activation flag for periodic
+        --          degenerated fix. False by default.
        
     Face (me) returns Face from TopoDS;
-       ---C++: inline
+        ---C++: inline
         ---Purpose: Returns a face which corresponds to the current state
         --  Warning: The finally produced face may be another one ... but with the
         --          same support
 
     Result (me) returns Shape from TopoDS;
-       ---C++: inline
-       ---Purpose: Returns resulting shape (Face or Shell if splitted)
-       --          To be used instead of Face() if FixMissingSeam involved
+        ---C++: inline
+        ---Purpose: Returns resulting shape (Face or Shell if splitted)
+        --          To be used instead of Face() if FixMissingSeam involved
 
     Add (me: mutable; wire: Wire from TopoDS);
         ---Purpose: Add a wire to current face using BRep_Builder.
-       --          Wire is added without taking into account orientation of face
-       --          (as if face were FORWARD). 
+        --          Wire is added without taking into account orientation of face
+        --          (as if face were FORWARD). 
         ---Warning: Method is retained for compatibility with previous versions.
 
     Perform (me: mutable) returns Boolean;
         ---Purpose: Performs all the fixes, depending on modes
-       -- Function Status returns the status of last call to Perform()
-       --          ShapeExtend_OK   : face was OK, nothing done
-       --          ShapeExtend_DONE1: some wires are fixed
-       --          ShapeExtend_DONE2: orientation of wires fixed
-       --          ShapeExtend_DONE3: missing seam added
-       --          ShapeExtend_DONE4: small area wire removed
-       --          ShapeExtend_DONE5: natural bounds added
-       --          ShapeExtend_FAIL1: some fails during fixing wires
-       --          ShapeExtend_FAIL2: cannot fix orientation of wires
-       --          ShapeExtend_FAIL3: cannot add missing seam
-       --          ShapeExtend_FAIL4: cannot remove small area wire
+        -- Function Status returns the status of last call to Perform()
+        --          ShapeExtend_OK   : face was OK, nothing done
+        --          ShapeExtend_DONE1: some wires are fixed
+        --          ShapeExtend_DONE2: orientation of wires fixed
+        --          ShapeExtend_DONE3: missing seam added
+        --          ShapeExtend_DONE4: small area wire removed
+        --          ShapeExtend_DONE5: natural bounds added
+        --          ShapeExtend_FAIL1: some fails during fixing wires
+        --          ShapeExtend_FAIL2: cannot fix orientation of wires
+        --          ShapeExtend_FAIL3: cannot add missing seam
+        --          ShapeExtend_FAIL4: cannot remove small area wire
 
     FixOrientation (me: mutable) returns Boolean;
         ---Purpose: Fixes orientation of wires on the face
-       --          It tries to make all wires lie outside all others (according
-       --          to orientation) by reversing orientation of some of them. 
-       --          If face lying on sphere or torus has single wire and 
+        --          It tries to make all wires lie outside all others (according
+        --          to orientation) by reversing orientation of some of them. 
+        --          If face lying on sphere or torus has single wire and 
         --          AddNaturalBoundMode is True, that wire is not reversed in 
         --          any case (supposing that natural bound will be added).
-       --          Returns True if wires were reversed
+        --          Returns True if wires were reversed
 
     FixOrientation (me: mutable; MapWires : in out DataMapOfShapeListOfShape from TopTools)
     returns Boolean;
         ---Purpose: Fixes orientation of wires on the face
-       --          It tries to make all wires lie outside all others (according
-       --          to orientation) by reversing orientation of some of them. 
-       --          If face lying on sphere or torus has single wire and 
+        --          It tries to make all wires lie outside all others (according
+        --          to orientation) by reversing orientation of some of them. 
+        --          If face lying on sphere or torus has single wire and 
         --          AddNaturalBoundMode is True, that wire is not reversed in 
         --          any case (supposing that natural bound will be added).
-       --          Returns True if wires were reversed
-       --          OutWires return information about out wires + list of
-       --          internal wires for each (for performing split face).
+        --          Returns True if wires were reversed
+        --          OutWires return information about out wires + list of
+        --          internal wires for each (for performing split face).
 
     FixAddNaturalBound(me: mutable) returns Boolean;
         ---Purpose: Adds natural boundary on face if it is missing.
-       --          Two cases are supported:
-       --          - face has no wires
-       --          - face lies on geometrically double-closed surface 
+        --          Two cases are supported:
+        --          - face has no wires
+        --          - face lies on geometrically double-closed surface 
         --            (sphere or torus) and none of wires is left-oriented
-       --          Returns True if natural boundary was added
+        --          Returns True if natural boundary was added
     
     FixMissingSeam (me: mutable) returns Boolean;
         ---Purpose: Detects and fixes the special case when face on a closed
         --          surface is given by two wires closed in 3d but with gap in 2d.
         --          In that case it creates a new wire from the two, and adds a 
         --          missing seam edge
-       --          Returns True if missing seam was added
+        --          Returns True if missing seam was added
 
     FixSmallAreaWire (me: mutable) returns Boolean;
-       ---Purpose: Detects wires with small area (that is less than 
-       --          100*Precision::PConfusion(). Removes these wires if they are internal.
-       --  Returns : True if at least one small wire removed,
-       --          False if does nothing.
+        ---Purpose: Detects wires with small area (that is less than 
+        --          100*Precision::PConfusion(). Removes these wires if they are internal.
+        --  Returns : True if at least one small wire removed,
+        --         False if does nothing.
+        
     FixLoopWire(me: mutable; aResWires : out SequenceOfShape from TopTools) returns Boolean;
-       ---Purpose: Detects if wire has a loop and fixes this situation by splitting on the few parts.
-       --          if wire has a loops and it was splitted Status was set to value ShapeExtend_DONE6.
+        ---Purpose: Detects if wire has a loop and fixes this situation by splitting on the few parts.
+        --          if wire has a loops and it was splitted Status was set to value ShapeExtend_DONE6.
        
     SplitEdge (me: mutable; sewd: WireData from ShapeExtend; num: Integer from Standard;
                            param: Real from Standard; vert: Vertex from TopoDS;
@@ -209,35 +214,43 @@ is
 
     FixIntersectingWires (me: mutable) returns Boolean;
         ---Purpose: Detects and fixes the special case when face has more than one wire
-       --          and this wires have intersection point
+        --          and this wires have intersection point
 
     FixWiresTwoCoincEdges (me: mutable) returns Boolean;
         ---Purpose: If wire contains two coincidence edges it must be removed
-    -- Queries on status after Perform()
+        -- Queries on status after Perform()
 
     FixSplitFace (me: mutable; MapWires : DataMapOfShapeListOfShape from TopTools)
     returns Boolean;
         ---Purpose: Split face if there are more than one out wire
-       --          using inrormation after FixOrientation()
+        --          using inrormation after FixOrientation()
+        
+    FixPeriodicDegenerated (me: mutable)
+    returns Boolean;
+        ---Purpose: Fixes topology for a specific case when face is composed
+        --          by a single wire belting a periodic surface. In that case
+        --          a degenerated edge is reconstructed in the degenerated pole
+        --          of the surface. Initial wire gets consistent orientation.
+        --          Must be used in couple and before FixMissingSeam routine
 
     Status (me; status: Status from ShapeExtend) returns Boolean;
-       ---Purpose: Returns the status of last call to Perform()
-       --          ShapeExtend_OK   : face was OK, nothing done
-       --          ShapeExtend_DONE1: some wires are fixed
-       --          ShapeExtend_DONE2: orientation of wires fixed
-       --          ShapeExtend_DONE3: missing seam added
-       --          ShapeExtend_DONE4: small area wire removed
-       --          ShapeExtend_DONE5: natural bounds added
-       --          ShapeExtend_DONE8: face may be splited
-       --          ShapeExtend_FAIL1: some fails during fixing wires
-       --          ShapeExtend_FAIL2: cannot fix orientation of wires
-       --          ShapeExtend_FAIL3: cannot add missing seam
-       --          ShapeExtend_FAIL4: cannot remove small area wire
-       ---C++: inline
+        ---Purpose: Returns the status of last call to Perform()
+        --          ShapeExtend_OK   : face was OK, nothing done
+        --          ShapeExtend_DONE1: some wires are fixed
+        --          ShapeExtend_DONE2: orientation of wires fixed
+        --          ShapeExtend_DONE3: missing seam added
+        --          ShapeExtend_DONE4: small area wire removed
+        --          ShapeExtend_DONE5: natural bounds added
+        --          ShapeExtend_DONE8: face may be splited
+        --          ShapeExtend_FAIL1: some fails during fixing wires
+        --          ShapeExtend_FAIL2: cannot fix orientation of wires
+        --          ShapeExtend_FAIL3: cannot add missing seam
+        --          ShapeExtend_FAIL4: cannot remove small area wire
+        ---C++: inline
 
     FixWireTool (me: mutable) returns Wire from ShapeFix;
-       ---Purpose: Returns tool for fixing wires.
-       ---C++: inline
+        ---Purpose: Returns tool for fixing wires.
+        ---C++: inline
 
 fields
 
@@ -247,15 +260,17 @@ fields
     myFixWire: Wire from ShapeFix is protected;
     myFwd    : Boolean is protected;
 
-    myFixWireMode           : Integer;
-    myFixOrientationMode    : Integer;
-    myFixAddNaturalBoundMode: Integer;
-    myFixMissingSeamMode    : Integer;
-    myFixSmallAreaWireMode  : Integer;
-    myFixLoopWiresMode      : Integer; --gka 08.01.2004
-    myFixIntersectingWiresMode  : Integer;  -- skl 23.12.2003
-    myFixSplitFaceMode      : Integer; -- skl 03.02.2004
-    myAutoCorrectPrecisionMode: Integer; --skl 26.03.2010
+    myFixWireMode              : Integer;
+    myFixOrientationMode       : Integer;
+    myFixAddNaturalBoundMode   : Integer;
+    myFixMissingSeamMode       : Integer;
+    myFixSmallAreaWireMode     : Integer;
+    myFixLoopWiresMode         : Integer; -- gka 08.01.2004
+    myFixIntersectingWiresMode : Integer; -- skl 23.12.2003
+    myFixSplitFaceMode         : Integer; -- skl 03.02.2004
+    myAutoCorrectPrecisionMode : Integer; -- skl 26.03.2010
+    myFixPeriodicDegenerated   : Integer; -- ssv 29.09.2011
+    
     myStatus : Integer is protected;
 
 end Face;
index 2c6255bbc8f8021c3f8b37436da677b2fb038186..51eccf3b304f5fca0646c0fc661b467ea1841010 100755 (executable)
 #include <BRep_Builder.hxx>
 #include <BRepTopAdaptor_FClass2d.hxx>
 #include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
 
 #include <Message_Msg.hxx>  
 #include <ShapeBuild_ReShape.hxx>
 #include <ShapeFix_Edge.hxx>
 #include <ShapeAnalysis_Edge.hxx>
 #include <Bnd_Box2d.hxx>
+#include <Geom_Circle.hxx>
 #include <Geom_SphericalSurface.hxx>
 #include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_ConicalSurface.hxx>
 #include <ShapeAnalysis_Wire.hxx>
 #include <ShapeAnalysis_Surface.hxx>
 
@@ -124,15 +129,16 @@ ShapeFix_Face::ShapeFix_Face(const TopoDS_Face &face)
 
 void ShapeFix_Face::ClearModes()
 {
-  myFixWireMode = -1;
-  myFixOrientationMode = -1;
-  myFixAddNaturalBoundMode = -1;
-  myFixMissingSeamMode = -1;
-  myFixSmallAreaWireMode = -1;
+  myFixWireMode              = -1;
+  myFixOrientationMode       = -1;
+  myFixAddNaturalBoundMode   = -1;
+  myFixMissingSeamMode       = -1;
+  myFixSmallAreaWireMode     = -1;
   myFixIntersectingWiresMode = -1;
-  myFixLoopWiresMode =-1;
-  myFixSplitFaceMode =-1;
-  myAutoCorrectPrecisionMode = 1;
+  myFixLoopWiresMode         = -1;
+  myFixSplitFaceMode         = -1;
+  myAutoCorrectPrecisionMode =  1;
+  myFixPeriodicDegenerated   = -1;
 }
 
 //=======================================================================
@@ -445,6 +451,11 @@ Standard_Boolean ShapeFix_Face::Perform()
   
   myResult = myFace;
   TopoDS_Shape savShape = myFace; //gka BUG 6555
+
+  // Specific case for conic surfaces
+  if ( NeedFix(myFixPeriodicDegenerated) )
+    this->FixPeriodicDegenerated();
+
   // fix missing seam
   if ( NeedFix ( myFixMissingSeamMode ) ) {
     if ( FixMissingSeam() ) {
@@ -2241,3 +2252,229 @@ Standard_Boolean ShapeFix_Face::FixSplitFace(const TopTools_DataMapOfShapeListOf
 
   return Standard_False;
 }
+
+//=======================================================================
+//function : IsPeriodicConicalLoop
+//purpose  : Checks whether the passed wire makes up a periodic loop on
+//           passed conical surface
+//=======================================================================
+
+static Standard_Boolean IsPeriodicConicalLoop(const Handle(Geom_ConicalSurface)& theSurf,
+                                              const TopoDS_Wire& theWire,
+                                              const Standard_Real theTolerance,
+                                              Standard_Real& theMinU,
+                                              Standard_Real& theMaxU,
+                                              Standard_Real& theMinV,
+                                              Standard_Real& theMaxV,
+                                              Standard_Boolean& isUDecrease)
+{
+  if ( theSurf.IsNull() )
+    Standard_False;
+
+  ShapeAnalysis_Edge aSAE;
+  TopLoc_Location aLoc;
+
+  Standard_Real aCumulDeltaU = 0.0, aCumulDeltaUAbs = 0.0;
+  Standard_Real aMinU = RealLast();
+  Standard_Real aMinV = aMinU;
+  Standard_Real aMaxU = -aMinU;
+  Standard_Real aMaxV = aMaxU;
+
+  // Iterate over the edges to check whether the wire is periodic on conical surface
+  BRepTools_WireExplorer aWireExp(theWire);
+  for ( ; aWireExp.More(); aWireExp.Next() )
+  {
+    const TopoDS_Edge& aCurrentEdge = aWireExp.Current();
+    Handle(Geom2d_Curve) aC2d;
+    Standard_Real aPFirst, aPLast;
+
+    aSAE.PCurve(aCurrentEdge, theSurf, aLoc, aC2d, aPFirst, aPLast, Standard_True);
+
+    if ( aC2d.IsNull() )
+      return Standard_False;
+
+    gp_Pnt2d aUVFirst = aC2d->Value(aPFirst),
+             aUVLast = aC2d->Value(aPLast);
+
+    Standard_Real aUFirst = aUVFirst.X(), aULast = aUVLast.X();
+    Standard_Real aVFirst = aUVFirst.Y(), aVLast = aUVLast.Y();
+
+    Standard_Real aCurMaxU = Max(aUFirst, aULast),
+                  aCurMinU = Min(aUFirst, aULast);
+    Standard_Real aCurMaxV = Max(aVFirst, aVLast),
+                  aCurMinV = Min(aVFirst, aVLast);
+    
+    if ( aCurMinU < aMinU )
+      aMinU = aCurMinU;
+    if ( aCurMaxU > aMaxU )
+      aMaxU = aCurMaxU;
+    if ( aCurMinV < aMinV )
+      aMinV = aCurMinV;
+    if ( aCurMaxV > aMaxV )
+      aMaxV = aCurMaxV;
+
+    Standard_Real aDeltaU = aULast - aUFirst;
+
+    aCumulDeltaU += aDeltaU;
+    aCumulDeltaUAbs += Abs(aDeltaU);
+  }
+
+  theMinU = aMinU;
+  theMaxU = aMaxU;
+  theMinV = aMinV;
+  theMaxV = aMaxV;
+  isUDecrease = (aCumulDeltaU < 0 ? Standard_True : Standard_False);
+
+  Standard_Boolean is2PIDelta = Abs(aCumulDeltaUAbs - 2*M_PI) <= theTolerance;
+  Standard_Boolean isAroundApex = Abs(theMaxU - theMinU) > 2*M_PI - theTolerance;
+
+  return is2PIDelta && isAroundApex;
+}
+
+//=======================================================================
+//function : FixPeriodicDegenerated
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean ShapeFix_Face::FixPeriodicDegenerated() 
+{
+  /* =====================
+   *  Prepare fix routine
+   * ===================== */
+
+  if ( !Context().IsNull() )
+  {
+    TopoDS_Shape aSh = Context()->Apply(myFace);
+    myFace = TopoDS::Face(aSh);
+  }
+
+  /* ================================================
+   *  Check if fix can be applied on the passed face
+   * ================================================ */
+
+  // Collect all wires owned by the face
+  TopTools_SequenceOfShape aWireSeq;
+  for ( TopoDS_Iterator aWireIt(myFace, Standard_False); aWireIt.More(); aWireIt.Next() )
+  {
+    const TopoDS_Shape& aSubSh = aWireIt.Value();
+    if (  aSubSh.ShapeType() != TopAbs_WIRE || ( aSubSh.Orientation() != TopAbs_FORWARD &&
+                                                 aSubSh.Orientation() != TopAbs_REVERSED ) ) 
+      continue;
+
+    aWireSeq.Append( aWireIt.Value() );
+  }
+
+  // Get number of wires and surface
+  Standard_Integer aNbWires = aWireSeq.Length();
+  Handle(Geom_Surface) aSurface = BRep_Tool::Surface(myFace);
+
+  // Only single wires on conical surfaces are checked
+  if ( aNbWires != 1 || aSurface.IsNull() || 
+       aSurface->DynamicType() != STANDARD_TYPE(Geom_ConicalSurface) )
+    return Standard_False;
+
+  // Get the single wire
+  TopoDS_Wire aSoleWire = TopoDS::Wire( aWireSeq.Value(1) );
+
+  // Check whether this wire is belting the conical surface by period
+  Handle(Geom_ConicalSurface) aConeSurf = Handle(Geom_ConicalSurface)::DownCast(aSurface);
+  Standard_Real aMinLoopU = 0.0, aMaxLoopU = 0.0, aMinLoopV = 0.0, aMaxLoopV = 0.0;
+  Standard_Boolean isUDecrease = Standard_False;
+
+  Standard_Boolean isConicLoop = IsPeriodicConicalLoop(aConeSurf, aSoleWire, Precision(),
+                                                       aMinLoopU, aMaxLoopU,
+                                                       aMinLoopV, aMaxLoopV,
+                                                       isUDecrease);
+
+  if ( !isConicLoop )
+    return Standard_False;
+
+  /* ===============
+   *  Retrieve apex
+   * =============== */
+
+  // Get base circle of the conical surface (the circle it was built from)
+  Handle(Geom_Curve) aConeBaseCrv = aConeSurf->VIso(0.0);
+  Handle(Geom_Circle) aConeBaseCirc = Handle(Geom_Circle)::DownCast(aConeBaseCrv);
+
+  // Retrieve conical props
+  Standard_Real aConeBaseR = aConeBaseCirc->Radius();
+  Standard_Real aSemiAngle = aConeSurf->SemiAngle();
+
+  if ( fabs(aSemiAngle) <= Precision::Confusion() )
+    return Standard_False; // Bad surface
+
+  // Find the V parameter of the apex
+  Standard_Real aConeBaseH = aConeBaseR / Sin(aSemiAngle);
+  Standard_Real anApexV = -aConeBaseH;
+
+  // Get apex vertex
+  TopoDS_Vertex anApex = BRepBuilderAPI_MakeVertex( aConeSurf->Apex() );
+
+  // ====================================
+  //  Build degenerated edge in the apex
+  // ====================================
+        
+  TopoDS_Edge anApexEdge;
+  BRep_Builder aBuilder;
+  aBuilder.MakeEdge(anApexEdge);
+
+  // Check if positional relationship between the initial wire and apex
+  // line in 2D is going to be consistent
+  if ( fabs(anApexV - aMinLoopV) <= Precision() ||
+       fabs(anApexV - aMaxLoopV) <= Precision() ||
+      ( anApexV < aMaxLoopV && anApexV > aMinLoopV ) )
+    return Standard_False;
+
+  Handle(Geom2d_Line) anApexCurve2d;
+
+  // Apex curve below the wire
+  if ( anApexV < aMinLoopV )
+  {
+    anApexCurve2d = new Geom2d_Line( gp_Pnt2d(aMinLoopU, anApexV), gp_Dir2d(1, 0) );
+    if ( !isUDecrease )
+      aSoleWire.Reverse();
+  }
+
+  // Apex curve above the wire
+  if ( anApexV > aMaxLoopV )
+  {
+    anApexCurve2d = new Geom2d_Line( gp_Pnt2d(aMaxLoopU, anApexV), gp_Dir2d(-1, 0) );
+    if ( isUDecrease )
+      aSoleWire.Reverse();
+  }
+
+  // Create degenerated edge & wire for apex
+  aBuilder.UpdateEdge( anApexEdge, anApexCurve2d, myFace, Precision() );
+  aBuilder.Add( anApexEdge, anApex );
+  aBuilder.Add( anApexEdge, anApex.Reversed() );
+  aBuilder.Degenerated(anApexEdge, Standard_True);
+  aBuilder.Range( anApexEdge, 0, fabs(aMaxLoopU - aMinLoopU) );
+  TopoDS_Wire anApexWire = BRepBuilderAPI_MakeWire(anApexEdge);
+
+  // ===============================================================
+  //  Finalize the fix building new face and setting up the results
+  // ===============================================================
+
+  // Collect the resulting set of wires
+  TopTools_SequenceOfShape aNewWireSeq;
+  aNewWireSeq.Append(aSoleWire);
+  aNewWireSeq.Append(anApexWire);
+
+  // Assemble new face
+  TopoDS_Face aNewFace = TopoDS::Face( myFace.EmptyCopied() );
+  aNewFace.Orientation(TopAbs_FORWARD);
+  BRep_Builder aFaceBuilder;
+  for ( Standard_Integer i = 1; i <= aNewWireSeq.Length(); i++ )
+  {
+    TopoDS_Wire aNewWire = TopoDS::Wire( aNewWireSeq.Value(i) );
+    aFaceBuilder.Add(aNewFace, aNewWire);
+  }
+  aNewFace.Orientation( myFace.Orientation() );
+  // Adjust the resulting state of the healing tool
+  myResult = aNewFace;
+  Context()->Replace(myFace, myResult);
+
+  return Standard_True;
+}