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