0025334: BRepOffsetAPI_MakeOffset algorithm crashes on some customer's shape
[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   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.First());
484   Line.InsertBefore(1,new Geom2d_CartesianPoint(Curve->StartPoint()));
485   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Last());
486   Line.Append(new Geom2d_CartesianPoint(Curve->EndPoint()));
487   
488   for ( Standard_Integer i = 2; i <= Line.Length() - 2; i++) {
489     if ( Abs(CrossProd(Line.Value(i),Line.Value(i+1),DotProd)) > 1.E-8 ||
490          DotProd < 0. ) {
491       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i));
492       Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->EndPoint()));
493       i++;
494     }
495   }
496 }
497
498 //=============================================================================
499 //function : DoubleLine
500 //purpose  :
501 //=============================================================================
502 void MAT2d_Circuit::DoubleLine 
503   (      TColGeom2d_SequenceOfGeometry& Line,
504          MAT2d_SequenceOfConnexion&     ConnexionFrom,
505    const Handle(MAT2d_Connexion)&       ConnexionFather,
506    const Standard_Real                  SideRef)
507 const
508
509   Handle(Standard_Type)          Type;
510   Handle(Geom2d_TrimmedCurve)    Curve;
511   Standard_Integer               NbItems = Line.Length();
512   Standard_Integer               i;
513   Standard_Real                  ProVec,DotProd;
514   Handle(MAT2d_Connexion)        CC;
515
516   //--------------------------
517   // Completion de la ligne.
518   //--------------------------
519   if (!myIsOpenResult)
520   {
521     for ( i = NbItems - 1; i > 1; i--){
522       Type = Line.Value(i)->DynamicType();
523       if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
524         Line.Append(Line.Value(i));
525       }
526       else {
527         Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)->Copy());
528         Curve->Reverse();
529         Line.Append(Curve);
530       }
531     }
532   }
533
534   //------------------------------------------
535   // Repartition des connexions sur la ligne
536   //------------------------------------------
537   Standard_Integer IAfter       = ConnexionFrom.Length();
538   Standard_Integer NbConnexions = IAfter;
539   Standard_Integer IndCOF;
540
541   for (i = 1; i <= IAfter; i++) {
542     CC     = ConnexionFrom.Value(i);
543     IndCOF = CC->IndexItemOnFirst();
544     Type = Line.Value(IndCOF)->DynamicType();
545
546     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
547       if (IndCOF!= NbItems && IndCOF!= 1) {
548         ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd);
549         if ((ProVec)*SideRef > 0){
550            CC->IndexItemOnFirst(2*NbItems - IndCOF);
551            ConnexionFrom.InsertAfter(IAfter,CC);
552            ConnexionFrom.Remove(i);
553            IAfter--;
554            i--;
555          }
556       }
557     }
558     else  if (Side(CC,Line) != SideRef){
559       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF));
560       CC->IndexItemOnFirst(2*NbItems - IndCOF);
561       CC->ParameterOnFirst(Curve->ReversedParameter(CC->ParameterOnFirst()));
562       ConnexionFrom.InsertAfter(IAfter,CC);
563       ConnexionFrom.Remove(i);
564       IAfter--;
565       i--;
566     }
567   }
568
569   //---------------------------
570   // Mise a jour connexion pere.  
571   //---------------------------
572   if (!ConnexionFather.IsNull()) {
573     CC     = ConnexionFather->Reverse();
574     IndCOF = CC->IndexItemOnFirst();
575     Type = Line.Value(IndCOF)->DynamicType();
576
577     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
578       if (IndCOF != NbItems && IndCOF != 1) {
579         ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd);
580         if ((ProVec)*SideRef > 0){
581           ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF);
582          }
583       }
584     }
585     else  if (Side(CC,Line) != SideRef){
586       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF));
587       ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF);
588       ConnexionFather->ParameterOnSecond
589         (Curve->ReversedParameter(ConnexionFather->ParameterOnSecond()));
590     }
591   } 
592   
593   //-------------------------------------
594   // Suppression des cassures rentrantes.
595   //-------------------------------------
596   Standard_Integer        IndLine = 1;
597   Standard_Integer        ICorres = 1;
598   TColStd_Array1OfInteger Corres(1,Line.Length());
599     
600   while (Line.Value(IndLine) != Line.Last()){
601     Corres(ICorres) = IndLine;
602     Type = Line.Value(IndLine)->DynamicType();
603
604     if (Type == STANDARD_TYPE(Geom2d_CartesianPoint) && 
605         ICorres != 1 && ICorres != NbItems)  {
606
607       if (!IsSharpCorner(Line.Value(IndLine - 1),
608                          Line.Value(IndLine + 1),SideRef)){
609         Line.Remove(IndLine);
610         IndLine--;
611         Corres(ICorres) =0;
612       }
613     }
614     IndLine++;
615     ICorres++;
616   }
617   Corres(ICorres) = IndLine;
618
619   if (!myIsOpenResult)
620   {
621     for (i = 1; i < 2*NbItems - 2; i++) {
622       if (Corres(i) == 0)
623         Corres(i) = Corres(2*NbItems - i);
624     }
625     
626 #ifdef DEB
627     if (AffichCircuit) {
628       for (i = 1; i <= 2*NbItems - 2; i++) {
629         cout<< "Correspondance "<< i<<" -> "<<Corres(i)<<endl;
630       }
631     }
632 #endif
633     
634     //----------------------------
635     // Mise a jour des Connexions.
636     //----------------------------
637     for ( i = 1; i <= NbConnexions; i++){
638       CC = ConnexionFrom.ChangeValue(i);
639       CC->IndexItemOnFirst(Corres(CC->IndexItemOnFirst()));
640     }
641     
642     if (!ConnexionFather.IsNull()) {
643       ConnexionFather
644         ->IndexItemOnSecond(Corres(ConnexionFather->IndexItemOnSecond()));
645     }
646   }
647 }
648
649
650 //=============================================================================
651 //function : InsertCorner
652 //purpose :
653 //=============================================================================
654 void  MAT2d_Circuit::InsertCorner (TColGeom2d_SequenceOfGeometry& Line) const
655 {
656   Standard_Integer              i,isuiv;
657   Handle(Geom2d_TrimmedCurve)   Curve;
658   Standard_Boolean              Insert;
659
660   for ( i = 1; i <= Line.Length(); i++) {
661     isuiv  = (i == Line.Length()) ? 1 : i + 1;
662     Insert = IsSharpCorner(Line.Value(i),Line.Value(isuiv),direction);
663
664 #ifdef DEB
665   if (AffichCircuit) {
666     if (Insert) {
667       Curve      = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
668 #ifdef DRAW
669       gp_Pnt2d P = Curve->StartPoint();
670       Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Draw_vert); 
671       dout << dr;
672       dout.Flush();
673 #endif
674     }
675   }
676 #endif
677
678     if (Insert) {     
679       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
680       Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->StartPoint()));
681       i++;
682     }
683   }
684 }
685
686 //=============================================================================
687 //function : NumberOfItem
688 //purpose :
689 //=============================================================================
690 Standard_Integer  MAT2d_Circuit::NumberOfItems()const 
691 {
692   return geomElements.Length();
693 }
694
695 //=============================================================================
696 //function : LineLength 
697 //purpose  :
698 //=============================================================================
699 Standard_Integer MAT2d_Circuit::LineLength(const Standard_Integer I) const
700 {
701   return linesLength(I);
702 }
703
704 //=============================================================================
705 //function : Value
706 //purpose  :
707 //=============================================================================
708 Handle(Geom2d_Geometry)  MAT2d_Circuit::Value 
709        (const Standard_Integer Index)const
710 {
711   return geomElements.Value(Index);
712 }
713
714 //=============================================================================
715 //function : RefToEqui
716 //purpose  :
717 //=============================================================================
718 const TColStd_SequenceOfInteger&  MAT2d_Circuit::RefToEqui
719        (const Standard_Integer IndLine, 
720         const Standard_Integer IndCurve) const
721 {
722   MAT2d_BiInt Key(IndLine,IndCurve);
723   return linkRefEqui(Key);
724 }
725
726 //=============================================================================
727 //function : SortRefToEqui
728 //purpose  :
729 //=============================================================================
730 void MAT2d_Circuit::SortRefToEqui (const MAT2d_BiInt& BiRef)
731 {
732   Standard_Integer i;
733   TColStd_SequenceOfInteger&  S = linkRefEqui.ChangeFind(BiRef);
734   TColStd_SequenceOfInteger   SFin;
735
736   for( i = 1; i <=  S.Length(); i++){
737     if (!ConnexionOn(S.Value(i))) break;
738   }
739   if ( i > 1 && i <= S.Length()) {
740     SFin = S;
741     SFin.Split(i,S);
742     S.Append(SFin);
743   }
744 }
745
746 //=============================================================================
747 //function : Connexion
748 //purpose  :
749 //=============================================================================
750 Handle(MAT2d_Connexion) MAT2d_Circuit::Connexion(const Standard_Integer I)const
751 {
752   return connexionMap(I);
753 }
754
755 //=============================================================================
756 //function : ConnexionOn
757 //purpose  :
758 //=============================================================================
759 Standard_Boolean  MAT2d_Circuit::ConnexionOn(const Standard_Integer I)const
760 {
761   return connexionMap.IsBound(I);
762 }
763
764 //=============================================================================
765 //function : Side
766 //purpose  :
767 //=============================================================================
768 Standard_Real MAT2d_Circuit::Side
769   (const Handle(MAT2d_Connexion)&               C1,
770    const TColGeom2d_SequenceOfGeometry&         Line)
771 const
772 {
773   Handle(Geom2d_TrimmedCurve) Curve;
774
775   gp_Vec2d Vect1(C1->PointOnSecond().X() - C1->PointOnFirst().X(),
776                  C1->PointOnSecond().Y() - C1->PointOnFirst().Y());
777   Curve = Handle(Geom2d_TrimmedCurve)::DownCast
778                                        (Line.Value(C1->IndexItemOnFirst()));
779   gp_Vec2d Vect2 = Curve->DN(C1->ParameterOnFirst(),1);  
780   if ( (Vect1^Vect2) > 0.) return - 1.; else return 1.;
781 }
782
783 //=============================================================================
784 //function : PassByLast
785 //purpose  :
786 //=============================================================================
787 Standard_Boolean MAT2d_Circuit::PassByLast
788   (const Handle(MAT2d_Connexion)& C1,
789    const Handle(MAT2d_Connexion)& C2) const
790 {
791   if (C2->IndexFirstLine() == C1->IndexSecondLine()){
792     if (C2->IndexItemOnFirst() < C1->IndexItemOnSecond()) {
793       return Standard_True;
794     }
795     else if (C2->IndexItemOnFirst() == C1->IndexItemOnSecond()) {
796       if (C1->IndexFirstLine() == C2->IndexSecondLine()) {
797         return Standard_True;
798       }
799       if (C2->ParameterOnFirst() == C1->ParameterOnSecond()) {
800         gp_Vec2d Vect1(C1->PointOnSecond(),C1->PointOnFirst());
801         gp_Vec2d Vect2(C2->PointOnFirst(),C2->PointOnSecond());
802         if ((Vect1^Vect2)*direction > 0) {
803           return Standard_True;
804         }
805       }
806       else if (C2->ParameterOnFirst() < C1->ParameterOnSecond()) {
807         return Standard_True;
808       }
809     }
810   }
811   return Standard_False;
812 }
813
814 //=============================================================================
815 //function : UpDateLink
816 //purpose  :
817 //=============================================================================
818 void MAT2d_Circuit::UpDateLink(const Standard_Integer IFirst,
819                                const Standard_Integer ILine,
820                                const Standard_Integer ICurveFirst,
821                                const Standard_Integer ICurveLast)
822 {
823   Standard_Integer IEqui = IFirst;
824   Standard_Integer i;
825
826   for (i = ICurveFirst; i <= ICurveLast; i++) {
827     MAT2d_BiInt Key(ILine,i);
828     if (linkRefEqui.IsBound(Key)) {
829       linkRefEqui(Key).Append(IEqui);
830     }
831     else {
832       TColStd_SequenceOfInteger L;
833       linkRefEqui.Bind(Key,L);
834       linkRefEqui(Key).Append(IEqui);
835     }
836     IEqui++;
837   }
838 }
839
840 //==========================================================================
841 //function : CrossProd 
842 //purpose  : Calcul le produit vectoriel et scalaire  entre les directions des
843 //            tangentes a la fin de Geom1 et au debut de Geom2.
844 //            Geom1 et Geom2 doivent etre des courbes.
845 //==========================================================================
846 static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1,
847                                const Handle(Geom2d_Geometry)& Geom2,
848                                      Standard_Real&           DotProd)
849 {
850   Handle(Geom2d_TrimmedCurve) Curve;
851
852   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
853   gp_Dir2d Dir1(Curve->DN(Curve->LastParameter(),1));
854   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
855   gp_Dir2d Dir2(Curve->DN(Curve->FirstParameter(),1));
856   DotProd = Dir1.Dot(Dir2);
857   return Dir1^Dir2;
858 }
859
860
861
862
863
864 #ifdef DEB
865 //==========================================================================
866 //function : MAT2d_DrawCurve
867 //purpose  : Affichage d une courbe <aCurve> de Geom2d. dans une couleur
868 //            definie par <Indice>.
869 //            Indice = 1 jaune,
870 //            Indice = 2 bleu,
871 //            Indice = 3 rouge,
872 //            Indice = 4 vert.
873 //==========================================================================
874 void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve,
875                      const Standard_Integer      /*Indice*/)
876 {  
877   Handle(Standard_Type)      type = aCurve->DynamicType();
878   Handle(Geom2d_Curve)       curve,CurveDraw;
879 #ifdef DRAW
880   Handle(DrawTrSurf_Curve2d) dr;
881   Draw_Color                 Couleur;
882 #endif
883
884   if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
885     curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
886     type = curve->DynamicType();    
887     // PB de representation des courbes semi_infinies.
888     gp_Parab2d gpParabola;
889     gp_Hypr2d  gpHyperbola;
890     Standard_Real Focus;
891     Standard_Real Limit = 50000.;
892     Standard_Real delta = 400;
893
894     // PB de representation des courbes semi_infinies.
895     if (aCurve->LastParameter() == Precision::Infinite()) {
896       
897       if (type == STANDARD_TYPE(Geom2d_Parabola)) {
898         gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d();
899         Focus = gpParabola.Focal();
900         Standard_Real Val1 = Sqrt(Limit*Focus);
901         Standard_Real Val2 = Sqrt(Limit*Limit);
902                       delta= (Val1 <= Val2 ? Val1:Val2);
903       }
904       else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) {
905         gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d();
906         Standard_Real Majr  = gpHyperbola.MajorRadius();
907         Standard_Real Minr  = gpHyperbola.MinorRadius();
908         Standard_Real Valu1 = Limit/Majr;
909         Standard_Real Valu2 = Limit/Minr;
910         Standard_Real Val1  = Log(Valu1+Sqrt(Valu1*Valu1-1));
911         Standard_Real Val2  = Log(Valu2+Sqrt(Valu2*Valu2+1));
912                       delta  = (Val1 <= Val2 ? Val1:Val2);
913       }
914       CurveDraw = new Geom2d_TrimmedCurve(aCurve,
915                                           aCurve->FirstParameter(),
916                                           aCurve->FirstParameter() + delta);
917     }
918     else {
919       CurveDraw = aCurve;
920     }
921     // fin PB.
922   }
923   else {
924     CurveDraw = aCurve;
925   }
926
927 #ifdef DRAW
928   if      (Indice == 1) Couleur = Draw_jaune;
929   else if (Indice == 2) Couleur = Draw_bleu;
930   else if (Indice == 3) Couleur = Draw_rouge;
931   else if (Indice == 4) Couleur = Draw_vert;
932
933   if (type == STANDARD_TYPE(Geom2d_Circle))
934     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30);
935   else if (type  == STANDARD_TYPE(Geom2d_Line))
936     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2);
937   else
938     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500);
939
940   dout << dr;
941   dout.Flush();
942 #endif
943 }
944
945 #endif
946