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