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