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