0022492: Scaled sphere (Solid with BSplineSurface) is wrongly exported in STEP.
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_WireDivide.cxx
1 // File:        ShapeUpgrade_FaceDivide.cxx
2 // Created:     Thu Apr 15 13:10:17 1999
3 // Author:      Roman LYGIN
4 //              <rln@kinox.nnov.matra-dtv.fr>
5 //    gka 23.06.99 S4208: using tool SU_TransferParameter 
6 //    pdn 13.07.99 synchronizing splitting values on 3d curve and pcurve
7 //    abv 14.07.99 dealing with edges without 3d curve
8 //    svv 10.01.00 porting on DEC
9
10 #include <ShapeUpgrade_WireDivide.ixx>
11 #include <ShapeUpgrade.hxx>
12 #include <BRep_Tool.hxx>
13 #include <BRep_Builder.hxx>
14 #include <BRepLib_MakeFace.hxx>
15 #include <BRepLib_MakeWire.hxx>
16 #include <TopoDS.hxx>
17 #include <TopoDS_Vertex.hxx>
18 #include <TopoDS_Edge.hxx>
19 #include <TopoDS_Iterator.hxx>
20 #include <ShapeBuild_Edge.hxx>
21 #include <ShapeAnalysis_Edge.hxx>
22 #include <Precision.hxx>
23 #include <TopExp.hxx>
24 #include <TopExp_Explorer.hxx>
25 #include <TColStd_HSequenceOfReal.hxx>
26 #include <TColGeom_HArray1OfCurve.hxx>
27 #include <TColGeom2d_HArray1OfCurve.hxx>
28 #include <gp_Pnt.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom2d_Curve.hxx>
31 #include <ShapeExtend.hxx>
32 #include <TColStd_Array1OfBoolean.hxx>
33 #include <ShapeBuild_ReShape.hxx>
34 #include <ShapeAnalysis_TransferParametersProj.hxx>
35 #include <ShapeUpgrade_FixSmallCurves.hxx>
36 #include <TopTools_SequenceOfShape.hxx>
37 #include <TColStd_SequenceOfReal.hxx>
38 #include <GeomAdaptor_HSurface.hxx>
39 #include <Geom2dAdaptor_HCurve.hxx>
40 #include <ShapeAnalysis_Curve.hxx>
41 #include <Adaptor3d_CurveOnSurface.hxx>
42
43 //=======================================================================
44 //function : ShapeUpgrade_WireDivide
45 //purpose  : 
46 //=======================================================================
47
48 ShapeUpgrade_WireDivide::ShapeUpgrade_WireDivide():
49        ShapeUpgrade_Tool(), myStatus(0)
50 {
51 //  if (ShapeUpgrade::Debug()) cout <<"ShapeUpgrade_WireDivide"<<endl;
52   mySplitCurve3dTool = new ShapeUpgrade_SplitCurve3d;
53   mySplitCurve2dTool = new ShapeUpgrade_SplitCurve2d;
54   myTransferParamTool = new ShapeAnalysis_TransferParametersProj;
55   myEdgeMode = 2;
56   myFixSmallCurveTool = new ShapeUpgrade_FixSmallCurves; 
57   myEdgeDivide = new ShapeUpgrade_EdgeDivide;
58 }
59
60 //=======================================================================
61 //function : Init
62 //purpose  : 
63 //=======================================================================
64
65 void ShapeUpgrade_WireDivide::Init(const TopoDS_Wire& W,
66                                    const TopoDS_Face& F) 
67 {
68 //  if (ShapeUpgrade::Debug()) cout <<"ShapeUpgrade_WireDivide::Init with Wire, Face"<<endl;
69   myWire = W;
70   myFace = F;
71   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
72 }
73
74 //=======================================================================
75 //function : Init
76 //purpose  : 
77 //=======================================================================
78
79 void ShapeUpgrade_WireDivide::Init(const TopoDS_Wire& W,
80                                    const Handle(Geom_Surface)& S) 
81 {
82 //  if (ShapeUpgrade::Debug()) cout <<"ShapeUpgrade_WireDivide::Init with Wire, Surface "<<endl;
83   myWire = W;
84   BRepLib_MakeFace mkf(S, Precision::Confusion());
85   myFace = mkf.Face();
86   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
87 }
88
89 //=======================================================================
90 //function : Load
91 //purpose  : 
92 //=======================================================================
93
94 void ShapeUpgrade_WireDivide::Load(const TopoDS_Wire& W)
95 {
96   myWire = W;
97 }
98
99 //=======================================================================
100 //function : Load
101 //purpose  : 
102 //=======================================================================
103
104 void ShapeUpgrade_WireDivide::Load(const TopoDS_Edge& E)
105 {
106   BRepLib_MakeWire MakeWire (E);
107   if (MakeWire.IsDone())
108     Load (MakeWire.Wire());
109 }
110
111 //=======================================================================
112 //function : SetFace
113 //purpose  : 
114 //=======================================================================
115
116 void ShapeUpgrade_WireDivide::SetFace(const TopoDS_Face& F)
117 {
118   myFace = F;
119 }
120
121 //=======================================================================
122 //function : SetSurface
123 //purpose  : 
124 //=======================================================================
125
126 void ShapeUpgrade_WireDivide::SetSurface(const Handle(Geom_Surface)& S)
127 {
128   BRepLib_MakeFace mkf(S, Precision::Confusion());
129   myFace = mkf.Face();
130 }
131
132 //=======================================================================
133 //function : SetSurface
134 //purpose  : 
135 //=======================================================================
136
137 void ShapeUpgrade_WireDivide::SetSurface(const Handle(Geom_Surface)& S,
138                                          const TopLoc_Location& L)
139 {
140   BRep_Builder B;
141   B.MakeFace(myFace,S,L,Precision::Confusion());
142 }
143
144 //=======================================================================
145 //function : Perform
146 //purpose  : 
147 //=======================================================================
148
149 static void CorrectSplitValues(const Handle(TColStd_HSequenceOfReal) orig3d,
150                                const Handle(TColStd_HSequenceOfReal) orig2d,
151                                Handle(TColStd_HSequenceOfReal) new2d,
152                                Handle(TColStd_HSequenceOfReal) new3d)
153 {
154   Standard_Real preci = Precision::PConfusion();
155   Standard_Integer len3d = orig3d->Length();
156   Standard_Integer len2d = orig2d->Length();
157   TColStd_Array1OfBoolean fixNew2d (1, len3d);
158   fixNew2d.Init (Standard_False);
159   TColStd_Array1OfBoolean fixNew3d (1, len2d);
160   fixNew3d.Init (Standard_False);
161   Standard_Real Last3d = orig3d->Value(len3d);
162   Standard_Real Last2d = orig2d->Value(len2d);
163
164   Standard_Integer i;// svv #1
165   for( i = 1; i <= len3d ; i++) {
166     Standard_Real par = new2d->Value(i);
167     Standard_Integer index = 0;
168     for(Standard_Integer j = 1; j <= len2d && !index; j++)
169       if(Abs(par-orig2d->Value(j)) < preci)
170         index = j;
171     if(index&&!fixNew3d(index)) {
172       Standard_Real newPar = orig2d->Value(index);
173       new2d->SetValue(i,newPar);
174       fixNew2d(i) = Standard_True;
175       Standard_Real newPar3d = orig3d->Value(i);
176       new3d->SetValue(index,newPar3d);
177       fixNew3d(index) = Standard_True;
178     }
179   }
180   
181   for(i = 1; i <= len2d ; i++) {
182     Standard_Real par = new3d->Value(i);
183     Standard_Integer index = 0;
184     for(Standard_Integer j = 1; j <= len3d && !index; j++)
185       if(Abs(par-orig3d->Value(j)) < preci)
186         index = j;
187     if(index&&!fixNew2d(index)) {
188       Standard_Real newPar = orig3d->Value(index);
189       new3d->SetValue(i,newPar);
190       fixNew3d(i) = Standard_True;
191       Standard_Real newPar2d = orig2d->Value(i);
192       new2d->SetValue(index,newPar2d);
193       fixNew2d(index) = Standard_True;
194     }
195   }
196   
197   Standard_Real dpreci = 2* preci;
198   for(i = 1; i < len3d; i++) {
199     Standard_Real dist = new2d->Value(i+1) - new2d->Value(i);
200     if(dist < preci) {
201       if(fixNew2d(i+1)) {
202         //changing
203         Standard_Real tmp = new2d->Value(i+1);
204         new2d->SetValue(i+1,new2d->Value(i)+dpreci);
205         new2d->SetValue(i,tmp);
206         fixNew2d(i) = Standard_True;
207         fixNew2d(i+1) = Standard_False;
208       } 
209       else
210         new2d->SetValue(i+1,new2d->Value(i)+dpreci);
211     }
212   }
213   if(new2d->Value(len3d) > Last3d) {
214     Standard_Integer ind; // svv #1
215     for( ind = len3d; ind > 1 && !fixNew2d(ind); ind--);
216     Standard_Real lastFix = new2d->Value(ind);
217     for(i = len3d; i >= ind; i--) { 
218       new2d->SetValue(i,lastFix);
219       lastFix-=dpreci;
220     }
221   }
222   
223   for(i = 1; i < len2d; i++) {
224     Standard_Real dist = new3d->Value(i+1) - new3d->Value(i);
225     if(dist < preci) {
226       if(fixNew3d(i+1)) {
227         //changing
228         Standard_Real tmp = new3d->Value(i+1);
229         new3d->SetValue(i+1,new3d->Value(i)+dpreci);
230         new3d->SetValue(i,tmp);
231         fixNew3d(i) = Standard_True;
232         fixNew3d(i+1) = Standard_False;
233       }
234       else 
235         new3d->SetValue(i+1,new3d->Value(i)+dpreci);
236     }
237   }
238   if(new3d->Value(len2d) > Last2d) {
239     Standard_Integer ind; // svv #1
240     for(ind = len2d; ind > 1 && !fixNew3d(ind); ind--);
241     Standard_Real lastFix = new3d->Value(ind);
242     for(i = len2d; i >= ind; i--) { 
243       new3d->SetValue(i,lastFix);
244       lastFix-=dpreci;
245     }
246   }
247 }      
248
249 void ShapeUpgrade_WireDivide::Perform ()
250 {
251   
252   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
253   
254 //  if (ShapeUpgrade::Debug()) cout << "ShapeUpgrade_WireDivide::Perform" << endl;
255   
256   BRep_Builder B;
257   ShapeAnalysis_Edge sae;
258     
259   TopoDS_Wire newWire;
260   B.MakeWire (newWire);
261   TopLoc_Location Loc;
262   Handle(Geom_Surface) Surf;
263   if(!myFace.IsNull())
264     Surf = BRep_Tool::Surface(myFace, Loc);
265   
266   Standard_Boolean isSplit3d = Standard_True;
267   switch(myEdgeMode) {
268      case 0: if(!myFace.IsNull()) isSplit3d = Standard_False; break;
269      case 1: if(myFace.IsNull()) isSplit3d = Standard_False; break;
270      default : break;  
271   }
272   myEdgeDivide->SetFace(myFace);
273   if(isSplit3d)
274     myEdgeDivide->SetSplitCurve3dTool(GetSplitCurve3dTool());
275   myEdgeDivide->SetSplitCurve2dTool(GetSplitCurve2dTool());
276   for (TopoDS_Iterator ItW (myWire,Standard_False); ItW.More(); ItW.Next()) {
277     // for each Edge:
278     TopoDS_Shape sh = Context()->Apply(ItW.Value(),TopAbs_SHAPE);
279     for(TopExp_Explorer exp(sh,TopAbs_EDGE); exp.More(); exp.Next()) {
280       TopoDS_Edge E = TopoDS::Edge(exp.Current());
281 //      if (ShapeUpgrade::Debug()) cout << ".. Edge " << (void*) &(*E.TShape()) << endl;
282       
283       // skip degenerated edges (and also INTERNAL/EXTERNAL, to avoid failures)
284       if ( E.Orientation() == TopAbs_INTERNAL || E.Orientation() == TopAbs_EXTERNAL ) {
285         B.Add ( newWire, E );
286         continue;
287       }
288       
289       if(!myEdgeDivide->Compute(E)) {
290         B.Add ( newWire, E );
291         continue;
292       }   
293       // first iteration: getting split knots
294       // on 3D curve: preliminary
295       
296       Handle(ShapeAnalysis_TransferParameters) theTransferParamTool =  GetTransferParamTool();
297       theTransferParamTool->SetMaxTolerance(MaxTolerance());
298       theTransferParamTool->Init(E,myFace);
299       Standard_Boolean wasSR = theTransferParamTool->IsSameRange();
300       
301       // on pcurve(s): all knots
302       // assume that if seam-edge, its pcurve1 and pcurve2 has the same split knots !!!
303       Handle(TColStd_HSequenceOfReal) theKnots3d = myEdgeDivide->Knots3d();
304       Handle(TColStd_HSequenceOfReal) theKnots2d = myEdgeDivide->Knots2d();
305       
306       // second iteration: transfer parameters and build segments
307       Handle(TColStd_HSequenceOfReal) SplitValues2d;
308       Handle(TColStd_HSequenceOfReal) SplitValues3d;
309       if(myEdgeDivide->HasCurve2d() && myEdgeDivide->HasCurve3d() ) {
310         SplitValues2d = theTransferParamTool->Perform(theKnots3d,Standard_True);
311         SplitValues3d = theTransferParamTool->Perform(theKnots2d,Standard_False);
312         CorrectSplitValues(theKnots3d,theKnots2d,SplitValues2d,SplitValues3d);
313       }
314       Handle(ShapeUpgrade_SplitCurve3d) theSplit3dTool = myEdgeDivide->GetSplitCurve3dTool();
315       Handle(ShapeUpgrade_SplitCurve2d) theSplit2dTool = myEdgeDivide->GetSplitCurve2dTool();
316       
317       if ( myEdgeDivide->HasCurve2d() ) {
318         if(! theKnots3d.IsNull() ) {
319           SplitValues2d->Remove(1);
320           SplitValues2d->Remove(SplitValues2d->Length());
321           theSplit2dTool->SetSplitValues (SplitValues2d);
322         }
323         theSplit2dTool->Build(Standard_True);
324       }
325       if ( myEdgeDivide->HasCurve3d() ) {
326         if( ! theKnots2d.IsNull() ) {
327           SplitValues3d->Remove(1);
328           SplitValues3d->Remove(SplitValues3d->Length());
329           theSplit3dTool->SetSplitValues (SplitValues3d);
330         }
331         theSplit3dTool->Build (Standard_True);
332       }
333       // get 2d and 3d split values which should be the same
334       if ( myEdgeDivide->HasCurve2d() ) theKnots2d = theSplit2dTool->SplitValues(); 
335       if ( myEdgeDivide->HasCurve3d() ) theKnots3d = theSplit3dTool->SplitValues();
336       
337       Standard_Boolean isSeam = Standard_False;
338       if (! myFace.IsNull() )
339         isSeam = BRep_Tool::IsClosed ( E, myFace );
340       Handle(TColGeom2d_HArray1OfCurve) theSegments2d;
341       if(myEdgeDivide->HasCurve2d())
342         theSegments2d = theSplit2dTool->GetCurves();
343       Handle(TColGeom2d_HArray1OfCurve) theSegments2dR;
344       if ( isSeam ) {
345         Handle(Geom2d_Curve) c2;
346         Standard_Real f2, l2;    
347 //smh#8
348         TopoDS_Shape tmpE = E.Reversed();
349         TopoDS_Edge erev = TopoDS::Edge (tmpE );
350         if ( sae.PCurve ( erev, myFace, c2, f2, l2, Standard_False) ) {
351           theSplit2dTool->Init (c2, f2, l2);
352           if(!theKnots2d.IsNull())
353             theSplit2dTool->SetSplitValues (theKnots2d);
354           theSplit2dTool->Perform (Standard_True);
355           Handle(TColStd_HSequenceOfReal) revKnots2d = theSplit2dTool->SplitValues();
356           if(revKnots2d->Length()!=revKnots2d->Length()) {
357             isSeam = Standard_False;
358 #ifdef DEB
359             cout << "Error: ShapeUpgrade_WireDivide: seam has different splitting values on pcurvesd" << endl;
360 #endif
361           }
362           else
363             theSegments2dR = theSplit2dTool->GetCurves();
364         }
365         else isSeam = Standard_False;
366       }
367       
368       // Exploring theEdge
369       TopoDS_Vertex V1o = TopExp::FirstVertex (E, Standard_False);
370       TopoDS_Vertex V2o = TopExp::LastVertex  (E, Standard_False);
371       Standard_Boolean isForward = ( E.Orientation() == TopAbs_FORWARD );
372       Standard_Real TolEdge = BRep_Tool::Tolerance (E);
373       Standard_Boolean isDeg = BRep_Tool::Degenerated ( E );
374
375       // Copy vertices to protect original shape against SameParamseter
376 //smh#8
377       TopoDS_Shape emptyCopiedV1 = V1o.EmptyCopied();
378       TopoDS_Vertex V1 = TopoDS::Vertex ( emptyCopiedV1 );
379       Context()->Replace ( V1o, V1 );
380       TopoDS_Vertex V2;
381       if ( V1o.IsSame ( V2o ) ) {
382 //smh#8
383         TopoDS_Shape tmpV = V1.Oriented(V2o.Orientation() );
384         V2 = TopoDS::Vertex ( tmpV ); 
385       }
386       else {
387 //smh#8
388         TopoDS_Shape emptyCopied = V2o.EmptyCopied();
389         V2 = TopoDS::Vertex ( emptyCopied );
390         Context()->Replace ( V2o, V2 );
391       }
392
393       //collect NM vertices
394      
395       Standard_Real af,al;
396       Handle(Geom_Curve) c3d;
397       Adaptor3d_CurveOnSurface AdCS;
398       if(myEdgeDivide->HasCurve3d()) 
399         sae.Curve3d(E,c3d,af,al,Standard_False);
400       else if(myEdgeDivide->HasCurve2d() && !Surf.IsNull()) {
401         Handle(Geom2d_Curve) c2d;
402         sae.PCurve ( E, myFace, c2d, af, al, Standard_False); 
403         Handle(GeomAdaptor_HSurface) AdS = new GeomAdaptor_HSurface(Surf);
404         Handle(Geom2dAdaptor_HCurve) AC2d  = new Geom2dAdaptor_HCurve(c2d,af,al);
405         AdCS.Load(AC2d);
406         AdCS.Load(AdS);
407       }
408       TopTools_SequenceOfShape aSeqNMVertices;
409       TColStd_SequenceOfReal aSeqParNM;
410       TopoDS_Iterator aItv(E,Standard_False);
411       ShapeAnalysis_Curve sac;
412       for ( ; aItv.More() ; aItv.Next()) {
413         if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
414            aItv.Value().Orientation() == TopAbs_EXTERNAL) {
415           TopoDS_Vertex aVold = TopoDS::Vertex(aItv.Value());
416           aSeqNMVertices.Append(aVold);
417           gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aVold));
418           Standard_Real ppar;
419           gp_Pnt pproj;
420           if(!c3d.IsNull())
421             sac.Project(c3d,aP,Precision(),pproj,ppar,af,al,Standard_False);
422           else  
423             sac.Project(AdCS,aP,Precision(),pproj,ppar);
424           aSeqParNM.Append(ppar);
425         }
426       }
427       
428       // creating new edge(s)
429       Handle(TColGeom_HArray1OfCurve) theSegments3d;
430       if(myEdgeDivide->HasCurve3d()) theSegments3d = theSplit3dTool->GetCurves();
431       
432       Standard_Integer nbc = 0;
433       if (!theSegments3d.IsNull()) {
434         nbc = theSegments3d->Length();
435         if ( !theSegments2d.IsNull() ) {
436           Standard_Integer nbc2d = theSegments2d->Length();
437           if (nbc!=nbc2d) {
438 #ifdef DEB
439             cout<<"Error: Number of intervals are not equal for 2d 3d. Ignored."<<endl;
440 #endif
441             nbc = Min( nbc,nbc2d);
442           }
443         }
444       }
445       else
446         if(!theSegments2d.IsNull())// if theSegments have different length ???
447           nbc = theSegments2d->Length(); 
448       
449       if ( nbc <= 1 && ! theSplit3dTool->Status ( ShapeExtend_DONE ) && 
450                        ! theSplit2dTool->Status ( ShapeExtend_DONE ) ) {
451         B.Add ( newWire, E );
452         continue;
453       }
454       
455      myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
456       
457       TopoDS_Wire resWire;
458       B.MakeWire (resWire);
459 //      TopoDS_Vertex firstVertex, lastVertex;
460       Standard_Integer numE =0;
461       gp_Pnt pntV1 = BRep_Tool::Pnt(V1);
462       //gp_Pnt pntV2 = BRep_Tool::Pnt(V2); // pntV2 not used - see below (skl)
463       Standard_Real V1Tol = LimitTolerance( BRep_Tool::Tolerance(V1) );
464       //Standard_Real V2Tol = LimitTolerance( BRep_Tool::Tolerance(V2) ); // V2Tol not used - see below (skl)
465       
466       Handle(ShapeUpgrade_FixSmallCurves) FixSmallCurveTool = GetFixSmallCurveTool(); //gka Precision
467       FixSmallCurveTool->SetMinTolerance(MinTolerance());
468       FixSmallCurveTool->Init(E, myFace);
469       FixSmallCurveTool->SetSplitCurve3dTool(theSplit3dTool);
470       FixSmallCurveTool->SetSplitCurve2dTool(theSplit2dTool);
471       FixSmallCurveTool->SetPrecision(MinTolerance());
472       Standard_Integer Savnum =0;
473       Standard_Real SavParf;
474       Standard_Integer Small = 0;
475       for ( Standard_Integer icurv = 1; icurv <= nbc; icurv++ ) {
476       
477         Handle(Geom_Curve) theNewCurve3d;
478         if(!theSegments3d.IsNull()) theNewCurve3d = theSegments3d->Value(icurv);
479         
480         Handle(Geom2d_Curve) theNewPCurve1;
481         if(!theSegments2d.IsNull()) theNewPCurve1 = theSegments2d->Value(icurv);
482         Handle(Geom2d_Curve) revPCurve;
483         if(isSeam) 
484           revPCurve = theSegments2dR->Value(icurv);
485         // construction of the intermediate Vertex
486         TopoDS_Vertex V;
487         if ( icurv <= nbc && nbc != 1 && ! isDeg ) {
488           Standard_Real par,parf /*,SavParl*/;
489           //Standard_Real SaveParf; // SaveParf not used - see below (skl)
490           gp_Pnt P,P1,PM;
491           // if edge has 3d curve, take point from it
492           if ( ! theNewCurve3d.IsNull() ) { 
493             if(theNewCurve3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
494               par = theNewCurve3d->LastParameter();
495               parf = theNewCurve3d->FirstParameter();
496             }
497             else {
498               par = theKnots3d->Value (icurv + 1);
499               parf = theKnots3d->Value (icurv);
500             }
501             P = theNewCurve3d->Value (par);
502             P1 = theNewCurve3d->Value (parf);
503             PM = theNewCurve3d->Value ((parf+par)/2);
504           }
505           // else use pcurve and surface (suppose that both exist)
506           else {
507             if ( Surf.IsNull() ) Surf = BRep_Tool::Surface ( myFace, Loc );
508             if ( theNewPCurve1->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) ) {
509               par = theNewPCurve1->LastParameter();
510               parf = theNewPCurve1->FirstParameter();
511             }
512             else {
513               par = theKnots2d->Value (icurv + 1);
514               parf = theKnots2d->Value (icurv);
515             }
516             gp_Pnt2d p2d = theNewPCurve1->Value (par);
517             gp_Pnt2d p2df = theNewPCurve1->Value (parf);
518             gp_Pnt2d p2dM = theNewPCurve1->Value ((parf+par)/2);
519             P = Surf->Value ( p2d.X(), p2d.Y() );
520             P1 = Surf->Value ( p2df.X(), p2df.Y() );
521             PM = Surf->Value ( p2dM.X(), p2dM.Y() );
522             P.Transform ( Loc.Transformation() );
523             P1.Transform ( Loc.Transformation() );
524             PM.Transform ( Loc.Transformation() );
525           }
526           if(P.Distance(pntV1) < MinTolerance() && P.Distance(PM) < MinTolerance() && !myFace.IsNull()) {
527             if(!Small) {
528               SavParf = parf;
529               Savnum = icurv;
530             }
531             //SavParl = par;
532             Small++;
533             if(icurv == nbc) {
534               TopoDS_Vertex VVV = V1;
535               VVV.Orientation ( V2.Orientation() );
536               Context()->Replace(V2,VVV);
537             }
538             continue;
539           }
540           if(Small) {
541             if(P.Distance(P1) > MinTolerance() || P.Distance(PM) > MinTolerance()) {
542               //FixSmallCurveTool->Perform(prevEdge,theNewCurve3d,theNewPCurve1,revPCurve,SavParf,SavParl);
543               gp_Pnt pmid = 0.5 * ( pntV1.XYZ() + P1.XYZ() );
544               B.UpdateVertex(V1,pmid,0);
545             }
546             else {
547               Handle(Geom_Curve) atmpCurve;
548               Handle(Geom2d_Curve) atmpCurve2d1,atmprepcurve;
549               if(FixSmallCurveTool->Approx( atmpCurve,atmpCurve2d1,atmprepcurve,SavParf,par)) { //BRepTools
550                 theNewCurve3d = atmpCurve;
551                 theNewPCurve1 = atmpCurve2d1;
552                 revPCurve = atmprepcurve;
553               }
554               else {
555                 gp_Pnt pmid = 0.5 * ( pntV1.XYZ() + P1.XYZ() );
556                 B.UpdateVertex(V1,pmid,0);
557               }
558             }
559             Small =0;
560           }
561           //pdn
562          /* if(P.Distance (pntV1) < V1Tol) 
563             V = V1;
564           else if (P.Distance (pntV2) < V2Tol) {
565             V = V2;
566             V1Tol = V2Tol;
567             pntV1 = pntV2;
568           }
569           else {*/
570           if(icurv != nbc)  {
571             B.MakeVertex (V, P, TolEdge); //tolerance of the edge
572             pntV1 = P;
573             V1Tol = LimitTolerance( TolEdge );
574           }
575           else V = V2;
576          // else  V2;
577          // }
578 //        if (ShapeUpgrade::Debug()) cout <<"... New intermediate Vertex (" 
579 //          <<P.X()<<","<<P.Y()<<","<<P.Z()<<") :"<<(void*) &(*V.TShape())
580 //            <<" with Tolerance "<<TolEdge <<endl;
581         }
582         //else V = V2;
583         
584         TopoDS_Edge newEdge;
585         ShapeBuild_Edge sbe;
586         if ( isForward ) {
587           V1.Orientation ( TopAbs_FORWARD );
588           V.Orientation ( TopAbs_REVERSED );
589           newEdge = sbe.CopyReplaceVertices ( E, V1, V );
590         }
591         else {
592           V1.Orientation ( TopAbs_REVERSED );
593           V.Orientation ( TopAbs_FORWARD );
594           newEdge = sbe.CopyReplaceVertices ( E, V, V1 );
595         }
596         sbe.CopyPCurves ( newEdge, E );
597         if(!theNewCurve3d.IsNull())
598           B.UpdateEdge ( newEdge, theNewCurve3d, 0. );
599         else if ( isDeg )
600           B.Degenerated( newEdge, Standard_True);
601         //if(isSeam) {
602          // Handle(Geom2d_Curve) revPCurve = theSegments2dR->Value(icurv);
603           //if(newEdge.Orientation()==TopAbs_FORWARD)
604             //B.UpdateEdge ( newEdge, theNewPCurve1, revPCurve, myFace, 0. );
605           //else
606             //B.UpdateEdge ( newEdge, revPCurve, theNewPCurve1, myFace, 0. );
607         //}
608         //else if ( ! myFace.IsNull() ) 
609           //B.UpdateEdge ( newEdge, theNewPCurve1, myFace, 0. );
610         
611         Standard_Real f3d = 0., l3d =0.;
612         if(!Savnum) Savnum = icurv;
613         Standard_Boolean srNew;
614         if(!theNewCurve3d.IsNull()) {
615           if(theNewCurve3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
616             f3d = theNewCurve3d->FirstParameter();
617             l3d = theNewCurve3d->LastParameter();
618             srNew = ((f3d == theKnots3d->Value (Savnum)) && (l3d == theKnots3d->Value (icurv + 1)));
619           }
620           else  {
621             f3d = theKnots3d->Value (Savnum);
622             l3d = theKnots3d->Value (icurv + 1);
623             srNew = Standard_True;
624           }
625         }
626         else
627           srNew = Standard_True;
628       
629         Standard_Real f2d=0, l2d=0;
630         if(!theNewPCurve1.IsNull()){
631           if(theNewPCurve1->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve))) {
632             f2d = theNewPCurve1->FirstParameter();
633             l2d = theNewPCurve1->LastParameter();
634             srNew &= ((f2d == theKnots2d->Value (Savnum)) && (l2d == theKnots2d->Value (icurv + 1)));
635           }
636           else {
637             f2d = theKnots2d->Value (Savnum);
638             l2d = theKnots2d->Value (icurv + 1);
639           }
640         }
641         //if(!Savnum) Savnum = icurv; 
642         if(!theNewCurve3d.IsNull())
643           theTransferParamTool->TransferRange(newEdge,theKnots3d->Value (Savnum),theKnots3d->Value (icurv + 1),Standard_False);
644         else
645           theTransferParamTool->TransferRange(newEdge,theKnots2d->Value (Savnum),theKnots2d->Value (icurv + 1),Standard_True);
646         /*
647         Standard_Real alpha = (theKnots3d->Value (icurv) - f)/(l - f);
648         Standard_Real beta  = (theKnots3d->Value (icurv + 1) - f)/(l - f);
649         sbe.CopyRanges(newEdge,E, alpha, beta);*/
650         Savnum =0;
651         Handle(Geom2d_Curve) c2dTmp;
652         Standard_Real setF, setL;
653         if( ! myFace.IsNull() && sae.PCurve (newEdge, myFace, c2dTmp, setF, setL, Standard_False))
654           srNew &= ( (setF==f2d) && (setL==l2d) );
655
656         if(isSeam) {
657           // Handle(Geom2d_Curve  revPCurve = theSegments2dR->Value(icurv);
658           if(newEdge.Orientation()==TopAbs_FORWARD)
659             B.UpdateEdge ( newEdge, theNewPCurve1, revPCurve, myFace, 0. );
660           else
661             B.UpdateEdge ( newEdge, revPCurve, theNewPCurve1, myFace, 0. );
662         }
663         else if ( ! myFace.IsNull() ) {
664           B.UpdateEdge ( newEdge, theNewPCurve1, myFace, 0. );
665         }
666           
667         if(!theNewCurve3d.IsNull())
668           sbe.SetRange3d(newEdge,f3d,l3d);
669         if(!theNewPCurve1.IsNull())
670           B.Range ( newEdge, myFace, f2d, l2d);
671         if((!wasSR || !srNew)&&!BRep_Tool::Degenerated(newEdge) )
672           B.SameRange(newEdge, Standard_False);
673
674           //addition NM vertices to new edges
675           Standard_Real afpar = (myEdgeDivide->HasCurve3d() ? f3d : f2d);
676                                 
677           Standard_Real alpar = (myEdgeDivide->HasCurve3d() ? l3d: l2d);
678           Standard_Integer n =1;
679           for( ; n <= aSeqParNM.Length(); n++) {
680             Standard_Real apar = aSeqParNM.Value(n);
681             TopoDS_Vertex aVold = TopoDS::Vertex(aSeqNMVertices.Value(n));
682             TopoDS_Vertex aNMVer =ShapeAnalysis_TransferParametersProj::CopyNMVertex(aVold,newEdge,E);
683             Context()->Replace(aVold,aNMVer);
684             if(fabs(apar - afpar) <= Precision::PConfusion()) 
685               Context()->Replace(aNMVer,V1);
686             else if(fabs(apar - alpar) <= Precision::PConfusion()) 
687               Context()->Replace(aNMVer,V);
688             else if( apar > afpar && apar <alpar) 
689               B.Add (newEdge,aNMVer);
690             else continue;  
691             aSeqNMVertices.Remove(n);
692             aSeqParNM.Remove(n);
693             n--;
694           }
695           
696           
697 //      if (ShapeUpgrade::Debug()) cout <<"... New Edge " 
698 //        <<(void*) &(*newEdge.TShape())<<" on vertices "
699 //          <<(void*) &(*V1.TShape())<<", " <<(void*) &(*V.TShape())
700 //            <<" with Tolerance "<<TolEdge <<endl;
701         B.Add ( resWire, newEdge );
702         B.Add ( newWire, newEdge );
703         numE++;
704         V1 = V;
705       }
706       if(numE)
707         Context()->Replace(E,resWire);
708       else
709         Context()->Remove(E);
710     }
711   }
712   if ( Status ( ShapeExtend_DONE ) ) {
713 //smh#8
714     TopoDS_Shape tmpW = Context()->Apply ( newWire ).Oriented(myWire.Orientation());
715     myWire = TopoDS::Wire (tmpW );
716   }
717 }
718
719 //=======================================================================
720 //function : Face
721 //purpose  : 
722 //=======================================================================
723
724 const TopoDS_Wire& ShapeUpgrade_WireDivide::Wire() const
725 {
726   return myWire;
727 }
728
729 //=======================================================================
730 //function : Status
731 //purpose  : 
732 //=======================================================================
733
734 Standard_Boolean ShapeUpgrade_WireDivide::Status (const ShapeExtend_Status status) const
735 {
736   return ShapeExtend::DecodeStatus ( myStatus, status );
737 }
738
739 //=======================================================================
740 //function : SetSplitCurve3dTool
741 //purpose  : 
742 //=======================================================================
743
744 void ShapeUpgrade_WireDivide::SetSplitCurve3dTool(const Handle(ShapeUpgrade_SplitCurve3d)& splitCurve3dTool)
745 {
746   mySplitCurve3dTool = splitCurve3dTool;
747 }
748
749 //=======================================================================
750 //function : SetSplitCurve2dTool
751 //purpose  : 
752 //=======================================================================
753
754 void ShapeUpgrade_WireDivide::SetSplitCurve2dTool(const Handle(ShapeUpgrade_SplitCurve2d)& splitCurve2dTool)
755 {
756   mySplitCurve2dTool = splitCurve2dTool;
757 }
758
759 //=======================================================================
760 //function : GetSplitCurve3dTool
761 //purpose  : 
762 //=======================================================================
763
764 Handle(ShapeUpgrade_SplitCurve3d) ShapeUpgrade_WireDivide::GetSplitCurve3dTool() const
765 {
766   return mySplitCurve3dTool;
767 }
768
769 //=======================================================================
770 //function : GetSplitCurve2dTool
771 //purpose  : 
772 //=======================================================================
773
774 Handle(ShapeUpgrade_SplitCurve2d) ShapeUpgrade_WireDivide::GetSplitCurve2dTool() const
775 {
776   return mySplitCurve2dTool;
777 }
778
779 //=======================================================================
780 //function : SetEdgeDivideTool
781 //purpose  : 
782 //=======================================================================
783
784 void ShapeUpgrade_WireDivide::SetEdgeDivideTool(const Handle (ShapeUpgrade_EdgeDivide)& edgeDivideTool)
785 {
786   myEdgeDivide = edgeDivideTool;
787 }
788
789 //=======================================================================
790 //function : GetEdgeDivideTool
791 //purpose  : 
792 //=======================================================================
793
794 Handle (ShapeUpgrade_EdgeDivide) ShapeUpgrade_WireDivide::GetEdgeDivideTool() const
795 {
796   return myEdgeDivide;
797 }
798
799 //=======================================================================
800 //function : SetTransferParamTool
801 //purpose  : 
802 //=======================================================================
803
804 void ShapeUpgrade_WireDivide::SetTransferParamTool(const Handle(ShapeAnalysis_TransferParameters)& TransferParam)
805 {
806   myTransferParamTool = TransferParam;
807 }
808
809 //=======================================================================
810 //function : GetTransferParamTool
811 //purpose  : 
812 //=======================================================================
813
814 Handle(ShapeAnalysis_TransferParameters) ShapeUpgrade_WireDivide::GetTransferParamTool()
815 {
816   return myTransferParamTool;
817 }
818
819 //=======================================================================
820 //function : SetEdgeMode
821 //purpose  : 
822 //=======================================================================
823
824  void ShapeUpgrade_WireDivide::SetEdgeMode(const Standard_Integer EdgeMode) 
825 {
826   myEdgeMode = EdgeMode;
827 }
828
829 //=======================================================================
830 //function : SetFixSmallCurveTool
831 //purpose  : 
832 //=======================================================================
833
834  void ShapeUpgrade_WireDivide::SetFixSmallCurveTool(const Handle(ShapeUpgrade_FixSmallCurves)& FixSmallCurvesTool) 
835 {
836   myFixSmallCurveTool = FixSmallCurvesTool; 
837 }
838
839 //=======================================================================
840 //function : GetFixSmallCurveTool
841 //purpose  : 
842 //=======================================================================
843
844  Handle(ShapeUpgrade_FixSmallCurves) ShapeUpgrade_WireDivide::GetFixSmallCurveTool() const
845 {
846   return  myFixSmallCurveTool;
847 }