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