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