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