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