0404580e267477669a593f3acf75de259f1f7714
[occt.git] / src / BRepFill / BRepFill_CompatibleWires.cxx
1 // Created on: 1998-07-02
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1998-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
18 #include <Bnd_Box.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepBndLib.hxx>
23 #include <BRepCheck_Wire.hxx>
24 #include <BRepExtrema_DistShapeShape.hxx>
25 #include <BRepFill.hxx>
26 #include <BRepFill_CompatibleWires.hxx>
27 #include <BRepGProp.hxx>
28 #include <BRepLib.hxx>
29 #include <BRepLib_FindSurface.hxx>
30 #include <BRepLib_MakeEdge.hxx>
31 #include <BRepLib_MakeWire.hxx>
32 #include <BRepLProp.hxx>
33 #include <BRepTools_WireExplorer.hxx>
34 #include <Geom_Plane.hxx>
35 #include <Geom_Surface.hxx>
36 #include <gp.hxx>
37 #include <gp_Ax2.hxx>
38 #include <gp_Circ.hxx>
39 #include <gp_Elips.hxx>
40 #include <gp_Pln.hxx>
41 #include <gp_Vec.hxx>
42 #include <GProp_GProps.hxx>
43 #include <GProp_PrincipalProps.hxx>
44 #include <Precision.hxx>
45 #include <Standard_ConstructionError.hxx>
46 #include <Standard_NoSuchObject.hxx>
47 #include <TColgp_HArray1OfPnt.hxx>
48 #include <TColgp_HArray1OfVec.hxx>
49 #include <TColStd_Array1OfInteger.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TColStd_MapOfInteger.hxx>
52 #include <TColStd_SequenceOfReal.hxx>
53 #include <TopAbs.hxx>
54 #include <TopExp.hxx>
55 #include <TopExp_Explorer.hxx>
56 #include <TopoDS.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Wire.hxx>
59 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
60 #include <TopTools_DataMapOfShapeListOfShape.hxx>
61 #include <TopTools_HSequenceOfShape.hxx>
62 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
63 #include <TopTools_ListIteratorOfListOfShape.hxx>
64 #include <TopTools_ListOfShape.hxx>
65 #include <TopTools_SequenceOfShape.hxx>
66
67 #ifdef OCCT_DEBUG_EFV
68 static void EdgesFromVertex (const TopoDS_Wire&   W,
69                              const TopoDS_Vertex& V, 
70                              TopoDS_Edge& E1, 
71                              TopoDS_Edge& E2)
72 {
73   TopTools_IndexedDataMapOfShapeListOfShape Map;
74   TopExp::MapShapesAndAncestors(W,TopAbs_VERTEX,TopAbs_EDGE,Map);
75
76   const TopTools_ListOfShape& List = Map.FindFromKey(V);
77   TopoDS_Edge          e1   = TopoDS::Edge(List.First());
78   TopoDS_Edge          e2   = TopoDS::Edge(List. Last());
79
80   BRepTools_WireExplorer anExp;
81   Standard_Integer I1=0, I2=0, NE=0;
82
83   for(anExp.Init(W); anExp.More(); anExp.Next()) {
84     NE++;
85     const TopoDS_Edge& ECur = anExp.Current();
86     if (e1.IsSame(ECur)) {
87       I1 = NE;
88     }
89     if (e2.IsSame(ECur)) {
90       I2 = NE;
91     }
92   }
93
94   if (Abs(I2-I1)==1) {
95     // consecutive numbers
96     if (I2==I1+1) {
97       E1 = e1;
98       E2 = e2;
99     }
100     else {
101       E1 = e2;
102       E2 = e1;
103     }
104   }
105   else {
106     // non consecutive numbers on a closed wire
107     if (I1==1&&I2==NE) {
108       E1 = e2;
109       E2 = e1;
110     }
111     else {
112       E1 = e1;
113       E2 = e2;
114     }
115   }
116 }
117                                       
118 #endif
119 static void SeqOfVertices (const TopoDS_Wire&   W,
120                            TopTools_SequenceOfShape& S)
121 {
122   S.Clear();
123   Standard_Integer jj, cpt = 0;
124   TopExp_Explorer PE;
125   for (PE.Init(W,TopAbs_VERTEX); PE.More(); PE.Next()) {
126     cpt++;
127     Standard_Boolean trouve=Standard_False;
128     for (jj=1;jj<=S.Length() && (!trouve);jj++) {
129       if (S.Value(jj).IsSame(PE.Current())) trouve = Standard_True; 
130       }
131       if (!trouve) S.Append(PE.Current());
132     }
133 }
134                                       
135
136 static Standard_Boolean PlaneOfWire (const TopoDS_Wire& W, gp_Pln& P)
137 {
138   Standard_Boolean isplane = Standard_True;
139   BRepLib_FindSurface findPlanarSurf;
140   Handle(Geom_Surface) S;
141   TopLoc_Location      L;
142
143   GProp_GProps GP;
144   gp_Pnt Bary;
145   Standard_Boolean isBaryDefined = Standard_False;
146
147 // shielding for particular cases : only one edge circle or ellipse
148 // on a closed wire !
149
150   Standard_Boolean wClosed = W.Closed();
151   if (!wClosed)
152   {
153     // it is checked if the vertices are the same.
154     TopoDS_Vertex V1, V2;
155     TopExp::Vertices(W,V1,V2);
156     if ( V1.IsSame(V2)) wClosed = Standard_True;
157   }
158
159   if (wClosed)
160   {
161     Standard_Integer nbEdges = 0;
162     TopoDS_Iterator anIter;
163     anIter.Initialize(W);
164     for(; anIter.More(); anIter.Next())
165       nbEdges ++;
166
167     if(nbEdges == 1)
168     {
169       GeomAdaptor_Curve AdC;
170       Standard_Real first, last;
171       anIter.Initialize(W);
172       AdC.Load(BRep_Tool::Curve(TopoDS::Edge(anIter.Value()), first, last));
173
174       if (AdC.GetType() == GeomAbs_Circle)
175       {
176         Bary = AdC.Circle().Location();
177         isBaryDefined = Standard_True;
178       }
179
180       if (AdC.GetType() == GeomAbs_Ellipse)
181       {
182         Bary = AdC.Ellipse().Location();
183         isBaryDefined = Standard_True;
184       }
185     }
186   }
187
188   if (!isBaryDefined)
189   {
190     BRepGProp::LinearProperties(W,GP);
191     Bary = GP.CentreOfMass();
192   }
193
194   findPlanarSurf.Init(W, -1, Standard_True);
195   if ( findPlanarSurf.Found())
196   {
197     S = findPlanarSurf.Surface();
198     L = findPlanarSurf.Location();
199     if (!L.IsIdentity()) S = Handle(Geom_Surface)::
200       DownCast(S->Transformed(L.Transformation()));
201     P = (Handle(Geom_Plane)::DownCast(S))->Pln();
202     P.SetLocation(Bary);
203   }
204   else
205   {
206     // wire not plane !
207     GProp_PrincipalProps Pp  = GP.PrincipalProperties();
208     gp_Vec Vec;
209     Standard_Real R1, R2, R3,Tol = Precision::Confusion();
210     Pp.RadiusOfGyration(R1,R2,R3);
211     Standard_Real RMax = Max(Max(R1,R2),R3);
212     if ( ( Abs(RMax-R1)<Tol && Abs(RMax-R2)<Tol )
213       || ( Abs(RMax-R1)<Tol && Abs(RMax-R3)<Tol ) 
214       || ( Abs(RMax-R2)<Tol && Abs(RMax-R3)<Tol ) )
215       isplane = Standard_False;
216     else
217     {
218       if (R1>=R2 && R1>=R3)
219       {
220         Vec = Pp.FirstAxisOfInertia();
221       }
222       else if (R2>=R1 && R2>=R3)
223       {
224         Vec = Pp.SecondAxisOfInertia();
225       }
226       else if (R3>=R1 && R3>=R2)
227       {
228         Vec = Pp.ThirdAxisOfInertia();
229       }
230       gp_Dir NDir(Vec);
231       if (R3<=R2 && R3<=R1)
232       {
233         Vec = Pp.ThirdAxisOfInertia();
234       }
235       else if (R2<=R1 && R2<=R3)
236       {
237         Vec = Pp.SecondAxisOfInertia();
238       }
239       else if (R1<=R2 && R1<=R3)
240       {
241         Vec = Pp.FirstAxisOfInertia();
242       }
243       gp_Dir XDir(Vec);
244       gp_Ax3 repere(Bary,NDir,XDir);
245       Geom_Plane GPlan(repere);
246       P = GPlan.Pln();
247     }
248   }
249
250   return isplane;
251
252 }
253                                       
254
255 static void WireContinuity (const TopoDS_Wire& W,
256                             GeomAbs_Shape& contW)
257 {
258   contW = GeomAbs_CN;
259   GeomAbs_Shape cont;
260   Standard_Boolean IsDegenerated = Standard_False;
261
262   BRepTools_WireExplorer anExp;
263   Standard_Integer nbEdges=0;
264   Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape();
265   for(anExp.Init(W); anExp.More(); anExp.Next()) {
266     nbEdges++;
267     Edges->Append(anExp.Current());
268     if (BRep_Tool::Degenerated(anExp.Current())) IsDegenerated = Standard_True;
269   }
270   
271   if (!IsDegenerated) {
272
273     Standard_Boolean testconti = Standard_True;
274
275     for (Standard_Integer j=1;j<=nbEdges;j++) {
276       
277       TopoDS_Edge Edge1, Edge2;
278       
279       if (j == nbEdges) {
280         Edge1 = TopoDS::Edge (Edges->Value(nbEdges));
281         Edge2 = TopoDS::Edge (Edges->Value(1));
282       }
283       else {
284         Edge1 = TopoDS::Edge (Edges->Value(j));
285         Edge2 = TopoDS::Edge (Edges->Value(j+1));
286       } 
287       
288       TopoDS_Vertex V1,V2,Vbid;
289       TopExp::Vertices(Edge1,Vbid,V1,Standard_True);
290       TopExp::Vertices(Edge2,V2,Vbid,Standard_True);
291       Standard_Real U1 = BRep_Tool::Parameter(V1,Edge1);
292       Standard_Real U2 = BRep_Tool::Parameter(V2,Edge2);
293       BRepAdaptor_Curve Curve1(Edge1);
294       BRepAdaptor_Curve Curve2(Edge2);
295       Standard_Real Eps = BRep_Tool::Tolerance(V2) + BRep_Tool::Tolerance(V1);
296       
297       if(j == nbEdges) 
298         testconti = Curve1.Value(U1).IsEqual(Curve2.Value(U2), Eps);
299       
300       if(testconti) {
301         cont = BRepLProp::Continuity(Curve1,Curve2,U1,U2,
302                                      Eps, Precision::Angular()); 
303         if (cont <= contW) contW = cont;
304       }
305     }
306   }
307   
308 }
309
310 static void TrimEdge (const TopoDS_Edge&              CurrentEdge,
311                       const TColStd_SequenceOfReal&   CutValues,
312                       const Standard_Real   t0, const Standard_Real   t1,
313                       const Standard_Boolean          SeqOrder,
314                       TopTools_SequenceOfShape& S)
315
316 {
317   S.Clear();
318   Standard_Integer j, ndec=CutValues.Length();
319   Standard_Real first,last,m0,m1;
320   Handle(Geom_Curve) C = BRep_Tool::Curve(CurrentEdge,first,last);
321
322   TopoDS_Vertex Vf,Vl,Vbid,V0,V1;
323   TopAbs_Orientation CurrentOrient = CurrentEdge.Orientation();
324   TopExp::Vertices(CurrentEdge,Vf,Vl);
325   Vbid.Nullify();
326
327   if (SeqOrder) {
328     // from first to last
329     m0 = first;
330     V0 = Vf;
331     for (j=1; j<=ndec; j++) {
332       // piece of edge  
333       m1 = (CutValues.Value(j)-t0)*(last-first)/(t1-t0)+first;
334       TopoDS_Edge CutE = BRepLib_MakeEdge(C,V0,Vbid,m0,m1);
335       CutE.Orientation(CurrentOrient);
336       S.Append(CutE);
337       m0 = m1;
338       V0 = TopExp::LastVertex(CutE);
339       if (j==ndec) {
340         // last piece
341         TopoDS_Edge LastE = BRepLib_MakeEdge(C,V0,Vl,m0,last);
342         LastE.Orientation(CurrentOrient);
343         S.Append(LastE);
344       }
345     }
346   }
347   else {
348     // from last to first
349     m1 = last;
350     V1 = Vl;
351     for (j=ndec; j>=1; j--) {
352       // piece of edge  
353       m0 = (CutValues.Value(j)-t0)*(last-first)/(t1-t0)+first;
354       TopoDS_Edge CutE = BRepLib_MakeEdge(C,Vbid,V1,m0,m1);
355       CutE.Orientation(CurrentOrient);
356       S.Append(CutE);
357       m1 = m0;
358       V1 = TopExp::FirstVertex(CutE);
359       if (j==1) {
360         // last piece
361         TopoDS_Edge LastE = BRepLib_MakeEdge(C,Vf,V1,first,m1);
362         LastE.Orientation(CurrentOrient);
363         S.Append(LastE);
364       }
365     }
366   }
367 }
368
369
370
371 static Standard_Boolean SearchRoot (const TopoDS_Vertex& V,
372                                     const TopTools_DataMapOfShapeListOfShape& Map,
373                                     TopoDS_Vertex& VRoot)
374 {
375   Standard_Boolean trouve = Standard_False;
376   VRoot.Nullify();
377   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it;
378   for (it.Initialize(Map); it.More(); it.Next()) {
379     const TopTools_ListOfShape & List = it.Value();
380     TopTools_ListIteratorOfListOfShape itL;
381     Standard_Boolean ilyest = Standard_False;
382     for (itL.Initialize(List); itL.More(); itL.Next()) {
383       TopoDS_Vertex Vcur = TopoDS::Vertex(itL.Value());
384       if (Vcur.IsSame(V)) {
385         ilyest = Standard_True;
386       }
387       if (ilyest) break;
388     }
389     if (ilyest) {
390       trouve = Standard_True;
391       VRoot = TopoDS::Vertex(it.Key());
392     }
393     if (trouve) break;
394   }
395   return trouve;
396 }
397
398 static Standard_Boolean SearchVertex (const TopTools_ListOfShape& List,
399                                       const TopoDS_Wire&   W,
400                                       TopoDS_Vertex& VonW)
401 {
402   Standard_Boolean trouve = Standard_False;
403   VonW.Nullify();
404   TopTools_SequenceOfShape SeqV;
405   SeqOfVertices(W,SeqV);
406   for (Standard_Integer ii=1;ii<=SeqV.Length();ii++) {
407     TopoDS_Vertex Vi = TopoDS::Vertex(SeqV.Value(ii));
408     TopTools_ListIteratorOfListOfShape itL;
409     Standard_Boolean ilyest = Standard_False;
410     for (itL.Initialize(List); itL.More(); itL.Next()) {
411       TopoDS_Vertex Vcur = TopoDS::Vertex(itL.Value());
412       if (Vcur.IsSame(Vi)) {
413         ilyest = Standard_True;
414       }
415       if (ilyest) break;
416     }
417     if (ilyest) {
418       trouve = Standard_True;
419       VonW = Vi;
420     }
421     if (trouve) break;
422   }
423   return trouve;
424 }
425
426
427 static Standard_Boolean EdgeIntersectOnWire (const gp_Pnt& P1,
428                                              const gp_Pnt& P2,
429                                              Standard_Real percent,
430                                              const TopTools_DataMapOfShapeListOfShape& Map,
431                                              const TopoDS_Wire&   W,
432                                              TopoDS_Vertex& Vsol,
433                                              TopoDS_Wire&   newW)
434 {
435
436   BRepTools_WireExplorer anExp;
437
438   // construction of the edge of intersection
439   Standard_Boolean NewVertex = Standard_False;
440   gp_Lin droite(P1,gp_Dir(gp_Vec(P1,P2)));
441   // ATTENTION : it is required to construct a half-straight
442   //             but there is a bug in BRepExtrema_DistShapeShape
443   //             it is enough to take 100 * distance between P1 and P2
444   //             hoping that it is enough until the bug is corrected
445   //  Standard_Real dernierparam = Precision::Infinite();
446   // ATTENTION : return !!
447   //             100 is better than 10 but it is too much !
448   //             finally, nothing is better than a blocking box
449   //  Standard_Real dernierparam = 100 * P1.Distance(P2);
450   Bnd_Box B;
451   BRepBndLib::Add(W,B);
452   Standard_Real x1,x2,y1,y2,z1,z2;
453   B.Get(x1,y1,z1,x2,y2,z2);
454   gp_Pnt BP1(x1,y1,z1), BP2(x2,y2,z2);
455   Standard_Real diag = BP1.Distance(BP2);
456   Standard_Real dernierparam = diag;
457   BRepLib_MakeEdge ME(droite,0.,dernierparam);
458   TopoDS_Edge ECur = BRepLib_MakeEdge(droite,0.,P1.Distance(P2));
459
460   // calculate the intersection by BRepExtrema (point of min distance)
461   BRepExtrema_DistShapeShape DSS(ME.Edge(),W);
462   if (DSS.IsDone()) {
463     // choose the solution closest to P2
464     Standard_Integer isol = 1;
465     gp_Pnt Psol = DSS.PointOnShape2(isol);
466     Standard_Real dss = P2.Distance(Psol);
467     for (Standard_Integer iss=2; iss<=DSS.NbSolution(); iss++) {
468       gp_Pnt Pss = DSS.PointOnShape2(iss);
469       Standard_Real aDist = P2.Distance(Pss);
470       if (dss > aDist) {
471         dss = aDist;
472         isol = iss;
473 #ifdef OCCT_DEBUG
474         Psol = Pss;
475 #endif
476       }
477     }
478
479     // is the solution a new vertex ?
480     NewVertex = (DSS.SupportTypeShape2(isol) != BRepExtrema_IsVertex);
481     if (NewVertex) {
482       TopoDS_Shape aLocalShape = DSS.SupportOnShape2(isol);
483       TopoDS_Edge E = TopoDS::Edge(aLocalShape);
484 //      TopoDS_Edge E = TopoDS::Edge(DSS.SupportOnShape2(isol));
485       Standard_Real tol = Precision::PConfusion();
486       Standard_Real first,last,param;
487       BRep_Tool::Range(E,first,last);
488       tol = Max(tol,percent*Abs(last-first));
489       DSS.ParOnEdgeS2(isol,param);
490       if (Abs(first-param)<tol) {
491         NewVertex = Standard_False;
492         Vsol = TopExp::FirstVertex(E);
493       }
494       else if (Abs(last-param)<tol) {
495         NewVertex = Standard_False;
496         Vsol = TopExp::LastVertex(E);
497       }
498       // check
499       if (!NewVertex) {
500         TopoDS_Vertex VRoot;
501         if (SearchRoot(Vsol,Map,VRoot)) NewVertex = Standard_True;
502       }
503     }
504     else {
505       TopoDS_Shape aLocalShape = DSS.SupportOnShape2(isol);
506       Vsol = TopoDS::Vertex(aLocalShape);
507 //      Vsol = TopoDS::Vertex(DSS.SupportOnShape2(isol));
508     }
509
510     // it is required to cut the edge
511     if (NewVertex) {
512       TopoDS_Shape aLocalShape = DSS.SupportOnShape2(isol);
513       TopoDS_Edge E = TopoDS::Edge(aLocalShape);
514 //      TopoDS_Edge E = TopoDS::Edge(DSS.SupportOnShape2(isol));
515       Standard_Real first,last,param;
516       DSS.ParOnEdgeS2(isol,param);
517       BRep_Tool::Range(E,first,last);
518       BRepLib_MakeWire MW;
519       for (anExp.Init(W); anExp.More(); anExp.Next()) {
520         if (E.IsSame(anExp.Current())) {
521           Standard_Boolean SO 
522             = (anExp.CurrentVertex().IsSame(TopExp::FirstVertex(E)));
523           TopTools_SequenceOfShape SE;
524           SE.Clear();
525           TColStd_SequenceOfReal SR;
526           SR.Clear();
527           SR.Append(param);
528           TrimEdge(E,SR,first,last,SO,SE);
529           TopoDS_Vertex VV1,VV2;
530           TopExp::Vertices(TopoDS::Edge(SE.Value(1)),VV1,VV2);
531           if (TopExp::FirstVertex(E).IsSame(VV1)
532               || TopExp::LastVertex(E).IsSame(VV1)) {
533             Vsol = VV2;
534           }
535           if (TopExp::FirstVertex(E).IsSame(VV2)
536               || TopExp::LastVertex(E).IsSame(VV2)) {
537             Vsol = VV1;
538           }
539           for (Standard_Integer k=1; k<=SE.Length(); k++) {
540             MW.Add(TopoDS::Edge(SE.Value(k)));
541           }
542         }
543         else {
544           MW.Add(anExp.Current());
545         }
546       }
547       newW = MW.Wire();
548     }
549     else {
550       newW = W;
551     }
552     
553     
554   }
555
556   return NewVertex;
557
558 }
559
560
561 static void Transform (const Standard_Boolean WithRotation,
562                        const gp_Pnt& P,
563                        const gp_Pnt& Pos1,
564                        const gp_Vec& Ax1,
565                        const gp_Pnt& Pos2,
566                        const gp_Vec& Ax2,
567                        gp_Pnt& Pnew)
568 {
569
570   Pnew = P.Translated (Pos1,Pos2);
571   gp_Vec axe1 = Ax1, axe2 = Ax2; 
572   if (!axe1.IsParallel(axe2,1.e-4)) {
573     gp_Vec Vtrans(Pos1,Pos2),Vsign;
574     Standard_Real alpha,beta,sign=1;
575     alpha = Vtrans.Dot(axe1);
576     beta = Vtrans.Dot(axe2);
577     if (alpha<-1.e-7) axe1 *=-1;
578     if (beta<1.e-7) axe2 *=-1;
579     alpha = Vtrans.Dot(axe1);
580     beta = Vtrans.Dot(axe2);
581     gp_Vec norm2 = axe1 ^ axe2;
582     Vsign.SetLinearForm(Vtrans.Dot(axe1),axe2,-Vtrans.Dot(axe2),axe1);
583     alpha = Vsign.Dot(axe1);
584     beta = Vsign.Dot(axe2);
585     Standard_Boolean pasnul = (Abs(alpha)>1.e-4 && Abs(beta)>1.e-4);
586     if ( alpha*beta>0.0 && pasnul ) sign=-1;
587     gp_Ax1 Norm(Pos2,norm2);
588     Standard_Real ang = axe1.AngleWithRef(axe2,norm2);
589     if (!WithRotation) {
590       if (ang>M_PI/2) ang = ang - M_PI;
591       if (ang<-M_PI/2) ang = ang + M_PI;
592     }
593     ang *= sign;
594     Pnew = Pnew.Rotated (Norm,ang);
595   }
596 }
597
598 static void BuildConnectedEdges(const TopoDS_Wire& aWire,
599                                 const TopoDS_Edge& StartEdge,
600                                 const TopoDS_Vertex& StartVertex,
601                                 TopTools_ListOfShape& ConnectedEdges)
602 {
603   TopTools_IndexedDataMapOfShapeListOfShape MapVE;
604   TopExp::MapShapesAndAncestors(aWire, TopAbs_VERTEX, TopAbs_EDGE, MapVE);
605   TopoDS_Edge CurEdge = StartEdge;
606   TopoDS_Vertex CurVertex = StartVertex;
607   TopoDS_Vertex Origin, V1, V2;
608   TopExp::Vertices(StartEdge, V1, V2);
609   Origin = (V1.IsSame(StartVertex))? V2 : V1;
610
611   for (;;)
612     {
613       TopTools_ListIteratorOfListOfShape itE( MapVE.FindFromKey(CurVertex) );
614       for (; itE.More(); itE.Next())
615         {
616           TopoDS_Edge anEdge = TopoDS::Edge(itE.Value());
617           if (!anEdge.IsSame(CurEdge))
618             {
619               ConnectedEdges.Append(anEdge);
620               TopExp::Vertices(anEdge, V1, V2);
621               CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
622               CurEdge = anEdge;
623               break;
624             }
625         }
626       if (CurVertex.IsSame(Origin))
627         break;
628     }
629 }
630                                       
631 //=======================================================================
632 //function : BRepFill_CompatibleWires
633 //purpose  : 
634 //=======================================================================
635
636 BRepFill_CompatibleWires::BRepFill_CompatibleWires() 
637 :myIsDone(Standard_False)
638 {
639 }
640
641
642 //=======================================================================
643 //function : BRepFill_CompatibleWires
644 //purpose  : 
645 //=======================================================================
646
647 BRepFill_CompatibleWires::BRepFill_CompatibleWires(const TopTools_SequenceOfShape& Sections)
648 {
649   Init(Sections);
650 }
651
652
653 //=======================================================================
654 //function : Init
655 //purpose  : 
656 //=======================================================================
657
658 void BRepFill_CompatibleWires::Init(const TopTools_SequenceOfShape& Sections)
659 {
660   myInit = Sections;
661   myWork = Sections;
662   myPercent = 0.01;
663   myIsDone = Standard_False;
664   myMap.Clear();
665
666 }
667
668
669 //=======================================================================
670 //function : SetPercent
671 //purpose  : 
672 //=======================================================================
673
674 void BRepFill_CompatibleWires::SetPercent(const Standard_Real Percent)
675 {
676   if (0.<Percent && Percent<1.) myPercent = Percent;
677
678 }
679
680
681 //=======================================================================
682 //function : IsDone
683 //purpose  : 
684 //=======================================================================
685
686 Standard_Boolean BRepFill_CompatibleWires::IsDone() const 
687 {
688   return myIsDone;
689 }
690
691
692 //=======================================================================
693 //function : Shape
694 //purpose  : 
695 //=======================================================================
696
697 const TopTools_SequenceOfShape& BRepFill_CompatibleWires::Shape() const 
698 {
699   return myWork;
700 }
701
702
703 //=======================================================================
704 //function : GeneratedShapes
705 //purpose  : 
706 //=======================================================================
707
708 const TopTools_ListOfShape& BRepFill_CompatibleWires::GeneratedShapes
709 (const TopoDS_Edge& SubSection) const
710 {  
711
712   if (myMap.IsBound(SubSection)) {
713     return myMap(SubSection);
714   }
715   else {
716     static TopTools_ListOfShape Empty;
717     return Empty;
718   }
719 }
720
721
722 //=======================================================================
723 //function : Perform
724 //purpose  : 
725 //=======================================================================
726
727 void BRepFill_CompatibleWires::Perform (const Standard_Boolean WithRotation)
728 {
729   // compute origin and orientation on wires to avoid twisted results
730   // and update wires to have same number of edges
731
732   // determination of report:
733   // if the number of elements is the same and if the wires have discontinuities
734   // by tangency, the report is not carried out by curvilinear abscissa
735   Standard_Integer nbSects = myWork.Length(), i;
736   BRepTools_WireExplorer anExp;
737   Standard_Integer nbmax=0, nbmin=0;
738   TColStd_Array1OfInteger nbEdges(1,nbSects);
739   Standard_Boolean report;
740   GeomAbs_Shape contS=GeomAbs_CN;
741   GeomAbs_Shape cont;
742   for (i=1; i<=nbSects; i++) {
743     TopoDS_Shape aLocalShape = myWork(i).Oriented(TopAbs_FORWARD);
744     myWork(i) = TopoDS::Wire(aLocalShape);
745 //    myWork(i) = TopoDS::Wire(myWork(i).Oriented(TopAbs_FORWARD));
746     TopoDS_Wire W = TopoDS::Wire(myWork(i));
747     WireContinuity(W,cont);
748     if (cont<contS) contS=cont;
749     nbEdges(i) = 0;
750     for(anExp.Init(W); anExp.More(); anExp.Next() ) nbEdges(i)++;
751     if (i==1) nbmin = nbEdges(i);
752     if (nbmax<nbEdges(i)) nbmax = nbEdges(i);
753     if (nbmin>nbEdges(i)) nbmin = nbEdges(i);
754   } 
755   // if the number of elements is not the same or if all wires are at least
756   // C1, the report is carried out by curvilinear abscissa of cuts, otherwise 
757   // a report vertex / Vertex is done
758   report = (nbmax != nbmin || contS >= GeomAbs_C1 );
759   
760   // initialization of the map
761   Standard_Integer nbE = 0;
762   TopTools_ListOfShape Empty;
763   for (i=1; i<=nbSects; i++) {
764     TopoDS_Wire W = TopoDS::Wire(myWork(i));
765     for(anExp.Init(W); anExp.More(); anExp.Next() ) {
766       TopoDS_Edge E = TopoDS::Edge(anExp.Current());
767       myMap.Bind(E,Empty);
768       myMap(E).Append(E);
769       nbE++;
770     }
771   } 
772   
773   // open/closed sections
774   // initialisation of myDegen1, myDegen2
775   Standard_Integer ideb=1, ifin=myWork.Length();
776   // check if the first wire is punctual
777   myDegen1 = Standard_True;
778   for(anExp.Init(TopoDS::Wire(myWork(ideb))); anExp.More(); anExp.Next()) {
779     myDegen1 = myDegen1 && (BRep_Tool::Degenerated(anExp.Current()));
780   }
781   if (myDegen1) ideb++;
782   // check if the last wire is punctual
783   myDegen2 = Standard_True;
784   for(anExp.Init(TopoDS::Wire(myWork(ifin))); anExp.More(); anExp.Next()) {
785     myDegen2 = myDegen2 && (BRep_Tool::Degenerated(anExp.Current()));
786   }
787   if (myDegen2) ifin--;
788   
789   Standard_Boolean wClosed, allClosed = Standard_True, allOpen = Standard_True;
790   for (i=ideb; i<=ifin; i++) {
791     wClosed = myWork(i).Closed();
792     if (!wClosed) {
793       // check if the vertices are the same.
794       TopoDS_Vertex V1, V2;
795       TopExp::Vertices(TopoDS::Wire(myWork(i)),V1,V2);
796       if ( V1.IsSame(V2)) wClosed = Standard_True;
797     }
798     allClosed = (allClosed && wClosed);
799     allOpen = (allOpen && !wClosed);
800   }
801   
802   if (allClosed) {
803     // All sections are closed 
804     if (report) {
805       // same number of elements  
806       SameNumberByPolarMethod(WithRotation);
807     }
808     else {
809       // origin
810       ComputeOrigin(Standard_False);
811     }
812     myIsDone = Standard_True;
813   }
814   else if (allOpen) {
815     // All sections are open
816     // origin
817     SearchOrigin();
818     // same number of elements
819     if (report) {
820       SameNumberByACR(report);
821     }
822     myIsDone = Standard_True;
823   }
824   else {
825     // There are open and closed sections :
826     // not processed
827     Standard_DomainError::Raise("Sections must be all closed or all open");
828   }
829   
830 }
831
832
833
834
835 //=======================================================================
836 //function : Generated
837 //purpose  : 
838 //=======================================================================
839
840 const TopTools_DataMapOfShapeListOfShape&  BRepFill_CompatibleWires::Generated() const 
841 {
842   return myMap;
843 }
844
845
846 //=======================================================================
847 //function : SameNumberByPolarMethod
848 //purpose  : 
849 //=======================================================================
850
851 void BRepFill_CompatibleWires::
852               SameNumberByPolarMethod(const Standard_Boolean WithRotation)
853 {
854
855   // initialisation 
856   Standard_Integer NbSects=myWork.Length();
857   BRepTools_WireExplorer anExp;
858   
859   Standard_Boolean allClosed = Standard_True;
860   Standard_Integer i,ii,ideb=1,ifin=NbSects;
861   for (i=1; i<=NbSects; i++) {
862     Handle(BRepCheck_Wire) Checker = new BRepCheck_Wire(TopoDS::Wire(myWork(i)));
863     allClosed = (allClosed && (Checker->Closed() == BRepCheck_NoError));
864     //allClosed = (allClosed && myWork(i).Closed());
865   }
866   if (!allClosed)
867     Standard_NoSuchObject::Raise("BRepFill_CompatibleWires::SameNumberByPolarMethod : the wires must be closed");
868   
869   // sections ponctuelles, sections bouclantes ?
870   if (myDegen1) ideb++;
871   if (myDegen2) ifin--;
872   Standard_Boolean vClosed = (!myDegen1) && (!myDegen2)
873                                 && (myWork(ideb).IsSame(myWork(ifin)));
874
875   //Removing degenerated edges
876   for (i = ideb; i <= ifin; i++)
877   {
878     Standard_Boolean hasDegEdge = Standard_False;
879     TopoDS_Iterator anItw(myWork(i));
880     for (; anItw.More(); anItw.Next())
881     {
882       const TopoDS_Edge& anEdge = TopoDS::Edge(anItw.Value());
883       if (BRep_Tool::Degenerated(anEdge))
884       {
885         hasDegEdge = Standard_True;
886         break;
887       }
888     }
889     if (hasDegEdge)
890     {
891       TopoDS_Wire aNewWire;
892       BRep_Builder aBBuilder;
893       aBBuilder.MakeWire(aNewWire);
894       for (anItw.Initialize(myWork(i)); anItw.More(); anItw.Next())
895       {
896         const TopoDS_Edge& anEdge = TopoDS::Edge(anItw.Value());
897         if (!BRep_Tool::Degenerated(anEdge))
898           aBBuilder.Add(aNewWire, anEdge);
899       }
900       myWork(i) = aNewWire;
901     }
902   }
903   
904   // Nombre max de decoupes possibles
905   Standard_Integer NbMaxV = 0;
906   for (i=1; i<=NbSects; i++) {
907     for(anExp.Init(TopoDS::Wire(myWork(i))); anExp.More(); anExp.Next()) {
908       NbMaxV++;
909     }
910   }
911   
912   // construction of tables of planes of wires 
913   gp_Pln P;
914   Handle(TColgp_HArray1OfPnt) Pos
915     = new (TColgp_HArray1OfPnt) (1,NbSects);
916   Handle(TColgp_HArray1OfVec) Axe
917     = new (TColgp_HArray1OfVec) (1,NbSects);
918   for (i=ideb;i<=ifin;i++) {
919     if (PlaneOfWire(TopoDS::Wire(myWork(i)),P)) {
920       Pos->SetValue(i,P.Location());
921       Axe->SetValue(i,gp_Vec(P.Axis().Direction()));
922     }
923   }
924   TopTools_SequenceOfShape SeqV;
925   if (myDegen1) {
926     SeqOfVertices(TopoDS::Wire(myWork(1)),SeqV);
927     Pos->SetValue(1,BRep_Tool::Pnt(TopoDS::Vertex(SeqV.Value(1))));
928     Axe->SetValue(1,Axe->Value(ideb));
929   }
930   if (myDegen2) {
931     SeqOfVertices(TopoDS::Wire(myWork(NbSects)),SeqV);
932     Pos->SetValue(NbSects,BRep_Tool::Pnt(TopoDS::Vertex(SeqV.Value(1))));
933     Axe->SetValue(NbSects,Axe->Value(ifin));
934   }
935   
936   // construction of RMap, map of reports of wire i to wire i-1
937   TopTools_DataMapOfShapeListOfShape RMap;
938   RMap.Clear();
939   
940   // loop on i
941   for (i=ifin; i>ideb; i--) {
942     
943     const TopoDS_Wire& wire1 = TopoDS::Wire(myWork(i));
944     
945     // sequence of vertices of the first wire
946     SeqOfVertices(wire1,SeqV);
947     if (SeqV.Length()>NbMaxV) 
948       Standard_NoSuchObject::Raise("BRepFill::SameNumberByPolarMethod failed");
949     
950     // loop on vertices of wire1
951     for (ii=1;ii<=SeqV.Length();ii++) {
952       
953       TopoDS_Vertex Vi = TopoDS::Vertex(SeqV.Value(ii));
954       
955       // init of RMap for Vi
956       TopTools_ListOfShape Init;
957       Init.Clear();
958       RMap.Bind(Vi,Init);
959       
960       // it is required to find intersection Vi - wire2
961       gp_Pnt Pi = BRep_Tool::Pnt(Vi);
962       
963       // return Pi in the current plane
964       gp_Pnt Pnew;
965       Transform(WithRotation,Pi,
966                 Pos->Value(i),Axe->Value(i), 
967                 Pos->Value(i-1),Axe->Value(i-1),Pnew);
968       
969       // calculate the intersection
970       TopoDS_Shape Support;
971       Standard_Boolean NewVertex;
972       TopoDS_Vertex Vsol;
973       TopoDS_Wire newwire;
974       if (Pnew.Distance(Pos->Value(i-1))>Precision::Confusion()) {
975         Standard_Real percent = myPercent;
976         NewVertex = EdgeIntersectOnWire(Pos->Value(i-1),Pnew,percent,
977                                     RMap,TopoDS::Wire(myWork(i-1)),
978                                     Vsol,newwire);
979         if (NewVertex) myWork(i-1) = newwire;
980         RMap(Vi).Append(Vsol);
981       }
982       
983     } // loop on  ii
984   }   // loop on  i
985   
986   // initialisation of MapVLV, map of correspondences vertex - list of vertices
987   TopTools_DataMapOfShapeListOfShape MapVLV;
988   SeqOfVertices(TopoDS::Wire(myWork(ideb)),SeqV);
989   Standard_Integer SizeMap = SeqV.Length();
990   MapVLV.Clear();
991   for (ii=1;ii<=SizeMap;ii++) {
992     TopoDS_Vertex Vi = TopoDS::Vertex(SeqV.Value(ii));
993     TopTools_ListOfShape Init;
994     Init.Clear();
995     Init.Append(Vi);
996     MapVLV.Bind(Vi,Init);
997     Standard_Integer NbV = 1;
998     TopoDS_Vertex V0,V1;
999     V0 = Vi;
1000     Standard_Boolean tantque = SearchRoot(V0,RMap,V1);
1001     while (tantque) {
1002       MapVLV(Vi).Append(V1);
1003       NbV++;
1004       // test on NbV required for looping sections 
1005       if (V1.IsSame(Vi) || NbV >= myWork.Length()) {
1006         tantque = Standard_False;
1007       }
1008       else {
1009         V0 = V1;
1010         tantque = SearchRoot(V0,RMap,V1);
1011       }
1012     }
1013   }
1014   
1015   // loop on i
1016   for (i=ideb; i<ifin; i++) {
1017     
1018     const TopoDS_Wire& wire1 = TopoDS::Wire(myWork(i));
1019     
1020     // sequence of vertices of the first wire
1021     SeqOfVertices(wire1,SeqV);
1022     if ( SeqV.Length()>NbMaxV || SeqV.Length()>SizeMap ) 
1023       Standard_NoSuchObject::Raise("BRepFill::SameNumberByPolarMethod failed");
1024     
1025
1026     // next wire 
1027     const TopoDS_Wire& wire2 = TopoDS::Wire(myWork(i+1));
1028     
1029     // loop on vertices of wire1
1030     for (ii=1;ii<=SeqV.Length();ii++) {
1031       
1032       TopoDS_Vertex Vi = TopoDS::Vertex(SeqV.Value(ii));
1033       TopoDS_Vertex VRoot;
1034       VRoot.Nullify();
1035       Standard_Boolean intersect = Standard_True;
1036       if (SearchRoot(Vi,MapVLV,VRoot)) {
1037         const TopTools_ListOfShape& LVi = MapVLV(VRoot);
1038         TopoDS_Vertex VonW;
1039         VonW.Nullify();
1040         intersect = (!SearchVertex(LVi,wire2,VonW));
1041       }
1042       
1043       if (intersect) {
1044         // it is necessary to find intersection Vi - wire2
1045         gp_Pnt Pi = BRep_Tool::Pnt(Vi);
1046         
1047         // return Pi in the current plane
1048         gp_Pnt Pnew;
1049         Transform(WithRotation,Pi,
1050                   Pos->Value(i),Axe->Value(i), 
1051                   Pos->Value(i+1),Axe->Value(i+1),Pnew);
1052         
1053         // calculate the intersection
1054         TopoDS_Shape Support;
1055         Standard_Boolean NewVertex;
1056         TopoDS_Vertex Vsol;
1057         TopoDS_Wire newwire;
1058         if (Pnew.Distance(Pos->Value(i+1))>Precision::Confusion()) {
1059           Standard_Real percent = myPercent;
1060           NewVertex = EdgeIntersectOnWire(Pos->Value(i+1),Pnew,percent,
1061                                       MapVLV,TopoDS::Wire(myWork(i+1)),
1062                                       Vsol,newwire);
1063           MapVLV(VRoot).Append(Vsol);
1064           if (NewVertex) myWork(i+1) = newwire;
1065         }
1066         
1067       }
1068     } // loop on ii
1069   }   // loop on i
1070   
1071   // regularize wires following MapVLV
1072   TopoDS_Wire wire = TopoDS::Wire(myWork(ideb));
1073
1074   // except for the last if the sections loop 
1075   Standard_Integer ibout = ifin;
1076   if (vClosed) ibout--;
1077
1078   for ( i=ideb+1; i<=ibout; i++) {
1079
1080     BRepLib_MakeWire MW;
1081
1082     anExp.Init(wire);
1083     TopoDS_Edge ECur = anExp.Current();
1084     TopoDS_Vertex VF,VL;
1085     TopExp::Vertices(ECur,VF,VL,Standard_True);
1086     Standard_Real U1 = BRep_Tool::Parameter(VF,ECur);
1087     Standard_Real U2 = BRep_Tool::Parameter(VL,ECur);
1088     BRepAdaptor_Curve Curve(ECur);
1089     gp_Pnt PPs = Curve.Value(0.1*(U1+9*U2));
1090     TopTools_ListIteratorOfListOfShape itF(MapVLV(VF)),itL(MapVLV(VL));
1091     Standard_Integer rang = ideb;
1092     while (rang < i) {
1093       itF.Next();
1094       itL.Next();
1095       rang++;
1096     }
1097     TopoDS_Vertex V1 = TopoDS::Vertex(itF.Value()), V2 = TopoDS::Vertex(itL.Value());
1098     TopoDS_Edge Esol;
1099     Standard_Real scalmax=0.;
1100     TopoDS_Iterator itW( myWork(i) );
1101     
1102     for(; itW.More(); itW.Next())
1103       {
1104         TopoDS_Edge E = TopoDS::Edge(itW.Value());
1105         TopoDS_Vertex VVF,VVL;
1106         TopExp::Vertices(E,VVF,VVL,Standard_True);
1107         
1108         // parse candidate edges
1109         Standard_Real scal1,scal2;
1110         if ( (V1.IsSame(VVF)&&V2.IsSame(VVL)) || (V2.IsSame(VVF)&&V1.IsSame(VVL)) ) {
1111           Standard_Real U1param = BRep_Tool::Parameter(VVF,E);
1112           Standard_Real U2param = BRep_Tool::Parameter(VVL,E);
1113           BRepAdaptor_Curve CurveE(E);
1114           gp_Pnt PP1 = CurveE.Value(0.1*(U1param +9* U2param));
1115           gp_Pnt PP2 = CurveE.Value(0.1*(9* U1param + U2param));
1116   
1117           for (rang=i;rang>ideb;rang--) {
1118             Transform(WithRotation, PP1,
1119                       Pos->Value(rang), Axe->Value(rang),
1120                       Pos->Value(rang-1), Axe->Value(rang-1), PP1);
1121             Transform(WithRotation, PP2,
1122                       Pos->Value(rang), Axe->Value(rang),
1123                       Pos->Value(rang-1), Axe->Value(rang-1), PP2);
1124           }
1125           gp_Vec Ns(Pos->Value(ideb),PPs);
1126           Ns = Ns.Normalized();
1127           gp_Vec N1(Pos->Value(ideb),PP1);
1128           N1 = N1.Normalized();
1129           gp_Vec N2(Pos->Value(ideb),PP2);
1130           N2 = N2.Normalized();
1131           scal1 = N1.Dot(Ns);
1132           if (scal1>scalmax) {
1133             scalmax = scal1;
1134             Esol = E;
1135           }
1136           scal2 = N2.Dot(Ns);
1137           if (scal2>scalmax) {
1138             scalmax = scal2;
1139             TopoDS_Shape aLocalShape = E.Reversed();
1140             Esol = TopoDS::Edge(aLocalShape);
1141           }
1142         }
1143       } //end of for(; itW.More(); itW.Next())
1144     if (Esol.IsNull())
1145       Standard_ConstructionError::Raise("BRepFill :: profiles are inconsistent");
1146     MW.Add(Esol);
1147
1148     TopTools_ListOfShape ConnectedEdges;
1149     BuildConnectedEdges( TopoDS::Wire(myWork(i)), Esol, V2, ConnectedEdges );
1150
1151     TopTools_ListIteratorOfListOfShape itCE(ConnectedEdges);
1152     for(; anExp.More(), itCE.More(); anExp.Next(), itCE.Next())
1153       {
1154         ECur = anExp.Current();
1155         TopExp::Vertices(ECur,VF,VL,Standard_True);
1156         U1 = BRep_Tool::Parameter(VF,ECur);
1157         U2 = BRep_Tool::Parameter(VL,ECur);
1158         Curve.Initialize(ECur);
1159         PPs = Curve.Value(0.1*(U1+9*U2));
1160         
1161         TopoDS_Edge E = TopoDS::Edge(itCE.Value());
1162         TopoDS_Vertex VVF,VVL;
1163         TopExp::Vertices(E,VVF,VVL,Standard_True);
1164
1165         // parse candidate edges
1166         Standard_Real scal1,scal2;
1167         U1 = BRep_Tool::Parameter(VVF,E);
1168         U2 = BRep_Tool::Parameter(VVL,E);
1169         Curve.Initialize(E);
1170         gp_Pnt PP1 = Curve.Value(0.1*(U1+9*U2));
1171         gp_Pnt PP2 = Curve.Value(0.1*(9*U1+U2));
1172         
1173         for (rang=i;rang>ideb;rang--) {
1174           Transform(WithRotation, PP1,
1175                     Pos->Value(rang), Axe->Value(rang),
1176                     Pos->Value(rang-1), Axe->Value(rang-1), PP1);
1177           Transform(WithRotation, PP2,
1178                     Pos->Value(rang), Axe->Value(rang),
1179                     Pos->Value(rang-1), Axe->Value(rang-1), PP2);
1180         }
1181         gp_Vec Ns(Pos->Value(ideb),PPs);
1182         Ns = Ns.Normalized();
1183         gp_Vec N1(Pos->Value(ideb),PP1);
1184         N1 = N1.Normalized();
1185         gp_Vec N2(Pos->Value(ideb),PP2);
1186         N2 = N2.Normalized();
1187         scal1 = N1.Dot(Ns);
1188         scal2 = N2.Dot(Ns);
1189         if (scal2>scal1)
1190           E.Reverse();
1191         MW.Add(E);
1192       }
1193     myWork(i) = MW.Wire();
1194   }
1195   
1196   // blocking sections?
1197   if (vClosed) myWork(myWork.Length()) = myWork(1);
1198
1199   // check the number of edges for debug
1200   Standard_Integer nbmax=0, nbmin=0;
1201   for ( i=ideb; i<=ifin; i++) {
1202     Standard_Integer nbEdges=0;
1203     for(anExp.Init(TopoDS::Wire(myWork(i))); anExp.More(); anExp.Next()) {
1204       nbEdges++;
1205     }
1206     if (i==ideb) nbmin = nbEdges;
1207     if (nbmax<nbEdges) nbmax = nbEdges;
1208     if (nbmin>nbEdges) nbmin = nbEdges;
1209   }
1210   if (nbmin!=nbmax) {
1211     Standard_NoSuchObject::Raise("BRepFill_CompatibleWires::SameNumberByPolarMethod failed");
1212   }
1213
1214 }
1215
1216 //=======================================================================
1217 //function : SameNumberByACR
1218 //purpose  : 
1219 //=======================================================================
1220
1221 void BRepFill_CompatibleWires::SameNumberByACR(const  Standard_Boolean  report)
1222 {
1223   // find the dimension
1224   Standard_Integer ideb=1, ifin=myWork.Length();
1225   BRepTools_WireExplorer anExp;
1226
1227   // point sections, blocking  sections?
1228   if (myDegen1) ideb++;
1229   if (myDegen2) ifin--;
1230   Standard_Boolean vClosed = (!myDegen1) && (!myDegen2)
1231                                 && (myWork(ideb).IsSame(myWork(ifin)));
1232
1233   Standard_Integer nbSects = myWork.Length(), i;
1234   Standard_Integer nbmax=0, nbmin=0;
1235   TColStd_Array1OfInteger nbEdges(1,nbSects);
1236   for (i=1; i<=nbSects; i++) {
1237     nbEdges(i) = 0;
1238     for(anExp.Init(TopoDS::Wire(myWork(i))); anExp.More(); anExp.Next()) {
1239       nbEdges(i)++;
1240     }
1241     if (i==1) nbmin = nbEdges(i);
1242     if (nbmax<nbEdges(i)) nbmax = nbEdges(i);
1243     if (nbmin>nbEdges(i)) nbmin = nbEdges(i);
1244   }
1245
1246   if (nbmax>1) {
1247     // several edges
1248
1249     if (report || nbmin<nbmax) {
1250       // insertion of cuts
1251       Standard_Integer nbdec=(nbmax-1)*nbSects+1;
1252       TColStd_Array1OfReal dec(1,nbdec);
1253       dec.Init(0);
1254       dec(2)=1;
1255
1256       TColStd_Array1OfReal WireLen(1, nbSects);
1257       
1258       // calculate the table of cuts
1259       Standard_Integer j,k,l;
1260       for (i=1; i<=nbSects; i++) {
1261         // current wire
1262         const TopoDS_Wire& wire1 = TopoDS::Wire(myWork(i));
1263         Standard_Integer nbE = 0;
1264         for(anExp.Init(wire1); anExp.More(); anExp.Next()) {
1265           nbE++;
1266         }
1267         // length and ACR of the wire 
1268         TColStd_Array1OfReal ACR(0,nbE);
1269         ACR.Init(0);
1270         BRepFill::ComputeACR(wire1, ACR);
1271         WireLen(i) = ACR(0);
1272         // insertion of ACR of the wire in the table of cuts
1273         for (j=1; j<ACR.Length()-1; j++) {
1274           k=1;
1275           while (dec(k)<ACR(j)) {
1276             k++;
1277             if (k>nbdec) break;
1278           }
1279           if (dec(k-1)<ACR(j)&& ACR(j)<dec(k)) {
1280             for (l=nbdec-1;l>=k;l--) {
1281               dec(l+1)=dec(l);
1282             }
1283             dec(k) = ACR(j);
1284           }
1285         }
1286       }
1287       
1288       // table of cuts
1289       k=1;
1290       while (dec(k)<1) {
1291         k++;
1292         if (k>nbdec) break;
1293       }
1294       nbdec = k-1;
1295       TColStd_Array1OfReal dec2(1,nbdec);
1296       for (k=1;k<=nbdec;k++) {
1297         dec2(k) = dec(k);
1298       }
1299       
1300       //Check of cuts: are all the new edges long enouph or not
1301       TColStd_MapOfInteger CutsToRemove;
1302       for (k = 1; k <= nbdec; k++)
1303       {
1304         Standard_Real Knot1 = dec2(k);
1305         Standard_Real Knot2 = (k == nbdec)? 1. : dec2(k+1);
1306         Standard_Real AllLengthsNull = Standard_True;
1307         for (i = 1; i <= nbSects; i++)
1308         {
1309           Standard_Real EdgeLen = (Knot2 - Knot1) * WireLen(i);
1310           if (EdgeLen > Precision::Confusion())
1311           {
1312             AllLengthsNull = Standard_False;
1313             break;
1314           }
1315         }
1316         if (AllLengthsNull)
1317           CutsToRemove.Add(k);
1318       }
1319       Standard_Integer NewNbDec = nbdec - CutsToRemove.Extent();
1320       TColStd_Array1OfReal dec3(1, NewNbDec);
1321       i = 1;
1322       for (k = 1; k <= nbdec; k++)
1323         if (!CutsToRemove.Contains(k))
1324           dec3(i++) = dec2(k);
1325       ///////////////////
1326       
1327       // insertion of cuts in each wire
1328       for (i=1; i<=nbSects; i++) {
1329         const TopoDS_Wire& oldwire = TopoDS::Wire(myWork(i));
1330         Standard_Real tol = Precision::Confusion() / WireLen(i);
1331         TopoDS_Wire newwire = BRepFill::InsertACR(oldwire, dec3, tol);
1332         BRepTools_WireExplorer anExp1,anExp2;
1333         anExp1.Init(oldwire);
1334         anExp2.Init(newwire);
1335         for (;anExp1.More();anExp1.Next()) {
1336           const TopoDS_Edge& Ecur = anExp1.Current();
1337           if (!Ecur.IsSame(TopoDS::Edge(anExp2.Current()))) {
1338             TopTools_ListOfShape LE;
1339             LE.Clear();
1340             gp_Pnt P1,P2;
1341             const TopoDS_Vertex& V1 = anExp1.CurrentVertex();
1342             TopoDS_Vertex VF,VR;
1343             TopExp::Vertices(Ecur,VF,VR,Standard_True);
1344             if (V1.IsSame(VF)) P1 = BRep_Tool::Pnt(VR);
1345             if (V1.IsSame(VR)) P1 = BRep_Tool::Pnt(VF);
1346             TopoDS_Vertex V2 = anExp2.CurrentVertex();
1347             TopExp::Vertices(TopoDS::Edge(anExp2.Current()),
1348                              VF,VR,Standard_True);
1349             if (V2.IsSame(VF)) P2 = BRep_Tool::Pnt(VR);
1350             if (V2.IsSame(VR)) P2 = BRep_Tool::Pnt(VF);
1351             while (P1.Distance(P2)>1.e-3) {
1352               LE.Append(anExp2.Current());
1353               anExp2.Next();
1354               V2 = anExp2.CurrentVertex();
1355               TopExp::Vertices(TopoDS::Edge(anExp2.Current()),
1356                                VF,VR,Standard_True);
1357               if (V2.IsSame(VF)) P2 = BRep_Tool::Pnt(VR);
1358               if (V2.IsSame(VR)) P2 = BRep_Tool::Pnt(VF);
1359               if (P1.Distance(P2)<=1.e-3) {
1360                 LE.Append(anExp2.Current());
1361                 anExp2.Next();
1362               }
1363             }
1364
1365             TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itmap;
1366             //TopTools_ListIteratorOfListOfShape itlist;
1367             TopoDS_Edge Ancestor;
1368             Standard_Integer nbedge, nblist=0;
1369             Standard_Boolean found = Standard_False;
1370
1371             for (itmap.Initialize(myMap);itmap.More()&&(!found);itmap.Next()) {
1372               nblist++;
1373               TopTools_ListIteratorOfListOfShape itlist(itmap.Value());
1374               nbedge = 0;
1375               while (itlist.More()&&(!found)) {
1376                 nbedge++;
1377                 TopoDS_Edge ECur = TopoDS::Edge(itlist.Value());
1378                     
1379                 if (Ecur.IsSame(ECur)) {
1380                   Ancestor = TopoDS::Edge(itmap.Key());
1381                   found = Standard_True;
1382                   myMap(Ancestor).InsertBefore(LE,itlist);
1383                   myMap(Ancestor).Remove(itlist);
1384                 }
1385                 if (itlist.More()) itlist.Next();
1386               }
1387               
1388             }
1389
1390           }
1391           else {
1392             anExp2.Next();
1393           }
1394           
1395         }
1396         myWork(i) = newwire;
1397       }
1398       
1399     }
1400   }
1401   
1402   // blocking sections ?
1403   if (vClosed) myWork(myWork.Length()) = myWork(1);
1404
1405   // check the number of edges for debug
1406   nbmax = 0;
1407   for (i=ideb; i<=ifin; i++) {
1408     nbEdges(i) = 0;
1409     for(anExp.Init(TopoDS::Wire(myWork(i))); anExp.More(); anExp.Next()) {
1410       nbEdges(i)++;
1411     }
1412     if (i==ideb) nbmin = nbEdges(i);
1413     if (nbmax<nbEdges(i)) nbmax = nbEdges(i);
1414     if (nbmin>nbEdges(i)) nbmin = nbEdges(i);
1415   }
1416   if (nbmax!=nbmin) 
1417     Standard_NoSuchObject::Raise("BRepFill_CompatibleWires::SameNumberByACR failed");
1418 }
1419
1420 //=======================================================================
1421 //function : ComputeOrigin
1422 //purpose  : 
1423 //=======================================================================
1424
1425 void BRepFill_CompatibleWires::ComputeOrigin(const  Standard_Boolean /*polar*/ )
1426 {
1427   // reorganize the wires respecting orientation and origin
1428   
1429   TopoDS_Vertex Vdeb, Vfin;
1430   gp_Pnt Pdeb, Psuiv, PPs;
1431
1432   BRepTools_WireExplorer anExp;
1433
1434   Standard_Boolean wClosed, allClosed = Standard_True;
1435
1436   Standard_Integer NbSects = myWork.Length();
1437   Standard_Integer i, ideb=1,ifin=NbSects;
1438
1439   // point sections, blocking sections 
1440   if (myDegen1) ideb++;
1441   if (myDegen2) ifin--;
1442   Standard_Boolean vClosed = (!myDegen1) && (!myDegen2)
1443                                 && (myWork(ideb).IsSame(myWork(ifin)));
1444   
1445   
1446   for (i=ideb; i<=ifin; i++) {
1447     wClosed = myWork(i).Closed();
1448     if (!wClosed) {
1449       // check if the vertices are the same.
1450       TopoDS_Vertex V1, V2;
1451       TopExp::Vertices(TopoDS::Wire(myWork(i)),V1,V2);
1452       if ( V1.IsSame(V2)) wClosed = Standard_True;
1453     }
1454     allClosed = (allClosed && wClosed);
1455   }
1456 /*
1457   for (i=ideb; i<=ifin; i++) {
1458     allClosed = (allClosed && myWork(i).Closed());
1459   }
1460 */
1461   if (!allClosed) 
1462     Standard_NoSuchObject::Raise("BRepFill_CompatibleWires::ComputeOrigin : the wires must be closed");
1463
1464 /*  
1465   // Max number of possible cuts
1466   Standard_Integer NbMaxV = 0;
1467   for (i=1; i<=NbSects; i++) {
1468     for(anExp.Init(TopoDS::Wire(myWork(i))); anExp.More(); anExp.Next()) {
1469       NbMaxV++;
1470     }
1471   }
1472   
1473   // construction of tables of planes of wires 
1474   gp_Pln P;  
1475   Handle(TColgp_HArray1OfPnt) Pos
1476     = new (TColgp_HArray1OfPnt) (1,NbSects);
1477   Handle(TColgp_HArray1OfVec) Axe
1478     = new (TColgp_HArray1OfVec) (1,NbSects);
1479   for (i=ideb;i<=ifin;i++) {
1480     if (PlaneOfWire(TopoDS::Wire(myWork(i)),P)) {
1481       Pos->SetValue(i,P.Location());
1482       Axe->SetValue(i,gp_Vec(P.Axis().Direction()));
1483     }
1484   }
1485   TopTools_SequenceOfShape SeqV;
1486   if (myDegen1) {
1487     SeqOfVertices(TopoDS::Wire(myWork(1)),SeqV);
1488     Pos->SetValue(1,BRep_Tool::Pnt(TopoDS::Vertex(SeqV.Value(1))));
1489     Axe->SetValue(1,Axe->Value(ideb));
1490   }
1491   if (myDegen2) {
1492     SeqOfVertices(TopoDS::Wire(myWork(NbSects)),SeqV);
1493     Pos->SetValue(NbSects,BRep_Tool::Pnt(TopoDS::Vertex(SeqV.Value(1))));
1494     Axe->SetValue(NbSects,Axe->Value(ifin));
1495   }
1496 */
1497
1498   //Consider that all wires have same number of edges (polar==Standard_False)
1499   TopTools_SequenceOfShape PrevSeq;
1500   TopTools_SequenceOfShape PrevEseq;
1501   Standard_Integer theLength = 0;
1502   const TopoDS_Wire& wire = TopoDS::Wire( myWork(ideb) );
1503   for (anExp.Init(wire); anExp.More(); anExp.Next())
1504     {
1505       PrevSeq.Append(anExp.CurrentVertex());
1506       PrevEseq.Append(anExp.Current());
1507       theLength++;
1508     }
1509
1510   Standard_Integer nbs, NbSamples = 0;
1511   if (theLength <= 2)
1512     NbSamples = 4;
1513   gp_Pln FirstPlane;
1514   PlaneOfWire(TopoDS::Wire(myWork(ideb)), FirstPlane);
1515   gp_Pnt FirstBary = FirstPlane.Location();
1516   gp_Vec NormalOfFirstPlane = FirstPlane.Axis().Direction();
1517   for (i = ideb+1; i <= ifin; i++)
1518     {
1519       const TopoDS_Wire& aWire = TopoDS::Wire(myWork(i));
1520
1521       //Compute offset vector as current bary center projected on first plane
1522       //to first bary center
1523       gp_Pln CurPlane;
1524       PlaneOfWire(aWire, CurPlane);
1525       gp_Pnt CurBary = CurPlane.Location();
1526       gp_Vec aVec(FirstBary, CurBary);
1527       gp_Vec anOffsetProj = (aVec * NormalOfFirstPlane) * NormalOfFirstPlane;
1528       CurBary.Translate(-anOffsetProj); //projected current bary center
1529       gp_Vec Offset(CurBary, FirstBary);
1530       
1531       TopoDS_Wire newwire;
1532       BRep_Builder BB;
1533       BB.MakeWire(newwire);
1534       
1535       TopTools_SequenceOfShape SeqVertices, SeqEdges;
1536       for (anExp.Init(aWire); anExp.More(); anExp.Next())
1537         {
1538           SeqVertices.Append( anExp.CurrentVertex() );
1539           SeqEdges.Append( anExp.Current() );
1540         }
1541       
1542       Standard_Real MinSumDist = Precision::Infinite();
1543       Standard_Integer jmin = 1, j, k, n;
1544       Standard_Boolean forward = Standard_False;
1545       if (i == myWork.Length() && myDegen2)
1546         {
1547           // last point section
1548           jmin = 1;
1549           forward = Standard_True;
1550         }
1551       else
1552         for (j = 1; j <= theLength; j++)
1553           {
1554             //Forward
1555             Standard_Real SumDist = 0.;
1556             for (k = j, n = 1; k <= theLength; k++, n++)
1557               {
1558                 const TopoDS_Vertex& Vprev = TopoDS::Vertex( PrevSeq(n) );
1559                 gp_Pnt Pprev = BRep_Tool::Pnt(Vprev);
1560                 const TopoDS_Vertex& V = TopoDS::Vertex( SeqVertices(k) );
1561                 gp_Pnt P = BRep_Tool::Pnt(V).XYZ() + Offset.XYZ();
1562                 SumDist += Pprev.Distance(P);
1563                 if (NbSamples > 0)
1564                 {
1565                   const TopoDS_Edge& PrevEdge = TopoDS::Edge(PrevEseq(n));
1566                   const TopoDS_Edge& CurEdge = TopoDS::Edge(SeqEdges(k));
1567                   BRepAdaptor_Curve PrevEcurve(PrevEdge);
1568                   BRepAdaptor_Curve Ecurve(CurEdge);
1569                   Standard_Real SampleOnPrev = (PrevEcurve.LastParameter()-PrevEcurve.FirstParameter())/NbSamples;
1570                   Standard_Real SampleOnCur = (Ecurve.LastParameter()-Ecurve.FirstParameter())/NbSamples;
1571                   for (nbs = 1; nbs <= NbSamples-1; nbs++)
1572                   {
1573                     Standard_Real ParOnPrev = (PrevEdge.Orientation() == TopAbs_FORWARD)?
1574                       (PrevEcurve.FirstParameter() + nbs*SampleOnPrev) :
1575                       (PrevEcurve.FirstParameter() + (NbSamples-nbs)*SampleOnPrev);
1576                     Standard_Real ParOnCur = (CurEdge.Orientation() == TopAbs_FORWARD)?
1577                       (Ecurve.FirstParameter() + nbs*SampleOnCur) :
1578                       (Ecurve.FirstParameter() + (NbSamples-nbs)*SampleOnCur);
1579                     gp_Pnt PonPrev = PrevEcurve.Value(ParOnPrev);
1580                     gp_Pnt PonCur = Ecurve.Value(ParOnCur).XYZ() + Offset.XYZ();
1581                     SumDist += PonPrev.Distance(PonCur);
1582                   }
1583                 }
1584               }
1585             for (k = 1; k < j; k++, n++)
1586               {
1587                 const TopoDS_Vertex& Vprev = TopoDS::Vertex( PrevSeq(n) );
1588                 gp_Pnt Pprev = BRep_Tool::Pnt(Vprev);
1589                 const TopoDS_Vertex& V = TopoDS::Vertex( SeqVertices(k) );
1590                 gp_Pnt P = BRep_Tool::Pnt(V).XYZ() + Offset.XYZ();
1591                 SumDist += Pprev.Distance(P);
1592                 if (NbSamples > 0)
1593                 {
1594                   const TopoDS_Edge& PrevEdge = TopoDS::Edge(PrevEseq(n));
1595                   const TopoDS_Edge& CurEdge = TopoDS::Edge(SeqEdges(k));
1596                   BRepAdaptor_Curve PrevEcurve(PrevEdge);
1597                   BRepAdaptor_Curve Ecurve(CurEdge);
1598                   Standard_Real SampleOnPrev = (PrevEcurve.LastParameter()-PrevEcurve.FirstParameter())/NbSamples;
1599                   Standard_Real SampleOnCur = (Ecurve.LastParameter()-Ecurve.FirstParameter())/NbSamples;
1600                   for (nbs = 1; nbs <= NbSamples-1; nbs++)
1601                   {
1602                     Standard_Real ParOnPrev = (PrevEdge.Orientation() == TopAbs_FORWARD)?
1603                       (PrevEcurve.FirstParameter() + nbs*SampleOnPrev) :
1604                       (PrevEcurve.FirstParameter() + (NbSamples-nbs)*SampleOnPrev);
1605                     Standard_Real ParOnCur = (CurEdge.Orientation() == TopAbs_FORWARD)?
1606                       (Ecurve.FirstParameter() + nbs*SampleOnCur) :
1607                       (Ecurve.FirstParameter() + (NbSamples-nbs)*SampleOnCur);
1608                     gp_Pnt PonPrev = PrevEcurve.Value(ParOnPrev);
1609                     gp_Pnt PonCur = Ecurve.Value(ParOnCur).XYZ() + Offset.XYZ();
1610                     SumDist += PonPrev.Distance(PonCur);
1611                   }
1612                 }
1613               }
1614             if (SumDist < MinSumDist)
1615               {
1616                 MinSumDist = SumDist;
1617                 jmin = j;
1618                 forward = Standard_True;
1619               }
1620             
1621             //Backward
1622             SumDist = 0.;
1623             for (k = j, n = 1; k >= 1; k--, n++)
1624               {
1625                 const TopoDS_Vertex& Vprev = TopoDS::Vertex( PrevSeq(n) );
1626                 gp_Pnt Pprev = BRep_Tool::Pnt(Vprev);
1627                 const TopoDS_Vertex& V = TopoDS::Vertex( SeqVertices(k) );
1628                 gp_Pnt P = BRep_Tool::Pnt(V).XYZ() + Offset.XYZ();
1629                 SumDist += Pprev.Distance(P);
1630                 if (NbSamples > 0)
1631                 {
1632                   Standard_Integer k_cur = k-1;
1633                   if (k_cur == 0)
1634                     k_cur = theLength;
1635                   const TopoDS_Edge& PrevEdge = TopoDS::Edge(PrevEseq(n));
1636                   const TopoDS_Edge& CurEdge = TopoDS::Edge(SeqEdges(k_cur));
1637                   BRepAdaptor_Curve PrevEcurve(PrevEdge);
1638                   BRepAdaptor_Curve Ecurve(CurEdge);
1639                   Standard_Real SampleOnPrev = (PrevEcurve.LastParameter()-PrevEcurve.FirstParameter())/NbSamples;
1640                   Standard_Real SampleOnCur = (Ecurve.LastParameter()-Ecurve.FirstParameter())/NbSamples;
1641                   for (nbs = 1; nbs <= NbSamples-1; nbs++)
1642                   {
1643                     Standard_Real ParOnPrev = (PrevEdge.Orientation() == TopAbs_FORWARD)?
1644                       (PrevEcurve.FirstParameter() + nbs*SampleOnPrev) :
1645                       (PrevEcurve.FirstParameter() + (NbSamples-nbs)*SampleOnPrev);
1646                     Standard_Real ParOnCur = (CurEdge.Orientation() == TopAbs_FORWARD)?
1647                       (Ecurve.FirstParameter() + (NbSamples-nbs)*SampleOnCur) :
1648                       (Ecurve.FirstParameter() + nbs*SampleOnCur);
1649                     gp_Pnt PonPrev = PrevEcurve.Value(ParOnPrev);
1650                     gp_Pnt PonCur = Ecurve.Value(ParOnCur).XYZ() + Offset.XYZ();
1651                     SumDist += PonPrev.Distance(PonCur);
1652                   }
1653                 }
1654               }
1655             for (k = theLength; k > j; k--, n++)
1656               {
1657                 const TopoDS_Vertex& Vprev = TopoDS::Vertex( PrevSeq(n) );
1658                 gp_Pnt Pprev = BRep_Tool::Pnt(Vprev);
1659                 const TopoDS_Vertex& V = TopoDS::Vertex( SeqVertices(k) );
1660                 gp_Pnt P = BRep_Tool::Pnt(V).XYZ() + Offset.XYZ();
1661                 SumDist += Pprev.Distance(P);
1662                 if (NbSamples > 0)
1663                 {
1664                   const TopoDS_Edge& PrevEdge = TopoDS::Edge(PrevEseq(n));
1665                   const TopoDS_Edge& CurEdge = TopoDS::Edge(SeqEdges(k-1));
1666                   BRepAdaptor_Curve PrevEcurve(PrevEdge);
1667                   BRepAdaptor_Curve Ecurve(CurEdge);
1668                   Standard_Real SampleOnPrev = (PrevEcurve.LastParameter()-PrevEcurve.FirstParameter())/NbSamples;
1669                   Standard_Real SampleOnCur = (Ecurve.LastParameter()-Ecurve.FirstParameter())/NbSamples;
1670                   for (nbs = 1; nbs <= NbSamples-1; nbs++)
1671                   {
1672                     Standard_Real ParOnPrev = (PrevEdge.Orientation() == TopAbs_FORWARD)?
1673                       (PrevEcurve.FirstParameter() + nbs*SampleOnPrev) :
1674                       (PrevEcurve.FirstParameter() + (NbSamples-nbs)*SampleOnPrev);
1675                     Standard_Real ParOnCur = (CurEdge.Orientation() == TopAbs_FORWARD)?
1676                       (Ecurve.FirstParameter() + (NbSamples-nbs)*SampleOnCur) :
1677                       (Ecurve.FirstParameter() + nbs*SampleOnCur);
1678                     gp_Pnt PonPrev = PrevEcurve.Value(ParOnPrev);
1679                     gp_Pnt PonCur = Ecurve.Value(ParOnCur).XYZ() + Offset.XYZ();
1680                     SumDist += PonPrev.Distance(PonCur);
1681                   }
1682                 }
1683               }
1684             if (SumDist < MinSumDist)
1685               {
1686                 MinSumDist = SumDist;
1687                 jmin = j;
1688                 forward = Standard_False;
1689               }
1690           }
1691       
1692       PrevSeq.Clear();
1693       PrevEseq.Clear();
1694       if (forward)
1695         {
1696           for (j = jmin; j <= theLength; j++)
1697             {
1698               BB.Add( newwire, TopoDS::Edge(SeqEdges(j)) );
1699               PrevSeq.Append( SeqVertices(j) );
1700               PrevEseq.Append( SeqEdges(j) );
1701             }
1702           for (j = 1; j < jmin; j++)
1703             {
1704               BB.Add( newwire, TopoDS::Edge(SeqEdges(j)) );
1705               PrevSeq.Append( SeqVertices(j) );
1706               PrevEseq.Append( SeqEdges(j) );
1707             }
1708         }
1709       else
1710         {
1711           for (j = jmin-1; j >= 1; j--)
1712             {
1713               TopoDS_Shape aLocalShape = SeqEdges(j).Reversed();
1714               BB.Add( newwire, TopoDS::Edge(aLocalShape) );
1715               //PrevSeq.Append( SeqVertices(j) );
1716               PrevEseq.Append( SeqEdges(j).Reversed() );
1717             }
1718           for (j = theLength; j >= jmin; j--)
1719             {
1720               TopoDS_Shape aLocalShape = SeqEdges(j).Reversed();
1721               BB.Add( newwire, TopoDS::Edge(aLocalShape) );
1722               //PrevSeq.Append( SeqVertices(j) );
1723               PrevEseq.Append( SeqEdges(j).Reversed() );
1724             }
1725           for (j = jmin; j >= 1; j--)
1726             PrevSeq.Append( SeqVertices(j) );
1727           for (j = theLength; j > jmin; j--)
1728             PrevSeq.Append( SeqVertices(j) );
1729         }
1730       
1731       newwire.Closed( Standard_True );
1732       newwire.Orientation( TopAbs_FORWARD );
1733       myWork(i) = newwire;
1734     }
1735 #ifdef OCCT_DEBUG_EFV
1736
1737   for ( i=ideb; i<=myWork.Length(); i++) {
1738     
1739     const TopoDS_Wire& wire = TopoDS::Wire(myWork(i));
1740     
1741     Standard_Integer nbEdges=0;
1742     for(anExp.Init(TopoDS::Wire(myWork(i))); anExp.More(); anExp.Next())
1743       nbEdges++;
1744     TopExp::Vertices(wire,Vdeb,Vfin);
1745     Standard_Boolean wClosed = wire.Closed();
1746     if (!wClosed) {
1747       // on regarde quand meme si les vertex sont les memes.
1748       if ( Vdeb.IsSame(Vfin)) wClosed = Standard_True;
1749     }
1750     
1751     
1752     TopoDS_Vertex Vsuiv, VF, VR;
1753     TopoDS_Wire newwire;
1754     BRep_Builder BW;
1755     BW.MakeWire(newwire);
1756     if (i==ideb) {
1757       anExp.Init(wire);
1758       const TopoDS_Edge Ecur = TopoDS::Edge(anExp.Current());
1759       TopExp::Vertices(Ecur,VF,VR);
1760       if (Vdeb.IsSame(VF)) Vsuiv=VR;
1761       else if (Vdeb.IsSame(VR)) Vsuiv=VF;
1762       else {
1763         // par defaut on prend l'origine sur cette arete
1764         if (VR.IsSame(TopoDS::Vertex(anExp.CurrentVertex()))) {
1765           Vdeb = VR;
1766           Vsuiv = VF;
1767         }
1768         else {
1769           Vdeb = VF;
1770           Vsuiv = VR;
1771         }
1772       }
1773       Pdeb=BRep_Tool::Pnt(Vdeb);
1774       Psuiv=BRep_Tool::Pnt(Vsuiv);
1775       Standard_Real U1 = BRep_Tool::Parameter(Vdeb,Ecur);
1776       Standard_Real U2 = BRep_Tool::Parameter(Vsuiv,Ecur);
1777       BRepAdaptor_Curve Curve(Ecur);
1778       PPs = Curve.Value(0.25*(U1+3*U2));
1779       myWork(ideb) = wire;
1780     }
1781     else {
1782       // on ramene Pdeb, Psuiv et PPs dans le plan courant
1783       gp_Pnt Pnew,Pnext,PPn; 
1784       Transform(Standard_True,Pdeb,Pos->Value(i-1),Axe->Value(i-1), 
1785                               Pos->Value(i),Axe->Value(i),Pnew);
1786       Transform(Standard_True,Psuiv,Pos->Value(i-1),Axe->Value(i-1), 
1787                               Pos->Value(i),Axe->Value(i),Pnext);
1788       Transform(Standard_True,PPs,Pos->Value(i-1),Axe->Value(i-1), 
1789                               Pos->Value(i),Axe->Value(i),PPn);
1790       
1791       Standard_Real distmini,dist;
1792       Standard_Integer rang=0,rangdeb=0;
1793       TopoDS_Vertex Vmini;
1794       gp_Pnt Pmini,P1,P2;
1795       SeqOfVertices(wire,SeqV);
1796       if (SeqV.Length()>NbMaxV) 
1797         Standard_NoSuchObject::Raise("BRepFill::ComputeOrigin failed");
1798       if (!polar) {
1799         // choix du vertex le plus proche comme origine
1800         distmini = Precision::Infinite();
1801         for (Standard_Integer ii=1;ii<=SeqV.Length();ii++) {
1802           P1 = BRep_Tool::Pnt(TopoDS::Vertex(SeqV.Value(ii)));
1803           dist = P1.Distance(Pnew);
1804           if (dist<distmini) {
1805             distmini = dist;
1806             Vmini = TopoDS::Vertex(SeqV.Value(ii));
1807           }
1808         }
1809         if (!Vmini.IsNull()) Pmini = BRep_Tool::Pnt(Vmini);
1810       }
1811       else {
1812         
1813         // recherche du vertex correspondant a la projection conique
1814         Standard_Real angmin, angV, eta = Precision::Angular();
1815         TopoDS_Vertex Vopti;
1816         angmin = M_PI/2;
1817         distmini = Precision::Infinite();
1818         gp_Dir dir0(gp_Vec(Pnew,P.Location()));
1819         for (Standard_Integer ii=1;ii<=SeqV.Length();ii++) {
1820           P1 = BRep_Tool::Pnt(TopoDS::Vertex(SeqV.Value(ii)));
1821           dist = Pnew.Distance(P1);
1822           if (dist<Precision::Confusion()) {
1823             angV = 0.0;
1824           }
1825           else {
1826             gp_Dir dir1(gp_Vec(Pnew,P1));
1827             angV = dir1.Angle(dir0);
1828           }
1829           if (angV>M_PI/2) angV = M_PI - angV;
1830           if (angmin>angV+eta) {
1831             distmini = dist;
1832             angmin = angV;
1833             Vopti = TopoDS::Vertex(SeqV.Value(ii));
1834           }
1835           else if (Abs(angmin-angV)<eta) {
1836             if (dist<distmini) {
1837               distmini = dist;
1838               angmin = angV;
1839               Vopti = TopoDS::Vertex(SeqV.Value(ii));
1840             }
1841           }
1842         }
1843         gp_Pnt Popti;
1844         if (!Vopti.IsNull()) Popti = BRep_Tool::Pnt(Vopti);
1845         Vmini = Vopti;
1846         
1847       }
1848
1849       distmini = Precision::Infinite();
1850       for (anExp.Init(wire); anExp.More(); anExp.Next()) {
1851         TopoDS_Edge Ecur = anExp.Current();
1852         TopoDS_Vertex Vcur = anExp.CurrentVertex();
1853         TopExp::Vertices(Ecur,VF,VR);
1854         if (VF.IsSame(Vmini)) {
1855           P1 = BRep_Tool::Pnt(VR);
1856           dist = P1.Distance(Pnext);
1857           if (dist<=distmini) {
1858             distmini = dist;
1859             Vsuiv = VR;
1860           }
1861         }
1862         if (VR.IsSame(Vmini)) {
1863           P1 = BRep_Tool::Pnt(VF);
1864           dist = P1.Distance(Pnext);
1865           if (dist<distmini) {
1866             distmini = dist;
1867             Vsuiv = VF;
1868           }
1869         }
1870       }
1871       
1872       // choix du sens de parcours en fonction de Pnext
1873       Standard_Boolean parcours = Standard_False;
1874       if (i==myWork.Length() && myDegen2) {
1875         // derniere section ponctuelle
1876         rangdeb = 1;
1877         parcours = Standard_True;
1878       }
1879       else {
1880         // cas general
1881         gp_Pnt Pbout = Pnext;
1882         TopoDS_Edge E1,E2;
1883         TopoDS_Vertex V1,V2;
1884         EdgesFromVertex(wire,Vmini,E1,E2);
1885         
1886         TopExp::Vertices(E1,V1,V2,Standard_True);
1887 #ifndef OCCT_DEBUG
1888         Standard_Real U1=0, U2=0;
1889 #else
1890         Standard_Real U1, U2;
1891 #endif
1892         if (Vmini.IsSame(V1)) { 
1893           P1 = BRep_Tool::Pnt(V2);
1894           U1 = 0.25*(BRep_Tool::Parameter(V1,E1)+3*BRep_Tool::Parameter(V2,E1));
1895         }
1896         if (Vmini.IsSame(V2)) {
1897           P1 = BRep_Tool::Pnt(V1);
1898           U1 = 0.25*(3*BRep_Tool::Parameter(V1,E1)+BRep_Tool::Parameter(V2,E1));
1899         }
1900         
1901         TopExp::Vertices(E2,V1,V2,Standard_True);
1902         if (Vmini.IsSame(V1)) { 
1903           P2 = BRep_Tool::Pnt(V2);
1904           U2 = 0.25*(BRep_Tool::Parameter(V1,E2)+3*BRep_Tool::Parameter(V2,E2));
1905         }
1906         if (Vmini.IsSame(V2)) {
1907           P2 = BRep_Tool::Pnt(V1);
1908           U2 = 0.25*(3*BRep_Tool::Parameter(V1,E2)+BRep_Tool::Parameter(V2,E2));
1909         }
1910         
1911         if (Abs(Pbout.Distance(P1)-Pbout.Distance(P2))<Precision::Confusion()) {
1912           // cas limite ; on se decale un peu
1913           Pbout = PPn;
1914           BRepAdaptor_Curve Curve1(E1);
1915           P1 = Curve1.Value(U1);
1916           BRepAdaptor_Curve Curve2(E2);
1917           P2 = Curve2.Value(U2);
1918         }
1919         
1920         // calcul de rangdeb
1921         rangdeb = 0;
1922         if (Pbout.Distance(P1)<Pbout.Distance(P2)){
1923           // P1 est plus proche; parcours = False
1924           parcours = Standard_False;
1925           rang = 0;
1926           for (anExp.Init(wire); anExp.More(); anExp.Next()) {
1927             rang++;
1928             TopoDS_Edge Ecur = anExp.Current();
1929             if (E1.IsSame(Ecur)) {
1930               rangdeb = rang;
1931             }
1932           }
1933           BRepAdaptor_Curve Curve(E1);
1934           PPs = Curve.Value(U1);
1935         }
1936         else {
1937           // P2 est plus proche; parcours = True
1938           parcours = Standard_True;
1939           rang = 0;
1940           for (anExp.Init(wire); anExp.More(); anExp.Next()) {
1941             rang++;
1942             TopoDS_Edge Ecur = anExp.Current();
1943             if (E2.IsSame(Ecur)) {
1944               rangdeb = rang;
1945             }
1946           }
1947           BRepAdaptor_Curve Curve(E2);
1948           PPs = Curve.Value(U2);
1949         }
1950       }
1951
1952       // reconstruction du wire a partir de rangdeb
1953       TopTools_SequenceOfShape SeqEdges;
1954       SeqEdges.Clear();
1955       for (anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
1956         SeqEdges.Append(anExp.Current());
1957       }
1958       if (parcours) {
1959         for (rang=rangdeb;rang<=nbEdges;rang++) {
1960           BW.Add(newwire,TopoDS::Edge(SeqEdges.Value(rang)));
1961         }
1962         for (rang=1;rang<rangdeb;rang++) {
1963           BW.Add(newwire,TopoDS::Edge(SeqEdges.Value(rang)));
1964         }
1965       }
1966       else {
1967         for (rang=rangdeb;rang>=1;rang--) {
1968           TopoDS_Shape aLocalShape = SeqEdges.Value(rang).Reversed();
1969           BW.Add(newwire,TopoDS::Edge(aLocalShape));
1970 //        BW.Add(newwire,TopoDS::Edge(SeqEdges.Value(rang).Reversed()));
1971         }
1972         for (rang=nbEdges;rang>rangdeb;rang--) {
1973           TopoDS_Shape aLocalShape = SeqEdges.Value(rang).Reversed();
1974           BW.Add(newwire,TopoDS::Edge(aLocalShape));
1975 //        BW.Add(newwire,TopoDS::Edge(SeqEdges.Value(rang).Reversed()));
1976         }
1977       }
1978       
1979       myWork(i) = newwire.Oriented(TopAbs_FORWARD);
1980       
1981       // on passe au wire suivant
1982       if (!Vmini.IsNull()) Pdeb=BRep_Tool::Pnt(Vmini);
1983       if (!Vsuiv.IsNull()) Psuiv=BRep_Tool::Pnt(Vsuiv);
1984     }
1985   }
1986 #endif
1987   
1988   // blocking sections ?
1989   if (vClosed) myWork(myWork.Length()) = myWork(1);
1990 }
1991
1992 //=======================================================================
1993 //function : SearchOrigin
1994 //purpose  : 
1995 //=======================================================================
1996
1997 void BRepFill_CompatibleWires::SearchOrigin()
1998 {
1999   // reorganize the open wires respecting orientation and origin
2000   
2001   gp_Pln P0,P;  
2002
2003   TopoDS_Vertex Vdeb, Vfin;
2004   gp_Pnt Pdeb,  Pfin;//,Psuiv;
2005
2006   BRepTools_WireExplorer anExp;
2007
2008   Standard_Boolean allOpen = Standard_True;
2009   Standard_Integer ideb=1, ifin=myWork.Length();
2010   if (myDegen1) ideb++;
2011   if (myDegen2) ifin--;
2012   Standard_Boolean vClosed = (!myDegen1) && (!myDegen2)
2013                                 && (myWork(ideb).IsSame(myWork(ifin)));
2014   
2015 //  for (Standard_Integer i=ideb; i<=ifin; i++) {
2016   Standard_Integer i;
2017   for  (i=ideb; i<=ifin; i++) {
2018     allOpen = (allOpen && !myWork(i).Closed());
2019   }
2020   if (!allOpen)
2021     Standard_NoSuchObject::Raise("BRepFill_CompatibleWires::SearchOrigin : the wires must be open");
2022
2023   // init
2024
2025   TopoDS_Wire wire1 = TopoDS::Wire(myWork(ideb));
2026   wire1.Orientation(TopAbs_FORWARD);
2027   TopExp::Vertices(wire1,Vdeb,Vfin);
2028   Pdeb = BRep_Tool::Pnt(Vdeb);
2029   Pfin = BRep_Tool::Pnt(Vfin);
2030   Standard_Boolean isline0 = (!PlaneOfWire(wire1,P0)), isline;
2031   myWork(ideb) = wire1;
2032   //OCC86
2033   anExp.Init(wire1);
2034   TopoDS_Edge E0 = anExp.Current(), E;
2035
2036   for ( i=ideb+1; i<=ifin; i++) {
2037
2038     TopoDS_Wire wire = TopoDS::Wire(myWork(i));
2039     wire.Orientation(TopAbs_FORWARD);
2040
2041     TopTools_SequenceOfShape SeqEdges;
2042     SeqEdges.Clear();
2043     Standard_Integer nbEdges=0;
2044     //OCC86  for(anExp.Init(wire); anExp.More(); anExp.Next()) {
2045     for(anExp.Init(wire), E = anExp.Current(); anExp.More(); anExp.Next()) {
2046       SeqEdges.Append(anExp.Current());
2047       nbEdges++;
2048     }
2049     TopExp::Vertices(wire,Vdeb,Vfin);
2050     isline = (!PlaneOfWire(wire,P));
2051
2052     TopoDS_Vertex Vmini;
2053     TopoDS_Wire newwire;
2054     BRep_Builder BW;
2055     BW.MakeWire(newwire);
2056     Standard_Boolean parcours = Standard_True;
2057
2058     if (isline0 || isline) {
2059       
2060       // particular case of straight segments 
2061       gp_Pnt P1 = BRep_Tool::Pnt(Vdeb),
2062              P2 = BRep_Tool::Pnt(Vfin);
2063       Standard_Real dist1, dist2;
2064       dist1 = Pdeb.Distance(P1)+Pfin.Distance(P2);
2065       dist2 = Pdeb.Distance(P2)+Pfin.Distance(P1);
2066       parcours = (dist2>=dist1);
2067     }
2068     
2069     else {
2070       //OCC86
2071       gp_Pnt P1 = BRep_Tool::Pnt(Vdeb), P1o = Pdeb,
2072              P2 = BRep_Tool::Pnt(Vfin), P2o = Pfin;
2073 /*    // return Pdeb in the current plane
2074       gp_Pnt Pnew = Pdeb.Translated (P0.Location(),P.Location());
2075       gp_Ax1 A0 = P0.Axis();
2076       gp_Ax1 A1 = P.Axis();
2077       
2078       if (!A0.IsParallel(A1,1.e-4)) {
2079         gp_Vec vec1(A0.Direction()), vec2(A1.Direction()), 
2080         norm = vec1 ^ vec2;
2081         gp_Ax1 Norm(P.Location(),norm);
2082         Standard_Real ang = vec1.AngleWithRef(vec2,norm);
2083         if (ang > M_PI/2.0)
2084           ang = M_PI - ang;
2085         if (ang < -M_PI/2.0)
2086           ang = -M_PI - ang;
2087         if (Abs(ang-M_PI/2.0)<Precision::Angular()) {
2088           // cas d'ambiguite
2089           gp_Vec Vtrans(P0.Location(),P.Location()),Vsign;
2090           Standard_Real alpha,beta,sign=1;
2091           Vsign.SetLinearForm(Vtrans.Dot(vec1),vec2,-Vtrans.Dot(vec2),vec1);
2092           alpha = Vsign.Dot(vec1);
2093           beta = Vsign.Dot(vec2);
2094           Standard_Boolean pasnul = (Abs(alpha)>1.e-4 && Abs(beta)>1.e-4);
2095           if ( alpha*beta>0.0 && pasnul ) sign=-1;
2096           ang *= sign;
2097         }
2098         Pnew = Pnew.Rotated (Norm,ang);
2099       }
2100       // choix entre Vdeb et Vfin
2101       Standard_Real dist = Pnew.Distance(P1);
2102       parcours = (dist<Pnew.Distance(P2));
2103 */      
2104       if(P1.IsEqual(P2,Precision::Confusion()) || P1o.IsEqual(P2o,Precision::Confusion())){
2105         BRepAdaptor_Curve Curve0(E0), Curve(E);
2106         Curve0.D0(Curve0.FirstParameter() + Precision::Confusion(), P2o);
2107         Curve.D0(Curve.FirstParameter() + Precision::Confusion(), P2);
2108       };
2109       gp_Vec VDebFin0(P1o,P2o), VDebFin(P1,P2);
2110       Standard_Real AStraight = VDebFin0.Angle(VDebFin);
2111       parcours = (AStraight < M_PI/2.0? Standard_True: Standard_False);
2112     }
2113     
2114     // reconstruction of the wire
2115     Standard_Integer rang;
2116     if (parcours) {
2117       for (rang=1;rang<=nbEdges;rang++) {
2118         TopoDS_Shape alocalshape = SeqEdges.Value(rang);
2119         BW.Add(newwire,TopoDS::Edge(alocalshape));
2120 //      BW.Add(newwire,TopoDS::Edge(SeqEdges.Value(rang)));
2121       }
2122     }
2123     else {
2124       for (rang=nbEdges;rang>=1;rang--) {
2125         TopoDS_Shape alocalshape = SeqEdges.Value(rang).Reversed();
2126         BW.Add(newwire,TopoDS::Edge(alocalshape));
2127 //      BW.Add(newwire,TopoDS::Edge(SeqEdges.Value(rang).Reversed()));
2128       }
2129     }
2130
2131     // orientation of the wire
2132     newwire.Oriented(TopAbs_FORWARD);
2133     myWork(i) = newwire;
2134
2135     // passe to the next wire 
2136     if (parcours) {
2137       Pdeb = BRep_Tool::Pnt(Vdeb);
2138       Pfin = BRep_Tool::Pnt(Vfin);
2139     }
2140     else {
2141       Pfin = BRep_Tool::Pnt(Vdeb);
2142       Pdeb = BRep_Tool::Pnt(Vfin);
2143     }
2144     P0 = P;
2145     isline0 = isline;
2146     //OCC86
2147     E0 = E;
2148   }
2149   
2150   // blocking sections ?
2151   if (vClosed) myWork(myWork.Length()) = myWork(1);
2152 }