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