0022807: Loading of STEP entities in model during reading of STEP file requires redun...
[occt.git] / src / BRepFill / BRepFill_OffsetWire.cxx
1 // File:        BRepFill_OffsetWire.cxx
2 // Created:     Thu Apr 20 10:33:55 1995
3 // Author:      Bruno DUMORTIER
4 //              <dub@fuegox>
5
6 //  Modified by skv - Fri Jul  8 11:21:38 2005 OCC9145
7
8 #include <stdio.h>
9
10 #include <BRepFill_OffsetWire.ixx>
11
12 #include <BRepAdaptor_Curve.hxx>
13 #include <BRepAdaptor_Surface.hxx>
14
15 #include <BRepFill_DataMapOfNodeShape.hxx>
16 #include <BRepFill_DataMapOfShapeSequenceOfPnt.hxx>
17 #include <BRepFill_DataMapOfShapeSequenceOfReal.hxx> 
18 #include <BRepFill_DataMapOfOrientedShapeListOfShape.hxx> 
19 #include <BRepFill_TrimEdgeTool.hxx>
20 #include <BRepLib.hxx>
21 #include <BRepLib_MakeVertex.hxx>
22 #include <BRepLib_MakeFace.hxx>
23 #include <BRepLib_MakeWire.hxx>
24 #include <BRepLib_MakeEdge.hxx>
25 #include <BRepTools.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRep_TEdge.hxx>
29 #include <BRep_CurveRepresentation.hxx>
30 #include <BRep_GCurve.hxx>
31 #include <BRepTools_WireExplorer.hxx>
32 #include <BRepMAT2d_Explorer.hxx>
33 #include <Geom2dAdaptor_Curve.hxx>
34 #include <Geom2dAdaptor_HCurve.hxx>
35 #include <Adaptor3d_OffsetCurve.hxx>
36 #include <Adaptor3d_Curve.hxx>
37 #include <Geom_Surface.hxx>
38 #include <Geom_Plane.hxx>
39 #include <Geom2d_Curve.hxx>
40 #include <Geom2d_Circle.hxx>
41 #include <Geom2d_Line.hxx>
42 #include <Geom2d_TrimmedCurve.hxx>
43 #include <Geom2d_OffsetCurve.hxx>
44 #include <GeomAPI.hxx>
45 #include <Geom_TrimmedCurve.hxx>
46 #include <Geom_Circle.hxx>
47 #include <Geom_OffsetCurve.hxx>
48 #include <MAT_Arc.hxx>
49 #include <MAT_Node.hxx>
50 #include <MAT_Graph.hxx>
51 #include <MAT2d_CutCurve.hxx>
52 #include <Precision.hxx>
53 #include <Standard_NotImplemented.hxx>
54 #include <TColgp_SequenceOfPnt.hxx>
55 #include <TColStd_SequenceOfReal.hxx> 
56 #include <TopAbs.hxx> 
57 #include <TopExp.hxx>
58 #include <TopExp_Explorer.hxx>
59 #include <TopoDS.hxx>
60 #include <TopoDS_Wire.hxx>
61 #include <TopoDS_Compound.hxx>
62 #include <TopoDS_Iterator.hxx>
63 #include <TopTools_MapOfShape.hxx>
64 #include <TopTools_MapIteratorOfMapOfShape.hxx>
65 #include <TopTools_ListIteratorOfListOfShape.hxx>
66 #include <TopTools_DataMapOfShapeListOfShape.hxx>
67 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
68 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
69 #include <TopTools_SequenceOfShape.hxx>
70 #include <TopTools_ListOfShape.hxx>    
71 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>    
72 #include <TopTools_DataMapOfShapeSequenceOfShape.hxx>
73
74 #include <gp.hxx>
75 #include <gp_Vec.hxx>
76 #include <gp_Ax2.hxx>
77 #include <gp_Pln.hxx>
78 #include <gp_Dir2d.hxx>
79
80 #include <BRep_TVertex.hxx>
81 #include <TopTools_IndexedMapOfShape.hxx>
82 #include <Geom2d_BSplineCurve.hxx>
83 #include <TColgp_Array1OfPnt2d.hxx>
84 #include <TColStd_Array1OfReal.hxx>
85 #include <TColStd_Array1OfInteger.hxx>
86 #include <BRepTools_Substitution.hxx>
87 #include <BRepLib_MakeVertex.hxx>
88 #include <Geom2dLProp_CLProps2d.hxx>
89 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
90 #include <Standard_ErrorHandler.hxx>
91
92 #ifdef DRAW
93 #include <Draw.hxx>
94 #include <DrawTrSurf.hxx>
95 #include <DrawTrSurf_Curve2d.hxx>
96 #include <DBRep.hxx>
97 #endif
98
99 #ifdef DEB
100 static Standard_Boolean AffichGeom  = Standard_False;
101 static Standard_Boolean Affich2d    = Standard_False;
102 static Standard_Boolean AffichEdge  = Standard_False;
103 static Standard_Integer NbTRIMEDGES = 0;
104 static Standard_Integer NbOFFSET    = 0;
105 static Standard_Integer NbEDGES     = 0;
106 static Standard_Integer NbBISSEC    = 0;
107 #ifndef WNT
108 static char tname[100];
109 static Standard_CString name = tname ;
110 #endif
111 #endif
112
113 //  Modified by Sergey KHROMOV - Thu Nov 16 17:24:39 2000 Begin
114
115 static void QuasiFleche(const Adaptor3d_Curve& C,
116                         const Standard_Real Deflection2, 
117                         const Standard_Real Udeb,
118                         const gp_Pnt& Pdeb,
119                         const gp_Vec& Vdeb,
120                         const Standard_Real Ufin,
121                         const gp_Pnt& Pfin,
122                         const gp_Vec& Vfin,
123                         const Standard_Integer Nbmin,
124                         const Standard_Real Eps,
125                         TColStd_SequenceOfReal& Parameters,
126                         TColgp_SequenceOfPnt& Points);
127
128 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters,
129                                       TColgp_SequenceOfPnt&   Points,
130                                       const Adaptor3d_Curve& C, 
131                                       const Standard_Real Deflection,
132                                       const Standard_Real U1,
133                                       const Standard_Real U2,
134                                       const Standard_Real EPSILON,
135                                       const Standard_Integer Nbmin);
136
137 static void CheckBadEdges(const TopoDS_Face& Spine, const Standard_Real Offset,
138                           const BRepMAT2d_BisectingLocus& Locus, 
139                           const BRepMAT2d_LinkTopoBilo&   Link,
140                           TopTools_ListOfShape& BadEdges);
141
142 static Standard_Integer CutEdge (const TopoDS_Edge& E, 
143                                  const TopoDS_Face& F,
144                                        Standard_Integer ForceCut,
145                                        TopTools_ListOfShape& Cuts);
146
147
148 static void CutCurve (const Handle(Geom2d_TrimmedCurve)& C,
149                       const Standard_Integer nbParts,
150                             TColGeom2d_SequenceOfCurve& theCurves);
151 //  Modified by Sergey KHROMOV - Thu Nov 16 17:24:47 2000 End
152
153
154 static void EdgeVertices (const TopoDS_Edge&   E,
155                                 TopoDS_Vertex& V1, 
156                                 TopoDS_Vertex& V2)
157 {
158   if (E.Orientation() == TopAbs_REVERSED) {
159     TopExp::Vertices(E,V2,V1);
160   }
161   else {
162     TopExp::Vertices(E,V1,V2);
163   }
164 }
165                                       
166 static void UpdateDetromp (TopTools_ListOfShape&           Detromp1, 
167                            TopTools_ListOfShape&           Detromp2, 
168                            const TopTools_SequenceOfShape& Vertices, 
169                            const TColgp_SequenceOfPnt&     Params, 
170                            const Bisector_Bisec&           Bisec,
171                            const Standard_Boolean          SOnE,
172                            const Standard_Boolean          EOnE,
173                            const BRepFill_TrimEdgeTool&    Trim);
174
175 static Standard_Boolean VertexFromNode
176 (const Handle(MAT_Node)&      aNode, 
177  const Standard_Real          Offset,
178  gp_Pnt2d&                    PN,
179  BRepFill_DataMapOfNodeShape& MapNodeVertex,
180  TopoDS_Vertex&               VN);
181
182 static void StoreInMap (const TopoDS_Shape& V1,
183                         const TopoDS_Shape& V2,
184                         TopTools_IndexedDataMapOfShapeShape& MapVV);
185
186 static void TrimEdge (const TopoDS_Edge&              CurrentEdge,
187                       const TopTools_ListOfShape&     D,
188                             TopTools_SequenceOfShape& Sv,  
189                             TColStd_SequenceOfReal&   MapverPar,
190                             TopTools_SequenceOfShape& S,
191                             TopTools_IndexedDataMapOfShapeShape& MapVV);
192
193 static Standard_Boolean DoubleOrNotInside (const TopTools_ListOfShape& EC,
194                                            const TopoDS_Vertex&        V);
195
196 static Standard_Boolean IsSmallClosedEdge(const TopoDS_Edge& anEdge,
197                                           const TopoDS_Vertex& aVertex);
198
199 static void MakeCircle 
200 (const TopoDS_Edge&                          E, 
201  const TopoDS_Vertex&                        V, 
202  const TopoDS_Face&                          F,
203  const Standard_Real                         Offset, 
204  BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
205  const Handle(Geom_Plane)&                   RefPlane);
206
207 static void MakeOffset 
208 (const TopoDS_Edge&                          E,
209  const TopoDS_Face&                          F,
210  const Standard_Real                         Offset, 
211  BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
212  const Handle(Geom_Plane)&                   RefPlane);
213
214 //=======================================================================
215 //function : KPartCircle
216 //purpose  : 
217 //=======================================================================
218
219 static Standard_Boolean KPartCircle
220 (const TopoDS_Face&  mySpine,
221  const Standard_Real myOffset,
222  const Standard_Real Alt,
223  TopoDS_Shape&       myShape, 
224  BRepFill_IndexedDataMapOfOrientedShapeListOfShape& myMap,
225  Standard_Boolean&    myIsDone)
226 {
227   // The only contour which is a closed circle
228   TopExp_Explorer exp(mySpine,TopAbs_EDGE);
229   Standard_Integer NbEdges = 0;
230   TopoDS_Edge      E;
231
232   for (; exp.More(); exp.Next()) {
233     NbEdges++;
234     E = TopoDS::Edge(exp.Current());
235     if (NbEdges > 1) return Standard_False;
236   }
237   TopoDS_Vertex V1,V2;
238   TopExp::Vertices(E,V1,V2);
239   if (!V1.IsSame(V2)) return Standard_False;
240
241   Standard_Real      f,l;
242   TopLoc_Location    L;
243   Handle(Geom_Curve) C =  BRep_Tool::Curve(E,L,f,l);
244
245   if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
246     Handle(Geom_TrimmedCurve) Ct = Handle(Geom_TrimmedCurve)::DownCast(C);
247     C = Ct->BasisCurve();
248   }
249
250   if (!C->IsKind(STANDARD_TYPE(Geom_Circle))) return Standard_False;
251   Handle(Geom_Circle) CE = Handle(Geom_Circle)::DownCast(C);
252   Standard_Real anOffset = myOffset;
253   if (E.Orientation() == TopAbs_REVERSED) anOffset *= -1;
254   
255   if (anOffset < 0. || Abs(anOffset) < CE->Radius()) {
256     Handle(Geom_Circle) OC = new Geom_Circle (CE->Position(),CE->Radius() - anOffset);
257     myShape = BRepLib_MakeEdge(OC,f,l);
258
259     myShape.Orientation(E.Orientation());
260     myShape.Location(L);
261     if (Alt != 0.) {
262       BRepAdaptor_Surface S(mySpine,0);
263       gp_Ax1 Nor = S.Plane().Axis();
264       gp_Trsf T;
265       gp_Vec Trans(Nor.Direction());
266       Trans = Alt*Trans;
267       T.SetTranslation(Trans);
268       myShape.Move(TopLoc_Location(T));
269     }
270     
271     TopTools_ListOfShape LL;
272     LL.Append(myShape);
273     myMap.Add(E,LL);
274   }
275   myIsDone = Standard_True;
276   return Standard_True;
277 }
278
279 //=======================================================================
280 //function : BRepFill_OffsetWire
281 //purpose  : 
282 //=======================================================================
283
284 BRepFill_OffsetWire::BRepFill_OffsetWire() 
285 :myIsDone(Standard_False)
286 {
287 }
288
289
290 //=======================================================================
291 //function : BRepFill_OffsetWire
292 //purpose  : 
293 //=======================================================================
294
295 BRepFill_OffsetWire::BRepFill_OffsetWire(const TopoDS_Face&     Spine,
296                                          const GeomAbs_JoinType Join )
297 {
298   Init(Spine,Join);
299 }
300
301
302 //=======================================================================
303 //function : Init
304 //purpose  : 
305 //=======================================================================
306
307 void BRepFill_OffsetWire::Init(const TopoDS_Face&     Spine,
308                                const GeomAbs_JoinType Join )
309 {
310   Standard_NotImplemented_Raise_if(Join > GeomAbs_Arc,
311                                    "Only GeomAbs_Arc is implemented");
312
313   myIsDone   = Standard_False;
314   TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD);
315   mySpine    = TopoDS::Face(aLocalShape);
316 //  mySpine    = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD));
317   myJoinType = Join;
318
319   myMap.Clear();
320   myMapSpine.Clear();
321   //------------------------------------------------------------------
322   // cut the spine for bissectors.
323   //------------------------------------------------------------------
324 //  Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 Begin
325   static BRepMAT2d_Explorer Exp;
326
327   Exp.Perform(mySpine);
328
329 //  TopoDS_Face anOldSpine = mySpine;
330
331   mySpine = TopoDS::Face(Exp.ModifiedShape(mySpine));
332   PrepareSpine  ();
333
334 //  Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 End
335   TopoDS_Shape aShape;
336   BRepFill_IndexedDataMapOfOrientedShapeListOfShape aMap;
337   Standard_Boolean Done;
338   if (KPartCircle(myWorkSpine,1.,0.,aShape,aMap,Done)) return;
339   
340
341   //-----------------------------------------------------
342   // Calculate the map of bissectors to the left.  
343   // and Links Topology -> base elements of the map.
344   //-----------------------------------------------------
345   
346 //  Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 Begin
347 //   static BRepMAT2d_Explorer Exp;
348 //  Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 End
349   Exp.Perform(myWorkSpine);
350   myBilo.Compute(Exp,1,MAT_Left);
351   myLink.Perform(Exp,myBilo);
352 }
353
354
355 //=======================================================================
356 //function : IsDone
357 //purpose  : 
358 //=======================================================================
359
360 Standard_Boolean BRepFill_OffsetWire::IsDone() const 
361 {
362   return myIsDone;
363 }
364
365
366 //=======================================================================
367 //function : Spine
368 //purpose  : 
369 //=======================================================================
370
371 const TopoDS_Face& BRepFill_OffsetWire::Spine() const 
372 {
373   return mySpine;
374 }
375
376
377 //=======================================================================
378 //function : Shape
379 //purpose  : 
380 //=======================================================================
381
382 const TopoDS_Shape& BRepFill_OffsetWire::Shape() const 
383 {
384   return myShape;
385 }
386
387
388 //=======================================================================
389 //function : GeneratedShapes
390 //purpose  : 
391 //=======================================================================
392
393 const TopTools_ListOfShape& BRepFill_OffsetWire::GeneratedShapes
394 (const TopoDS_Shape& SpineShape)
395 {  
396   if (!myCallGen) {
397     if (!myMapSpine.IsEmpty()) {
398       // myMapSpine can be empty if passed by PerformWithBilo.
399       TopTools_DataMapIteratorOfDataMapOfShapeShape it(myMapSpine);
400       for (; it.More(); it.Next()) {
401         if (myMap.Contains(it.Key())) {
402           if (!myMap.Contains(it.Value())) {
403             TopTools_ListOfShape L;
404             myMap.Add(it.Value(),L);
405           }
406           if ( !it.Value().IsSame(it.Key())) {
407             myMap.ChangeFromKey(it.Value()).Append(myMap.ChangeFromKey(it.Key()));
408             //myMap.UnBind(it.Key());
409             TopoDS_Shape LastShape = myMap.FindKey(myMap.Extent());
410             TopTools_ListOfShape LastList;
411             LastList.Append(myMap(myMap.Extent()));
412             myMap.RemoveLast();
413             if (myMap.FindIndex(it.Key()) != 0)
414               myMap.Substitute(myMap.FindIndex(it.Key()), LastShape, LastList);
415           }
416         }
417         if (myMap.Contains(it.Key().Reversed())) {
418           if (!myMap.Contains(it.Value().Reversed())) {
419             TopTools_ListOfShape L;
420             myMap.Add(it.Value().Reversed(),L);
421           }
422           if ( !it.Value().IsSame(it.Key())) {
423             myMap.ChangeFromKey(it.Value().Reversed()).Append(myMap.ChangeFromKey(it.Key().Reversed()));
424             //myMap.UnBind(it.Key().Reversed());
425             TopoDS_Shape LastShape = myMap.FindKey(myMap.Extent());
426             TopTools_ListOfShape LastList;
427             LastList.Append(myMap(myMap.Extent()));
428             myMap.RemoveLast();
429             if (myMap.FindIndex(it.Key().Reversed()) != 0)
430               myMap.Substitute(myMap.FindIndex(it.Key().Reversed()), LastShape, LastList);
431           }
432         }
433       }
434     }
435     myCallGen = Standard_True;
436   }
437   
438   if (myMap.Contains(SpineShape)) {
439     return myMap.FindFromKey(SpineShape);
440   }
441   else {
442     static TopTools_ListOfShape Empty;
443     return Empty;
444   }
445 }
446
447
448 //=======================================================================
449 //function : JoinType
450 //purpose  : 
451 //=======================================================================
452
453 GeomAbs_JoinType BRepFill_OffsetWire::JoinType() const 
454 {
455   return myJoinType;
456 }
457
458 //=======================================================================
459 //function : Perform
460 //purpose  : 
461 //=======================================================================
462
463 void BRepFill_OffsetWire::Perform (const Standard_Real Offset,
464                                    const Standard_Real Alt)
465 {
466 //  Modified by skv - Fri Jul  8 11:21:38 2005 OCC9145 Begin
467   try {
468     OCC_CATCH_SIGNALS
469     myCallGen = Standard_False;
470     if (KPartCircle(mySpine,Offset,Alt,myShape,myMap,myIsDone)) return;
471
472     TopoDS_Face oldWorkSpain = myWorkSpine;
473
474     TopTools_ListOfShape BadEdges;
475     CheckBadEdges(myWorkSpine,Offset,myBilo,myLink,BadEdges);
476
477     if(!BadEdges.IsEmpty()) {
478       // Modification of myWorkSpine;
479       //cout << "Modification of myWorkSpine : " << BadEdges.Extent() << endl;
480       BRepTools_Substitution aSubst;
481       TopTools_ListIteratorOfListOfShape it(BadEdges);
482       TopTools_ListOfShape aL;
483       Standard_Real aDefl = .01 * Abs(Offset);
484       TColStd_SequenceOfReal Parameters;
485       TColgp_SequenceOfPnt Points;
486
487       for(; it.More(); it.Next()) {
488         aL.Clear();
489         Parameters.Clear();
490         Points.Clear();
491         const TopoDS_Shape& anE = it.Value();
492         TopoDS_Vertex Vf, Vl;
493         TopExp::Vertices(TopoDS::Edge(anE), Vf, Vl);
494
495         Standard_Real f, l;
496         Handle(Geom_Curve) G3d = BRep_Tool::Curve(TopoDS::Edge(anE),f,l);
497         GeomAdaptor_Curve  AC(G3d,f,l);
498
499         Standard_Boolean dummy = PerformCurve(Parameters, Points,
500                                               AC, aDefl, f, l, Precision::Confusion(),
501                                               2);
502
503         Standard_Integer NPnts = Points.Length();
504         if(NPnts > 2) {
505           //cout << NPnts << " points " << endl;
506           TopoDS_Vertex FV = Vf;
507           TopoDS_Vertex LV;
508           TopoDS_Edge newE;
509           Standard_Integer np;
510           for(np = 2; np < NPnts; np++) {
511             gp_Pnt LP = Points(np);
512             LV = BRepLib_MakeVertex(LP);
513             newE = BRepLib_MakeEdge(FV, LV);
514             aL.Append(newE);
515             FV = LV;
516           }
517           LV = Vl;
518           newE = BRepLib_MakeEdge(FV, LV);
519           aL.Append(newE);
520         }
521         else {
522           //cout << " 2 points " << endl;
523           TopoDS_Edge newE = BRepLib_MakeEdge(Vf, Vl);
524           aL.Append(newE);
525         }
526         //Update myMapSpine
527         if (myMapSpine.IsBound( anE ))
528           {
529             TopTools_ListIteratorOfListOfShape newit( aL );
530             for (; newit.More(); newit.Next())
531               {
532                 TopoDS_Edge NewEdge = TopoDS::Edge( newit.Value() );
533                 myMapSpine.Bind( NewEdge, myMapSpine(anE) );
534                 TopoDS_Vertex NewV1, NewV2;
535                 EdgeVertices( NewEdge, NewV1, NewV2 );
536                 if (!myMapSpine.IsBound(NewV1)) myMapSpine.Bind( NewV1, myMapSpine(anE) );
537                 if (!myMapSpine.IsBound(NewV2)) myMapSpine.Bind( NewV2, myMapSpine(anE) );
538               }
539             myMapSpine.UnBind( anE );
540           }
541         ///////////////////
542           aSubst.Substitute(anE, aL);
543       }
544
545       TopTools_DataMapOfShapeListOfShape wwmap;
546       TopoDS_Iterator itws( myWorkSpine );
547       for (; itws.More(); itws.Next())
548         {
549           TopoDS_Shape aWire = itws.Value();
550           aSubst.Build( aWire );
551           if (aSubst.IsCopied(aWire))
552             {
553               TopoDS_Wire NewWire = TopoDS::Wire( aSubst.Copy(aWire).First() );
554               NewWire.Closed( aWire.Closed() );
555               TopTools_ListOfShape Lw;
556               Lw.Append( NewWire );
557               wwmap.Bind( aWire, Lw );
558             }
559         }
560       aSubst.Clear();
561       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itmap( wwmap );
562       for (; itmap.More(); itmap.Next())
563         aSubst.Substitute( itmap.Key(), itmap.Value() );
564       aSubst.Build(myWorkSpine);
565       if(aSubst.IsCopied(myWorkSpine)) {
566         myWorkSpine = TopoDS::Face(aSubst.Copy(myWorkSpine).First());
567         //sprintf(name,"WS1");
568         //DBRep::Set(name,myWorkSpine);
569     
570         BRepMAT2d_Explorer newExp;
571         newExp.Perform(myWorkSpine);
572         BRepMAT2d_BisectingLocus newBilo;
573         BRepMAT2d_LinkTopoBilo newLink;
574         newBilo.Compute(newExp,1,MAT_Left);
575         newLink.Perform(newExp,newBilo);
576         PerformWithBiLo(myWorkSpine,Offset,newBilo,newLink,myJoinType,Alt);
577
578         myWorkSpine = oldWorkSpain;
579       }
580       else {
581         PerformWithBiLo(myWorkSpine,Offset,myBilo,myLink,myJoinType,Alt);
582       }
583     
584     }
585     else {
586       PerformWithBiLo(myWorkSpine,Offset,myBilo,myLink,myJoinType,Alt);
587     }
588
589   } catch (Standard_Failure) {
590     myShape.Nullify();
591     myIsDone = Standard_False;
592
593     return;
594   }
595 //  Modified by skv - Fri Jul  8 11:21:38 2005 OCC9145 End
596 //  Modified by Sergey KHROMOV - Thu Mar 14 10:48:15 2002 Begin
597   TopExp_Explorer anExp(myShape, TopAbs_WIRE);
598
599   for (; anExp.More(); anExp.Next()) {
600     const TopoDS_Shape &aWire = anExp.Current();
601
602     if (!aWire.Closed()) {
603       myShape.Nullify();
604       myIsDone = Standard_False;
605       Standard_ConstructionError::Raise("Offset wire is not closed.");
606     }
607   }
608 //  Modified by Sergey KHROMOV - Thu Mar 14 10:48:16 2002 End
609 }
610
611 //=======================================================================
612 //function : Compute
613 //purpose  : 
614 //=======================================================================
615
616 void Compute (const TopoDS_Face&  Spine,
617                     TopoDS_Shape& aShape,
618                     BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
619               const Standard_Real Alt)
620 {
621   BRep_Builder B;
622   B.MakeCompound(TopoDS::Compound(aShape));
623   Standard_Real ALT = Alt;
624   if ( Spine.Orientation() == TopAbs_REVERSED) ALT = -Alt;
625   gp_Trsf T;
626   T.SetTranslation(gp_Vec(0.,0.,ALT));
627   TopLoc_Location L(T);
628
629   for ( TopExp_Explorer exp(Spine,TopAbs_WIRE); exp.More(); exp.Next()) {
630     const TopoDS_Wire& CurW = TopoDS::Wire(exp.Current());
631     TopoDS_Shape aLocalShape = CurW.Moved(L);
632     TopoDS_Wire        NewW = TopoDS::Wire(aLocalShape);
633 //    TopoDS_Wire        NewW = TopoDS::Wire(CurW.Moved(L));
634     B.Add(aShape,NewW);
635     // update Map.
636     TopoDS_Iterator it1( CurW);
637     TopoDS_Iterator it2( NewW);
638     for ( ; it1.More(); it1.Next(), it2.Next()) {
639       TopTools_ListOfShape List;
640       List.Append(it2.Value());
641       Map.Add(it1.Value(), List);
642     }
643   }
644 }
645
646 //=======================================================================
647 //function : PerformWithBiLo
648 //purpose  : 
649 //=======================================================================
650
651 void BRepFill_OffsetWire::PerformWithBiLo
652 (const TopoDS_Face&              Spine,
653  const Standard_Real             Offset,
654  const BRepMAT2d_BisectingLocus& Locus, 
655        BRepMAT2d_LinkTopoBilo&   Link,
656  const GeomAbs_JoinType          Join,
657  const Standard_Real             Alt)
658 {
659   Standard_NotImplemented_Raise_if (Join > GeomAbs_Arc,
660                                     "Only GeomAbs_Arc is implemented");
661
662   myIsDone     = Standard_False;
663   TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD);
664   myWorkSpine  = TopoDS::Face(aLocalShape);
665 //  myWorkSpine  = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD));
666   myJoinType   = Join;
667   myOffset     = Offset ;
668   myShape.Nullify();
669
670
671   if (mySpine.IsNull()) {
672     TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD);
673     mySpine = TopoDS::Face(aLocalShape);
674 //    mySpine = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD));
675 }
676   myMap.Clear();
677
678   if ( Abs(myOffset) < Precision::Confusion()) {
679     Compute(mySpine,myShape,myMap,Alt);
680     myIsDone = Standard_True;
681     return;
682   }
683
684   //********************************
685   // Calculate for a non null offset 
686   //********************************
687   if (KPartCircle(mySpine,Offset,Alt,myShape,myMap,myIsDone)) return;
688
689   BRep_Builder myBuilder;
690   myBuilder.MakeCompound(TopoDS::Compound(myShape));
691   
692   //---------------------------------------------------------------------
693   // MapNodeVertex : associate to each node of the map (key1) and to
694   //                 each element of the profile (key2) a vertex (item).
695   // MapBis        : all edges or vertices (item) generated by 
696   //                 a bisectrice on a face or an edge (key) of revolution tubes.
697   // MapVerPar     : Map of parameters of vertices on parallel edges 
698   //                 the list contained in MapVerPar (E) corresponds to 
699   //                 parameters on E of vertices contained in MapBis(E);
700   //---------------------------------------------------------------------
701
702
703   BRepFill_DataMapOfNodeShape               MapNodeVertex; 
704   TopTools_DataMapOfShapeSequenceOfShape    MapBis;  
705   BRepFill_DataMapOfShapeSequenceOfReal     MapVerPar;
706
707   TopTools_DataMapOfShapeShape              EmptyMap;
708   TopTools_SequenceOfShape                  EmptySeq;
709   TopTools_ListOfShape                      EmptyList;
710   TColStd_SequenceOfReal                    EmptySeqOfReal;
711
712   Standard_Real ALT = Alt;
713   Handle(Geom_Plane) RefPlane = 
714     Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(myWorkSpine));
715   if ( myWorkSpine.Orientation() == TopAbs_REVERSED) ALT = -Alt;
716   RefPlane = Handle(Geom_Plane)::DownCast
717     (RefPlane->Translated( ALT * gp_Vec(RefPlane->Axis().Direction() )));
718
719   //---------------------------------------------------------------
720   // Construction of Circles and OffsetCurves
721   //---------------------------------------------------------------
722  
723   for (Standard_Integer ic = 1; ic <= Locus.NumberOfContours(); ic++) {
724     TopoDS_Shape PEE = Link.GeneratingShape(Locus.BasicElt(ic,Locus.NumberOfElts(ic)));
725     TopoDS_Shape& PE = PEE ;      
726     for (Standard_Integer ie = 1; ie <= Locus.NumberOfElts(ic); ie++) {
727       const TopoDS_Shape& SE = Link.GeneratingShape(Locus.BasicElt(ic,ie));
728       if (SE.ShapeType() == TopAbs_VERTEX) {
729         MakeCircle (TopoDS::Edge(PE),TopoDS::Vertex(SE),
730                     myWorkSpine,myOffset,myMap,RefPlane);
731       }
732       else {
733         MakeOffset (TopoDS::Edge(SE),myWorkSpine,myOffset,myMap,RefPlane);
734         PE = SE;
735       }
736     }
737   }
738
739
740 #ifdef DEB
741   if (AffichEdge) {
742     cout << " End Construction of geometric primitives "<<endl;
743   }
744 #endif
745
746
747   //---------------------------------------------------
748   // Construction of offset vertices.
749   //---------------------------------------------------
750   BRepFill_DataMapOfOrientedShapeListOfShape Detromp;
751   Handle(MAT_Arc)        CurrentArc;
752   Handle(Geom2d_Curve)   Bis, PCurve1, PCurve2 ;
753   Handle(Geom_Curve)     CBis;
754   Standard_Boolean       Reverse;
755   TopoDS_Edge            CurrentEdge;
756   TopoDS_Shape           S       [2];
757   TopoDS_Edge            E       [2];
758   TopLoc_Location        L;
759   Standard_Integer       j, k;
760
761   for (Standard_Integer i = 1; i <= Locus.Graph()->NumberOfArcs(); i++) {
762
763     CurrentArc           = Locus.Graph()->Arc(i);
764     Bisector_Bisec Bisec = Locus.GeomBis(CurrentArc,Reverse);
765     
766 #ifdef DRAW
767   if ( AffichGeom) {
768     sprintf(name,"BISSEC_%d",NbBISSEC++);
769     DrawTrSurf::Set(name,Bisec.Value());
770   }
771 #endif
772
773     //-------------------------------------------------------------------
774     // Return elements of the spine corresponding to separate basicElts.
775     //-------------------------------------------------------------------
776     S [0] = Link.GeneratingShape(CurrentArc->FirstElement());
777     S [1] = Link.GeneratingShape(CurrentArc->SecondElement());
778
779     TopTools_SequenceOfShape Vertices;
780     TColgp_SequenceOfPnt     Params;
781     
782     TopTools_DataMapOfShapeSequenceOfShape MapSeqVer;
783     BRepFill_DataMapOfShapeSequenceOfPnt   MapSeqPar;
784
785     //-----------------------------------------------------------
786     // Return parallel edges on each face.
787     // If no offset generated => move to the next bissectrice. 
788     //--------------------------------------------------------------
789     if (myMap.Contains(S[0]) && myMap.Contains(S[1])) {
790       E [0] = TopoDS::Edge(myMap.FindFromKey(S[0]).First());
791       E [1] = TopoDS::Edge(myMap.FindFromKey(S[1]).First());
792     }
793     else continue;
794
795     //-----------------------------------------------------------
796     // Construction of vertices corresponding to the node of the map.
797     // if they are on the offset.
798     //-----------------------------------------------------------
799     TopoDS_Vertex VS,VE;
800     Handle(MAT_Node) Node1, Node2;
801
802     if (Reverse) {
803       Node1 = CurrentArc->SecondNode();
804       Node2 = CurrentArc->FirstNode();
805     }
806     else  {
807       Node1 = CurrentArc->FirstNode();
808       Node2 = CurrentArc->SecondNode();
809     }
810     
811     Standard_Boolean StartOnEdge = 0, EndOnEdge = 0;
812     
813     if (!Node1->Infinite()) {
814       gp_Pnt2d aLocalPnt2d = Locus.GeomElt(Node1);
815       StartOnEdge = VertexFromNode(Node1, myOffset, aLocalPnt2d ,MapNodeVertex,VS);
816 //      StartOnEdge = VertexFromNode(Node1, myOffset, Locus.GeomElt(Node1),
817 //                                 MapNodeVertex,VS);
818     }
819     if (!Node2->Infinite()) {
820       gp_Pnt2d aLocalPnt2d = Locus.GeomElt(Node2) ;
821       EndOnEdge   = VertexFromNode(Node2, myOffset, aLocalPnt2d ,MapNodeVertex,VE);
822 //      EndOnEdge   = VertexFromNode(Node2, myOffset, Locus.GeomElt(Node2),
823 //                                 MapNodeVertex,VE);
824     }
825
826     //---------------------------------------------
827     // Construction of geometries.
828     //---------------------------------------------
829     BRepFill_TrimEdgeTool Trim (Bisec, 
830                                 Locus.GeomElt(CurrentArc->FirstElement()),
831                                 Locus.GeomElt(CurrentArc->SecondElement()),
832                                 myOffset);
833
834     //-----------------------------------------------------------
835     // Construction of vertices on edges parallel to the spine.
836     //-----------------------------------------------------------
837
838     Trim.IntersectWith(E [0], E [1], Params);
839
840     for (Standard_Integer s = 1; s <= Params.Length(); s++) {
841       TopoDS_Vertex VC;
842       myBuilder.MakeVertex (VC);
843       gp_Pnt2d P2  = Bisec.Value()->Value(Params.Value(s).X());
844       gp_Pnt   PVC(P2.X(),P2.Y(),0.);
845
846       myBuilder.UpdateVertex(VC,PVC,Precision::Confusion());
847       Vertices.Append(VC);
848     }
849     if (StartOnEdge) {
850       Standard_Boolean Start = 1;
851       Trim.AddOrConfuse(Start, E[0], E[1], Params);
852       if (Params.Length() == Vertices.Length()) 
853          Vertices.SetValue(1,VS);
854       
855       else
856         // the point was not found by IntersectWith
857         Vertices.Prepend(VS);
858     }
859     if (EndOnEdge) {      
860       Standard_Boolean Start = 0;
861       Trim.AddOrConfuse(Start, E[0], E[1], Params);
862       if (Params.Length() == Vertices.Length()) 
863          Vertices.SetValue(Params.Length(),VE);
864       
865       else
866         // the point was not found by IntersectWith
867         Vertices.Append(VE);
868     }
869
870     //------------------------------------------------------------
871     // Update Detromp.
872     // Detromp allows to remove vertices on the offset 
873     // corresponding to tangency zones
874     // Detromp ranks the vertices that limit
875     // the parts of the bissectrices located between the spine and the 
876     // offset.
877     //------------------------------------------------------------
878     if (!Detromp.IsBound(S[0])) Detromp.Bind(S[0],EmptyList);
879     if (!Detromp.IsBound(S[1])) Detromp.Bind(S[1],EmptyList);
880
881     
882     UpdateDetromp (Detromp(S[0]), Detromp(S[1]), Vertices, Params, 
883                    Bisec, StartOnEdge, EndOnEdge, Trim);
884     //----------------------------------------------
885     // Storage of vertices on parallel edges.
886     // fill MapBis and MapVerPar.
887     //----------------------------------------------
888     if (!Vertices.IsEmpty()) {
889       for (k = 0; k <= 1; k++) {
890         if (!MapBis.IsBound(E[k])) {
891           MapBis   .Bind(E[k],EmptySeq);
892           MapVerPar.Bind(E[k],EmptySeqOfReal);
893         } 
894         for (Standard_Integer ii = 1; ii <= Vertices.Length(); ii++) {
895           MapBis (E[k]).Append(Vertices.Value(ii));
896           if (k == 0) MapVerPar (E[k]).Append(Params.Value(ii).Y());
897           else        MapVerPar (E[k]).Append(Params.Value(ii).Z());
898         }
899       }
900     }
901     else {
902       //------------------------------------------------------------
903       // FOR COMPLETE CIRCLES. the parallel line can be contained
904       // in the zone without intersection with the border
905       // no intersection 
906       // if myoffset is < distance of nodes the parallel can be valid.
907       //-------------------------------------------------------------
908       for (k = 0; k <= 1; k++) {
909         if (!MapBis.IsBound(E[k])) {
910           if (Node1->Distance() > myOffset && Node2->Distance() > myOffset) {
911             MapBis   .Bind(E[k],EmptySeq); 
912             MapVerPar.Bind(E[k],EmptySeqOfReal);
913           }
914         }
915       }
916     }
917   }
918   
919 #ifdef DEB 
920   if (AffichEdge) {
921     cout << " End Construction of vertices on offsets"<<endl;
922   }
923 #endif
924
925   //----------------------------------
926   // Construction of parallel edges.
927   //----------------------------------
928   TopTools_IndexedDataMapOfShapeShape MapVV;
929
930   TopoDS_Shape CurrentSpine;
931
932   //BRepFill_DataMapIteratorOfDataMapOfOrientedShapeListOfShape ite1;  
933
934   for (j = 1; j <= myMap.Extent(); j++) {
935     CurrentSpine = myMap.FindKey(j);
936     CurrentEdge  = TopoDS::Edge(myMap(j).First());
937
938     myMap(j).Clear();
939     if (MapBis.IsBound(CurrentEdge)) {
940       TopTools_SequenceOfShape S;
941       if (!MapBis(CurrentEdge).IsEmpty()) {
942         TrimEdge (CurrentEdge,
943                   Detromp  (CurrentSpine),
944                   MapBis   (CurrentEdge) ,  
945                   MapVerPar(CurrentEdge) ,
946                   S, MapVV);
947         for ( k = 1; k <= S.Length(); k++) {
948           myMap(j).Append(S.Value(k));
949         }
950       }
951       else {
952         //-----------------
953         // Complete circles
954         //-----------------
955         myMap(j).Append(CurrentEdge);
956       }
957     }
958   }
959   
960   Standard_Integer ind;
961   for (ind = 1; ind <= MapVV.Extent(); ind++)
962     {
963       TopoDS_Vertex OldV = TopoDS::Vertex(MapVV.FindKey(ind));
964       TopoDS_Vertex NewV = TopoDS::Vertex(MapVV(ind));
965       gp_Pnt P1 = BRep_Tool::Pnt(OldV);
966       gp_Pnt P2 = BRep_Tool::Pnt(NewV);
967       myBuilder.UpdateVertex(NewV, P1.Distance(P2));
968       TopTools_ListOfShape LV;
969       LV.Append( NewV.Oriented(TopAbs_FORWARD) );
970       BRepTools_Substitution aSubst;
971       aSubst.Substitute( OldV, LV );
972       for (j = 1; j <= myMap.Extent(); j++)
973         {
974           TopTools_ListIteratorOfListOfShape itl(myMap(j));
975           for (; itl.More(); itl.Next())
976             {
977               aSubst.Build(itl.Value());
978               if (aSubst.IsCopied(itl.Value()))
979                 {
980                   const TopTools_ListOfShape& listSh = aSubst.Copy(itl.Value());
981                   TopAbs_Orientation SaveOr = itl.Value().Orientation();
982                   itl.Value() = listSh.First();
983                   itl.Value().Orientation(SaveOr);
984                 }
985             }
986         }
987     }
988       
989   //----------------------------------
990   // Construction of offset wires.
991   //----------------------------------
992   MakeWires ();
993
994   // Update vertices ( Constructed in the plane Z = 0) !!!
995   TopTools_MapOfShape MapVertex;
996   for ( TopExp_Explorer exp(myShape,TopAbs_VERTEX); exp.More(); exp.Next()) {
997     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
998     if ( MapVertex.Add(V)) {
999       gp_Pnt        P = BRep_Tool::Pnt(V);
1000       P = RefPlane->Value(P.X(),P.Y());
1001       myBuilder.UpdateVertex(V,P, Precision::Confusion());
1002     }
1003   }
1004
1005   // Construction of curves 3d.
1006   BRepLib::BuildCurves3d(myShape);
1007   MapVertex.Clear();
1008   TopExp_Explorer Explo( myShape, TopAbs_EDGE );
1009   for (; Explo.More(); Explo.Next())
1010     {
1011       TopoDS_Edge E = TopoDS::Edge( Explo.Current() );
1012       TopoDS_Vertex V1, V2;
1013       TopExp::Vertices( E, V1, V2 );
1014       Handle(BRep_TVertex)& TV1 = *((Handle(BRep_TVertex)*) &(V1).TShape());
1015       Handle(BRep_TVertex)& TV2 = *((Handle(BRep_TVertex)*) &(V2).TShape());
1016       
1017       TopLoc_Location loc;
1018       Standard_Real f, l;
1019       Handle( Geom_Curve ) theCurve = BRep_Tool::Curve( E, loc, f, l );
1020       theCurve = Handle( Geom_Curve )::DownCast( theCurve->Copy() );
1021       theCurve->Transform( loc.Transformation() );
1022       gp_Pnt f3d = theCurve->Value( f );
1023       gp_Pnt l3d = theCurve->Value( l );
1024
1025       Standard_Real dist1, dist2;
1026       dist1 = f3d.Distance( TV1->Pnt() );
1027       dist2 = l3d.Distance( TV2->Pnt() );
1028       if (! MapVertex.Contains( V1 ))
1029         {
1030           TV1->Pnt( f3d );
1031           MapVertex.Add( V1 );
1032         }
1033       else
1034         TV1->UpdateTolerance( 1.5*dist1 );
1035       if (! MapVertex.Contains( V2 ))
1036         {
1037           TV2->Pnt( l3d );
1038           MapVertex.Add( V2 );
1039         }
1040       else
1041         TV2->UpdateTolerance( 1.5*dist2 );
1042     }
1043
1044   FixHoles();
1045
1046   myIsDone = Standard_True;
1047 }
1048
1049
1050 //=======================================================================
1051 //function : Generated
1052 //purpose  : 
1053 //=======================================================================
1054
1055 BRepFill_IndexedDataMapOfOrientedShapeListOfShape& 
1056 BRepFill_OffsetWire::Generated() 
1057 {
1058   return myMap;
1059 }
1060
1061
1062 //=======================================================================
1063 //function : PrepareSpine
1064 //purpose  : 
1065 //=======================================================================
1066
1067 void BRepFill_OffsetWire::PrepareSpine()
1068 {
1069   BRep_Builder      B;
1070   TopTools_ListOfShape Cuts;
1071   TopTools_ListIteratorOfListOfShape IteCuts;
1072   TopoDS_Vertex V1,V2;
1073
1074   myWorkSpine.Nullify();
1075   myMapSpine.Clear();
1076
1077   TopLoc_Location L;
1078   const Handle(Geom_Surface)& S    = BRep_Tool::Surface  (mySpine,L);
1079   Standard_Real               TolF = BRep_Tool::Tolerance(mySpine);
1080   B.MakeFace(myWorkSpine,S,L,TolF);
1081   
1082   for (TopoDS_Iterator IteF(mySpine) ; IteF.More(); IteF.Next()) {
1083
1084     TopoDS_Wire NW;
1085     B.MakeWire (NW);
1086
1087 //  Modified by Sergey KHROMOV - Thu Nov 16 17:29:55 2000 Begin
1088     Standard_Integer ForcedCut = 0;
1089     Standard_Integer nbResEdges = -1;
1090     TopTools_IndexedMapOfShape EdgeMap;
1091
1092     TopExp::MapShapes(IteF.Value(), TopAbs_EDGE, EdgeMap);
1093     Standard_Integer nbEdges = EdgeMap.Extent();
1094     
1095     if (nbEdges == 1)
1096       ForcedCut = 2;
1097 //  Modified by Sergey KHROMOV - Thu Nov 16 17:29:48 2000 End
1098
1099     for (TopoDS_Iterator IteW(IteF.Value()); IteW.More(); IteW.Next()) {
1100       
1101       const TopoDS_Edge& E = TopoDS::Edge(IteW.Value());
1102       EdgeVertices(E,V1,V2);
1103       myMapSpine.Bind(V1,V1);
1104       myMapSpine.Bind(V2,V2);
1105       Cuts.Clear();
1106
1107       // Cut
1108       TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
1109 //  Modified by Sergey KHROMOV - Thu Nov 16 17:29:29 2000 Begin
1110       if (nbEdges == 2 && nbResEdges == 0)
1111         ForcedCut = 1;
1112 //  Modified by Sergey KHROMOV - Thu Nov 16 17:29:33 2000 End
1113       nbResEdges = CutEdge (TopoDS::Edge(aLocalShape), mySpine, ForcedCut, Cuts);
1114       
1115       if (Cuts.IsEmpty()) {
1116         B.Add(NW,E);
1117         myMapSpine.Bind(E,E);
1118       }
1119       else {    
1120         for (IteCuts.Initialize(Cuts); IteCuts.More(); IteCuts.Next()) {
1121           TopoDS_Edge NE = TopoDS::Edge(IteCuts.Value());
1122           NE.Orientation(E.Orientation());
1123           B.Add(NW,NE);
1124           myMapSpine.Bind(NE,E);
1125           EdgeVertices(NE,V1,V2);
1126           if (!myMapSpine.IsBound(V1)) myMapSpine.Bind(V1,E);
1127           if (!myMapSpine.IsBound(V2)) myMapSpine.Bind(V2,E);
1128         }
1129       }
1130     }
1131 //  Modified by Sergey KHROMOV - Thu Mar  7 09:17:41 2002 Begin
1132     TopoDS_Vertex aV1;
1133     TopoDS_Vertex aV2;
1134
1135     TopExp::Vertices(NW, aV1, aV2);
1136
1137     NW.Closed(aV1.IsSame(aV2));
1138 //  Modified by Sergey KHROMOV - Thu Mar  7 09:17:43 2002 End
1139     B.Add(myWorkSpine, NW);
1140   }
1141
1142 #ifdef DRAW
1143   if ( AffichEdge) {
1144     sprintf(name,"WS");
1145     DBRep::Set(name,myWorkSpine);
1146   }
1147 #endif
1148
1149 }
1150
1151 //=======================================================================
1152 //function : MakeWires
1153 //purpose  : 
1154 //=======================================================================
1155
1156 void BRepFill_OffsetWire::MakeWires()
1157 {
1158   //--------------------------------------------------------
1159   // creation of a single list of created parallel edges.
1160   //--------------------------------------------------------
1161   TopTools_SequenceOfShape TheEdges;
1162   TopTools_ListOfShape     TheWires;
1163   TopTools_ListIteratorOfListOfShape                          itl;
1164   //BRepFill_DataMapIteratorOfDataMapOfOrientedShapeListOfShape ite;  
1165   TopTools_IndexedDataMapOfShapeListOfShape                   MVE;
1166   //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape         MVEit;
1167   TopoDS_Vertex V1,V2,VF,CV;
1168   Standard_Integer i;
1169
1170   for (i = 1; i <= myMap.Extent(); i++) {    
1171     for (itl.Initialize(myMap(i)); itl.More(); itl.Next()) {
1172       const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
1173       TopExp::Vertices (E,V1,V2);
1174       if (V1.IsSame(V2) && IsSmallClosedEdge(E, V1))
1175         continue; //remove small closed edges
1176       if (!MVE.Contains(V1)) {
1177         TopTools_ListOfShape empty;
1178         MVE.Add(V1,empty);
1179       }
1180       MVE.ChangeFromKey(V1).Append(E);
1181       if (!MVE.Contains(V2)) {
1182         TopTools_ListOfShape empty;
1183         MVE.Add(V2,empty);
1184       }
1185       MVE.ChangeFromKey(V2).Append(E);
1186     }
1187   }
1188
1189   //--------------------------------------
1190   // Creation of parallel wires.
1191   //--------------------------------------
1192   BRep_Builder B;
1193
1194 //  Standard_Integer NbEdges;
1195 //  Standard_Boolean NewWire  = Standard_True;
1196 //  Standard_Boolean AddEdge  = Standard_False;
1197
1198   TopoDS_Wire      NW;
1199   Standard_Boolean End;
1200   TopoDS_Edge CE;
1201
1202   while (!MVE.IsEmpty()) {
1203     B.MakeWire(NW);
1204
1205     //MVEit.Initialize(MVE);
1206     for (i = 1; i <= MVE.Extent(); i++)
1207       if(MVE(i).Extent() == 1)
1208         break;
1209
1210     //if(!MVEit.More()) MVEit.Initialize(MVE);
1211     if (i > MVE.Extent())
1212       i = 1;
1213     
1214     CV  = VF = TopoDS::Vertex(MVE.FindKey(i));
1215     CE  = TopoDS::Edge(MVE(i).First());
1216     End = Standard_False;
1217     MVE.ChangeFromKey(CV).RemoveFirst(); 
1218
1219 //  Modified by Sergey KHROMOV - Thu Mar 14 11:29:59 2002 Begin
1220     Standard_Boolean isClosed = Standard_False;
1221 //  Modified by Sergey KHROMOV - Thu Mar 14 11:30:00 2002 End
1222
1223     while(!End) {      
1224       //-------------------------------
1225       // Construction of a wire.
1226       //-------------------------------
1227       TopExp::Vertices(CE,V1,V2);
1228       if (!CV.IsSame(V1)) CV = V1; else CV = V2;
1229
1230       B.Add (NW,CE);
1231
1232       if (VF.IsSame(CV) || !MVE.Contains(CV)) {
1233 //  Modified by Sergey KHROMOV - Thu Mar 14 11:30:14 2002 Begin
1234         isClosed = VF.IsSame(CV);
1235 //  Modified by Sergey KHROMOV - Thu Mar 14 11:30:15 2002 End
1236         End = Standard_True;
1237         //MVE.UnBind(VF);
1238         TopoDS_Shape LastShape = MVE.FindKey(MVE.Extent());
1239         TopTools_ListOfShape LastList;
1240         LastList.Append(MVE(MVE.Extent()));
1241         MVE.RemoveLast();
1242         if (MVE.FindIndex(VF) != 0)
1243           MVE.Substitute(MVE.FindIndex(VF), LastShape, LastList);
1244       }
1245
1246       if (!End) {
1247         if (MVE.FindFromKey(CV).Extent() > 2) {
1248           //cout <<"vertex on more that 2 edges in a face."<<endl;
1249         }
1250         for ( itl.Initialize(MVE.FindFromKey(CV)); itl.More(); itl.Next()) {
1251           if (itl.Value().IsSame(CE)) {
1252             MVE.ChangeFromKey(CV).Remove(itl);
1253             break;
1254           }
1255         }
1256         if (!MVE.FindFromKey(CV).IsEmpty()) {
1257           CE = TopoDS::Edge(MVE.FindFromKey(CV).First());
1258           MVE.ChangeFromKey(CV).RemoveFirst();
1259         }
1260         if (MVE.FindFromKey(CV).IsEmpty())
1261         {
1262           //MVE.UnBind(CV);
1263           TopoDS_Shape LastShape = MVE.FindKey(MVE.Extent());
1264           TopTools_ListOfShape LastList;
1265           LastList.Append(MVE(MVE.Extent()));
1266           MVE.RemoveLast();
1267           if (MVE.FindIndex(CV) != 0)
1268             MVE.Substitute(MVE.FindIndex(CV), LastShape, LastList);
1269         }
1270       }
1271     }
1272 //  Modified by Sergey KHROMOV - Thu Mar 14 11:29:31 2002 Begin
1273 //     NW.Closed(Standard_True);
1274     NW.Closed(isClosed);
1275 //  Modified by Sergey KHROMOV - Thu Mar 14 11:29:37 2002 End
1276     TheWires.Append(NW);
1277   }
1278
1279   // update myShape :
1280   //      -- if only one wire : myShape is a Wire
1281   //      -- if several wires : myShape is a Compound.
1282   if ( TheWires.Extent() == 1) {
1283     myShape = TheWires.First();
1284   }
1285   else {
1286     TopoDS_Compound R;
1287     B.MakeCompound(R);
1288     TopTools_ListIteratorOfListOfShape it(TheWires);
1289     for ( ; it.More(); it.Next()) {
1290       B.Add(R, it.Value());
1291     }
1292     myShape = R;
1293   }
1294   
1295 }
1296
1297 //=======================================================================
1298 //function : FixHoles
1299 //purpose  : 
1300 //=======================================================================
1301
1302 void BRepFill_OffsetWire::FixHoles()
1303 {
1304   TopTools_SequenceOfShape ClosedWires, UnclosedWires, IsolatedWires;
1305
1306   Standard_Real MaxTol = 0.;
1307   Standard_Integer i;
1308   BRep_Builder BB;
1309
1310   TopExp_Explorer Explo( mySpine, TopAbs_VERTEX );
1311   for (; Explo.More(); Explo.Next())
1312     {
1313       const TopoDS_Vertex& aVertex = TopoDS::Vertex( Explo.Current() );
1314       Standard_Real Tol = BRep_Tool::Tolerance(aVertex);
1315       if (Tol > MaxTol)
1316         MaxTol = Tol;
1317     }
1318   MaxTol *= 100.;
1319
1320   Explo.Init( myShape, TopAbs_WIRE );
1321   for (; Explo.More(); Explo.Next())
1322     {
1323       TopoDS_Shape aWire = Explo.Current();
1324       // Remove duplicated edges
1325       TopTools_DataMapOfShapeListOfShape EEmap;
1326       TopoDS_Iterator it( aWire );
1327       for (; it.More(); it.Next())
1328         {
1329           const TopoDS_Shape& anEdge = it.Value();
1330           if (! EEmap.IsBound( anEdge ))
1331             {
1332               TopTools_ListOfShape LE;
1333               EEmap.Bind( anEdge, LE );
1334             }
1335           else
1336             EEmap(anEdge).Append( anEdge );
1337         }
1338       aWire.Free( Standard_True );
1339       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape mapit( EEmap );
1340       for (; mapit.More(); mapit.Next())
1341         {
1342           const TopTools_ListOfShape& LE = mapit.Value();
1343           TopTools_ListIteratorOfListOfShape itl( LE );
1344           for (; itl.More(); itl.Next())
1345             BB.Remove( aWire, itl.Value() );
1346         }
1347       // Sorting
1348       if (aWire.Closed())
1349         ClosedWires.Append( aWire );
1350       else
1351         UnclosedWires.Append( aWire );
1352     }
1353   
1354   while (!UnclosedWires.IsEmpty())
1355     {
1356       TopoDS_Wire& Base = TopoDS::Wire( UnclosedWires(1) );
1357       TopoDS_Vertex Vf, Vl;
1358       TopExp::Vertices( Base, Vf, Vl );
1359       gp_Pnt Pf, Pl;
1360       Pf = BRep_Tool::Pnt(Vf);
1361       Pl = BRep_Tool::Pnt(Vl);
1362       Standard_Real DistF = RealLast(), DistL = RealLast();
1363       Standard_Integer IndexF, IndexL;
1364       Standard_Boolean IsFirstF, IsFirstL;
1365       for (Standard_Integer i = 2; i <= UnclosedWires.Length(); i++)
1366         {
1367           TopoDS_Wire aWire = TopoDS::Wire( UnclosedWires(i) );
1368           TopoDS_Vertex V1, V2;
1369           TopExp::Vertices( aWire, V1, V2 );
1370           gp_Pnt P1, P2;
1371           P1 = BRep_Tool::Pnt(V1);
1372           P2 = BRep_Tool::Pnt(V2);
1373           Standard_Real dist = Pf.Distance( P1 );
1374           if (dist < DistF)
1375             {
1376               DistF = dist;
1377               IndexF = i;
1378               IsFirstF = Standard_True;
1379             }
1380           dist = Pf.Distance( P2 );
1381           if (dist < DistF)
1382             {
1383               DistF = dist;
1384               IndexF = i;
1385               IsFirstF = Standard_False;
1386             }
1387           dist = Pl.Distance( P1 );
1388           if (dist < DistL)
1389             {
1390               DistL = dist;
1391               IndexL = i;
1392               IsFirstL = Standard_True;
1393             }
1394           dist = Pl.Distance( P2 );
1395           if (dist < DistL)
1396             {
1397               DistL = dist;
1398               IndexL = i;
1399               IsFirstL = Standard_False;
1400             }
1401         }
1402       TopoDS_Wire theWire;
1403       TopoDS_Edge theEdge;
1404       TopoDS_Vertex theVertex;
1405       Standard_Real CommonTol;
1406       Standard_Boolean TryToClose = Standard_True;
1407       if (DistF <= MaxTol && DistL <= MaxTol && IndexF == IndexL && IsFirstF == IsFirstL)
1408         {
1409           if (DistF < DistL)
1410             {
1411               DistL = RealLast();
1412               IndexL++;
1413             }
1414           else
1415             {
1416               DistF = RealLast();
1417               IndexF++;
1418             }
1419           TryToClose = Standard_False;
1420         }
1421       if (DistF <= MaxTol)
1422         {
1423           theWire = TopoDS::Wire( UnclosedWires(IndexF) );
1424           TopoDS_Vertex V1, V2;
1425           TopExp::Vertices( theWire, V1, V2 );
1426           TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1427           TopExp::MapShapesAndAncestors( theWire, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
1428           theEdge = (IsFirstF)? TopoDS::Edge(VEmap.FindFromKey( V1 ).First()) :
1429             TopoDS::Edge(VEmap.FindFromKey( V2 ).First());
1430           TopoDS_Iterator it( theWire );
1431           for (; it.More(); it.Next())
1432             {
1433               TopoDS_Edge anEdge = TopoDS::Edge( it.Value() );
1434               if (IsFirstF) anEdge.Reverse();
1435               if (!anEdge.IsSame( theEdge ))
1436                 BB.Add( Base, anEdge );
1437             }
1438           theVertex = (IsFirstF)? V1 : V2;
1439           CommonTol = Max( BRep_Tool::Tolerance(Vf), BRep_Tool::Tolerance(theVertex) );
1440           if (DistF <= CommonTol)
1441             {
1442               theEdge.Free( Standard_True );
1443               Vf.Orientation( theVertex.Orientation() );
1444               BB.Remove( theEdge, theVertex );
1445               BB.Add( theEdge, Vf );
1446               BB.UpdateVertex( Vf, CommonTol );
1447               if (IsFirstF) theEdge.Reverse();
1448               BB.Add( Base, theEdge );
1449             }
1450           else
1451             {
1452               if (IsFirstF) theEdge.Reverse();
1453               BB.Add( Base, theEdge );
1454               // Creating new edge from theVertex to Vf
1455               TopoDS_Edge NewEdge = BRepLib_MakeEdge( theVertex, Vf );
1456               BB.Add( Base, NewEdge );
1457             }
1458         }
1459       if (DistL <= MaxTol && IndexL != IndexF)
1460         {
1461           theWire = TopoDS::Wire( UnclosedWires(IndexL) );
1462           TopoDS_Vertex V1, V2;
1463           TopExp::Vertices( theWire, V1, V2 );
1464           TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1465           TopExp::MapShapesAndAncestors( theWire, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
1466           theEdge = (IsFirstL)? TopoDS::Edge(VEmap.FindFromKey( V1 ).First()) :
1467             TopoDS::Edge(VEmap.FindFromKey( V2 ).First());
1468           TopoDS_Iterator it( theWire );
1469           for (; it.More(); it.Next())
1470             {
1471               TopoDS_Edge anEdge = TopoDS::Edge( it.Value() );
1472               if (!IsFirstL) anEdge.Reverse();
1473               if (!anEdge.IsSame( theEdge ))
1474                 BB.Add( Base, anEdge );
1475             }
1476           theVertex = (IsFirstL)? V1 : V2;
1477           CommonTol = Max( BRep_Tool::Tolerance(Vl), BRep_Tool::Tolerance(theVertex) );
1478           if (DistL <= CommonTol)
1479             {
1480               theEdge.Free( Standard_True );
1481               Vl.Orientation( theVertex.Orientation() );
1482               BB.Remove( theEdge, theVertex );
1483               BB.Add( theEdge, Vl );
1484               BB.UpdateVertex( Vl, CommonTol );
1485               if (!IsFirstL) theEdge.Reverse();
1486               BB.Add( Base, theEdge );
1487             }
1488           else
1489             {
1490               if (!IsFirstL) theEdge.Reverse();
1491               BB.Add( Base, theEdge );
1492               // Creating new edge from Vl to theVertex
1493               TopoDS_Edge NewEdge = BRepLib_MakeEdge( Vl, theVertex );
1494               BB.Add( Base, NewEdge );
1495             }
1496         }
1497       // Check if it is possible to close resulting wire
1498       if (TryToClose)
1499         {
1500           TopExp::Vertices( Base, Vf, Vl );
1501           CommonTol = Max( BRep_Tool::Tolerance(Vf), BRep_Tool::Tolerance(Vl) );
1502           TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1503           TopExp::MapShapesAndAncestors( Base, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
1504           TopoDS_Edge Efirst, Elast;
1505           Efirst = TopoDS::Edge(VEmap.FindFromKey( Vf ).First());
1506           Elast  = TopoDS::Edge(VEmap.FindFromKey( Vl ).First());
1507           Pf = BRep_Tool::Pnt(Vf);
1508           Pl = BRep_Tool::Pnt(Vl);
1509           Standard_Real Dist = Pf.Distance(Pl);
1510           if (Dist <= CommonTol)
1511             {
1512               Elast.Free( Standard_True );
1513               Vf.Orientation( Vl.Orientation() );
1514               BB.Remove( Elast, Vl );
1515               BB.Add( Elast, Vf );
1516               BB.UpdateVertex( Vf, CommonTol );
1517               Base.Closed( Standard_True );
1518             }
1519           else if (Dist <= MaxTol)
1520             {
1521               // Creating new edge from Vl to Vf
1522               TopoDS_Edge NewEdge = BRepLib_MakeEdge( Vf, Vl );
1523               BB.Add( Base, NewEdge );
1524               Base.Closed( Standard_True );
1525             }
1526         }
1527       // Updating sequences ClosedWires and UnclosedWires
1528       if (DistF <= MaxTol)
1529         UnclosedWires.Remove( IndexF );
1530       if (DistL <= MaxTol && IndexL != IndexF)
1531         {
1532           if (DistF <= MaxTol && IndexL > IndexF)
1533             IndexL--;
1534           UnclosedWires.Remove( IndexL );
1535         }
1536       if (Base.Closed())
1537         {
1538           ClosedWires.Append( Base );
1539           UnclosedWires.Remove( 1 );
1540         }
1541       else if (DistF > MaxTol && DistL > MaxTol)
1542         {
1543           IsolatedWires.Append( Base );
1544           UnclosedWires.Remove( 1 );
1545         }
1546     }
1547
1548   // Updating myShape
1549   if (ClosedWires.Length() + IsolatedWires.Length() == 1)
1550     {
1551       if (!ClosedWires.IsEmpty())
1552         myShape = ClosedWires.First();
1553       else
1554         myShape = IsolatedWires.First();
1555     }
1556   else
1557     {
1558       TopoDS_Compound R;
1559       BB.MakeCompound( R );
1560       for (i = 1; i <= ClosedWires.Length(); i++)
1561         BB.Add( R, ClosedWires(i) );
1562       for (i = 1; i <= IsolatedWires.Length(); i++)
1563         BB.Add( R, IsolatedWires(i) );
1564       myShape = R;
1565     }
1566 }
1567
1568 //=======================================================================
1569 //function : CutEdge
1570 //purpose  : Cut edge at the extrema of curvatures and points of inflexion.
1571 //           So, closed circles are cut in two.
1572 //           If <Cuts> is empty, the edge is not modified.
1573 //           The first and the last vertex of the initial edge 
1574 //           belong to the first and the last parts respectively.
1575 //=======================================================================
1576 Standard_Integer CutEdge (const TopoDS_Edge& E, 
1577                           const TopoDS_Face& F,
1578                                 Standard_Integer ForceCut,
1579                                 TopTools_ListOfShape& Cuts)
1580 {
1581   Cuts.Clear();
1582   MAT2d_CutCurve              Cuter;
1583   TColGeom2d_SequenceOfCurve  theCurves;
1584   Standard_Real               f,l;
1585   Handle(Geom2d_Curve)        C2d;
1586   Handle(Geom2d_TrimmedCurve) CT2d;
1587 //  Modified by Sergey KHROMOV - Wed Mar  6 17:36:25 2002 Begin
1588   Standard_Real               aTol = BRep_Tool::Tolerance(E);
1589   Handle(Geom_Curve)          aC;
1590 //  Modified by Sergey KHROMOV - Wed Mar  6 17:36:25 2002 End
1591   
1592   TopoDS_Vertex V1,V2,VF,VL;
1593   TopExp::Vertices (E,V1,V2);
1594   BRep_Builder B;
1595   
1596   C2d  = BRep_Tool::CurveOnSurface (E,F,f,l);
1597 //  Modified by Sergey KHROMOV - Wed Mar  6 17:36:54 2002 Begin
1598   aC   = BRep_Tool::Curve(E,f,l);
1599 //  Modified by Sergey KHROMOV - Wed Mar  6 17:36:54 2002 End
1600   CT2d = new Geom2d_TrimmedCurve(C2d,f,l);
1601   //if (E.Orientation() == TopAbs_REVERSED) CT2d->Reverse();
1602
1603   if (CT2d->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Circle)) &&
1604       ( Abs(f-l) >= PI) ) {
1605     return 0;
1606     //---------------------------
1607     // Cut closed circle.
1608     //---------------------------
1609     Standard_Real m = (f + l)*0.5;
1610 //  Modified by Sergey KHROMOV - Wed Mar  6 17:37:28 2002 Begin
1611     gp_Pnt        P = aC->Value(m);
1612
1613     VL = BRepLib_MakeVertex(P);
1614     B.UpdateVertex(VL, aTol);
1615 //  Modified by Sergey KHROMOV - Wed Mar  6 17:37:30 2002 End
1616     TopoDS_Shape aLocalShape = E.EmptyCopied();
1617     TopoDS_Edge FE = TopoDS::Edge(aLocalShape);  
1618     TopoDS_Edge LE = TopoDS::Edge(aLocalShape);  
1619 //    TopoDS_Edge FE = TopoDS::Edge(E.EmptyCopied());    
1620 //    TopoDS_Edge LE = TopoDS::Edge(E.EmptyCopied());
1621     FE.Orientation(TopAbs_FORWARD);
1622     LE.Orientation(TopAbs_FORWARD);
1623     B.Add  (FE,V1);
1624     B.Add  (FE,VL.Oriented(TopAbs_REVERSED));
1625     B.Range(FE, f, m);    
1626     B.Add  (LE,V2);
1627     B.Add  (LE,VL.Oriented(TopAbs_FORWARD));
1628     B.Range(LE, m, l);
1629     Cuts.Append(FE.Oriented(E.Orientation()));
1630     Cuts.Append(LE.Oriented(E.Orientation()));
1631     //--------
1632     // Return.
1633     //--------
1634     return 2;
1635   }
1636
1637   //-------------------------
1638   // Cut curve.
1639   //-------------------------
1640   Cuter.Perform(CT2d);
1641
1642 //  Modified by Sergey KHROMOV - Thu Nov 16 17:28:29 2000 Begin
1643   if (ForceCut == 0) {
1644     if (Cuter.UnModified()) {
1645     //-----------------------------
1646     // edge not modified => return.
1647     //-----------------------------
1648       return 0;
1649     } else {
1650       for (Standard_Integer k = 1; k <= Cuter.NbCurves(); k++)
1651         theCurves.Append(Cuter.Value(k));
1652     }
1653   } else if (ForceCut == 1) {
1654     if (Cuter.UnModified()) {
1655       CutCurve (CT2d, 2, theCurves);
1656     } else {
1657       for (Standard_Integer k = 1; k <= Cuter.NbCurves(); k++)
1658         theCurves.Append(Cuter.Value(k));
1659     }
1660   } else if (ForceCut == 2) {
1661     if (Cuter.UnModified()) {
1662       CutCurve (CT2d, 3, theCurves);
1663     } else {
1664       if (Cuter.NbCurves() == 2) {
1665         Handle(Geom2d_TrimmedCurve)CC = Cuter.Value(1);
1666
1667         if (CC->LastParameter() > (l+f)/2.) {
1668           CutCurve (CC, 2, theCurves);
1669           theCurves.Append(Cuter.Value(2));
1670         } else {
1671           theCurves.Append(CC);
1672           CutCurve (Cuter.Value(2), 2, theCurves);
1673         }
1674       } else {
1675         for (Standard_Integer k = 1; k <= Cuter.NbCurves(); k++)
1676           theCurves.Append(Cuter.Value(k));
1677       }
1678     }
1679   }
1680 //  Modified by Sergey KHROMOV - Thu Nov 16 17:28:37 2000 End
1681
1682   //--------------------------------------
1683   // Creation of cut edges.
1684   //--------------------------------------
1685   VF = V1;
1686
1687   for (Standard_Integer k = 1; k <= theCurves.Length(); k++) {
1688
1689     Handle(Geom2d_TrimmedCurve)CC = Handle(Geom2d_TrimmedCurve)::DownCast(theCurves.Value(k));
1690
1691     if (k == theCurves.Length()) {VL = V2;}
1692     else { 
1693 //  Modified by Sergey KHROMOV - Wed Mar  6 17:38:02 2002 Begin
1694       gp_Pnt        P = aC->Value(CC->LastParameter());
1695
1696       VL = BRepLib_MakeVertex(P);
1697       B.UpdateVertex(VL, aTol);
1698 //  Modified by Sergey KHROMOV - Wed Mar  6 17:38:05 2002 End
1699     }
1700     TopoDS_Shape aLocalShape = E.EmptyCopied();
1701     TopoDS_Edge NE = TopoDS::Edge(aLocalShape);
1702 //      TopoDS_Edge NE = TopoDS::Edge(E.EmptyCopied());
1703     NE.Orientation(TopAbs_FORWARD);
1704     B.Add  (NE,VF.Oriented(TopAbs_FORWARD));
1705     B.Add  (NE,VL.Oriented(TopAbs_REVERSED));      
1706     B.Range(NE,CC->FirstParameter(),CC->LastParameter());
1707     Cuts.Append(NE.Oriented(E.Orientation()));
1708     VF = VL;
1709   }
1710
1711   return theCurves.Length();
1712 }
1713
1714 //  Modified by Sergey KHROMOV - Thu Nov 16 17:27:56 2000 Begin
1715 //=======================================================================
1716 //function : CutCurve
1717 //purpose  : 
1718 //=======================================================================
1719
1720 void CutCurve (const Handle(Geom2d_TrimmedCurve)& C,
1721                const Standard_Integer nbParts,
1722                      TColGeom2d_SequenceOfCurve& theCurves)
1723 {
1724   Handle(Geom2d_TrimmedCurve) TrimC;
1725   Standard_Real               UF,UL,UC;
1726   Standard_Real               Step;
1727   gp_Pnt2d                    PF,PL,PC;
1728   Standard_Real               PTol  = Precision::PConfusion()*10;
1729   Standard_Real               Tol   = Precision::Confusion()*10;
1730   Standard_Boolean            YaCut = Standard_False;
1731
1732   UF = C->FirstParameter();
1733   UL = C->LastParameter ();
1734   PF = C->Value(UF);
1735   PL = C->Value(UL);
1736
1737   Step = (UL - UF)/nbParts;
1738
1739   for (Standard_Integer i = 1; i < nbParts; i++) {
1740
1741     UC = UF + i*Step;
1742     PC = C->Value(UC);
1743
1744     if (UC - UF > PTol && PC.Distance(PF) > Tol) {
1745       if ( UL - UC < PTol || PL.Distance(PC) < Tol)
1746         continue;
1747
1748       TrimC = new Geom2d_TrimmedCurve(C,UF,UC);
1749       theCurves.Append(TrimC);
1750       UF = UC;
1751       PF = PC;
1752       YaCut = Standard_True;
1753     }
1754   }
1755   if (YaCut) {
1756     TrimC = new Geom2d_TrimmedCurve(C,UF,UL);
1757     theCurves.Append(TrimC);
1758   } else
1759     theCurves.Append(C);
1760 }
1761 //  Modified by Sergey KHROMOV - Thu Nov 16 17:28:13 2000 End
1762
1763 //=======================================================================
1764 //function : MakeCircle
1765 //purpose  : 
1766 //=======================================================================
1767
1768 void MakeCircle (const TopoDS_Edge&          E,
1769                  const TopoDS_Vertex&        V,
1770                  const TopoDS_Face&          F,
1771                  const Standard_Real         Offset, 
1772                        BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
1773                  const Handle(Geom_Plane)&   RefPlane)
1774 {
1775   // evaluate the Axis of the Circle.
1776   Standard_Real f,l;
1777   Handle(Geom2d_Curve) GC = BRep_Tool::CurveOnSurface(E,F,f,l);
1778   gp_Vec2d DX;
1779   gp_Pnt2d P;
1780
1781   if (E.Orientation() == TopAbs_FORWARD) {
1782     GC->D1(l,P,DX);
1783     DX.Reverse();
1784   }
1785   else GC->D1(f,P,DX);
1786
1787   gp_Ax2d Axis(P,gp_Dir2d(DX));
1788   Handle(Geom2d_Circle) Circ 
1789     = new  Geom2d_Circle(Axis, Abs(Offset), Offset < 0.);
1790
1791   // Bind the edges in my Map.
1792   TopoDS_Edge OE = BRepLib_MakeEdge(Circ, RefPlane);
1793   TopTools_ListOfShape LL;
1794
1795   LL.Append(OE);
1796   Map.Add(V,LL);
1797
1798 #ifdef DRAW
1799   if ( AffichGeom && !OE.IsNull()) {
1800     sprintf(name,"OFFSET_%d",++NbOFFSET);
1801     DBRep::Set(name,OE);
1802   }
1803 #endif
1804 }
1805
1806 //=======================================================================
1807 //function : MakeOffset
1808 //purpose  : 
1809 //=======================================================================
1810
1811 void MakeOffset (const TopoDS_Edge&        E, 
1812                  const TopoDS_Face&        F,
1813                  const Standard_Real       Offset, 
1814                        BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
1815                  const Handle(Geom_Plane)& RefPlane)
1816 {
1817   Standard_Real f,l;
1818   Standard_Real anOffset = Offset;
1819
1820   if (E.Orientation() == TopAbs_REVERSED) anOffset *= -1;
1821
1822   Handle(Geom2d_Curve) G2d = BRep_Tool::CurveOnSurface(E,F,f,l);
1823   Handle(Geom2d_Curve) G2dOC;
1824
1825   Geom2dAdaptor_Curve  AC(G2d,f,l);
1826   if ( AC.GetType() == GeomAbs_Circle) {
1827     // if the offset is greater otr equal to the radius and the side of the  
1828     // concavity of the circle => edge null.
1829     gp_Circ2d C1(AC.Circle());
1830 #ifdef DEB
1831     Standard_Real radius = 
1832 #endif
1833                            C1.Radius();
1834     gp_Ax22d axes( C1.Axis());
1835     gp_Dir2d Xd = axes.XDirection();
1836     gp_Dir2d Yd = axes.YDirection();
1837     Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X();
1838     Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.;
1839
1840     if (anOffset*Signe < AC.Circle().Radius()) {
1841
1842       Handle(Geom2dAdaptor_HCurve) AHC = 
1843         new Geom2dAdaptor_HCurve(G2d);
1844       Adaptor3d_OffsetCurve   Off(AHC,-anOffset);
1845       Handle(Geom2d_Circle) CC = new Geom2d_Circle(Off.Circle());      
1846
1847       Standard_Real Delta = 2*PI - l + f;
1848       f -= 0.2*Delta; l += 0.2*Delta;
1849
1850       G2dOC = new Geom2d_TrimmedCurve(CC,f,l);
1851     }
1852   }
1853   else if (AC.GetType() == GeomAbs_Line) {
1854     Handle(Geom2dAdaptor_HCurve) AHC = 
1855       new Geom2dAdaptor_HCurve(G2d);
1856     Adaptor3d_OffsetCurve Off(AHC,anOffset);
1857     Handle(Geom2d_Line)       CC = new Geom2d_Line(Off.Line());
1858     Standard_Real Delta = (l - f);
1859     f -= Delta; l += Delta;
1860     G2dOC = new Geom2d_TrimmedCurve(CC,f,l);
1861   }
1862   else {
1863
1864     anOffset = -anOffset;
1865     Handle(Geom2d_TrimmedCurve) G2dT = new Geom2d_TrimmedCurve(G2d,f,l);
1866     G2dOC = new Geom2d_OffsetCurve( G2dT, anOffset);
1867
1868   }
1869
1870   // Bind the edges in my Map.
1871   if (!G2dOC.IsNull()) {
1872     TopoDS_Edge OE = BRepLib_MakeEdge(G2dOC, RefPlane);
1873     OE.Orientation(E.Orientation());
1874     TopTools_ListOfShape LL;
1875     LL.Append(OE);
1876     Map.Add(E,LL);
1877
1878 #ifdef DRAW  
1879     if (AffichGeom && !OE.IsNull()) {
1880       sprintf(name,"OFFSET_%d",++NbOFFSET);
1881       DBRep::Set(name,OE);
1882       Standard_Real ii = 0;
1883     }
1884 #endif
1885     
1886   }
1887 }  
1888
1889 //=======================================================================
1890 //function : UpdateDetromp
1891 //purpose  : For each interval on bissectrice defined by parameters
1892 //           test if the medium point is at a distance > offset 
1893 //           in this case vertices corresponding to the extremities of the interval
1894 //           are ranked in the proofing.
1895 //           => If the same vertex appears in the proofing, the 
1896 //           border of the zone of proximity is tangent to the offset .
1897 //=======================================================================
1898
1899 void UpdateDetromp (TopTools_ListOfShape&           Detromp1,
1900                     TopTools_ListOfShape&           Detromp2, 
1901                     const TopTools_SequenceOfShape& Vertices, 
1902                     const TColgp_SequenceOfPnt&     Params, 
1903                     const Bisector_Bisec&           Bisec,
1904                     const Standard_Boolean          SOnE,
1905                     const Standard_Boolean          EOnE,
1906                     const BRepFill_TrimEdgeTool&    Trim)
1907 {
1908   Standard_Integer ii = 1;
1909   Standard_Real    U1,U2;
1910   TopoDS_Vertex    V1,V2;
1911
1912   Handle(Geom2d_Curve) Bis = Bisec.Value();
1913
1914   U1 = Bis->FirstParameter();
1915   
1916   if (SOnE) { 
1917     // the first point of the bissectrice is on the offset
1918     V1 = TopoDS::Vertex(Vertices.Value(ii));
1919     ii++; 
1920   }
1921
1922   while (ii <= Vertices.Length()) {
1923     U2 = Params.Value(ii).X();
1924     V2 = TopoDS::Vertex(Vertices.Value(ii));
1925
1926     gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
1927     if (!Trim.IsInside(P)) {
1928       if (!V1.IsNull()) {
1929           Detromp1.Append(V1);
1930           Detromp2.Append(V1);
1931       }
1932       Detromp1.Append(V2);
1933       Detromp2.Append(V2);
1934     }
1935     U1 = U2;
1936     V1 = V2;
1937     ii ++;
1938   }
1939
1940   // test medium point between the last parameter and the end of the bissectrice.
1941   U2 = Bis->LastParameter();
1942   if (!EOnE) {
1943     if (!Precision::IsInfinite(U2)) {
1944       gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
1945       if (!Trim.IsInside(P)) {
1946         if (!V1.IsNull()) {
1947           Detromp1.Append(V1);
1948           Detromp2.Append(V1);
1949         }
1950       }
1951     }
1952     else {
1953       if (!V1.IsNull()) {
1954         Detromp1.Append(V1);
1955         Detromp2.Append(V1);
1956       }
1957     }
1958   }    
1959 }
1960
1961 //=======================================================================
1962 //function : VertexFromNode
1963 //purpose  : 
1964 //=======================================================================
1965
1966 Standard_Boolean VertexFromNode (const Handle(MAT_Node)&      aNode, 
1967                                  const Standard_Real          Offset,
1968                                   gp_Pnt2d&                   PN,
1969                                  BRepFill_DataMapOfNodeShape& MapNodeVertex,
1970                                  TopoDS_Vertex&               VN)
1971 {  
1972   Standard_Boolean Status;
1973   Standard_Real    Tol = Precision::Confusion();
1974   BRep_Builder     B;
1975
1976   if (!aNode->Infinite() && Abs(aNode->Distance()-Offset) < Tol) {
1977     //------------------------------------------------
1978     // the Node gives a vertex on the offset
1979     //------------------------------------------------
1980     if (MapNodeVertex.IsBound(aNode)) {
1981       VN = TopoDS::Vertex(MapNodeVertex(aNode));
1982     }
1983     else { 
1984       gp_Pnt P(PN.X(),PN.Y(),0.);
1985       B.MakeVertex (VN);
1986       B.UpdateVertex(VN,P, Precision::Confusion());
1987       MapNodeVertex.Bind(aNode,VN);
1988     }
1989     Status = Standard_True;
1990   }
1991   else Status = Standard_False;
1992
1993   return Status;
1994 }
1995
1996
1997 //=======================================================================
1998 //function : StoreInMap
1999 //purpose  : 
2000 //=======================================================================
2001
2002 void StoreInMap (const TopoDS_Shape& V1,
2003                  const TopoDS_Shape& V2,
2004                  TopTools_IndexedDataMapOfShapeShape& MapVV)
2005 {
2006   TopoDS_Shape OldV = V1, NewV = V2;
2007   Standard_Integer i;
2008
2009   if (MapVV.Contains(V2))
2010     NewV = MapVV.FindFromKey(V2);
2011
2012   if (MapVV.Contains(V1))
2013     MapVV.ChangeFromKey(V1) = NewV;
2014
2015   for (i = 1; i <= MapVV.Extent(); i++)
2016     if (MapVV(i).IsSame(V1))
2017       MapVV(i) = NewV;
2018
2019   MapVV.Add(V1, NewV);
2020 }
2021
2022 //=======================================================================
2023 //function : TrimEdge
2024 //purpose  : 
2025 //=======================================================================
2026
2027 void TrimEdge (const TopoDS_Edge&              E,
2028                const TopTools_ListOfShape&     Detromp,
2029                      TopTools_SequenceOfShape& TheVer,
2030                      TColStd_SequenceOfReal&   ThePar,
2031                      TopTools_SequenceOfShape& S,
2032                      TopTools_IndexedDataMapOfShapeShape& MapVV)
2033 {
2034   Standard_Boolean         Change = Standard_True;
2035   BRep_Builder             TheBuilder;
2036   S.Clear();
2037
2038   //-----------------------------------------------------------
2039   // Parse two sequences depending on the parameter on the edge.
2040   //-----------------------------------------------------------
2041   while (Change) {
2042     Change = Standard_False;
2043     for (Standard_Integer i = 1; i < ThePar.Length(); i++) {
2044       if (ThePar.Value(i) > ThePar.Value(i+1)) {
2045         ThePar.Exchange(i,i+1);
2046         TheVer.Exchange(i,i+1);
2047         Change = Standard_True;
2048       }
2049     }
2050   }
2051
2052   //----------------------------------------------------------
2053   // If a vertex is not in the proofing, it is eliminated.
2054   //----------------------------------------------------------
2055   if (!BRep_Tool::Degenerated(E)) {
2056     for (Standard_Integer k = 1; k <= TheVer.Length(); k ++) {
2057       if ( DoubleOrNotInside (Detromp,
2058                               TopoDS::Vertex(TheVer.Value(k)))) {
2059         TheVer.Remove(k);
2060         ThePar.Remove(k);
2061         k--;
2062       }
2063     }
2064   }
2065
2066   //----------------------------------------------------------
2067   // If a vertex_double appears twice in the proofing 
2068   // the vertex is removed.
2069   // otherwise preserve only one of its representations.
2070   //----------------------------------------------------------
2071   if (!BRep_Tool::Degenerated(E)) {
2072     for (Standard_Integer k = 1; k < TheVer.Length(); k ++) {
2073       if (TheVer.Value(k).IsSame(TheVer.Value(k+1)) || 
2074          Abs(ThePar.Value(k)-ThePar.Value(k+1)) <= Precision::PConfusion()) {
2075
2076         if(k+1 == TheVer.Length()) {
2077           StoreInMap(TheVer(k), TheVer(k+1), MapVV);
2078           TheVer.Remove(k);
2079           ThePar.Remove(k);
2080         }
2081         else {
2082           StoreInMap(TheVer(k+1), TheVer(k), MapVV);
2083           TheVer.Remove(k+1);
2084           ThePar.Remove(k+1);
2085         }
2086         /*
2087         if ( DoubleOrNotInside (Detromp,
2088                                 TopoDS::Vertex(TheVer.Value(k)))) {
2089           TheVer.Remove(k);
2090           ThePar.Remove(k);
2091           k--;
2092         }
2093         */
2094         k--;
2095       }
2096     }
2097   }
2098   //-----------------------------------------------------------
2099   // Creation of edges.
2100   // the number of vertices should be even. The created edges  
2101   // go from a vertex with uneven index i to vertex i+1;
2102   //-----------------------------------------------------------
2103   for (Standard_Integer k = 1; k < TheVer.Length(); k = k+2) {
2104     TopoDS_Shape aLocalShape = E.EmptyCopied();
2105     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
2106 //    TopoDS_Edge NewEdge = TopoDS::Edge(E.EmptyCopied());
2107
2108     if (NewEdge.Orientation() == TopAbs_REVERSED) {
2109       TheBuilder.Add  (NewEdge,TheVer.Value(k)  .Oriented(TopAbs_REVERSED));
2110       TheBuilder.Add  (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_FORWARD));
2111     }
2112     else {      
2113       TheBuilder.Add  (NewEdge,TheVer.Value(k)  .Oriented(TopAbs_FORWARD));
2114       TheBuilder.Add  (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_REVERSED));
2115     }
2116
2117
2118     TheBuilder.Range(NewEdge,ThePar.Value(k),ThePar.Value(k+1));
2119
2120 #ifdef DRAW
2121     if ( AffichEdge) {
2122       sprintf(name,"TRIMEDGE_%d",NbTRIMEDGES);
2123       DBRep::Set(name,NewEdge);  
2124     }
2125     if (Affich2d) {
2126       TopLoc_Location L;
2127       Standard_Real f,l;
2128       Handle(Geom_Surface) Surf;  
2129       Handle(Geom2d_Curve) C;
2130       BRep_Tool::CurveOnSurface(NewEdge,C,Surf,L,f,l);
2131       sprintf(name,"OFFSET2d_%d",NbTRIMEDGES++);
2132       Handle(Geom2d_TrimmedCurve) C2d = new Geom2d_TrimmedCurve(C,f,l);
2133       Handle(DrawTrSurf_Curve2d) dr =
2134         new DrawTrSurf_Curve2d(C2d,Standard_False);
2135       dr->SetColor(Draw_bleu);
2136       Draw::Set(name,dr);
2137     }
2138 #endif
2139
2140     S.Append(NewEdge);
2141   }
2142 }
2143
2144 //=======================================================================
2145 //function : DoubleOrNotInside
2146 //purpose  : return True if V appears twice in LV or is not inside.
2147 //=======================================================================
2148
2149 Standard_Boolean DoubleOrNotInside (const TopTools_ListOfShape& LV,
2150                                     const TopoDS_Vertex&        V)
2151 {  
2152   Standard_Boolean Vu = Standard_False;
2153   TopTools_ListIteratorOfListOfShape it(LV);
2154
2155   for ( ; it.More(); it.Next()) {
2156     if (V.IsSame(it.Value())) {
2157       if  (Vu) return Standard_True;
2158       else       Vu = Standard_True;
2159     }
2160   }
2161   if (Vu) return Standard_False;
2162   else    return Standard_True;   
2163 }
2164
2165 Standard_Boolean IsSmallClosedEdge(const TopoDS_Edge& anEdge,
2166                                    const TopoDS_Vertex& aVertex)
2167 {
2168   gp_Pnt PV = BRep_Tool::Pnt(aVertex);
2169   gp_Pnt2d PV2d, Pfirst, Plast, Pmid;
2170   PV2d.SetCoord( PV.X(), PV.Y() );
2171
2172   Handle(Geom2d_Curve) PCurve;
2173   Handle( BRep_CurveRepresentation ) CurveRep =
2174     ((Handle(BRep_TEdge)::DownCast(anEdge.TShape()))->Curves()).First();
2175   PCurve = CurveRep->PCurve();
2176
2177   Standard_Real fpar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First();
2178   Standard_Real lpar = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last();
2179   Pfirst = PCurve->Value(fpar);
2180   Plast  = PCurve->Value(lpar);
2181   Pmid   = PCurve->Value((fpar + lpar)*0.5);
2182
2183   Standard_Real theTol = BRep_Tool::Tolerance(aVertex);
2184   theTol *= 1.5;
2185
2186   Standard_Real dist1 = Pfirst.Distance(PV2d);
2187   Standard_Real dist2 = Plast.Distance(PV2d);
2188   Standard_Real dist3 = Pmid.Distance(PV2d);
2189
2190   if (dist1 <= theTol && dist2 <= theTol && dist3 <= theTol)
2191     return Standard_True;
2192
2193   return Standard_False;
2194 }
2195
2196 static void CheckBadEdges(const TopoDS_Face& Spine, const Standard_Real Offset,
2197                           const BRepMAT2d_BisectingLocus& Locus, 
2198                           const BRepMAT2d_LinkTopoBilo&   Link,
2199                           TopTools_ListOfShape& BadEdges)
2200 {
2201
2202   TopoDS_Face F = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD));
2203   Standard_Real eps = Precision::Confusion(); 
2204   Standard_Real LimCurv = 1./Offset;
2205
2206   TopTools_MapOfShape aMap;
2207
2208   for (Standard_Integer ic = 1; ic <= Locus.NumberOfContours(); ic++) {
2209     for (Standard_Integer ie = 1; ie <= Locus.NumberOfElts(ic); ie++) {
2210       const TopoDS_Shape& SE = Link.GeneratingShape(Locus.BasicElt(ic,ie));
2211       if (SE.ShapeType() == TopAbs_EDGE) {
2212
2213         if (aMap.Contains(SE)) {
2214           //cout << "Edge is treated second time" << endl;
2215           continue;
2216         }
2217
2218         TopoDS_Edge E = TopoDS::Edge(SE);
2219
2220         Standard_Real f,l;
2221
2222         Handle(Geom2d_Curve) G2d = BRep_Tool::CurveOnSurface(E,F,f,l);
2223
2224         Geom2dAdaptor_Curve  AC(G2d,f,l);
2225         GeomAbs_CurveType aCType = AC.GetType();
2226
2227         if(aCType != GeomAbs_Line && aCType != GeomAbs_Circle) {
2228
2229           Standard_Boolean reverse = Standard_False;
2230           if (E.Orientation() == TopAbs_FORWARD) reverse = Standard_True;
2231
2232           gp_Pnt2d P, Pc;
2233           gp_Dir2d N;
2234
2235           Geom2dLProp_CLProps2d aCLProps(G2d, 2, eps);
2236
2237           aCLProps.SetParameter(f);
2238           if(!aCLProps.IsTangentDefined()) {
2239             BadEdges.Append(SE);
2240             aMap.Add(SE);
2241             continue;
2242           }
2243
2244           P = aCLProps.Value();
2245           Standard_Real Crv = aCLProps.Curvature();
2246
2247           if(Crv >= eps) {
2248             aCLProps.Tangent(N);
2249             Standard_Real x = N.Y(), y = -N.X();
2250             N.SetCoord(x, y);
2251             if (reverse) N.Reverse();
2252             aCLProps.CentreOfCurvature(Pc);
2253             gp_Vec2d Dir( P, Pc );
2254             if (N.Dot(Dir) > 0.) {
2255               if (LimCurv <= Crv + eps) {
2256                 BadEdges.Append(SE);
2257                 aMap.Add(SE);
2258                 continue;
2259               }
2260             }
2261           }  
2262
2263           aCLProps.SetParameter(l);
2264           if(!aCLProps.IsTangentDefined()) {
2265             BadEdges.Append(SE);
2266             aMap.Add(SE);
2267             continue;
2268           }
2269
2270           P = aCLProps.Value();
2271           Crv = aCLProps.Curvature();
2272
2273           if(Crv >= eps) {
2274             aCLProps.Tangent(N);
2275             Standard_Real x = N.Y(), y = -N.X();
2276             N.SetCoord(x, y);
2277             if (reverse) N.Reverse();
2278             aCLProps.CentreOfCurvature(Pc);
2279             gp_Vec2d Dir( P, Pc );
2280             if (N.Dot(Dir) > 0.) {
2281               if (LimCurv <= Crv + eps) {
2282                 BadEdges.Append(SE);
2283                 aMap.Add(SE);
2284                 continue;
2285               }
2286             }
2287           }  
2288         }
2289       }
2290     }
2291   }
2292 }
2293
2294
2295 //=======================================================================
2296 //function : PerformCurve
2297 //purpose  : 
2298 //=======================================================================
2299
2300 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters,
2301                                       TColgp_SequenceOfPnt&   Points,
2302                                       const Adaptor3d_Curve& C, 
2303                                       const Standard_Real Deflection,
2304                                       const Standard_Real U1,
2305                                       const Standard_Real U2,
2306                                       const Standard_Real EPSILON,
2307                                       const Standard_Integer Nbmin)
2308 {
2309   Standard_Real UU1 = Min(U1, U2);
2310   Standard_Real UU2 = Max(U1, U2);
2311
2312   gp_Pnt Pdeb, Pfin;
2313   gp_Vec Ddeb,Dfin;
2314   C.D1(UU1,Pdeb,Ddeb);
2315   Parameters.Append(UU1);
2316   Points.Append(Pdeb);
2317
2318   C.D1(UU2,Pfin,Dfin);
2319   QuasiFleche(C,Deflection*Deflection,
2320               UU1,Pdeb,
2321               Ddeb,
2322               UU2,Pfin,
2323               Dfin,
2324               Nbmin,
2325               EPSILON*EPSILON,
2326               Parameters,Points);
2327   return Standard_True;
2328 }
2329 //=======================================================================
2330 //function : QuasiFleche
2331 //purpose  : 
2332 //=======================================================================
2333
2334 static void QuasiFleche(const Adaptor3d_Curve& C,
2335                         const Standard_Real Deflection2, 
2336                         const Standard_Real Udeb,
2337                         const gp_Pnt& Pdeb,
2338                         const gp_Vec& Vdeb,
2339                         const Standard_Real Ufin,
2340                         const gp_Pnt& Pfin,
2341                         const gp_Vec& Vfin,
2342                         const Standard_Integer Nbmin,
2343                         const Standard_Real Eps,
2344                         TColStd_SequenceOfReal& Parameters,
2345                         TColgp_SequenceOfPnt& Points)
2346 {
2347   Standard_Integer Ptslength = Points.Length();
2348   Standard_Real Udelta = Ufin-Udeb;
2349   gp_Pnt Pdelta;
2350   gp_Vec Vdelta;
2351   if (Nbmin > 2) {
2352     Udelta /=(Nbmin-1);
2353     C.D1(Udeb+Udelta,Pdelta,Vdelta);
2354   }
2355   else {
2356     Pdelta = Pfin;
2357     Vdelta = Vfin;
2358   }
2359
2360
2361   Standard_Real Norme = gp_Vec(Pdeb,Pdelta).SquareMagnitude();
2362   Standard_Real theFleche=0;
2363   Standard_Boolean flecheok = Standard_False;
2364   if (Norme > Eps) { 
2365     // Evaluation of the arrow by interpolation. See IntWalk_IWalking_5.gxx
2366     Standard_Real N1 = Vdeb.SquareMagnitude();
2367     Standard_Real N2 = Vdelta.SquareMagnitude();
2368     if (N1 > Eps && N2 > Eps) {
2369       Standard_Real Normediff = 
2370         (Vdeb.Normalized().XYZ()-Vdelta.Normalized().XYZ()).SquareModulus();
2371       if (Normediff > Eps) {
2372         theFleche = Normediff*Norme/64.;
2373         flecheok = Standard_True;
2374       }
2375     }
2376   }
2377   if (!flecheok) {
2378     gp_Pnt Pmid((Pdeb.XYZ()+Pdelta.XYZ())/2.);
2379     gp_Pnt Pverif(C.Value(Udeb+Udelta/2.));
2380     theFleche = Pmid.SquareDistance(Pverif);
2381   }
2382
2383   if (theFleche < Deflection2) {
2384     Parameters.Append(Udeb+Udelta);
2385     Points.Append(Pdelta);
2386   }
2387   else {
2388     QuasiFleche(C,Deflection2,Udeb,Pdeb,
2389                 Vdeb,
2390                 Udeb+Udelta,Pdelta,
2391                 Vdelta,
2392                 3,
2393                 Eps,
2394                 Parameters,Points);
2395
2396   }
2397
2398   if (Nbmin > 2) {
2399     QuasiFleche(C,Deflection2,Udeb+Udelta,Pdelta,
2400                 Vdelta,
2401                 Ufin,Pfin,
2402                 Vfin,
2403                 Nbmin-(Points.Length()-Ptslength),
2404                 Eps,
2405                 Parameters,Points);
2406   }
2407 }
2408