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