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