]> OCCT Git - occt-copy.git/commitdiff
25970: Shape Healing - enable parallel reconstruction of pcurves CR25970
authorazn <azn@opencascade.com>
Tue, 31 Mar 2015 10:44:33 +0000 (13:44 +0300)
committerazn <azn@opencascade.com>
Wed, 3 Jun 2015 11:01:06 +0000 (14:01 +0300)
- Parallel context for adding pcurve has been updated.
- Fix some problems connected with dataraces and locks.
- Integration of parallel processing pcurves to the ShapeFix_Wire::FixEdgeCurves();

src/ShapeAnalysis/ShapeAnalysis_Surface.cxx
src/ShapeExtend/FILES [new file with mode: 0644]
src/ShapeExtend/ShapeExtend.cdl
src/ShapeExtend/ShapeExtend_SequenceOfInteger.hxx [new file with mode: 0644]
src/ShapeExtend/ShapeExtend_SequenceOfShape.hxx [new file with mode: 0644]
src/ShapeExtend/ShapeExtend_WireData.cdl
src/ShapeExtend/ShapeExtend_WireData.cxx
src/ShapeFix/ShapeFix_Wire.cxx

index 1b9877676bf56e899152ec01e41b7669b64d020f..59a4095781ab09bbffbd27ec715904ab6302efe3 100644 (file)
@@ -785,11 +785,11 @@ Standard_Boolean ShapeAnalysis_Surface::SurfaceNewton(const gp_Pnt2d &p2dPrev,
                                                       const Standard_Real preci,
                                                       gp_Pnt2d &sol)
 {
-  GeomAdaptor_Surface& SurfAdapt = Adaptor3d()->ChangeSurface();
+  const GeomAdaptor_Surface& aSurfaceAdaptor = Adaptor3d()->ChangeSurface();
   Standard_Real uf, ul, vf, vl;
   Bounds(uf, ul, vf, vl);
-  Standard_Real du = SurfAdapt.UResolution (preci);
-  Standard_Real dv = SurfAdapt.VResolution (preci);
+  Standard_Real du = aSurfaceAdaptor.UResolution (preci);
+  Standard_Real dv = aSurfaceAdaptor.VResolution (preci);
   Standard_Real UF = uf - du, UL = ul + du;
   Standard_Real VF = vf - dv, VL = vl + dv;
 
@@ -797,11 +797,11 @@ Standard_Boolean ShapeAnalysis_Surface::SurfaceNewton(const gp_Pnt2d &p2dPrev,
   Standard_Real Tol = Precision::Confusion();
   Standard_Real Tol2 = Tol * Tol;//, rs2p=1e10;
   Standard_Real U = p2dPrev.X(), V = p2dPrev.Y();
-  gp_Vec rsfirst = P3D.XYZ() - Value ( U, V ).XYZ(); //pdn
+  gp_Vec rsfirst = P3D.XYZ() - aSurfaceAdaptor.Value( U, V ).XYZ(); //pdn
   for ( Standard_Integer i=0; i < 25; i++ ) {
     gp_Vec ru, rv, ruu, rvv, ruv;
     gp_Pnt pnt;
-    mySurf->D2 ( U, V, pnt, ru, rv, ruu, rvv, ruv );
+    aSurfaceAdaptor.D2( U, V, pnt, ru, rv, ruu, rvv, ruv );
 
     // normal
     Standard_Real ru2 = ru * ru, rv2 = rv * rv;
@@ -809,8 +809,8 @@ Standard_Boolean ShapeAnalysis_Surface::SurfaceNewton(const gp_Pnt2d &p2dPrev,
     Standard_Real nrm2 = n.SquareMagnitude();
     if ( nrm2 < 1e-10 ) break; // n == 0, use standard
 
-    // descriminant
-    gp_Vec rs = P3D.XYZ() - Value ( U, V ).XYZ();
+    // descriminantx
+    gp_Vec rs = P3D.XYZ() - aSurfaceAdaptor.Value( U, V ).XYZ();
     Standard_Real rSuu = ( rs * ruu );
     Standard_Real rSvv = ( rs * rvv );
     Standard_Real rSuv = ( rs * ruv );
@@ -996,20 +996,20 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
       S = (uf+ul)/2;  T = (vf+vl)/2;  // yaura aumoins qqchose
       //pdn to fix hangs PRO17015
       if ((surftype==GeomAbs_SurfaceOfExtrusion)&&Precision::IsInfinite(uf)&&Precision::IsInfinite(ul)) {
-       //conic case
-       gp_Pnt2d prev(S,T);
-       gp_Pnt2d solution;
-       if (SurfaceNewton(prev,P3D,preci,solution)) {
+        //conic case
+        gp_Pnt2d prev(S,T);
+        gp_Pnt2d solution;
+        if (SurfaceNewton(prev,P3D,preci,solution)) {
 #ifdef OCCT_DEBUG
-         cout <<"Newton found point on conic extrusion"<<endl;
+          cout <<"Newton found point on conic extrusion"<<endl;
 #endif
-         return solution;
-       }
+          return solution;
+        }
 #ifdef OCCT_DEBUG
-       cout <<"Newton failed point on conic extrusion"<<endl;
+        cout <<"Newton failed point on conic extrusion"<<endl;
 #endif
-       uf = -500;
-       ul = 500;
+        uf = -500;
+        ul = 500;
       }
 
       if (Precision::IsInfinite(uf)) uf = -1000;
@@ -1020,38 +1020,38 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
       //:30 by abv 2.12.97: speed optimization
       // code is taken from GeomAPI_ProjectPointOnSurf
       if ( ! myExtOK ) {
-//      Standard_Real du = Abs(ul-uf)/100;  Standard_Real dv = Abs(vl-vf)/100;
-//      if (IsUClosed()) du = 0;  if (IsVClosed()) dv = 0;
-//  Forcer appel a IsU-VClosed
-       if (myUCloseVal < 0) IsUClosed();
-       if (myVCloseVal < 0) IsVClosed();
-    Standard_Real du = 0., dv = 0.;
-    //extension of the surface range is limited to non-offset surfaces as the latter
-    //can throw exception (e.g. Geom_UndefinedValue) when computing value - see id23943
-    if (!mySurf->IsKind (STANDARD_TYPE (Geom_OffsetSurface))) {
-      //modified by rln during fixing CSR # BUC60035 entity #D231
-      du = Min (myUDelt, SurfAdapt.UResolution (preci));
-      dv = Min (myVDelt, SurfAdapt.VResolution (preci));
-    }
+        //      Standard_Real du = Abs(ul-uf)/100;  Standard_Real dv = Abs(vl-vf)/100;
+        //      if (IsUClosed()) du = 0;  if (IsVClosed()) dv = 0;
+        //  Forcer appel a IsU-VClosed
+        if (myUCloseVal < 0) IsUClosed();
+        if (myVCloseVal < 0) IsVClosed();
+        Standard_Real du = 0., dv = 0.;
+        //extension of the surface range is limited to non-offset surfaces as the latter
+        //can throw exception (e.g. Geom_UndefinedValue) when computing value - see id23943
+        if (!mySurf->IsKind (STANDARD_TYPE (Geom_OffsetSurface))) {
+          //modified by rln during fixing CSR # BUC60035 entity #D231
+          du = Min (myUDelt, SurfAdapt.UResolution (preci));
+          dv = Min (myVDelt, SurfAdapt.VResolution (preci));
+        }
         myExtSrf = mySurf;
-       Standard_Real Tol = Precision::PConfusion();
+        Standard_Real Tol = Precision::PConfusion();
         myExtPS.SetFlag (Extrema_ExtFlag_MIN);
-       myExtPS.Initialize ( myExtSrf, uf-du, ul+du, vf-dv, vl+dv, Tol, Tol );
-       myExtOK = Standard_True;
+        myExtPS.Initialize ( myExtSrf, uf-du, ul+du, vf-dv, vl+dv, Tol, Tol );
+        myExtOK = Standard_True;
       }
       myExtPS.Perform ( P3D );
       Standard_Integer nPSurf = ( myExtPS.IsDone() ? myExtPS.NbExt() : 0 );
 
       if ( nPSurf > 0 ) {
-       Standard_Real dist2Min = myExtPS.SquareDistance( 1 );
-       Standard_Integer indMin=1;
-       for (Standard_Integer sol = 2; sol <= nPSurf ; sol++) {
-         Standard_Real dist2 = myExtPS.SquareDistance(sol);
-         if ( dist2Min > dist2 ) {
-           dist2Min = dist2;
-           indMin = sol;
-         }
-       }
+        Standard_Real dist2Min = myExtPS.SquareDistance( 1 );
+        Standard_Integer indMin=1;
+        for (Standard_Integer sol = 2; sol <= nPSurf ; sol++) {
+          Standard_Real dist2 = myExtPS.SquareDistance(sol);
+          if ( dist2Min > dist2 ) {
+            dist2Min = dist2;
+            indMin = sol;
+          }
+        }
         myExtPS.Point(indMin).Parameter ( S, T );
         // PTV 26.06.2002 WORKAROUND protect OCC486. Remove after fix bug.
         // file CEA_cuve-V5.igs Entityes 244, 259, 847, 925
@@ -1060,86 +1060,86 @@ gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real
         gp_Pnt aCheckPnt = mySurf->Value( S, T );
         dist2Min = P3D.SquareDistance(aCheckPnt);
         // end of WORKAROUND
-       Standard_Real disSurf = sqrt (dist2Min);//, disCurv =1.e10;
-
-       // Test de projection merdeuse sur les bords :
-       Standard_Real UU = S, VV = T, DistMinOnIso = RealLast();  // myGap;
-//     ForgetNewton(P3D, mySurf, preci, UU, VV, DistMinOnIso);
-
-       //test added by rln on 08/12/97
-//     DistMinOnIso = UVFromIso (P3D, preci, UU, VV);
-       Standard_Boolean possLockal = Standard_False; //:study S4030 (optimizing)
-       if (disSurf > preci) {
-         gp_Pnt2d pp(UU,VV);
-         if ( SurfaceNewton(pp,P3D,preci,pp))  { //:q2 abv 16 Mar 99: PRO7226 #412920
-           Standard_Real dist = P3D.Distance ( Value(pp) );
-           if ( dist < disSurf ) {
-             disSurf = dist;
-             S = UU = pp.X();
-             T = VV = pp.Y();
-           }
-         }
-         if ( disSurf < 10*preci)
-           if (mySurf->Continuity() != GeomAbs_C0){
-             Standard_Real Tol = Precision::Confusion();
-             gp_Vec D1U, D1V;
-             gp_Pnt pnt;
-             mySurf->D1(UU, VV, pnt, D1U, D1V);
-             gp_Vec b = D1U.Crossed(D1V);
-             gp_Vec a (pnt, P3D);
-             Standard_Real ab = a.Dot(b);
-             Standard_Real nrm2 = b.SquareMagnitude();
-             if ( nrm2 > 1e-10 ) {
-               Standard_Real dist = a.SquareMagnitude() - (ab*ab)/nrm2;
-               possLockal = ( dist < Tol*Tol );
-             }
-           }
-         if (!possLockal) {
-           DistMinOnIso = UVFromIso (P3D, preci, UU, VV);
-         }
-       }
+        Standard_Real disSurf = sqrt (dist2Min);//, disCurv =1.e10;
+
+        // Test de projection merdeuse sur les bords :
+        Standard_Real UU = S, VV = T, DistMinOnIso = RealLast();  // myGap;
+        //     ForgetNewton(P3D, mySurf, preci, UU, VV, DistMinOnIso);
+
+        //test added by rln on 08/12/97
+        //     DistMinOnIso = UVFromIso (P3D, preci, UU, VV);
+        Standard_Boolean possLockal = Standard_False; //:study S4030 (optimizing)
+        if (disSurf > preci) {
+          gp_Pnt2d pp(UU,VV);
+          if ( SurfaceNewton(pp,P3D,preci,pp))  { //:q2 abv 16 Mar 99: PRO7226 #412920
+            Standard_Real dist = P3D.Distance ( Value(pp) );
+            if ( dist < disSurf ) {
+              disSurf = dist;
+              S = UU = pp.X();
+              T = VV = pp.Y();
+            }
+          }
+          if ( disSurf < 10*preci)
+            if (mySurf->Continuity() != GeomAbs_C0){
+              Standard_Real Tol = Precision::Confusion();
+              gp_Vec D1U, D1V;
+              gp_Pnt pnt;
+              mySurf->D1(UU, VV, pnt, D1U, D1V);
+              gp_Vec b = D1U.Crossed(D1V);
+              gp_Vec a (pnt, P3D);
+              Standard_Real ab = a.Dot(b);
+              Standard_Real nrm2 = b.SquareMagnitude();
+              if ( nrm2 > 1e-10 ) {
+                Standard_Real dist = a.SquareMagnitude() - (ab*ab)/nrm2;
+                possLockal = ( dist < Tol*Tol );
+              }
+            }
+            if (!possLockal) {
+              DistMinOnIso = UVFromIso (P3D, preci, UU, VV);
+            }
+        }
 
-       if (disSurf > DistMinOnIso) {
-         // On prend les parametres UU et VV;
-         S = UU;
-         T = VV;
-         myGap = DistMinOnIso;
-       }
-       else {
-         myGap = disSurf;
-       }
+        if (disSurf > DistMinOnIso) {
+          // On prend les parametres UU et VV;
+          S = UU;
+          T = VV;
+          myGap = DistMinOnIso;
+        }
+        else {
+          myGap = disSurf;
+        }
 
-       // On essaie Intersection Droite Passant par P3D / Surface
-//     if ((myGap > preci)&&(!possLockal) ) {
-//       Standard_Real SS, TT;
-//       disCurv = FindUV(P3D, mySurf, S, T, SS, TT);
-//       if (disCurv < preci || disCurv < myGap) {
-//         S = SS;
-//         T = TT;
-//       }
-//     }
+        // On essaie Intersection Droite Passant par P3D / Surface
+        //     if ((myGap > preci)&&(!possLockal) ) {
+        //       Standard_Real SS, TT;
+        //       disCurv = FindUV(P3D, mySurf, S, T, SS, TT);
+        //       if (disCurv < preci || disCurv < myGap) {
+        //         S = SS;
+        //         T = TT;
+        //       }
+        //     }
 
       }
       else {
 #ifdef OCCT_DEBUG
-       cout << "Warning: ShapeAnalysis_Surface::ValueOfUV(): Extrema failed, doing Newton" << endl;
+        cout << "Warning: ShapeAnalysis_Surface::ValueOfUV(): Extrema failed, doing Newton" << endl;
 #endif
-       // on essai sur les bords
-       Standard_Real UU = S, VV = T;//, DistMinOnIso;
-//     ForgetNewton(P3D, mySurf, preci, UU, VV, DistMinOnIso);
-       myGap = UVFromIso (P3D, preci, UU, VV);
-//     if (DistMinOnIso > preci) {
-//       Standard_Real SS, TT;
-//       Standard_Real disCurv = FindUV(P3D, mySurf, UU, VV, SS, TT);
-//       if (disCurv < preci) {
-//         S = SS;
-//         T = TT;
-//       }
-//     }
-//     else {
-         S = UU;
-         T = VV;
-//     }
+        // on essai sur les bords
+        Standard_Real UU = S, VV = T;//, DistMinOnIso;
+        //     ForgetNewton(P3D, mySurf, preci, UU, VV, DistMinOnIso);
+        myGap = UVFromIso (P3D, preci, UU, VV);
+        //     if (DistMinOnIso > preci) {
+        //       Standard_Real SS, TT;
+        //       Standard_Real disCurv = FindUV(P3D, mySurf, UU, VV, SS, TT);
+        //       if (disCurv < preci) {
+        //         S = SS;
+        //         T = TT;
+        //       }
+        //     }
+        //     else {
+        S = UU;
+        T = VV;
+        //     }
       }
     }
     break;
diff --git a/src/ShapeExtend/FILES b/src/ShapeExtend/FILES
new file mode 100644 (file)
index 0000000..0a0ebda
--- /dev/null
@@ -0,0 +1,2 @@
+ShapeExtend_SequenceOfInteger.hxx
+ShapeExtend_SequenceOfShape.hxx
index 09329cb23716dfe493a2c32e032bab21d447a513..b0f4171cdc993e3dd149d10f8333288629c04afe 100644 (file)
@@ -94,7 +94,11 @@ is
        Uniform, -- each patch gives range 1.: Ui = i-1, Vj = j-1
        Unitary  -- uniform parametrisation with global range [0,1]
     end Parametrisation;
-    
+
+    imported SequenceOfInteger;
+
+    imported SequenceOfShape;
+
     deferred class ComplexCurve;
 
     class CompositeSurface;
diff --git a/src/ShapeExtend/ShapeExtend_SequenceOfInteger.hxx b/src/ShapeExtend/ShapeExtend_SequenceOfInteger.hxx
new file mode 100644 (file)
index 0000000..51687d3
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (c) 2015 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 _ShapeExtend_SequenceOfInteger_HeaderFile
+#define _ShapeExtend_SequenceOfInteger_HeaderFile
+
+#include <NCollection_Sequence.hxx>
+
+typedef NCollection_Sequence<Standard_Integer> ShapeExtend_SequenceOfInteger;
+
+#endif // _ShapeExtend_SequenceOfInteger_HeaderFile
diff --git a/src/ShapeExtend/ShapeExtend_SequenceOfShape.hxx b/src/ShapeExtend/ShapeExtend_SequenceOfShape.hxx
new file mode 100644 (file)
index 0000000..91880b4
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 2015 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 _ShapeExtend_SequenceOfShape_HeaderFile
+#define _ShapeExtend_SequenceOfShape_HeaderFile
+
+#include <TopoDS_Shape.hxx>
+#include <NCollection_Sequence.hxx>
+
+typedef NCollection_Sequence<TopoDS_Shape> ShapeExtend_SequenceOfShape;
+
+#endif // _ShapeExtend_SequenceOfShape_HeaderFile
index 5b80e65f6046b55a726d999f24143af5c024c6d7..1f8c8f006b03071faca2d24417239605b9518a19 100644 (file)
@@ -42,12 +42,13 @@ class WireData from ShapeExtend inherits TShared from MMgt
        --      ShapeExtend_WireData saves time and memory. 
 
 uses 
-    HSequenceOfInteger from TColStd,
     Shape              from TopoDS,
     Edge               from TopoDS, 
     Wire               from TopoDS, 
     Face               from TopoDS, 
-    HSequenceOfShape   from TopTools
+    HSequenceOfShape   from TopTools,
+    SequenceOfShape    from ShapeExtend,
+    SequenceOfInteger  from ShapeExtend
 
 is
 
@@ -216,10 +217,9 @@ is
        -- null shape is returned.
  
 fields
-
-    myEdges: HSequenceOfShape from TopTools;
     myNonmanifoldEdges : HSequenceOfShape from TopTools;
-    mySeams: HSequenceOfInteger from TColStd;
+    myEdges: SequenceOfShape   from ShapeExtend;
+    mySeams: SequenceOfInteger from ShapeExtend;
     mySeamF: Integer;
     mySeamR: Integer;
     myManifoldMode : Boolean;
index e23322b7ff22ac9c06bc2bf516f477863da0abd1..247d31b1cfdd0deaced6b2e5b0384f2581ad3d7d 100644 (file)
@@ -16,6 +16,7 @@
 //    abv 05.05.99  S4174: protection against INTERNAL/EXTERNAL edges
 
 #include <ShapeExtend_WireData.ixx>
+
 #include <Geom2d_Curve.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Vertex.hxx>
@@ -43,7 +44,7 @@ ShapeExtend_WireData::ShapeExtend_WireData()
 //=======================================================================
 
 ShapeExtend_WireData::ShapeExtend_WireData (const TopoDS_Wire& wire,
-                                           const Standard_Boolean chained,
+                                            const Standard_Boolean chained,
                                             const Standard_Boolean theManifold)
 {
   Init ( wire, chained ,theManifold);  
@@ -101,16 +102,16 @@ Standard_Boolean ShapeExtend_WireData::Init (const TopoDS_Wire& wire,
     }
     Vlast = V2;
     if(wire.Orientation() == TopAbs_REVERSED)
-      myEdges->Prepend( E );
+      myEdges.Prepend( E );
     else
-      myEdges->Append ( E );
+      myEdges.Append ( E );
   }
 
   if(!myManifoldMode) {
     Standard_Integer nb = myNonmanifoldEdges->Length();
     Standard_Integer i =1;
     for( ; i <= nb; i++)
-      myEdges->Append(myNonmanifoldEdges->Value(i));
+      myEdges.Append(myNonmanifoldEdges->Value(i));
     myNonmanifoldEdges->Clear();
   }
 //    refaire chainage ?  Par WireExplorer
@@ -118,7 +119,7 @@ Standard_Boolean ShapeExtend_WireData::Init (const TopoDS_Wire& wire,
 
   Clear();
   for ( BRepTools_WireExplorer we(wire); we.More(); we.Next() ) 
-    myEdges->Append ( TopoDS::Edge ( we.Current() ) );
+    myEdges.Append ( TopoDS::Edge ( we.Current() ) );
 
   return OK;
 }
@@ -130,11 +131,13 @@ Standard_Boolean ShapeExtend_WireData::Init (const TopoDS_Wire& wire,
 
 void ShapeExtend_WireData::Clear() 
 {
-  myEdges = new TopTools_HSequenceOfShape();
-  myNonmanifoldEdges = new TopTools_HSequenceOfShape;
-  mySeamF = mySeamR = -1;  
-  mySeams.Nullify();
+  myEdges.Clear();
+  mySeams.Clear();
+
+  mySeamF = mySeamR = -1;
+
   myManifoldMode = Standard_True;
+  myNonmanifoldEdges = new TopTools_HSequenceOfShape;
 }
 
 //=======================================================================
@@ -146,7 +149,7 @@ void ShapeExtend_WireData::ComputeSeams (const Standard_Boolean enforce)
 {
   if (mySeamF >= 0 && !enforce) return;
 
-  mySeams = new TColStd_HSequenceOfInteger();
+  mySeams.Clear();
   mySeamF = mySeamR = 0;
   TopoDS_Shape S;
   Standard_Integer i, nb = NbEdges();
@@ -165,13 +168,23 @@ void ShapeExtend_WireData::ComputeSeams (const Standard_Boolean enforce)
   
   //  ensuite on voit les Edges FORWARD qui y seraient deja -> on note leur n0
   //  c-a-d le n0 de la directe ET de la reverse
-  for (i = 1; i <= nb; i ++) {
+  for (i = 1; i <= nb; ++i)
+  {
     S = Edge(i);
     if (S.Orientation() == TopAbs_REVERSED) continue;
     Standard_Integer num = ME.FindIndex (S);
-    if (num <= 0) continue;
-    if (mySeamF == 0) { mySeamF = i; mySeamR = SE[num]; }
-    else { mySeams->Append(i); mySeams->Append( SE[num] ); }
+    if (num <= 0)
+      continue;
+    if (mySeamF == 0)
+    {
+      mySeamF = i;
+      mySeamR = SE[num];
+    }
+    else
+    {
+      mySeams.Append(i);
+      mySeams.Append(SE[num]);
+    }
   }
 
   delete [] SE;  // ne pas oublier !!
@@ -187,9 +200,9 @@ void ShapeExtend_WireData::SetLast (const Standard_Integer num)
   if (num == 0) return;
   Standard_Integer i, nb = NbEdges();
   for (i = nb; i > num; i--) {
-    TopoDS_Edge edge = TopoDS::Edge ( myEdges->Value(nb) );
-    myEdges->Remove (nb);
-    myEdges->InsertBefore (1, edge);
+    TopoDS_Edge edge = TopoDS::Edge ( myEdges(nb) );
+    myEdges.Remove(nb);
+    myEdges.InsertBefore(1, edge);
   }
   mySeamF = -1;
 }
@@ -226,10 +239,10 @@ void ShapeExtend_WireData::Add (const TopoDS_Edge& edge,
     
   if (edge.IsNull()) return;
   if (atnum == 0) {
-    myEdges->Append (edge);
+    myEdges.Append (edge);
   } 
   else {
-    myEdges->InsertBefore (atnum,edge);
+    myEdges.InsertBefore (atnum,edge);
   }
   mySeamF = -1;
 }
@@ -248,23 +261,23 @@ void ShapeExtend_WireData::Add (const TopoDS_Wire& wire,
   for (TopoDS_Iterator it(wire); it.More(); it.Next()) {
     TopoDS_Edge edge = TopoDS::Edge (it.Value());
     if(edge.Orientation()!= TopAbs_REVERSED &&
-        edge.Orientation() != TopAbs_FORWARD) {
+       edge.Orientation() != TopAbs_FORWARD) {
       if(myManifoldMode)
         myNonmanifoldEdges->Append(edge);
       else
-       aNMEdges.Append(edge);
+        aNMEdges.Append(edge);
       continue;
     }
     if (n == 0) {
-      myEdges->Append (edge);
+      myEdges.Append (edge);
     } else {
-      myEdges->InsertBefore (n,edge);
+      myEdges.InsertBefore (n,edge);
       n++;
     }
   }
   Standard_Integer i =1, nb = aNMEdges.Length();
   for( ; i <= nb ; i++)
-    myEdges->Append(aNMEdges.Value(i));
+    myEdges.Append(aNMEdges.Value(i));
   mySeamF = -1;
 }
 
@@ -274,7 +287,7 @@ void ShapeExtend_WireData::Add (const TopoDS_Wire& wire,
 //=======================================================================
 
 void ShapeExtend_WireData::Add (const Handle(ShapeExtend_WireData) &wire,
-                               const Standard_Integer atnum) 
+                                const Standard_Integer atnum)
 {
   if ( wire.IsNull() ) return;
   TopTools_SequenceOfShape aNMEdges;
@@ -289,27 +302,27 @@ void ShapeExtend_WireData::Add (const Handle(ShapeExtend_WireData) &wire,
     }
       
     if (n == 0 ) {
-      myEdges->Append ( wire->Edge(i) );
+      myEdges.Append ( wire->Edge(i) );
     } 
     else {
-      myEdges->InsertBefore ( n, wire->Edge(i) );
+      myEdges.InsertBefore ( n, wire->Edge(i) );
       n++;
     }
   }
   
   //non-manifold edges for non-manifold wire shoud be added at end
   for (i=1; i <=aNMEdges.Length(); i++)
-    myEdges->Append(aNMEdges.Value(i));
+    myEdges.Append(aNMEdges.Value(i));
   
   for (i=1; i <= wire->NbNonManifoldEdges(); i++) {
     if( myManifoldMode)
       myNonmanifoldEdges->Append(wire->NonmanifoldEdge(i));
     else {
       if (n == 0) 
-        myEdges->Append ( wire->Edge(i) );
+        myEdges.Append ( wire->Edge(i) );
     
       else {
-        myEdges->InsertBefore ( n, wire->Edge(i) );
+        myEdges.InsertBefore ( n, wire->Edge(i) );
         n++;
       }
     }
@@ -324,7 +337,7 @@ void ShapeExtend_WireData::Add (const Handle(ShapeExtend_WireData) &wire,
 //=======================================================================
 
 void ShapeExtend_WireData::Add (const TopoDS_Shape& shape,
-                              const Standard_Integer atnum) 
+                                const Standard_Integer atnum)
 {
   if      (shape.ShapeType() == TopAbs_EDGE) Add (TopoDS::Edge (shape), atnum);
   else if (shape.ShapeType() == TopAbs_WIRE) Add (TopoDS::Wire (shape), atnum);
@@ -370,11 +383,9 @@ void ShapeExtend_WireData::AddOriented (const TopoDS_Shape& shape,
 //purpose  : 
 //=======================================================================
 
-void ShapeExtend_WireData::Remove (const Standard_Integer num) 
+void ShapeExtend_WireData::Remove (const Standard_Integer num)
 {
-  myEdges->Remove ( num > 0 ? num : NbEdges() );
+  myEdges.Remove ( num > 0 ? num : NbEdges() );
   mySeamF = -1;
 }
 
@@ -387,7 +398,7 @@ void ShapeExtend_WireData::Set (const TopoDS_Edge& edge,
                               const Standard_Integer num) 
 {
   if(edge.Orientation()!= TopAbs_REVERSED &&
-        edge.Orientation() != TopAbs_FORWARD && myManifoldMode) {
+     edge.Orientation() != TopAbs_FORWARD && myManifoldMode) {
     if(num <= myNonmanifoldEdges->Length())
       myNonmanifoldEdges->SetValue(num,edge);
     else
@@ -395,7 +406,7 @@ void ShapeExtend_WireData::Set (const TopoDS_Edge& edge,
   }
   
   else
-    myEdges->SetValue ( ( num > 0 ? num : NbEdges() ), edge);
+    myEdges.SetValue( ( num > 0 ? num : NbEdges() ), edge);
   mySeamF = -1;
 }
 
@@ -410,16 +421,16 @@ void ShapeExtend_WireData::Reverse ()
 
   // inverser les edges + les permuter pour inverser le wire
   for (i = 1; i <= nb/2; i ++) {
-    TopoDS_Shape S1 = myEdges->Value(i);      S1.Reverse();
-    TopoDS_Shape S2 = myEdges->Value(nb+1-i); S2.Reverse();
-    myEdges->SetValue (i,      S2);
-    myEdges->SetValue (nb+1-i, S1);
+    TopoDS_Shape S1 = myEdges.Value(i);      S1.Reverse();
+    TopoDS_Shape S2 = myEdges.Value(nb+1-i); S2.Reverse();
+    myEdges.SetValue (i,      S2);
+    myEdges.SetValue (nb+1-i, S1);
   }
   //  nb d edges impair : inverser aussi l edge du milieu (rang inchange)
   if ( nb % 2 ) {    //  test impair
     i = (nb+1)/2;
-    TopoDS_Shape SI = myEdges->Value(i);      SI.Reverse();
-    myEdges->SetValue (i, SI);
+    TopoDS_Shape SI = myEdges.Value(i);      SI.Reverse();
+    myEdges.SetValue (i, SI);
   }
   mySeamF = -1;
 }
@@ -465,12 +476,12 @@ void ShapeExtend_WireData::Reverse (const TopoDS_Face &face)
   //  Les inverser revient a permuter leur role ... donc ne rien faire
   //  Il faut donc aussi permuter leurs pcurves
   ComputeSeams(Standard_True);
-  if (mySeamF > 0) SwapSeam (myEdges->Value(mySeamF),face);
-  if (mySeamR > 0) SwapSeam (myEdges->Value(mySeamR),face);
-  Standard_Integer nb = (mySeams.IsNull() ? 0 : mySeams->Length());
-  for ( Standard_Integer i = 1; i <= nb; i ++) {
-    SwapSeam (myEdges->Value(mySeams->Value(i)),face);
-  }
+  if (mySeamF > 0) SwapSeam (myEdges(mySeamF),face);
+  if (mySeamR > 0) SwapSeam (myEdges(mySeamR),face);
+
+  for (ShapeExtend_SequenceOfInteger::Iterator it(mySeams); it.More(); it.Next())
+    SwapSeam(myEdges(it.Value()), face);
+
   mySeamF = -1;
 }
 
@@ -481,7 +492,7 @@ void ShapeExtend_WireData::Reverse (const TopoDS_Face &face)
 
 Standard_Integer ShapeExtend_WireData::NbEdges() const
 {
-  return myEdges->Length();
+  return myEdges.Length();
 }
 
 //=======================================================================
@@ -489,14 +500,24 @@ Standard_Integer ShapeExtend_WireData::NbEdges() const
 //purpose  : 
 //=======================================================================
 
-TopoDS_Edge ShapeExtend_WireData::Edge (const Standard_Integer num) const
+TopoDS_Edge ShapeExtend_WireData::Edge(const Standard_Integer theIndex) const
 {
-  if (num < 0) {
-    TopoDS_Edge E = Edge (-num);
+  if (theIndex < 0)
+  {
+    TopoDS_Edge E = Edge(-theIndex);
     E.Reverse();
     return E;
   }
-  return TopoDS::Edge ( myEdges->Value ( num ) );
+
+  Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myEdges.Size(), "ShapeExtend_WireData::Edge")
+
+  // threadsafely find edge from sequence by index
+  ShapeExtend_SequenceOfShape::Iterator it(myEdges);
+  for (Standard_Integer aCurrentIdx = 0; it.More(); it.Next())
+    if (theIndex == ++aCurrentIdx)
+      break;
+
+  return TopoDS::Edge(it.Value());
 }
 //=======================================================================
 //function : NbNonManifoldEdges
@@ -539,17 +560,19 @@ Standard_Integer ShapeExtend_WireData::Index (const TopoDS_Edge& edge)
 //purpose  : 
 //=======================================================================
 
-Standard_Boolean ShapeExtend_WireData::IsSeam (const Standard_Integer num) 
+Standard_Boolean ShapeExtend_WireData::IsSeam(const Standard_Integer theIndex)
 {
-  if (mySeamF < 0) ComputeSeams();
+  if (mySeamF <  0) ComputeSeams();
   if (mySeamF == 0) return Standard_False;
   
-  if (num == mySeamF || num == mySeamR) return Standard_True;
-//  Pas suffisant : on regarde dans la liste
-  Standard_Integer i, nb = mySeams->Length();
-  for (i = 1; i <= nb; i ++) {
-    if (num == mySeams->Value(i)) return Standard_True;
-  }
+  if (theIndex == mySeamF || theIndex == mySeamR)
+    return Standard_True;
+
+  // try to find edge in the sequence.
+  for (ShapeExtend_SequenceOfInteger::Iterator it(mySeams); it.More(); it.Next())
+    if (theIndex == it.Value())
+      return Standard_True;
+
   return Standard_False;
 }
 
index 2505f0e2c5a1b22ca5f50e2596638d7ea452b90f..68226a937f5b234d939bb9dec6e462326989d04a 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_Failure.hxx>
+#include <OSD_Parallel.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <Precision.hxx>
 #include <Geom_Plane.hxx>
 #include <Geom_OffsetCurve.hxx>
 
+#include <NCollection_Array1.hxx>
 #include <TColStd_HSequenceOfReal.hxx>
 #include <Handle_Geom2dAdaptor_HCurve.hxx>
 #include <Adaptor3d_CurveOnSurface.hxx>
@@ -515,6 +517,129 @@ Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Real prec)
   return StatusConnected ( ShapeExtend_DONE );
 }
 
+//=======================================================================
+//function :
+//purpose  :
+//=======================================================================
+#include <NCollection_DataMap.hxx>
+namespace
+{
+  class ShapeFix_PCurveInitializer
+  {
+    //! Auxiliary thread ID  hasher.
+    struct Hasher
+    {
+      static Standard_Integer HashCode
+        (const Standard_ThreadId theKey, const Standard_Integer  theUpper)
+      {
+        return ::HashCode(reinterpret_cast<Standard_Address>(theKey), theUpper);
+      }
+
+      static Standard_Boolean IsEqual
+        (const Standard_ThreadId theKey1, const Standard_ThreadId theKey2)
+      {
+        return theKey1 == theKey2;
+      }
+    };
+
+    //! Auxiliary containers.
+    struct ShapeFix_PCurveContext
+    {
+      Handle(ShapeFix_Edge)         EdgeContext;
+      Handle(ShapeAnalysis_Surface) SurfaceContext;
+    };
+
+    typedef NCollection_Array1 <Standard_Integer> ShapeFix_ArrayOfStates;
+    typedef NCollection_DataMap<Standard_ThreadId, ShapeFix_PCurveContext, Hasher> ShapeFix_ContextMap;
+
+  public:
+    //! Constructor
+    ShapeFix_PCurveInitializer(const Standard_Real                  theTolerance,
+                               const TopoDS_Face&                   theFace,
+                               const Handle(ShapeExtend_WireData)&  theWireData,
+                               const Handle(ShapeAnalysis_Surface)& theSurface,
+                               const Handle(ShapeFix_Edge)&         theFixEdge)
+    : myPrecision(theTolerance),
+      myFace     (theFace),
+      myWireData (theWireData),
+      myStates   (1, theWireData->NbEdges())
+    {
+      myWireData->ComputeSeams(Standard_False);
+      myStates.Init(ShapeExtend::EncodeStatus(ShapeExtend_OK));
+
+      // bind context for main thread
+      myMainContext.EdgeContext    = theFixEdge;
+      myMainContext.SurfaceContext = theSurface;
+
+      myContexts.Bind(OSD_Thread::Current(), myMainContext);
+    }
+
+    //! Returns status of edge processing.
+    Standard_Boolean GetStatus(const Standard_Integer   theEdgeIndex,
+                               const ShapeExtend_Status theStatus) const
+    {
+      return ShapeExtend::DecodeStatus(theEdgeIndex, theStatus);
+    }
+
+    //! Returns surface context for current thread.
+    const ShapeFix_PCurveContext& GetContext() const
+    {
+      // try to find existing context
+      const Standard_ThreadId aThreadId = OSD_Thread::Current();
+
+      if  ( myContexts.IsBound(aThreadId) )
+        return myContexts(aThreadId);
+
+      Standard_Mutex::Sentry aLocker(myMutex);
+
+      // create new copy of main context
+      ShapeFix_PCurveContext aContext;
+      aContext.EdgeContext    = new ShapeFix_Edge();
+      aContext.SurfaceContext = new ShapeAnalysis_Surface(myMainContext.SurfaceContext->Surface());
+
+      myContexts.Bind(aThreadId, aContext);
+      return myContexts(aThreadId);
+    }
+
+    //! Functor
+    void operator() (const Standard_Integer theIndex) const
+    {
+      const TopoDS_Edge&     anEdge   = myWireData->Edge(theIndex);
+      const Standard_Boolean anIsSeam = myWireData->IsSeam(theIndex);
+
+      const ShapeFix_PCurveContext& aContext = GetContext();
+      aContext.EdgeContext->FixAddPCurve(anEdge, myFace, anIsSeam, aContext.SurfaceContext, myPrecision);
+
+      // Store current status
+      Standard_Integer& aCurrentStatus = myStates(theIndex);
+      if ( aContext.EdgeContext->Status(ShapeExtend_DONE) )
+        aCurrentStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
+      if ( aContext.EdgeContext->Status(ShapeExtend_DONE2) )
+        aCurrentStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE2);
+      if ( aContext.EdgeContext->Status(ShapeExtend_FAIL) )
+        aCurrentStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL);
+    }
+
+  private:
+    //! Empty copy constructor.
+    ShapeFix_PCurveInitializer(const ShapeFix_PCurveInitializer&);
+
+    //! Empty assignent operator.
+    ShapeFix_PCurveInitializer& operator=(const ShapeFix_PCurveInitializer&);
+
+  private:
+    const Standard_Real            myPrecision;
+    const TopoDS_Face&             myFace;
+    Handle(ShapeExtend_WireData)   myWireData;
+
+    ShapeFix_PCurveContext         myMainContext;
+
+    mutable Standard_Mutex         myMutex;
+    mutable ShapeFix_ArrayOfStates myStates;
+    mutable ShapeFix_ContextMap    myContexts;
+  };
+}
+
 //=======================================================================
 //function : FixEdgeCurves
 //purpose  : 
@@ -537,162 +662,196 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
     for ( i=1; i <= nb; i++ ) {
       theAdvFixEdge->FixReversed2d ( sbwd->Edge(i), face ); 
       if ( theAdvFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
       if ( theAdvFixEdge->Status ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
     }
   }
-  
+
   // add / remove pcurve
   if ( isReady && NeedFix ( myFixRemovePCurveMode, Standard_False ) ) {
     for ( i=1; i <= nb; i++ ) {
       myFixEdge->FixRemovePCurve ( sbwd->Edge(i), face );
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
     }
   }
 
-  if ( isReady && NeedFix ( myFixAddPCurveMode ) ) {
+  if ( isReady && NeedFix ( myFixAddPCurveMode ) )
+  {
     Standard_Integer overdegen = 0; //:c0
-    for ( i=1; i <= nb; i++ ) {
-      myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i), 
-                        myAnalyzer->Surface(), Precision() );
-      if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
-      if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
-
-      //if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 )
-      //     && BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
-      if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 ) ) {
-       // abv 24 Feb 00: trj3_s1-ac-214.stp #1631 etc.: try to split the edge in singularity
-       if ( ! Context().IsNull() ) { 
-         ShapeBuild_Edge sbe;
-         TopoDS_Edge E = sbwd->Edge ( i );
-         ShapeAnalysis_Curve SAC;
-         Standard_Real a, b;
-         Handle(Geom_Curve) C = BRep_Tool::Curve ( E, a, b );
-         Handle(ShapeAnalysis_Surface) S = myAnalyzer->Surface();
-         Standard_Integer nbs = S->NbSingularities(MinTolerance());
-         GeomAdaptor_Curve GAC ( C, a, b );
-         TColStd_SequenceOfReal seq;
-         for (Standard_Integer j=1; j <= nbs; j++) {
-           Standard_Real Preci;
-           gp_Pnt2d pd1, pd2;
-           gp_Pnt P3d, pr;
-           Standard_Real par1, par2, split;
-           Standard_Boolean tmpUIsoDeg;
-           S->Singularity (j, Preci, P3d, pd1, pd2, par1, par2, tmpUIsoDeg);
-           if ( SAC.Project ( GAC, P3d, MinTolerance(), pr, split, Standard_True ) < Max(Preci,MinTolerance()) ) {
-             if ( split - a > ::Precision::PConfusion() &&
-                  b - split > ::Precision::PConfusion() ) {
-               Standard_Integer k;
-               for ( k=1; k <= seq.Length(); k++ ) {
-                 if ( split < seq(k)-::Precision::PConfusion() ) {
-                   seq.InsertBefore ( k, split );
-                   break;
-                 }
-                 else if ( split < seq(k)+::Precision::PConfusion() ) break;
-               }
-               if ( k > seq.Length() ) seq.Append ( split );
-             }
-           }
-         }
-         if ( seq.Length() >0 ) { // supposed that edge is SP
-#ifdef OCCT_DEBUG
-           cout << "Edge going over singularity detected; splitted" << endl;
-#endif
-      Standard_Boolean isFwd = ( E.Orientation() == TopAbs_FORWARD );
-      E.Orientation ( TopAbs_FORWARD );
 
-      //if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
-      //  sbe.RemovePCurve ( E, face );
+    // perform parallel processing pcurves for each edge
+    const Standard_Real aPrecision = Precision();
+    ShapeFix_PCurveInitializer anInitializer
+      (aPrecision, face, sbwd, myAnalyzer->Surface(), myFixEdge);
+    OSD_Parallel::For(1, nb, anInitializer);
+
+    // check edges on splitting
+    Standard_Integer aNbSplitted  = 0;
+    Standard_Integer aPrevEdgeIdx = 0;
+    Standard_Boolean anIsDone2    = Standard_False;
+    for ( i = 1; i <= nb; ++i )
+    {
+      if (aNbSplitted != 0)
+      {
+        myFixEdge->FixAddPCurve( sbwd->Edge(i),
+                                 face,
+                                 sbwd->IsSeam(i),
+                                 myAnalyzer->Surface(),
+                                 aPrecision );
+
+        if ( myFixEdge->Status(ShapeExtend_DONE) )
+          myStatusEdgeCurves |= ShapeExtend::EncodeStatus(ShapeExtend_DONE3);
+        if ( myFixEdge->Status(ShapeExtend_FAIL) )
+          myStatusEdgeCurves |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL3);
+
+        anIsDone2 = myFixEdge->Status(ShapeExtend_DONE2);
+        --aNbSplitted;
+      }
+      else
+      {
+        ++aPrevEdgeIdx;
+        if ( anInitializer.GetStatus(aPrevEdgeIdx, ShapeExtend_DONE) )
+          myStatusEdgeCurves |= ShapeExtend::EncodeStatus(ShapeExtend_DONE3);
+        if ( anInitializer.GetStatus(aPrevEdgeIdx, ShapeExtend_FAIL) )
+          myStatusEdgeCurves |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL3);
 
-      //10.04.2003 skl for using trimmed lines as pcurves
-      ShapeAnalysis_Edge sae;
-      if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
-        sbe.RemovePCurve ( E, face );
-      else {
-        if(sae.HasPCurve(E,face)) {
-          Handle(Geom2d_Curve) C2d;
-          Standard_Real fp2d,lp2d;
-          if(sae.PCurve(E,face,C2d,fp2d,lp2d)) {
-            if( !C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
-              sbe.RemovePCurve(E,face);
-          }
-        }
+        anIsDone2 = anInitializer.GetStatus(aPrevEdgeIdx, ShapeExtend_DONE2);
       }
 
-//    myFixEdge->FixSameParameter ( E ); // to ensure SameRange & SP
-      BRep_Builder B;
-      TopoDS_Vertex V1, V2, V;
-      //ShapeAnalysis_Edge sae;
-      V1 = sae.FirstVertex ( E );
-      V2 = sae.LastVertex ( E );
-        
-      Handle(ShapeExtend_WireData) sw = new ShapeExtend_WireData;
-      for ( Standard_Integer k=0; k <= seq.Length(); k++ )
+      if ( !sbwd->IsSeam(i) && anIsDone2 == Standard_True )
       {
-        Standard_Real split = ( k < seq.Length() ? seq(k+1) : b );
-        if ( k < seq.Length() )
+        // abv 24 Feb 00: trj3_s1-ac-214.stp #1631 etc.: try to split the edge in singularity
+        if ( ! Context().IsNull() )
         {
-          B.MakeVertex ( V, C->Value(split), BRep_Tool::Tolerance(E) );
-          //try increase tolerance before splitting
-          Standard_Real aDist = BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V));
-          if (aDist < BRep_Tool::Tolerance(V1) * 1.01) {
-            B.UpdateVertex(V1, Max(aDist, BRep_Tool::Tolerance(V1)));
-            a = split;
-            V1 = V;
-            continue;
+          ShapeBuild_Edge sbe;
+          TopoDS_Edge E = sbwd->Edge ( i );
+          ShapeAnalysis_Curve SAC;
+          Standard_Real a, b;
+          Handle(Geom_Curve) C = BRep_Tool::Curve ( E, a, b );
+          Handle(ShapeAnalysis_Surface) S = myAnalyzer->Surface();
+          Standard_Integer nbs = S->NbSingularities(MinTolerance());
+          GeomAdaptor_Curve GAC ( C, a, b );
+          TColStd_SequenceOfReal seq;
+          for (Standard_Integer j=1; j <= nbs; j++) {
+            Standard_Real Preci;
+            gp_Pnt2d pd1, pd2;
+            gp_Pnt P3d, pr;
+            Standard_Real par1, par2, split;
+            Standard_Boolean tmpUIsoDeg;
+            S->Singularity (j, Preci, P3d, pd1, pd2, par1, par2, tmpUIsoDeg);
+            if ( SAC.Project ( GAC, P3d, MinTolerance(), pr, split, Standard_True ) < Max(Preci,MinTolerance()) ) {
+              if ( split - a > ::Precision::PConfusion() &&
+                   b - split > ::Precision::PConfusion() ) {
+                  Standard_Integer k;
+                  for ( k=1; k <= seq.Length(); k++ ) {
+                    if ( split < seq(k)-::Precision::PConfusion() ) {
+                      seq.InsertBefore ( k, split );
+                      break;
+                    }
+                    else if ( split < seq(k)+::Precision::PConfusion() ) break;
+                  }
+                  if ( k > seq.Length() ) seq.Append ( split );
+              }
+            }
           }
-          else
-          {
-            aDist = BRep_Tool::Pnt(V2).Distance(BRep_Tool::Pnt(V));
-            if (aDist < BRep_Tool::Tolerance(V2) * 1.01) {
-              B.UpdateVertex(V, Max(aDist, BRep_Tool::Tolerance(V2)));
-              b = split;
-              V2 = V;
-              continue;
+          if ( seq.Length() >0 ) { // supposed that edge is SP
+#ifdef OCCT_DEBUG
+            cout << "Edge going over singularity detected; splitted" << endl;
+#endif
+            Standard_Boolean isFwd = ( E.Orientation() == TopAbs_FORWARD );
+            E.Orientation ( TopAbs_FORWARD );
+
+            //if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
+            //  sbe.RemovePCurve ( E, face );
+
+            //10.04.2003 skl for using trimmed lines as pcurves
+            ShapeAnalysis_Edge sae;
+            if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
+              sbe.RemovePCurve ( E, face );
+            else {
+              if(sae.HasPCurve(E,face)) {
+                Handle(Geom2d_Curve) C2d;
+                Standard_Real fp2d,lp2d;
+                if(sae.PCurve(E,face,C2d,fp2d,lp2d)) {
+                  if( !C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
+                    sbe.RemovePCurve(E,face);
+                }
+              }
+            }
+
+            //    myFixEdge->FixSameParameter ( E ); // to ensure SameRange & SP
+            BRep_Builder B;
+            TopoDS_Vertex V1, V2, V;
+            //ShapeAnalysis_Edge sae;
+            V1 = sae.FirstVertex ( E );
+            V2 = sae.LastVertex ( E );
+
+            Handle(ShapeExtend_WireData) sw = new ShapeExtend_WireData;
+            for ( Standard_Integer k=0; k <= seq.Length(); k++ )
+            {
+              Standard_Real split = ( k < seq.Length() ? seq(k+1) : b );
+              if ( k < seq.Length() )
+              {
+                B.MakeVertex ( V, C->Value(split), BRep_Tool::Tolerance(E) );
+                //try increase tolerance before splitting
+                Standard_Real aDist = BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V));
+                if (aDist < BRep_Tool::Tolerance(V1) * 1.01) {
+                  B.UpdateVertex(V1, Max(aDist, BRep_Tool::Tolerance(V1)));
+                  a = split;
+                  V1 = V;
+                  continue;
+                }
+                else
+                {
+                  aDist = BRep_Tool::Pnt(V2).Distance(BRep_Tool::Pnt(V));
+                  if (aDist < BRep_Tool::Tolerance(V2) * 1.01) {
+                    B.UpdateVertex(V, Max(aDist, BRep_Tool::Tolerance(V2)));
+                    b = split;
+                    V2 = V;
+                    continue;
+                  }
+                }
+              }
+              else
+              {
+                V = V2;
+              }
+
+              TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
+              if( BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
+                //TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
+                B.Range ( edge, a, split );
+                sw->Add ( edge );
+              }
+              else {
+                //TopoDS_Edge edge = sbe.CopyReplaceVertices(sbwd->Edge(i),V1,V);
+                Handle(ShapeAnalysis_TransferParameters) sftp =
+                  new ShapeAnalysis_TransferParameters(E,face);
+                sftp->TransferRange(edge, a, split, Standard_False);
+                sw->Add(edge);
+              }
+              //sw->Add(edge);
+              a = split;
+              V1 = V;
             }
+            if ( ! isFwd ) {
+              sw->Reverse();
+              E.Orientation ( TopAbs_REVERSED );
+            }
+            Context()->Replace ( E, sw->Wire() );
+            UpdateWire();
+            nb = sbwd->NbEdges();
+            aNbSplitted += sw->NbEdges();
+            i--;
+            continue;
           }
         }
-        else
-        {
-          V = V2;
-        }
 
-        TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
-        if( BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
-          //TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
-          B.Range ( edge, a, split );
-          sw->Add ( edge );
-        }
-        else {
-          //TopoDS_Edge edge = sbe.CopyReplaceVertices(sbwd->Edge(i),V1,V);
-          Handle(ShapeAnalysis_TransferParameters) sftp =
-            new ShapeAnalysis_TransferParameters(E,face);
-          sftp->TransferRange(edge, a, split, Standard_False);
-          sw->Add(edge);
-        }
-        //sw->Add(edge);
-        a = split;
-        V1 = V;
-      }
-      if ( ! isFwd ) {
-        sw->Reverse();
-        E.Orientation ( TopAbs_REVERSED );
-      }
-      Context()->Replace ( E, sw->Wire() );
-      UpdateWire();
-      nb = sbwd->NbEdges();
-      i--;
-      continue;
-    }
-       }
-       
-       overdegen = i;
+        overdegen = i;
       }
     }
 
@@ -706,15 +865,15 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
       ShapeAnalysis_Edge sae;
       Standard_Integer k;
       for ( k = 1; k <= nb; k++) {
-       Standard_Real cf, cl;
-       Handle(Geom2d_Curve) c2d;
-       if ( ! sae.PCurve ( sbwd->Edge(k), face, c2d, cf, cl, Standard_True ) ) break;
-       vec += c2d->Value(cl).XY() - c2d->Value(cf).XY();
+        Standard_Real cf, cl;
+        Handle(Geom2d_Curve) c2d;
+        if ( ! sae.PCurve ( sbwd->Edge(k), face, c2d, cf, cl, Standard_True ) ) break;
+        vec += c2d->Value(cl).XY() - c2d->Value(cf).XY();
       }
       if ( k > nb && Abs ( Abs ( vec.X() ) - URange ) < 0.1 * URange ) {
-       sbe.RemovePCurve (sbwd->Edge ( overdegen ), face);
-       myFixEdge->Projector()->AdjustOverDegenMode() = Standard_False;
-       myFixEdge->FixAddPCurve ( sbwd->Edge(overdegen), face, sbwd->IsSeam(overdegen), myAnalyzer->Surface(), Precision());
+        sbe.RemovePCurve (sbwd->Edge ( overdegen ), face);
+        myFixEdge->Projector()->AdjustOverDegenMode() = Standard_False;
+        myFixEdge->FixAddPCurve ( sbwd->Edge(overdegen), face, sbwd->IsSeam(overdegen), myAnalyzer->Surface(), Precision());
       }
 #ifdef OCCT_DEBUG
       cout << "Edge going over singularity detected; pcurve adjusted" << endl;
@@ -727,16 +886,16 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
     for ( i=1; i <= nb; i++ ) {
       myFixEdge->FixRemoveCurve3d ( sbwd->Edge(i) );
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL4 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL4 );
     }
   }
   if ( NeedFix ( myFixAddCurve3dMode ) ) {
     for ( i=1; i <= nb; i++ ) {
       myFixEdge->FixAddCurve3d ( sbwd->Edge(i) );
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) {
         //:abv 29.08.01: Spatial_firex_lofting.sat: if 3d curve cannot
         // be built because edge has no pcurves either, remove that edge
@@ -753,19 +912,19 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
           myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
           FixConnected (i + 1, Precision());
         }
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL5 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL5 );
       }
     }
   }
-  
+
   // fix seam
   if ( isReady && NeedFix ( myFixSeamMode, Standard_False ) ) {
     for ( i=1; i <= nb; i++ ) {
       FixSeam ( i );
       if ( LastFixStatus ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
       if ( LastFixStatus ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL6 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL6 );
     }
   }
 
@@ -790,32 +949,32 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
         Standard_Real fp2d,lp2d;
         if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d)) {
           if( fabs(First-fp2d)>Precision::PConfusion() ||
-              fabs(Last-lp2d)>Precision::PConfusion() ) {
-            BRep_Builder B;
-            B.SameRange(sbwd->Edge(i),Standard_False);
+            fabs(Last-lp2d)>Precision::PConfusion() ) {
+              BRep_Builder B;
+              B.SameRange(sbwd->Edge(i),Standard_False);
           }
         }
       }
       myFixEdge->FixSameParameter ( sbwd->Edge(i) );
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
     }
   }
-    
+
   //:abv 10.06.02: porting C40 -> dev (CC670-12608.stp): moved from Perform()
   // Update with face is needed for plane surfaces (w/o stored pcurves)
   if ( NeedFix ( myFixVertexToleranceMode ) ) {
     for ( i=1; i <= nb; i++) {
       myFixEdge->FixVertexTolerance (sbwd->Edge (i), face);
       if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
       if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
-       myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
+        myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
     }
   }
-  
+
   return StatusEdgeCurves ( ShapeExtend_DONE );
 }