0025298: New option of BRepOffsetAPI_MakeOffset algorithm: processing of sharp corner...
[occt.git] / src / MAT2d / MAT2d_Circuit.cxx
1 // Created on: 1993-11-19
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #ifdef DRAW
18 #include <Draw_Appli.hxx>
19 #include <DrawTrSurf_Curve2d.hxx>
20 #include <Draw_Marker2D.hxx>
21 #endif
22 #ifdef DEB
23 #include <GCE2d_MakeSegment.hxx>
24 #include <Geom2d_Curve.hxx>
25 #include <Geom2d_Parabola.hxx>
26 #include <Geom2d_Hyperbola.hxx>
27 #include <Geom2d_TrimmedCurve.hxx>
28 #include <Geom2d_CartesianPoint.hxx>
29 #include <Geom2d_Line.hxx>
30 #include <Geom2d_Circle.hxx>
31 #endif
32
33 #include <MAT2d_Circuit.ixx>
34 #include <Geom2d_TrimmedCurve.hxx>
35 #include <Geom2d_CartesianPoint.hxx>
36 #include <Geom2d_Geometry.hxx>      
37 #include <TColStd_SequenceOfInteger.hxx>
38 #include <TColStd_Array1OfBoolean.hxx>
39 #include <TColStd_Array1OfInteger.hxx>
40 #include <MAT2d_BiInt.hxx>
41 #include <MAT2d_MiniPath.hxx>
42 #include <MAT2d_Connexion.hxx>
43 #include <MAT2d_SequenceOfConnexion.hxx>
44 #include <MAT2d_DataMapOfIntegerConnexion.hxx> 
45 #include <MAT2d_SequenceOfSequenceOfGeometry.hxx>
46 #include <MAT2d_DataMapOfBiIntSequenceOfInteger.hxx>
47 #include <MAT2d_DataMapIteratorOfDataMapOfBiIntSequenceOfInteger.hxx>
48 #include <Precision.hxx>
49 #include <Adaptor3d_OffsetCurve.hxx>
50 #include <Geom2dInt_GInter.hxx>
51 #include <Geom2dAdaptor_HCurve.hxx>
52 #include <IntRes2d_IntersectionPoint.hxx>
53
54 #ifdef DRAW
55   static Handle(DrawTrSurf_Curve2d) draw;
56   Standard_EXPORT Draw_Viewer dout;
57 #endif
58 #ifdef DEB
59   static void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve,
60                               const Standard_Integer      Indice);
61   static Standard_Boolean AffichCircuit = 0;
62 #endif
63
64 // static functions:
65
66 static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1,
67                                const Handle(Geom2d_Geometry)& Geom2,
68                                      Standard_Real&           DotProd);
69
70
71 //=============================================================================
72 //function : Constructor
73 //purpose :
74 //=============================================================================
75 MAT2d_Circuit::MAT2d_Circuit(const GeomAbs_JoinType aJoinType,
76                              const Standard_Boolean IsOpenResult)
77 {
78   myJoinType = aJoinType;
79   myIsOpenResult = IsOpenResult;
80 }
81
82 //=============================================================================
83 //function : Perform
84 //purpose :
85 //=============================================================================
86 void  MAT2d_Circuit::Perform
87   (       MAT2d_SequenceOfSequenceOfGeometry& FigItem,
88    const TColStd_SequenceOfBoolean          & IsClosed,
89    const Standard_Integer                     IndRefLine,
90    const Standard_Boolean                     Trigo)
91 {
92   Standard_Integer          NbLines = FigItem.Length();
93   Standard_Integer          i;
94   TColStd_Array1OfBoolean   Open(1,NbLines);
95   MAT2d_SequenceOfConnexion SVide;
96   Handle(MAT2d_Connexion)   ConnexionNul;
97
98   if (Trigo) direction = 1.; else direction = -1.;
99
100   //---------------------
101   // Reinitialisation SD.
102   //---------------------
103   geomElements.Clear();
104   connexionMap.Clear();
105   linkRefEqui.Clear();
106   linesLength.Clear();
107
108   //----------------------------
109   // Detection Lignes ouvertes.
110   //----------------------------
111   for ( i = 1; i <= NbLines; i++) {    
112     Handle(Geom2d_TrimmedCurve) Curve;
113     Curve = Handle(Geom2d_TrimmedCurve)::DownCast(FigItem.Value(i).First());
114     gp_Pnt2d P1 = Curve->StartPoint();  
115     Curve = Handle(Geom2d_TrimmedCurve)::DownCast(FigItem.Value(i).Last());
116     gp_Pnt2d P2 = Curve->EndPoint();
117 //  Modified by Sergey KHROMOV - Wed Mar  6 16:59:01 2002 Begin
118 //     if ( P1.IsEqual(P2,Precision::Confusion()))  Open(i) = Standard_False;
119 //     else                                         Open(i) = Standard_True;
120     if (IsClosed(i))                                Open(i) = Standard_False;
121     else if (P1.IsEqual(P2,Precision::Confusion())) Open(i) = Standard_False;
122     else                                            Open(i) = Standard_True;
123 //  Modified by Sergey KHROMOV - Wed Mar  6 16:59:04 2002 End
124   }
125     
126   //---------------------------------------------------------------
127   // Insertion des cassures saillantes ou
128   // ajout des extremites de chaque courbe si la ligne est ouverte.
129   //---------------------------------------------------------------
130   for ( i = 1; i <= NbLines; i++) {
131     if (Open(i)) {
132       InitOpen(FigItem.ChangeValue(i));  
133       linesLength.Append(FigItem.Value(i).Length());
134     }
135     else {
136       InsertCorner(FigItem.ChangeValue(i));
137       linesLength.Append(FigItem.Value(i).Length());
138     }
139   }
140
141   //---------------------------------
142   // Une seule ligne => Rien a faire.
143   //---------------------------------
144   if (NbLines == 1) {
145     if (Open(1)) {
146       DoubleLine(FigItem.ChangeValue(1),SVide,ConnexionNul,direction);  
147       linesLength.SetValue(1,FigItem.Value(1).Length());
148     }
149     geomElements  = FigItem.Value(1);
150     UpDateLink(1,1,1,geomElements.Length());     
151     linesLength.Append(FigItem.Value(1).Length());
152     return;
153   }
154     
155   //------------------
156   // Plusieurs lignes.
157   //------------------
158   
159   //---------------------------------------------------------
160   // Calcul de l ensemble des connexions realisant le chemin. 
161   //---------------------------------------------------------
162   MAT2d_MiniPath  Road;
163   Road.Perform(FigItem,IndRefLine,Trigo);
164   
165   //------------------------
166   // Fermeture ligne ouverte.
167   //-------------------------
168   for ( i = 1; i <= NbLines; i++) {
169     if (Open(i)) {
170       Handle(MAT2d_Connexion)  CF;
171       if (Road.IsRoot(i))      CF = ConnexionNul; else CF = Road.Father(i);
172       if (Road.IsConnexionsFrom(i)) {
173         DoubleLine(FigItem.ChangeValue(i),Road.ConnexionsFrom(i),
174                    CF,direction);  
175       }
176       else {
177         DoubleLine(FigItem.ChangeValue(i),SVide,CF,direction);  
178       }
179       linesLength.SetValue(i,FigItem.Value(i).Length());
180     }
181   }
182
183   //------------------------
184   // Construction du chemin.
185   //------------------------
186   Road.RunOnConnexions();
187
188 #ifdef DEB 
189   if (AffichCircuit) {
190     Standard_Integer NbConnexions = Road.Path().Length();
191     for (i = 1; i <= NbConnexions; i++) {
192       Handle(Geom2d_TrimmedCurve) edge;
193       edge = GCE2d_MakeSegment(Road.Path().Value(i)->PointOnFirst(),
194                                Road.Path().Value(i)->PointOnSecond());
195       MAT2d_DrawCurve(edge,2);
196     }
197   }
198 #endif
199
200   //-------------------------
201   // Construction du Circuit.
202   //-------------------------
203   ConstructCircuit(FigItem,IndRefLine,Road);
204 }
205
206 //=======================================================================
207 //function : IsSharpCorner
208 //purpose  : Return True Si le point commun entre <Geom1> et <Geom2> est 
209 //           une cassure saillante par rapport <Direction>
210 //=======================================================================
211
212 Standard_Boolean MAT2d_Circuit::IsSharpCorner(const Handle(Geom2d_Geometry)& Geom1,
213                                               const Handle(Geom2d_Geometry)& Geom2,
214                                               const Standard_Real Direction) const
215 {
216   Standard_Real    DotProd;
217   Standard_Real    ProVec = CrossProd (Geom1,Geom2,DotProd);
218   Standard_Integer NbTest = 1;
219   Standard_Real    DU = Precision::Confusion();
220   Handle(Geom2d_TrimmedCurve) C1,C2;
221
222   C1= Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
223   C2= Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
224 //  Modified by Sergey KHROMOV - Thu Oct 24 19:02:46 2002 Begin
225 // Add the same criterion as it is in MAT2d_Circuit::InitOpen(..)
226 //  Standard_Real  TolAng = 1.E-5;
227   Standard_Real  TolAng = 1.E-8;
228 //  Modified by Sergey KHROMOV - Thu Oct 24 19:02:47 2002 End
229
230   if (myJoinType == GeomAbs_Arc)
231   {
232     while (NbTest <= 10) {
233       if      ((ProVec)*Direction < -TolAng)                 
234         return Standard_True;                // Saillant.
235       if      ((ProVec)*Direction >  TolAng)
236         return Standard_False;              // Rentrant.
237       else { 
238         if (DotProd > 0) {
239           return Standard_False;            // Plat.
240         }
241         TolAng = 1.E-8;
242         Standard_Real U1 = C1->LastParameter()  - NbTest*DU;
243         Standard_Real U2 = C2->FirstParameter() + NbTest*DU;
244         gp_Dir2d Dir1(C1->DN(U1,1));
245         gp_Dir2d Dir2(C2->DN(U2,1));
246         DotProd = Dir1.Dot(Dir2);
247         ProVec  =  Dir1^Dir2;
248         NbTest++;
249       } 
250     }
251     
252     
253     
254     // Rebroussement.
255     // on calculde des paralleles aux deux courbes du cote du domaine
256     // de calcul
257     // Si pas dintersection => saillant.
258     // Sinon                => rentrant.
259     Standard_Real D ;
260     Standard_Real Tol   = Precision::Confusion();
261     Standard_Real MilC1 = (C1->LastParameter() + C1->FirstParameter())*0.5;
262     Standard_Real MilC2 = (C2->LastParameter() + C2->FirstParameter())*0.5;
263     gp_Pnt2d      P     = C1->Value(C1->LastParameter());
264     gp_Pnt2d      P1    = C1->Value(MilC1);
265     gp_Pnt2d      P2    = C2->Value(MilC2);
266     
267     D = Min(P1.Distance(P),P2.Distance(P));
268     D /= 10;
269     
270     if (Direction > 0.) D = -D;
271     
272     Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C1);
273     Handle(Geom2dAdaptor_HCurve) HC2 = new Geom2dAdaptor_HCurve(C2);
274     Adaptor3d_OffsetCurve OC1(HC1,D,MilC1,C1->LastParameter());
275     Adaptor3d_OffsetCurve OC2(HC2,D,C2->FirstParameter(),MilC2);
276     Geom2dInt_GInter Intersect; 
277     Intersect.Perform(OC1,OC2,Tol,Tol);
278     
279 #ifdef DEB
280     static Standard_Boolean Affich = 0;
281     if (Affich) {
282 #ifdef DRAW
283       Standard_Real DU1 = (OC1.LastParameter() - OC1.FirstParameter())/9.;
284       Standard_Real DU2 = (OC2.LastParameter() - OC2.FirstParameter())/9.;
285       for (Standard_Integer ki = 0; ki <= 9; ki++) {
286         gp_Pnt2d P1 = OC1.Value(OC1.FirstParameter()+ki*DU1);
287         gp_Pnt2d P2 = OC2.Value(OC2.FirstParameter()+ki*DU2);
288         Handle(Draw_Marker2D) dr1 = new Draw_Marker2D(P1,Draw_Plus,Draw_vert);
289         Handle(Draw_Marker2D) dr2 = new Draw_Marker2D(P2,Draw_Plus,Draw_rouge); 
290         dout << dr1;
291         dout << dr2;
292       }
293       dout.Flush();
294 #endif
295     }
296 #endif
297     
298     if (Intersect.IsDone() && !Intersect.IsEmpty()) {
299       return Standard_False;
300     }
301     else {
302       return Standard_True;
303     }
304   } //end of if (myJoinType == GeomAbs_Arc)
305   else if (myJoinType == GeomAbs_Intersection)
306   {
307     if (Abs(ProVec) <= TolAng &&
308         DotProd < 0)
309     {
310       while (NbTest <= 10)
311       {
312         Standard_Real U1 = C1->LastParameter()  - NbTest*DU;
313         Standard_Real U2 = C2->FirstParameter() + NbTest*DU;
314         gp_Dir2d Dir1(C1->DN(U1,1));
315         gp_Dir2d Dir2(C2->DN(U2,1));
316         DotProd = Dir1.Dot(Dir2);
317         ProVec  =  Dir1^Dir2;
318         if      ((ProVec)*Direction < -TolAng)                 
319           return Standard_True;                // Saillant.
320         if      ((ProVec)*Direction >  TolAng)
321           return Standard_False;              // Rentrant.
322         
323         NbTest++;
324       }
325       return Standard_False;
326     }
327     else
328       return Standard_False;
329   }
330   return Standard_False;
331 }
332
333 //=======================================================================
334 //function : SubSequence
335 //purpose  : 
336 //=======================================================================
337 static void SubSequence(const TColGeom2d_SequenceOfGeometry& S1,
338                               Standard_Integer               IF,
339                               Standard_Integer               IL,
340                               TColGeom2d_SequenceOfGeometry& S2)
341 {
342   S2.Clear();
343   for (Standard_Integer i = IF; i<= IL; i++){
344     S2.Append(S1.Value(i));
345   }
346 }
347
348                         
349 //=============================================================================
350 //function : ConstructCircuit
351 //purpose :
352 //=============================================================================
353 void  MAT2d_Circuit::ConstructCircuit
354   (const MAT2d_SequenceOfSequenceOfGeometry& FigItem, 
355    const Standard_Integer                    IndRefLine,
356    const MAT2d_MiniPath&                     Road)
357 {
358   Handle(MAT2d_Connexion)            PrevC,CurC;
359   TColGeom2d_SequenceOfGeometry      SetOfItem;
360   Standard_Integer                   NbConnexions;
361   Standard_Integer                   ILastItem;
362   Standard_Integer                   IndLast;
363   Standard_Integer                   i;
364   
365   NbConnexions = Road.Path().Length();
366   //-----------------------------------------------------
367   // Depart du premier element de la ligne de reference.
368   //-----------------------------------------------------
369   PrevC = Road.Path().Value(1);
370   SubSequence(FigItem.Value(IndRefLine),
371               1,
372               PrevC->IndexItemOnFirst(),
373               geomElements);
374   UpDateLink(1,IndRefLine,1,PrevC->IndexItemOnFirst());
375   connexionMap.Bind(geomElements.Length()+1,PrevC);
376   ILastItem = geomElements.Length();
377   
378   //-----------------------------------------------------------------------
379   // Ajout des portion de lignes delimites par deux connexions successives.
380   //-----------------------------------------------------------------------
381   for ( i = 2; i <= NbConnexions; i++) {
382     CurC = Road.Path().Value(i);
383     if (PassByLast(PrevC,CurC)) {
384       //------------------------------------------------------
385       // La portion passe par le dernier element de la ligne.
386       // - ajout de la portion de PrevC au dernier element 
387       //   de la ligne.
388       // - Si la ligne contient plus d'un element ajout de la 
389       //   portion du premier element de la ligne a CurC.
390       //------------------------------------------------------
391       IndLast = FigItem.Value(CurC->IndexFirstLine()).Length();
392       SubSequence (FigItem.Value(CurC->IndexFirstLine()),
393                    PrevC->IndexItemOnSecond(),
394                    IndLast,
395                    SetOfItem);
396       UpDateLink(ILastItem+1,CurC->IndexFirstLine(),
397                  PrevC->IndexItemOnSecond(),IndLast);
398       geomElements.Append(SetOfItem);
399       ILastItem = geomElements.Length();
400
401       if (FigItem.Value(CurC->IndexFirstLine()).Length() > 1) {
402         SubSequence(FigItem.Value(CurC->IndexFirstLine()),
403                     1,
404                     CurC->IndexItemOnFirst(),
405                     SetOfItem);
406         UpDateLink(ILastItem+1,CurC->IndexFirstLine(),
407                    1,CurC->IndexItemOnFirst());
408         geomElements.Append(SetOfItem);
409         ILastItem = geomElements.Length();
410       }
411       connexionMap.Bind(ILastItem+1,CurC);
412     }
413     else{     
414
415       //------------------------------------------------------
416       // La portion ne passe par le dernier element de la ligne.
417       //------------------------------------------------------
418       SubSequence(FigItem.Value(CurC->IndexFirstLine()),
419                   PrevC->IndexItemOnSecond(),
420                   CurC ->IndexItemOnFirst(),
421                   SetOfItem);
422       UpDateLink(ILastItem+1,CurC->IndexFirstLine(),
423                  PrevC->IndexItemOnSecond(),CurC->IndexItemOnFirst());
424       geomElements.Append(SetOfItem);
425       ILastItem = geomElements.Length();
426       connexionMap.Bind(ILastItem+1,CurC);
427     }
428     PrevC = CurC;
429   }
430
431   //-------------------------------------------------------------
432   // Fermeture : de la derniere connexion au dernier element de la
433   //             ligne de reference.
434   //-------------------------------------------------------------
435   IndLast = FigItem.Value(IndRefLine).Length();
436   if (IndLast == 1) {
437     connexionMap.Bind(1,CurC);
438     connexionMap.UnBind(ILastItem+1);
439   }
440   else {
441     SubSequence(FigItem.Value(IndRefLine),
442                 PrevC->IndexItemOnSecond(),
443                 IndLast,
444                 SetOfItem);
445     UpDateLink(ILastItem+1,IndRefLine,PrevC->IndexItemOnSecond(),IndLast);
446     geomElements.Append(SetOfItem);
447     ILastItem = geomElements.Length();
448   }
449
450   //--------------------------------------
451   // Tri des RefToEqui pour chaque element.
452   //--------------------------------------
453   MAT2d_DataMapIteratorOfDataMapOfBiIntSequenceOfInteger Ite;
454
455   for ( Ite.Initialize(linkRefEqui); Ite.More(); Ite.Next()) {
456     if (Ite.Value().Length() > 1) {
457       SortRefToEqui(Ite.Key());
458     }
459   }
460
461 #ifdef DEB   
462   if (AffichCircuit) {
463     ILastItem = geomElements.Length();
464     for (i = 1; i <= ILastItem; i++) {
465       if (geomElements.Value(i)->DynamicType() != STANDARD_TYPE(Geom2d_CartesianPoint) ){
466         MAT2d_DrawCurve
467           (Handle(Geom2d_Curve)::DownCast(geomElements.Value(i)),2);
468       }
469     }
470   }
471 #endif
472 }
473
474 //=============================================================================
475 //function : InitOpen
476 //purpose  :
477 //=============================================================================
478 void MAT2d_Circuit::InitOpen (TColGeom2d_SequenceOfGeometry& Line) const 
479
480   Handle(Geom2d_TrimmedCurve) Curve;
481   Standard_Real               DotProd;
482
483   if (!myIsOpenResult)
484   {
485     Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.First());
486     Line.InsertBefore(1,new Geom2d_CartesianPoint(Curve->StartPoint()));
487     Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Last());
488     Line.Append(new Geom2d_CartesianPoint(Curve->EndPoint()));
489   }
490
491   Standard_Integer addition = (myIsOpenResult)? 1 : 2;
492   for ( Standard_Integer i = addition; i <= Line.Length() - addition; i++) {
493     if ( Abs(CrossProd(Line.Value(i),Line.Value(i+1),DotProd)) > 1.E-8 ||
494          DotProd < 0. ) {
495       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i));
496       Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->EndPoint()));
497       i++;
498     }
499   }
500 }
501
502 //=============================================================================
503 //function : DoubleLine
504 //purpose  :
505 //=============================================================================
506 void MAT2d_Circuit::DoubleLine 
507   (      TColGeom2d_SequenceOfGeometry& Line,
508          MAT2d_SequenceOfConnexion&     ConnexionFrom,
509    const Handle(MAT2d_Connexion)&       ConnexionFather,
510    const Standard_Real                  SideRef)
511 const
512
513   Handle(Standard_Type)          Type;
514   Handle(Geom2d_TrimmedCurve)    Curve;
515   Standard_Integer               NbItems = Line.Length();
516   Standard_Integer               i;
517   Standard_Real                  ProVec,DotProd;
518   Handle(MAT2d_Connexion)        CC;
519
520   //--------------------------
521   // Completion de la ligne.
522   //--------------------------
523   if (!myIsOpenResult)
524   {
525     for ( i = NbItems - 1; i > 1; i--){
526       Type = Line.Value(i)->DynamicType();
527       if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
528         Line.Append(Line.Value(i));
529       }
530       else {
531         Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)->Copy());
532         Curve->Reverse();
533         Line.Append(Curve);
534       }
535     }
536   }
537
538   //------------------------------------------
539   // Repartition des connexions sur la ligne
540   //------------------------------------------
541   Standard_Integer IAfter       = ConnexionFrom.Length();
542   Standard_Integer NbConnexions = IAfter;
543   Standard_Integer IndCOF;
544
545   for (i = 1; i <= IAfter; i++) {
546     CC     = ConnexionFrom.Value(i);
547     IndCOF = CC->IndexItemOnFirst();
548     Type = Line.Value(IndCOF)->DynamicType();
549
550     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
551       if (IndCOF!= NbItems && IndCOF!= 1) {
552         ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd);
553         if ((ProVec)*SideRef > 0){
554            CC->IndexItemOnFirst(2*NbItems - IndCOF);
555            ConnexionFrom.InsertAfter(IAfter,CC);
556            ConnexionFrom.Remove(i);
557            IAfter--;
558            i--;
559          }
560       }
561     }
562     else  if (Side(CC,Line) != SideRef){
563       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF));
564       CC->IndexItemOnFirst(2*NbItems - IndCOF);
565       CC->ParameterOnFirst(Curve->ReversedParameter(CC->ParameterOnFirst()));
566       ConnexionFrom.InsertAfter(IAfter,CC);
567       ConnexionFrom.Remove(i);
568       IAfter--;
569       i--;
570     }
571   }
572
573   //---------------------------
574   // Mise a jour connexion pere.  
575   //---------------------------
576   if (!ConnexionFather.IsNull()) {
577     CC     = ConnexionFather->Reverse();
578     IndCOF = CC->IndexItemOnFirst();
579     Type = Line.Value(IndCOF)->DynamicType();
580
581     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
582       if (IndCOF != NbItems && IndCOF != 1) {
583         ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd);
584         if ((ProVec)*SideRef > 0){
585           ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF);
586          }
587       }
588     }
589     else  if (Side(CC,Line) != SideRef){
590       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF));
591       ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF);
592       ConnexionFather->ParameterOnSecond
593         (Curve->ReversedParameter(ConnexionFather->ParameterOnSecond()));
594     }
595   } 
596   
597   //-------------------------------------
598   // Suppression des cassures rentrantes.
599   //-------------------------------------
600   Standard_Integer        IndLine = 1;
601   Standard_Integer        ICorres = 1;
602   TColStd_Array1OfInteger Corres(1,Line.Length());
603     
604   while (Line.Value(IndLine) != Line.Last()){
605     Corres(ICorres) = IndLine;
606     Type = Line.Value(IndLine)->DynamicType();
607
608     if (Type == STANDARD_TYPE(Geom2d_CartesianPoint) && 
609         ICorres != 1 && ICorres != NbItems)  {
610
611       if (!IsSharpCorner(Line.Value(IndLine - 1),
612                          Line.Value(IndLine + 1),SideRef)){
613         Line.Remove(IndLine);
614         IndLine--;
615         Corres(ICorres) =0;
616       }
617     }
618     IndLine++;
619     ICorres++;
620   }
621   Corres(ICorres) = IndLine;
622
623   if (!myIsOpenResult)
624   {
625     for (i = 1; i < 2*NbItems - 2; i++) {
626       if (Corres(i) == 0)
627         Corres(i) = Corres(2*NbItems - i);
628     }
629     
630 #ifdef DEB
631     if (AffichCircuit) {
632       for (i = 1; i <= 2*NbItems - 2; i++) {
633         cout<< "Correspondance "<< i<<" -> "<<Corres(i)<<endl;
634       }
635     }
636 #endif
637     
638     //----------------------------
639     // Mise a jour des Connexions.
640     //----------------------------
641     for ( i = 1; i <= NbConnexions; i++){
642       CC = ConnexionFrom.ChangeValue(i);
643       CC->IndexItemOnFirst(Corres(CC->IndexItemOnFirst()));
644     }
645     
646     if (!ConnexionFather.IsNull()) {
647       ConnexionFather
648         ->IndexItemOnSecond(Corres(ConnexionFather->IndexItemOnSecond()));
649     }
650   }
651 }
652
653
654 //=============================================================================
655 //function : InsertCorner
656 //purpose :
657 //=============================================================================
658 void  MAT2d_Circuit::InsertCorner (TColGeom2d_SequenceOfGeometry& Line) const
659 {
660   Standard_Integer              i,isuiv;
661   Handle(Geom2d_TrimmedCurve)   Curve;
662   Standard_Boolean              Insert;
663
664   for ( i = 1; i <= Line.Length(); i++) {
665     isuiv  = (i == Line.Length()) ? 1 : i + 1;
666     Insert = IsSharpCorner(Line.Value(i),Line.Value(isuiv),direction);
667
668 #ifdef DEB
669   if (AffichCircuit) {
670     if (Insert) {
671       Curve      = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
672 #ifdef DRAW
673       gp_Pnt2d P = Curve->StartPoint();
674       Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Draw_vert); 
675       dout << dr;
676       dout.Flush();
677 #endif
678     }
679   }
680 #endif
681
682     if (Insert) {     
683       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
684       Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->StartPoint()));
685       i++;
686     }
687   }
688 }
689
690 //=============================================================================
691 //function : NumberOfItem
692 //purpose :
693 //=============================================================================
694 Standard_Integer  MAT2d_Circuit::NumberOfItems()const 
695 {
696   return geomElements.Length();
697 }
698
699 //=============================================================================
700 //function : LineLength 
701 //purpose  :
702 //=============================================================================
703 Standard_Integer MAT2d_Circuit::LineLength(const Standard_Integer I) const
704 {
705   return linesLength(I);
706 }
707
708 //=============================================================================
709 //function : Value
710 //purpose  :
711 //=============================================================================
712 Handle(Geom2d_Geometry)  MAT2d_Circuit::Value 
713        (const Standard_Integer Index)const
714 {
715   return geomElements.Value(Index);
716 }
717
718 //=============================================================================
719 //function : RefToEqui
720 //purpose  :
721 //=============================================================================
722 const TColStd_SequenceOfInteger&  MAT2d_Circuit::RefToEqui
723        (const Standard_Integer IndLine, 
724         const Standard_Integer IndCurve) const
725 {
726   MAT2d_BiInt Key(IndLine,IndCurve);
727   return linkRefEqui(Key);
728 }
729
730 //=============================================================================
731 //function : SortRefToEqui
732 //purpose  :
733 //=============================================================================
734 void MAT2d_Circuit::SortRefToEqui (const MAT2d_BiInt& BiRef)
735 {
736   Standard_Integer i;
737   TColStd_SequenceOfInteger&  S = linkRefEqui.ChangeFind(BiRef);
738   TColStd_SequenceOfInteger   SFin;
739
740   for( i = 1; i <=  S.Length(); i++){
741     if (!ConnexionOn(S.Value(i))) break;
742   }
743   if ( i > 1 && i <= S.Length()) {
744     SFin = S;
745     SFin.Split(i,S);
746     S.Append(SFin);
747   }
748 }
749
750 //=============================================================================
751 //function : Connexion
752 //purpose  :
753 //=============================================================================
754 Handle(MAT2d_Connexion) MAT2d_Circuit::Connexion(const Standard_Integer I)const
755 {
756   return connexionMap(I);
757 }
758
759 //=============================================================================
760 //function : ConnexionOn
761 //purpose  :
762 //=============================================================================
763 Standard_Boolean  MAT2d_Circuit::ConnexionOn(const Standard_Integer I)const
764 {
765   return connexionMap.IsBound(I);
766 }
767
768 //=============================================================================
769 //function : Side
770 //purpose  :
771 //=============================================================================
772 Standard_Real MAT2d_Circuit::Side
773   (const Handle(MAT2d_Connexion)&               C1,
774    const TColGeom2d_SequenceOfGeometry&         Line)
775 const
776 {
777   Handle(Geom2d_TrimmedCurve) Curve;
778
779   gp_Vec2d Vect1(C1->PointOnSecond().X() - C1->PointOnFirst().X(),
780                  C1->PointOnSecond().Y() - C1->PointOnFirst().Y());
781   Curve = Handle(Geom2d_TrimmedCurve)::DownCast
782                                        (Line.Value(C1->IndexItemOnFirst()));
783   gp_Vec2d Vect2 = Curve->DN(C1->ParameterOnFirst(),1);  
784   if ( (Vect1^Vect2) > 0.) return - 1.; else return 1.;
785 }
786
787 //=============================================================================
788 //function : PassByLast
789 //purpose  :
790 //=============================================================================
791 Standard_Boolean MAT2d_Circuit::PassByLast
792   (const Handle(MAT2d_Connexion)& C1,
793    const Handle(MAT2d_Connexion)& C2) const
794 {
795   if (C2->IndexFirstLine() == C1->IndexSecondLine()){
796     if (C2->IndexItemOnFirst() < C1->IndexItemOnSecond()) {
797       return Standard_True;
798     }
799     else if (C2->IndexItemOnFirst() == C1->IndexItemOnSecond()) {
800       if (C1->IndexFirstLine() == C2->IndexSecondLine()) {
801         return Standard_True;
802       }
803       if (C2->ParameterOnFirst() == C1->ParameterOnSecond()) {
804         gp_Vec2d Vect1(C1->PointOnSecond(),C1->PointOnFirst());
805         gp_Vec2d Vect2(C2->PointOnFirst(),C2->PointOnSecond());
806         if ((Vect1^Vect2)*direction > 0) {
807           return Standard_True;
808         }
809       }
810       else if (C2->ParameterOnFirst() < C1->ParameterOnSecond()) {
811         return Standard_True;
812       }
813     }
814   }
815   return Standard_False;
816 }
817
818 //=============================================================================
819 //function : UpDateLink
820 //purpose  :
821 //=============================================================================
822 void MAT2d_Circuit::UpDateLink(const Standard_Integer IFirst,
823                                const Standard_Integer ILine,
824                                const Standard_Integer ICurveFirst,
825                                const Standard_Integer ICurveLast)
826 {
827   Standard_Integer IEqui = IFirst;
828   Standard_Integer i;
829
830   for (i = ICurveFirst; i <= ICurveLast; i++) {
831     MAT2d_BiInt Key(ILine,i);
832     if (linkRefEqui.IsBound(Key)) {
833       linkRefEqui(Key).Append(IEqui);
834     }
835     else {
836       TColStd_SequenceOfInteger L;
837       linkRefEqui.Bind(Key,L);
838       linkRefEqui(Key).Append(IEqui);
839     }
840     IEqui++;
841   }
842 }
843
844 //==========================================================================
845 //function : CrossProd 
846 //purpose  : Calcul le produit vectoriel et scalaire  entre les directions des
847 //            tangentes a la fin de Geom1 et au debut de Geom2.
848 //            Geom1 et Geom2 doivent etre des courbes.
849 //==========================================================================
850 static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1,
851                                const Handle(Geom2d_Geometry)& Geom2,
852                                      Standard_Real&           DotProd)
853 {
854   Handle(Geom2d_TrimmedCurve) Curve;
855
856   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
857   gp_Dir2d Dir1(Curve->DN(Curve->LastParameter(),1));
858   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
859   gp_Dir2d Dir2(Curve->DN(Curve->FirstParameter(),1));
860   DotProd = Dir1.Dot(Dir2);
861   return Dir1^Dir2;
862 }
863
864
865
866
867
868 #ifdef DEB
869 //==========================================================================
870 //function : MAT2d_DrawCurve
871 //purpose  : Affichage d une courbe <aCurve> de Geom2d. dans une couleur
872 //            definie par <Indice>.
873 //            Indice = 1 jaune,
874 //            Indice = 2 bleu,
875 //            Indice = 3 rouge,
876 //            Indice = 4 vert.
877 //==========================================================================
878 void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve,
879                      const Standard_Integer      /*Indice*/)
880 {  
881   Handle(Standard_Type)      type = aCurve->DynamicType();
882   Handle(Geom2d_Curve)       curve,CurveDraw;
883 #ifdef DRAW
884   Handle(DrawTrSurf_Curve2d) dr;
885   Draw_Color                 Couleur;
886 #endif
887
888   if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
889     curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
890     type = curve->DynamicType();    
891     // PB de representation des courbes semi_infinies.
892     gp_Parab2d gpParabola;
893     gp_Hypr2d  gpHyperbola;
894     Standard_Real Focus;
895     Standard_Real Limit = 50000.;
896     Standard_Real delta = 400;
897
898     // PB de representation des courbes semi_infinies.
899     if (aCurve->LastParameter() == Precision::Infinite()) {
900       
901       if (type == STANDARD_TYPE(Geom2d_Parabola)) {
902         gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d();
903         Focus = gpParabola.Focal();
904         Standard_Real Val1 = Sqrt(Limit*Focus);
905         Standard_Real Val2 = Sqrt(Limit*Limit);
906                       delta= (Val1 <= Val2 ? Val1:Val2);
907       }
908       else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) {
909         gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d();
910         Standard_Real Majr  = gpHyperbola.MajorRadius();
911         Standard_Real Minr  = gpHyperbola.MinorRadius();
912         Standard_Real Valu1 = Limit/Majr;
913         Standard_Real Valu2 = Limit/Minr;
914         Standard_Real Val1  = Log(Valu1+Sqrt(Valu1*Valu1-1));
915         Standard_Real Val2  = Log(Valu2+Sqrt(Valu2*Valu2+1));
916                       delta  = (Val1 <= Val2 ? Val1:Val2);
917       }
918       CurveDraw = new Geom2d_TrimmedCurve(aCurve,
919                                           aCurve->FirstParameter(),
920                                           aCurve->FirstParameter() + delta);
921     }
922     else {
923       CurveDraw = aCurve;
924     }
925     // fin PB.
926   }
927   else {
928     CurveDraw = aCurve;
929   }
930
931 #ifdef DRAW
932   if      (Indice == 1) Couleur = Draw_jaune;
933   else if (Indice == 2) Couleur = Draw_bleu;
934   else if (Indice == 3) Couleur = Draw_rouge;
935   else if (Indice == 4) Couleur = Draw_vert;
936
937   if (type == STANDARD_TYPE(Geom2d_Circle))
938     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30);
939   else if (type  == STANDARD_TYPE(Geom2d_Line))
940     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2);
941   else
942     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500);
943
944   dout << dr;
945   dout.Flush();
946 #endif
947 }
948
949 #endif
950