38f314220506f8cd4968fe2e750fed4f0db4157a
[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 static Standard_Boolean IsSharpCorner (const Handle(Geom2d_Geometry)& Geom1,
71                                        const Handle(Geom2d_Geometry)& Geom2,
72                                        const Standard_Real&           Direction);
73
74 //=============================================================================
75 //function : Constructor
76 //purpose :
77 //=============================================================================
78 MAT2d_Circuit::MAT2d_Circuit()
79 {
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 : SubSequence
208 //purpose  : 
209 //=======================================================================
210 static void SubSequence(const TColGeom2d_SequenceOfGeometry& S1,
211                               Standard_Integer               IF,
212                               Standard_Integer               IL,
213                               TColGeom2d_SequenceOfGeometry& S2)
214 {
215   S2.Clear();
216   for (Standard_Integer i = IF; i<= IL; i++){
217     S2.Append(S1.Value(i));
218   }
219 }
220
221                         
222 //=============================================================================
223 //function : ConstructCircuit
224 //purpose :
225 //=============================================================================
226 void  MAT2d_Circuit::ConstructCircuit
227   (const MAT2d_SequenceOfSequenceOfGeometry& FigItem, 
228    const Standard_Integer                    IndRefLine,
229    const MAT2d_MiniPath&                     Road)
230 {
231   Handle(MAT2d_Connexion)            PrevC,CurC;
232   TColGeom2d_SequenceOfGeometry      SetOfItem;
233   Standard_Integer                   NbConnexions;
234   Standard_Integer                   ILastItem;
235   Standard_Integer                   IndLast;
236   Standard_Integer                   i;
237   
238   NbConnexions = Road.Path().Length();
239   //-----------------------------------------------------
240   // Depart du premier element de la ligne de reference.
241   //-----------------------------------------------------
242   PrevC = Road.Path().Value(1);
243   SubSequence(FigItem.Value(IndRefLine),
244               1,
245               PrevC->IndexItemOnFirst(),
246               geomElements);
247   UpDateLink(1,IndRefLine,1,PrevC->IndexItemOnFirst());
248   connexionMap.Bind(geomElements.Length()+1,PrevC);
249   ILastItem = geomElements.Length();
250   
251   //-----------------------------------------------------------------------
252   // Ajout des portion de lignes delimites par deux connexions successives.
253   //-----------------------------------------------------------------------
254   for ( i = 2; i <= NbConnexions; i++) {
255     CurC = Road.Path().Value(i);
256     if (PassByLast(PrevC,CurC)) {
257       //------------------------------------------------------
258       // La portion passe par le dernier element de la ligne.
259       // - ajout de la portion de PrevC au dernier element 
260       //   de la ligne.
261       // - Si la ligne contient plus d'un element ajout de la 
262       //   portion du premier element de la ligne a CurC.
263       //------------------------------------------------------
264       IndLast = FigItem.Value(CurC->IndexFirstLine()).Length();
265       SubSequence (FigItem.Value(CurC->IndexFirstLine()),
266                    PrevC->IndexItemOnSecond(),
267                    IndLast,
268                    SetOfItem);
269       UpDateLink(ILastItem+1,CurC->IndexFirstLine(),
270                  PrevC->IndexItemOnSecond(),IndLast);
271       geomElements.Append(SetOfItem);
272       ILastItem = geomElements.Length();
273
274       if (FigItem.Value(CurC->IndexFirstLine()).Length() > 1) {
275         SubSequence(FigItem.Value(CurC->IndexFirstLine()),
276                     1,
277                     CurC->IndexItemOnFirst(),
278                     SetOfItem);
279         UpDateLink(ILastItem+1,CurC->IndexFirstLine(),
280                    1,CurC->IndexItemOnFirst());
281         geomElements.Append(SetOfItem);
282         ILastItem = geomElements.Length();
283       }
284       connexionMap.Bind(ILastItem+1,CurC);
285     }
286     else{     
287
288       //------------------------------------------------------
289       // La portion ne passe par le dernier element de la ligne.
290       //------------------------------------------------------
291       SubSequence(FigItem.Value(CurC->IndexFirstLine()),
292                   PrevC->IndexItemOnSecond(),
293                   CurC ->IndexItemOnFirst(),
294                   SetOfItem);
295       UpDateLink(ILastItem+1,CurC->IndexFirstLine(),
296                  PrevC->IndexItemOnSecond(),CurC->IndexItemOnFirst());
297       geomElements.Append(SetOfItem);
298       ILastItem = geomElements.Length();
299       connexionMap.Bind(ILastItem+1,CurC);
300     }
301     PrevC = CurC;
302   }
303
304   //-------------------------------------------------------------
305   // Fermeture : de la derniere connexion au dernier element de la
306   //             ligne de reference.
307   //-------------------------------------------------------------
308   IndLast = FigItem.Value(IndRefLine).Length();
309   if (IndLast == 1) {
310     connexionMap.Bind(1,CurC);
311     connexionMap.UnBind(ILastItem+1);
312   }
313   else {
314     SubSequence(FigItem.Value(IndRefLine),
315                 PrevC->IndexItemOnSecond(),
316                 IndLast,
317                 SetOfItem);
318     UpDateLink(ILastItem+1,IndRefLine,PrevC->IndexItemOnSecond(),IndLast);
319     geomElements.Append(SetOfItem);
320     ILastItem = geomElements.Length();
321   }
322
323   //--------------------------------------
324   // Tri des RefToEqui pour chaque element.
325   //--------------------------------------
326   MAT2d_DataMapIteratorOfDataMapOfBiIntSequenceOfInteger Ite;
327
328   for ( Ite.Initialize(linkRefEqui); Ite.More(); Ite.Next()) {
329     if (Ite.Value().Length() > 1) {
330       SortRefToEqui(Ite.Key());
331     }
332   }
333
334 #ifdef DEB   
335   if (AffichCircuit) {
336     ILastItem = geomElements.Length();
337     for (i = 1; i <= ILastItem; i++) {
338       if (geomElements.Value(i)->DynamicType() != STANDARD_TYPE(Geom2d_CartesianPoint) ){
339         MAT2d_DrawCurve
340           (Handle(Geom2d_Curve)::DownCast(geomElements.Value(i)),2);
341       }
342     }
343   }
344 #endif
345 }
346
347 //=============================================================================
348 //function : InitOpen
349 //purpose  :
350 //=============================================================================
351 void MAT2d_Circuit::InitOpen (TColGeom2d_SequenceOfGeometry& Line) const 
352
353   Handle(Geom2d_TrimmedCurve) Curve;
354   Standard_Real               DotProd;
355  
356   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.First());
357   Line.InsertBefore(1,new Geom2d_CartesianPoint(Curve->StartPoint()));
358   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Last());
359   Line.Append(new Geom2d_CartesianPoint(Curve->EndPoint()));
360
361   for ( Standard_Integer i = 2; i <= Line.Length() - 2; i++) {
362     if ( Abs(CrossProd(Line.Value(i),Line.Value(i+1),DotProd)) > 1.E-8 ||
363          DotProd < 0. ) {
364       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i));
365       Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->EndPoint()));
366       i++;
367     }
368   }
369 }
370
371 //=============================================================================
372 //function : DoubleLine
373 //purpose  :
374 //=============================================================================
375 void MAT2d_Circuit::DoubleLine 
376   (      TColGeom2d_SequenceOfGeometry& Line,
377          MAT2d_SequenceOfConnexion&     ConnexionFrom,
378    const Handle(MAT2d_Connexion)&       ConnexionFather,
379    const Standard_Real                  SideRef)
380 const
381
382   Handle(Standard_Type)          Type;
383   Handle(Geom2d_TrimmedCurve)    Curve;
384   Standard_Integer               NbItems = Line.Length();
385   Standard_Integer               i;
386   Standard_Real                  ProVec,DotProd;
387   Handle(MAT2d_Connexion)        CC;
388
389   //--------------------------
390   // Completion de la ligne.
391   //--------------------------
392   for ( i = NbItems - 1; i > 1; i--){
393     Type = Line.Value(i)->DynamicType();
394     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
395       Line.Append(Line.Value(i));
396     }
397     else {
398       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)->Copy());
399       Curve->Reverse();
400       Line.Append(Curve);
401     }
402   }
403
404   //------------------------------------------
405   // Repartition des connexions sur la ligne
406   //------------------------------------------
407   Standard_Integer IAfter       = ConnexionFrom.Length();
408   Standard_Integer NbConnexions = IAfter;
409   Standard_Integer IndCOF;
410
411   for (i = 1; i <= IAfter; i++) {
412     CC     = ConnexionFrom.Value(i);
413     IndCOF = CC->IndexItemOnFirst();
414     Type = Line.Value(IndCOF)->DynamicType();
415
416     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
417       if (IndCOF!= NbItems && IndCOF!= 1) {
418         ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd);
419         if ((ProVec)*SideRef > 0){
420            CC->IndexItemOnFirst(2*NbItems - IndCOF);
421            ConnexionFrom.InsertAfter(IAfter,CC);
422            ConnexionFrom.Remove(i);
423            IAfter--;
424            i--;
425          }
426       }
427     }
428     else  if (Side(CC,Line) != SideRef){
429       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF));
430       CC->IndexItemOnFirst(2*NbItems - IndCOF);
431       CC->ParameterOnFirst(Curve->ReversedParameter(CC->ParameterOnFirst()));
432       ConnexionFrom.InsertAfter(IAfter,CC);
433       ConnexionFrom.Remove(i);
434       IAfter--;
435       i--;
436     }
437   }
438
439   //---------------------------
440   // Mise a jour connexion pere.  
441   //---------------------------
442   if (!ConnexionFather.IsNull()) {
443     CC     = ConnexionFather->Reverse();
444     IndCOF = CC->IndexItemOnFirst();
445     Type = Line.Value(IndCOF)->DynamicType();
446
447     if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
448       if (IndCOF != NbItems && IndCOF != 1) {
449         ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd);
450         if ((ProVec)*SideRef > 0){
451           ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF);
452          }
453       }
454     }
455     else  if (Side(CC,Line) != SideRef){
456       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF));
457       ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF);
458       ConnexionFather->ParameterOnSecond
459         (Curve->ReversedParameter(ConnexionFather->ParameterOnSecond()));
460     }
461   } 
462   
463   //-------------------------------------
464   // Suppression des cassures rentrantes.
465   //-------------------------------------
466   Standard_Integer        IndLine = 1;
467   Standard_Integer        ICorres = 1;
468   TColStd_Array1OfInteger Corres(1,Line.Length());
469     
470   while (Line.Value(IndLine) != Line.Last()){
471     Corres(ICorres) = IndLine;
472     Type = Line.Value(IndLine)->DynamicType();
473
474     if (Type == STANDARD_TYPE(Geom2d_CartesianPoint) && 
475         ICorres != 1 && ICorres != NbItems)  {
476
477       if (!IsSharpCorner(Line.Value(IndLine - 1),
478                          Line.Value(IndLine + 1),SideRef)){
479         Line.Remove(IndLine);
480         IndLine--;
481         Corres(ICorres) =0;
482       }
483     }
484     IndLine++;
485     ICorres++;
486   }
487   Corres(ICorres) = IndLine;
488   
489   for (i = 1; i < 2*NbItems - 2; i++) {
490     if (Corres(i) == 0) Corres(i) = Corres(2*NbItems - i);
491   }
492
493 #ifdef DEB
494   if (AffichCircuit) {
495     for (i = 1; i <= 2*NbItems - 2; i++) {
496       cout<< "Correspondance "<< i<<" -> "<<Corres(i)<<endl;
497     }
498   }
499 #endif
500
501   //----------------------------
502   // Mise a jour des Connexions.
503   //----------------------------
504   for ( i = 1; i <= NbConnexions; i++){
505     CC = ConnexionFrom.ChangeValue(i);
506     CC->IndexItemOnFirst(Corres(CC->IndexItemOnFirst()));
507   }
508
509   if (!ConnexionFather.IsNull()) {
510     ConnexionFather
511       ->IndexItemOnSecond(Corres(ConnexionFather->IndexItemOnSecond()));
512   }
513 }
514
515
516 //=============================================================================
517 //function : InsertCorner
518 //purpose :
519 //=============================================================================
520 void  MAT2d_Circuit::InsertCorner (TColGeom2d_SequenceOfGeometry& Line) const
521 {
522   Standard_Integer              i,isuiv;
523   Handle(Geom2d_TrimmedCurve)   Curve;
524   Standard_Boolean              Insert;
525
526   for ( i = 1; i <= Line.Length(); i++) {
527     isuiv  = (i == Line.Length()) ? 1 : i + 1;
528     Insert = IsSharpCorner(Line.Value(i),Line.Value(isuiv),direction);
529
530 #ifdef DEB
531   if (AffichCircuit) {
532     if (Insert) {
533       Curve      = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
534 #ifdef DRAW
535       gp_Pnt2d P = Curve->StartPoint();
536       Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Draw_vert); 
537       dout << dr;
538       dout.Flush();
539 #endif
540     }
541   }
542 #endif
543
544     if (Insert) {     
545       Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
546       Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->StartPoint()));
547       i++;
548     }
549   }
550 }
551
552 //=============================================================================
553 //function : NumberOfItem
554 //purpose :
555 //=============================================================================
556 Standard_Integer  MAT2d_Circuit::NumberOfItems()const 
557 {
558   return geomElements.Length();
559 }
560
561 //=============================================================================
562 //function : LineLength 
563 //purpose  :
564 //=============================================================================
565 Standard_Integer MAT2d_Circuit::LineLength(const Standard_Integer I) const
566 {
567   return linesLength(I);
568 }
569
570 //=============================================================================
571 //function : Value
572 //purpose  :
573 //=============================================================================
574 Handle(Geom2d_Geometry)  MAT2d_Circuit::Value 
575        (const Standard_Integer Index)const
576 {
577   return geomElements.Value(Index);
578 }
579
580 //=============================================================================
581 //function : RefToEqui
582 //purpose  :
583 //=============================================================================
584 const TColStd_SequenceOfInteger&  MAT2d_Circuit::RefToEqui
585        (const Standard_Integer IndLine, 
586         const Standard_Integer IndCurve) const
587 {
588   MAT2d_BiInt Key(IndLine,IndCurve);
589   return linkRefEqui(Key);
590 }
591
592 //=============================================================================
593 //function : SortRefToEqui
594 //purpose  :
595 //=============================================================================
596 void MAT2d_Circuit::SortRefToEqui (const MAT2d_BiInt& BiRef)
597 {
598   Standard_Integer i;
599   TColStd_SequenceOfInteger&  S = linkRefEqui.ChangeFind(BiRef);
600   TColStd_SequenceOfInteger   SFin;
601
602   for( i = 1; i <=  S.Length(); i++){
603     if (!ConnexionOn(S.Value(i))) break;
604   }
605   if ( i > 1 && i <= S.Length()) {
606     SFin = S;
607     SFin.Split(i,S);
608     S.Append(SFin);
609   }
610 }
611
612 //=============================================================================
613 //function : Connexion
614 //purpose  :
615 //=============================================================================
616 Handle(MAT2d_Connexion) MAT2d_Circuit::Connexion(const Standard_Integer I)const
617 {
618   return connexionMap(I);
619 }
620
621 //=============================================================================
622 //function : ConnexionOn
623 //purpose  :
624 //=============================================================================
625 Standard_Boolean  MAT2d_Circuit::ConnexionOn(const Standard_Integer I)const
626 {
627   return connexionMap.IsBound(I);
628 }
629
630 //=============================================================================
631 //function : Side
632 //purpose  :
633 //=============================================================================
634 Standard_Real MAT2d_Circuit::Side
635   (const Handle(MAT2d_Connexion)&               C1,
636    const TColGeom2d_SequenceOfGeometry&         Line)
637 const
638 {
639   Handle(Geom2d_TrimmedCurve) Curve;
640
641   gp_Vec2d Vect1(C1->PointOnSecond().X() - C1->PointOnFirst().X(),
642                  C1->PointOnSecond().Y() - C1->PointOnFirst().Y());
643   Curve = Handle(Geom2d_TrimmedCurve)::DownCast
644                                        (Line.Value(C1->IndexItemOnFirst()));
645   gp_Vec2d Vect2 = Curve->DN(C1->ParameterOnFirst(),1);  
646   if ( (Vect1^Vect2) > 0.) return - 1.; else return 1.;
647 }
648
649 //=============================================================================
650 //function : PassByLast
651 //purpose  :
652 //=============================================================================
653 Standard_Boolean MAT2d_Circuit::PassByLast
654   (const Handle(MAT2d_Connexion)& C1,
655    const Handle(MAT2d_Connexion)& C2) const
656 {
657   if (C2->IndexFirstLine() == C1->IndexSecondLine()){
658     if (C2->IndexItemOnFirst() < C1->IndexItemOnSecond()) {
659       return Standard_True;
660     }
661     else if (C2->IndexItemOnFirst() == C1->IndexItemOnSecond()) {
662       if (C1->IndexFirstLine() == C2->IndexSecondLine()) {
663         return Standard_True;
664       }
665       if (C2->ParameterOnFirst() == C1->ParameterOnSecond()) {
666         gp_Vec2d Vect1(C1->PointOnSecond(),C1->PointOnFirst());
667         gp_Vec2d Vect2(C2->PointOnFirst(),C2->PointOnSecond());
668         if ((Vect1^Vect2)*direction > 0) {
669           return Standard_True;
670         }
671       }
672       else if (C2->ParameterOnFirst() < C1->ParameterOnSecond()) {
673         return Standard_True;
674       }
675     }
676   }
677   return Standard_False;
678 }
679
680 //=============================================================================
681 //function : UpDateLink
682 //purpose  :
683 //=============================================================================
684 void MAT2d_Circuit::UpDateLink(const Standard_Integer IFirst,
685                                const Standard_Integer ILine,
686                                const Standard_Integer ICurveFirst,
687                                const Standard_Integer ICurveLast)
688 {
689   Standard_Integer IEqui = IFirst;
690   Standard_Integer i;
691
692   for (i = ICurveFirst; i <= ICurveLast; i++) {
693     MAT2d_BiInt Key(ILine,i);
694     if (linkRefEqui.IsBound(Key)) {
695       linkRefEqui(Key).Append(IEqui);
696     }
697     else {
698       TColStd_SequenceOfInteger L;
699       linkRefEqui.Bind(Key,L);
700       linkRefEqui(Key).Append(IEqui);
701     }
702     IEqui++;
703   }
704 }
705
706 //==========================================================================
707 //function : CrossProd 
708 //purpose  : Calcul le produit vectoriel et scalaire  entre les directions des
709 //            tangentes a la fin de Geom1 et au debut de Geom2.
710 //            Geom1 et Geom2 doivent etre des courbes.
711 //==========================================================================
712 static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1,
713                                const Handle(Geom2d_Geometry)& Geom2,
714                                      Standard_Real&           DotProd)
715 {
716   Handle(Geom2d_TrimmedCurve) Curve;
717
718   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
719   gp_Dir2d Dir1(Curve->DN(Curve->LastParameter(),1));
720   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
721   gp_Dir2d Dir2(Curve->DN(Curve->FirstParameter(),1));
722   DotProd = Dir1.Dot(Dir2);
723   return Dir1^Dir2;
724 }
725
726
727 //=======================================================================
728 //function : IsSharpCorner
729 //purpose  : Return True Si le point commun entre <Geom1> et <Geom2> est 
730 //           une cassure saillante par rapport <Direction>
731 //=======================================================================
732
733 static Standard_Boolean IsSharpCorner (const Handle(Geom2d_Geometry)& Geom1,
734                                        const Handle(Geom2d_Geometry)& Geom2,
735                                        const Standard_Real&           Direction)
736 {    
737   Standard_Real    DotProd;
738   Standard_Real    ProVec = CrossProd (Geom1,Geom2,DotProd);
739   Standard_Integer NbTest = 1;
740   Standard_Real    DU = Precision::Confusion();
741   Handle(Geom2d_TrimmedCurve) C1,C2;
742
743   C1= Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
744   C2= Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
745 //  Modified by Sergey KHROMOV - Thu Oct 24 19:02:46 2002 Begin
746 // Add the same criterion as it is in MAT2d_Circuit::InitOpen(..)
747 //  Standard_Real  TolAng = 1.E-5;
748   Standard_Real  TolAng = 1.E-8;
749 //  Modified by Sergey KHROMOV - Thu Oct 24 19:02:47 2002 End
750
751   while (NbTest <= 10) {
752     if      ((ProVec)*Direction < -TolAng)                 
753       return Standard_True;                // Saillant.
754     if      ((ProVec)*Direction >  TolAng)
755       return Standard_False;              // Rentrant.
756     else { 
757       if (DotProd > 0) {
758         return Standard_False;            // Plat.
759       }
760       TolAng = 1.E-8;
761       Standard_Real U1 = C1->LastParameter()  - NbTest*DU;
762       Standard_Real U2 = C2->FirstParameter() + NbTest*DU;
763       gp_Dir2d Dir1(C1->DN(U1,1));
764       gp_Dir2d Dir2(C2->DN(U2,1));
765       DotProd = Dir1.Dot(Dir2);
766       ProVec  =  Dir1^Dir2;
767       NbTest++;
768     } 
769   }
770   
771
772   
773   // Rebroussement.
774   // on calculde des paralleles aux deux courbes du cote du domaine
775   // de calcul
776   // Si pas dintersection => saillant.
777   // Sinon                => rentrant.
778   Standard_Real D ;
779   Standard_Real Tol   = Precision::Confusion();
780   Standard_Real MilC1 = (C1->LastParameter() + C1->FirstParameter())*0.5;
781   Standard_Real MilC2 = (C2->LastParameter() + C2->FirstParameter())*0.5;
782   gp_Pnt2d      P     = C1->Value(C1->LastParameter());
783   gp_Pnt2d      P1    = C1->Value(MilC1);
784   gp_Pnt2d      P2    = C2->Value(MilC2);
785   
786   D = Min(P1.Distance(P),P2.Distance(P));
787   D /= 10;
788
789   if (Direction > 0.) D = -D;
790   
791   Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C1);
792   Handle(Geom2dAdaptor_HCurve) HC2 = new Geom2dAdaptor_HCurve(C2);
793   Adaptor3d_OffsetCurve OC1(HC1,D,MilC1,C1->LastParameter());
794   Adaptor3d_OffsetCurve OC2(HC2,D,C2->FirstParameter(),MilC2);
795   Geom2dInt_GInter Intersect; 
796   Intersect.Perform(OC1,OC2,Tol,Tol);
797   
798 #ifdef DEB
799   static Standard_Boolean Affich = 0;
800   if (Affich) {
801 #ifdef DRAW
802     Standard_Real DU1 = (OC1.LastParameter() - OC1.FirstParameter())/9.;
803     Standard_Real DU2 = (OC2.LastParameter() - OC2.FirstParameter())/9.;
804     for (Standard_Integer ki = 0; ki <= 9; ki++) {
805       gp_Pnt2d P1 = OC1.Value(OC1.FirstParameter()+ki*DU1);
806       gp_Pnt2d P2 = OC2.Value(OC2.FirstParameter()+ki*DU2);
807       Handle(Draw_Marker2D) dr1 = new Draw_Marker2D(P1,Draw_Plus,Draw_vert);
808       Handle(Draw_Marker2D) dr2 = new Draw_Marker2D(P2,Draw_Plus,Draw_rouge); 
809       dout << dr1;
810       dout << dr2;
811     }
812     dout.Flush();
813 #endif
814   }
815 #endif
816   
817   if (Intersect.IsDone() && !Intersect.IsEmpty()) {
818     return Standard_False;
819   }
820   else {
821     return Standard_True;
822   }
823 }
824
825
826
827 #ifdef DEB
828 //==========================================================================
829 //function : MAT2d_DrawCurve
830 //purpose  : Affichage d une courbe <aCurve> de Geom2d. dans une couleur
831 //            definie par <Indice>.
832 //            Indice = 1 jaune,
833 //            Indice = 2 bleu,
834 //            Indice = 3 rouge,
835 //            Indice = 4 vert.
836 //==========================================================================
837 void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve,
838                      const Standard_Integer      /*Indice*/)
839 {  
840   Handle(Standard_Type)      type = aCurve->DynamicType();
841   Handle(Geom2d_Curve)       curve,CurveDraw;
842 #ifdef DRAW
843   Handle(DrawTrSurf_Curve2d) dr;
844   Draw_Color                 Couleur;
845 #endif
846
847   if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
848     curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
849     type = curve->DynamicType();    
850     // PB de representation des courbes semi_infinies.
851     gp_Parab2d gpParabola;
852     gp_Hypr2d  gpHyperbola;
853     Standard_Real Focus;
854     Standard_Real Limit = 50000.;
855     Standard_Real delta = 400;
856
857     // PB de representation des courbes semi_infinies.
858     if (aCurve->LastParameter() == Precision::Infinite()) {
859       
860       if (type == STANDARD_TYPE(Geom2d_Parabola)) {
861         gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d();
862         Focus = gpParabola.Focal();
863         Standard_Real Val1 = Sqrt(Limit*Focus);
864         Standard_Real Val2 = Sqrt(Limit*Limit);
865                       delta= (Val1 <= Val2 ? Val1:Val2);
866       }
867       else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) {
868         gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d();
869         Standard_Real Majr  = gpHyperbola.MajorRadius();
870         Standard_Real Minr  = gpHyperbola.MinorRadius();
871         Standard_Real Valu1 = Limit/Majr;
872         Standard_Real Valu2 = Limit/Minr;
873         Standard_Real Val1  = Log(Valu1+Sqrt(Valu1*Valu1-1));
874         Standard_Real Val2  = Log(Valu2+Sqrt(Valu2*Valu2+1));
875                       delta  = (Val1 <= Val2 ? Val1:Val2);
876       }
877       CurveDraw = new Geom2d_TrimmedCurve(aCurve,
878                                           aCurve->FirstParameter(),
879                                           aCurve->FirstParameter() + delta);
880     }
881     else {
882       CurveDraw = aCurve;
883     }
884     // fin PB.
885   }
886   else {
887     CurveDraw = aCurve;
888   }
889
890 #ifdef DRAW
891   if      (Indice == 1) Couleur = Draw_jaune;
892   else if (Indice == 2) Couleur = Draw_bleu;
893   else if (Indice == 3) Couleur = Draw_rouge;
894   else if (Indice == 4) Couleur = Draw_vert;
895
896   if (type == STANDARD_TYPE(Geom2d_Circle))
897     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30);
898   else if (type  == STANDARD_TYPE(Geom2d_Line))
899     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2);
900   else
901     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500);
902
903   dout << dr;
904   dout.Flush();
905 #endif
906 }
907
908 #endif
909