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