0025418: Debug output to be limited to OCC development environment
[occt.git] / src / MAT2d / MAT2d_Tool2d.cxx
1 // Created on: 1993-07-12
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 #define Debug(expr)  cout<<" MAT2d_Tool2d.cxx  :  expr :"<<expr<<endl;
18
19 #ifdef DRAW
20 #include <DBRep.hxx>
21 #include <DrawTrSurf.hxx>
22 #include <stdio.h>
23 #endif
24
25 #ifdef DRAW
26 #include <Draw_Appli.hxx>
27 #include <DrawTrSurf_Curve2d.hxx>
28 #include <GCE2d_MakeSegment.hxx>
29 #include <DrawTrSurf.hxx>
30 #endif
31
32 #include <MAT2d_Tool2d.ixx>
33 #include <MAT2d_MiniPath.hxx>
34 #include <MAT2d_Connexion.hxx>
35 #include <MAT2d_SequenceOfSequenceOfGeometry.hxx>
36 #include <MAT_Edge.hxx>
37 #include <Bisector_Curve.hxx>
38 #include <Bisector_BisecAna.hxx>
39 #include <Bisector_BisecCC.hxx>
40 #include <Bisector_Bisec.hxx>
41 #include <Bisector_Inter.hxx>
42 #include <IntRes2d_Domain.hxx>
43 #include <Extrema_ExtPC2d.hxx>
44 #include <Geom2dInt_GInter.hxx>
45 #include <IntRes2d_IntersectionPoint.hxx>
46 #include <IntRes2d_IntersectionSegment.hxx>
47 #include <Geom2d_Geometry.hxx>
48 #include <Geom2d_Point.hxx>
49 #include <Geom2d_Line.hxx>
50 #include <Geom2d_Circle.hxx>
51 #include <Geom2d_Curve.hxx>
52 #include <Geom2d_Parabola.hxx>
53 #include <Geom2d_Hyperbola.hxx>
54 #include <Geom2d_Ellipse.hxx>
55 #include <Geom2d_CartesianPoint.hxx>
56 #include <Geom2d_TrimmedCurve.hxx>
57 #include <Geom2dAdaptor_Curve.hxx>
58 #include <gp_Lin2d.hxx>
59 #include <gp_Hypr2d.hxx>
60 #include <gp_Parab2d.hxx>
61 #include <gp_Elips2d.hxx>
62 #include <gp_Circ2d.hxx>
63 #include <gp_Vec2d.hxx>
64 #include <TColStd_Array1OfReal.hxx>
65 #include <ElCLib.hxx>
66 #include <StdFail_NotDone.hxx>
67 #include <Standard_NotImplemented.hxx>
68 #include <Precision.hxx>
69
70 #ifdef DRAW
71   static Handle(DrawTrSurf_Curve2d) draw;
72 #endif
73 #ifdef OCCT_DEBUG
74   static void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve,
75                               const Standard_Integer      Indice);
76   static Standard_Boolean Store = Standard_False;
77 #endif
78
79 //=====================================================================
80 //  static functions 
81 //=====================================================================
82 static IntRes2d_Domain Domain
83   (const Handle(Geom2d_TrimmedCurve)& Bisector1,
84    const Standard_Real                Tolerance);
85
86 static Handle(Standard_Type) Type (const Handle(Geom2d_Geometry)& acurve);
87
88 static Standard_Boolean AreNeighbours(const Standard_Integer IEdge1,
89                                       const Standard_Integer IEdge2,
90                                       const Standard_Integer NbEdge);
91
92 static void SetTrim(Bisector_Bisec&  Bis , Handle(Geom2d_Curve)& Line1);
93
94 static Standard_Real MAT2d_TOLCONF = 1.e-7;
95
96 //============================================================================
97 //function : 
98 //purpose  :
99 //============================================================================
100 MAT2d_Tool2d::MAT2d_Tool2d()
101 {
102   theDirection         = 1.;
103   theJoinType = GeomAbs_Arc; //default
104   theNumberOfBisectors = 0;
105   theNumberOfVecs      = 0;
106   theNumberOfPnts      = 0;
107 }
108
109 //=============================================================================
110 //function : InitItems
111 //purpose  :
112 //=============================================================================
113 void  MAT2d_Tool2d::InitItems(const Handle(MAT2d_Circuit)& EquiCircuit) 
114 {
115   theGeomBisectors.Clear();
116   theGeomPnts.Clear();
117   theGeomVecs.Clear();
118   theLinesLength.Clear();
119   theNumberOfBisectors = 0;
120   theNumberOfVecs      = 0;
121   theNumberOfPnts      = 0; 
122    
123   theCircuit = EquiCircuit;
124 }
125                         
126 //=============================================================================
127 //function : Sense
128 //purpose  :
129 //=============================================================================
130 void MAT2d_Tool2d::Sense(const MAT_Side aside)
131 {
132   if(aside == MAT_Left) theDirection =  1.;
133   else                  theDirection = -1.;
134 }
135
136 //=============================================================================
137 //function : SetJoinType
138 //purpose  :
139 //=============================================================================
140 void MAT2d_Tool2d::SetJoinType(const GeomAbs_JoinType aJoinType)
141 {
142   theJoinType = aJoinType;
143 }
144
145 //=============================================================================
146 //function : NumberOfItems
147 //purpose  :
148 //=============================================================================
149 Standard_Integer MAT2d_Tool2d::NumberOfItems() const
150 {
151   return theCircuit->NumberOfItems();
152 }
153
154 //=============================================================================
155 //function : ToleranceOfConfusion
156 //purpose  :
157 //=============================================================================
158 Standard_Real MAT2d_Tool2d::ToleranceOfConfusion() const
159 {
160   return 2*MAT2d_TOLCONF;
161 }
162
163 //=============================================================================
164 //function : FirstPoint
165 //purpose  :
166 //=============================================================================
167 Standard_Integer MAT2d_Tool2d::FirstPoint(const Standard_Integer anitem,
168                                                 Standard_Real&   dist  ) 
169 {
170   Handle(Geom2d_Curve) curve;
171   Handle(Geom2d_Point) point;
172   theNumberOfPnts++;
173
174   if (theCircuit->ConnexionOn(anitem)){
175     gp_Pnt2d P1 = theCircuit->Connexion(anitem)->PointOnFirst();
176     gp_Pnt2d P2 = theCircuit->Connexion(anitem)->PointOnSecond();
177     theGeomPnts.Bind(theNumberOfPnts,gp_Pnt2d((P1.X() + P2.X())*0.5,
178                                               (P1.Y() + P2.Y())*0.5));
179     dist = P1.Distance(P2)*0.5;
180     return theNumberOfPnts;
181   }
182
183   Handle(Standard_Type) type;
184   type = theCircuit->Value(anitem)->DynamicType();
185   dist = 0.;
186
187   if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){
188     curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem));
189     theGeomPnts.Bind(theNumberOfPnts,curve->Value(curve->FirstParameter()));
190   }
191   else{
192     point = Handle(Geom2d_Point)::DownCast(theCircuit->Value(anitem));
193     theGeomPnts.Bind(theNumberOfPnts,point->Pnt2d());
194   }
195   return theNumberOfPnts;
196 }
197
198 //=============================================================================
199 //function : TangentBefore
200 //purpose  :
201 //=============================================================================
202 Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem,
203                                              const Standard_Boolean IsOpenResult)
204 {
205   Standard_Integer     item;
206   Handle(Geom2d_Curve) curve;
207   theNumberOfVecs++;
208
209   if (!IsOpenResult)
210     item  = (anitem == theCircuit->NumberOfItems()) ? 1 : (anitem + 1);
211   else
212     item = (anitem == theCircuit->NumberOfItems()) ? (anitem - 1) : (anitem + 1);
213   if (theCircuit->ConnexionOn(item)){
214     Standard_Real x1,y1,x2,y2;
215     theCircuit->Connexion(item)->PointOnFirst().Coord(x1,y1);
216     theCircuit->Connexion(item)->PointOnSecond().Coord(x2,y2);
217     theGeomVecs.Bind(theNumberOfVecs,gp_Vec2d((x2-x1),(y2-y1)));
218     return theNumberOfVecs;
219   }
220
221   Handle(Standard_Type) type;
222   type = theCircuit->Value(anitem)->DynamicType();
223   if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){
224     curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem));
225     theGeomVecs.Bind(theNumberOfVecs,curve->DN(curve->LastParameter(),1));
226   }
227   else {
228     curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item));
229     Standard_Real param = (IsOpenResult && anitem == theCircuit->NumberOfItems())?
230       curve->LastParameter() : curve->FirstParameter();
231     theGeomVecs.Bind(theNumberOfVecs,curve->DN(param,1));
232   }
233
234   return theNumberOfVecs;
235 }
236
237 //=============================================================================
238 //function : TangentAfter
239 //purpose  :
240 //=============================================================================
241 Standard_Integer MAT2d_Tool2d::TangentAfter(const Standard_Integer anitem,
242                                             const Standard_Boolean IsOpenResult)
243 {
244   Standard_Integer     item;
245   Handle(Geom2d_Curve) curve;
246   gp_Vec2d             thevector;
247   theNumberOfVecs++;
248
249   if (theCircuit->ConnexionOn(anitem)){
250     Standard_Real x1,y1,x2,y2;
251     theCircuit->Connexion(anitem)->PointOnFirst().Coord(x1,y1);
252     theCircuit->Connexion(anitem)->PointOnSecond().Coord(x2,y2);
253     theGeomVecs.Bind(theNumberOfVecs,gp_Vec2d((x1-x2),(y1-y2)));
254     return theNumberOfVecs;
255   }
256
257   Handle(Standard_Type) type;
258   type = theCircuit->Value(anitem)->DynamicType();
259   if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){
260     curve     = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem));
261     thevector = curve->DN(curve->FirstParameter(),1);
262   }
263   else {
264     if (!IsOpenResult)
265       item      = (anitem == 1) ? theCircuit->NumberOfItems() : (anitem - 1);
266     else
267       item = (anitem == 1) ? 2 : (anitem - 1);
268     curve     = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item));
269     Standard_Real param = (IsOpenResult && anitem == 1)?
270       curve->FirstParameter() : curve->LastParameter();
271     thevector = curve->DN(param,1);
272   }
273   theGeomVecs.Bind(theNumberOfVecs,thevector.Reversed());
274   return theNumberOfVecs;
275 }
276
277 //=============================================================================
278 //function : Tangent
279 //purpose  :
280 //=============================================================================
281 Standard_Integer MAT2d_Tool2d::Tangent(const Standard_Integer bisector)
282 {
283   theNumberOfVecs++;
284   theGeomVecs.Bind(theNumberOfVecs,GeomBis(bisector).Value()
285                    ->DN(GeomBis(bisector).Value()
286                         ->LastParameter(),1));
287   return theNumberOfVecs;
288 }
289
290 //=============================================================================
291 //function : CreateBisector
292 //purpose  :
293 //=============================================================================
294 void MAT2d_Tool2d::CreateBisector(const Handle(MAT_Bisector)& abisector)
295 {
296   Handle(Geom2d_Point)    point1,point2;
297   Handle(Geom2d_Geometry) elt1,elt2;
298   Bisector_Bisec          bisector;
299   Standard_Real           tolerance    = MAT2d_TOLCONF ;
300
301   Standard_Integer edge1number  = abisector->FirstEdge()->EdgeNumber();
302   Standard_Integer edge2number  = abisector->SecondEdge()->EdgeNumber();
303   Standard_Boolean ontheline    = AreNeighbours(edge1number,
304                                                 edge2number,
305                                                 NumberOfItems());
306   Standard_Boolean InitialNeighbour = ontheline;
307
308   if(theCircuit->ConnexionOn(edge2number)) ontheline = Standard_False;
309
310   elt1 = theCircuit->Value(edge1number);
311   elt2 = theCircuit->Value(edge2number);
312
313   Handle(Standard_Type) type1;
314   type1 = theCircuit->Value(edge1number)->DynamicType();
315   Handle(Standard_Type) type2;
316   type2 = theCircuit->Value(edge2number)->DynamicType();
317   Handle(Geom2d_Curve)  item1;
318   Handle(Geom2d_Curve)  item2;
319
320   if ( type1 != STANDARD_TYPE(Geom2d_CartesianPoint)){
321     item1 = Handle(Geom2d_Curve)::DownCast(elt1);
322   }
323
324   if ( type2 != STANDARD_TYPE(Geom2d_CartesianPoint)){
325     item2 = Handle(Geom2d_Curve)::DownCast(elt2);
326   }
327
328 #ifdef OCCT_DEBUG
329   Standard_Boolean Affich = Standard_False;
330   if (Affich) {
331     cout<<endl; 
332     cout<<"BISECTOR number :  "<<theNumberOfBisectors+1<<endl;
333     cout<<"  Item 1 : "<<endl;
334     cout<<edge1number<<endl;
335     cout<<endl;
336 //    elt1->Dump(1,1);
337     cout<<endl;
338     cout<<"  Item 2 : "<<endl;
339     cout<<edge2number<<endl;
340     cout<<endl;
341 //  elt2->Dump(1,1);
342     cout<<endl;
343   }
344 #endif
345
346   if(type1 != STANDARD_TYPE(Geom2d_CartesianPoint) && 
347      type2 != STANDARD_TYPE(Geom2d_CartesianPoint)) {
348     bisector.Perform(item1,item2,
349                      GeomPnt (abisector->IssuePoint()),
350                      GeomVec (abisector->FirstVector()),
351                      GeomVec (abisector->SecondVector()),
352                      theDirection,tolerance,ontheline);
353   }
354   else if(type1 == STANDARD_TYPE(Geom2d_CartesianPoint) && 
355           type2 == STANDARD_TYPE(Geom2d_CartesianPoint)) {
356     point1 = Handle(Geom2d_Point)::DownCast(elt1);
357     point2 = Handle(Geom2d_Point)::DownCast(elt2);
358     bisector.Perform(point1,point2,
359                      GeomPnt (abisector->IssuePoint()),
360                      GeomVec (abisector->FirstVector()),
361                      GeomVec (abisector->SecondVector()),
362                      theDirection,tolerance,ontheline);
363   }
364   else if(type1 == STANDARD_TYPE(Geom2d_CartesianPoint)) {
365     point1 = Handle(Geom2d_Point)::DownCast(elt1);
366     bisector.Perform(point1,item2,
367                      GeomPnt (abisector->IssuePoint()),
368                      GeomVec (abisector->FirstVector()),
369                      GeomVec (abisector->SecondVector()),
370                      theDirection,tolerance,ontheline);
371   }
372   else {
373     point2 = Handle(Geom2d_Point)::DownCast(elt2);
374     bisector.Perform(item1,point2,
375                      GeomPnt (abisector->IssuePoint()),
376                      GeomVec (abisector->FirstVector()),
377                      GeomVec (abisector->SecondVector()),
378                      theDirection,tolerance,ontheline);
379   }
380
381   //------------------------------
382   // Restriction de la bisectrice.
383   //-----------------------------
384   TrimBisec(bisector,edge1number,InitialNeighbour,1);
385   TrimBisec(bisector,edge2number,InitialNeighbour,2);
386
387   theNumberOfBisectors++;
388   theGeomBisectors.Bind(theNumberOfBisectors,bisector);
389
390   abisector->BisectorNumber(theNumberOfBisectors);
391   abisector->Sense(1);
392
393 #ifdef OCCT_DEBUG
394   Standard_Boolean AffichDraw = Standard_False;
395   if (AffichDraw) Dump(abisector->BisectorNumber(),1);
396   if (Store) {    
397     Handle(Standard_Type) Type1 = Type(bisector.Value()->BasisCurve());    
398     Handle(Geom2d_Curve)  BasisCurve;
399     if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) {
400       BasisCurve = Handle(Bisector_BisecAna)
401         ::DownCast(bisector.Value()->BasisCurve())->Geom2dCurve();
402 #ifdef DRAW
403       char  *name = new char[100];
404       sprintf(name,"BISSEC_%d",abisector->BisectorNumber());
405       DrawTrSurf::Set(name,BasisCurve);
406       delete [] name;
407 #endif
408     }
409   }
410 #endif
411 }
412
413 //=============================================================================
414 //function : TrimBisec
415 //purpose  : Restriction de la bisectrice.
416 //           Restriction des bissectrice separant deux elements lies par une
417 //           connexion ou l un au moins des elements est un cercle.
418 //           Cette restriction est necessaire a la logique de l algorithme.
419 //=============================================================================
420 void MAT2d_Tool2d::TrimBisec (      Bisector_Bisec&  B1,
421                               const Standard_Integer IndexEdge,
422                               const Standard_Boolean InitialNeighbour,
423                               const Standard_Integer StartOrEnd      ) const
424 {
425   Handle(Geom2d_Curve)        Curve;
426   Handle(Geom2d_TrimmedCurve) LineSupportDomain,Line;
427   Handle(Geom2d_Line)         Line1,Line2;
428   
429   //gp_Vec2d             Tan1,Tan2;
430   gp_Pnt2d             Ori; //PEdge;
431   Standard_Integer     INext;
432   INext = (IndexEdge == theCircuit->NumberOfItems()) ? 1  : (IndexEdge + 1);
433   
434   Handle(Standard_Type) EdgeType = theCircuit->Value(IndexEdge)->DynamicType();
435   
436   if (EdgeType != STANDARD_TYPE(Geom2d_CartesianPoint)) {
437     if(!InitialNeighbour) {
438       Curve = Handle(Geom2d_TrimmedCurve)
439         ::DownCast(theCircuit->Value(IndexEdge))->BasisCurve();
440       EdgeType = Curve->DynamicType();
441       //-------------------------------------------------------------------
442       // si l edge est liee a sa voisine  precedente par une connexion.
443       //-------------------------------------------------------------------
444       if (theCircuit->ConnexionOn(IndexEdge) && StartOrEnd == 1){
445         if (EdgeType == STANDARD_TYPE(Geom2d_Circle)) {
446           Ori = Handle(Geom2d_Circle)::DownCast(Curve)->Location();
447           gp_Pnt2d P2 = theCircuit->Connexion(IndexEdge)->PointOnFirst();
448           Line1       = new Geom2d_Line (Ori,gp_Dir2d(P2.X() - Ori.X(),
449                                                       P2.Y() - Ori.Y()));
450         }     
451       }
452       //-----------------------------------------------------------------------
453       // Si l edge est liee a sa voisine suivante par une connexion.
454       //-----------------------------------------------------------------------
455       if (theCircuit->ConnexionOn(INext) && StartOrEnd == 2){
456         if (EdgeType == STANDARD_TYPE(Geom2d_Circle)) {
457           Ori = Handle(Geom2d_Circle)::DownCast(Curve)->Location();
458           gp_Pnt2d P2 = theCircuit->Connexion(INext)->PointOnSecond();
459           Line2       = new Geom2d_Line (Ori,gp_Dir2d(P2.X() - Ori.X(),
460                                                       P2.Y() - Ori.Y()));
461         }
462       }
463       if (Line1.IsNull() && Line2.IsNull()) return;
464
465       //-----------------------------------------------------------------------
466       // Restriction de la bisectrice par les demi-droites liees aux connexions
467       // si elles existent.
468       //-----------------------------------------------------------------------
469       if (!Line1.IsNull()) {
470         Line = new Geom2d_TrimmedCurve(Line1,0.,Precision::Infinite());
471         SetTrim(B1,Line);
472       }
473       if (!Line2.IsNull()) {
474         Line = new Geom2d_TrimmedCurve(Line2,0.,Precision::Infinite());
475         SetTrim(B1,Line);
476       }
477     }
478   }
479 }
480
481 //=============================================================================
482 //function : TrimBisector
483 //purpose  :
484 //=============================================================================
485 Standard_Boolean MAT2d_Tool2d::TrimBisector
486   (const Handle(MAT_Bisector)& abisector)
487 {
488   Standard_Real param = abisector->FirstParameter();
489
490 #ifdef OCCT_DEBUG
491   Standard_Boolean Affich = Standard_False;
492   if (Affich) cout<<"TRIM de "<<abisector->BisectorNumber()<<endl;
493 #endif
494
495   Handle(Geom2d_TrimmedCurve) 
496     bisector = Handle(Geom2d_TrimmedCurve)
497       ::DownCast(ChangeGeomBis(abisector->BisectorNumber()).ChangeValue());
498   
499   if(bisector->BasisCurve()->IsPeriodic() && param == Precision::Infinite()) {
500     param = bisector->FirstParameter() + 2*M_PI;
501   }
502   if (param > bisector->BasisCurve()->LastParameter()) {
503    param = bisector->BasisCurve()->LastParameter(); 
504   }
505   if(bisector->FirstParameter() == param) return Standard_False;
506
507   bisector->SetTrim(bisector->FirstParameter(),param);
508   return Standard_True;
509 }
510
511 //=============================================================================
512 //function : TrimBisector
513 //purpose  :
514 //=============================================================================
515 Standard_Boolean MAT2d_Tool2d::TrimBisector
516   (const Handle(MAT_Bisector)& abisector,
517    const Standard_Integer      apoint)
518 {
519   Standard_Real Param;
520   Handle(Geom2d_TrimmedCurve)
521     Bisector = Handle(Geom2d_TrimmedCurve)::
522       DownCast(ChangeGeomBis(abisector->BisectorNumber()).ChangeValue());
523
524   Handle(Bisector_Curve) Bis = Handle(Bisector_Curve)::
525     DownCast(Bisector->BasisCurve());
526
527 //  Param = ParameterOnCurve(Bisector,theGeomPnts.Value(apoint));
528   Param = Bis->Parameter(GeomPnt (apoint));
529
530   if (Bisector->BasisCurve()->IsPeriodic()) {
531     if (Bisector->FirstParameter() > Param) Param = Param + 2*M_PI;
532   }
533   if(Bisector->FirstParameter() >= Param)return Standard_False;
534   if(Bisector->LastParameter()  <  Param)return Standard_False;
535   Bisector->SetTrim(Bisector->FirstParameter(),Param);
536
537 #ifdef OCCT_DEBUG
538   Standard_Boolean Affich = Standard_False;
539   if (Affich) MAT2d_DrawCurve(Bisector,2);
540 #endif  
541
542   return Standard_True;
543 }
544
545 //=============================================================================
546 //function : Projection
547 //purpose  :
548 //=============================================================================
549 Standard_Boolean MAT2d_Tool2d::Projection (const Standard_Integer IEdge   ,
550                                            const gp_Pnt2d&        PCom    ,
551                                                  Standard_Real&   Distance) 
552      const
553 {  
554   gp_Pnt2d                    PEdge;
555   Handle(Geom2d_Geometry)     Elt    = theCircuit->Value(IEdge);
556   Handle(Standard_Type)       Type   = Elt->DynamicType();      
557   Handle(Geom2d_TrimmedCurve) Curve; 
558   Standard_Integer            INext;   
559   Standard_Real               Eps = MAT2d_TOLCONF;//*10.;
560
561   if (Type == STANDARD_TYPE(Geom2d_CartesianPoint)) {   
562     PEdge     = Handle(Geom2d_Point)::DownCast(Elt)->Pnt2d();
563     Distance  = PCom.Distance(PEdge);   
564   }
565   else {
566     Distance = Precision::Infinite();
567     Curve    = Handle(Geom2d_TrimmedCurve)::DownCast(Elt);      
568     //-----------------------------------------------------------------------
569     // Calcul des parametres MinMax sur l edge si celui ci est lies a ses
570     // voisins par des connexions la courbe de calcul est limitee par 
571     // celles_ci.         
572     //-----------------------------------------------------------------------
573     Standard_Real ParamMin = Curve->FirstParameter();
574     Standard_Real ParamMax = Curve->LastParameter();
575     if (theCircuit->ConnexionOn(IEdge)) {
576       ParamMin = theCircuit->Connexion(IEdge)->ParameterOnSecond(); 
577     }
578     INext = (IEdge == theCircuit->NumberOfItems()) ? 1 : (IEdge + 1);
579     if (theCircuit->ConnexionOn(INext)) {
580       ParamMax = theCircuit->Connexion(INext)->ParameterOnFirst(); 
581       if (Curve->BasisCurve()->IsPeriodic()){
582         ElCLib::AdjustPeriodic(0.,2*M_PI,Eps,ParamMin,ParamMax);
583       }
584     }
585     //---------------------------------------------------------------------
586     // Constuction de la courbe pour les extremas et ajustement des bornes.
587     //---------------------------------------------------------------------
588     Geom2dAdaptor_Curve C1(Curve);
589     GeomAbs_CurveType TypeC1 = C1.GetType();
590     if (TypeC1 == GeomAbs_Circle) {
591       Standard_Real R       = C1.Circle().Radius();
592       Standard_Real EpsCirc = Eps;
593       if ( R < 1.)  EpsCirc = Eps/R;
594       if (!((ParamMax - ParamMin + 2*EpsCirc) < 2*M_PI)) {
595         ParamMax = ParamMax + EpsCirc; ParamMin = ParamMin - EpsCirc;
596       }
597     }
598     else {
599       ParamMax = ParamMax + Eps; ParamMin = ParamMin - Eps; 
600     }
601     //-----------------------------------------------------
602     // Calcul des extremas et stockage minimum de distance.
603     //-----------------------------------------------------
604     Extrema_ExtPC2d Extremas(PCom,C1,ParamMin,ParamMax);
605     if (Extremas.IsDone()){
606       if (Extremas.NbExt() == 0 ) return Standard_False; // Pas de solution!
607       for (Standard_Integer i = 1; i <= Extremas.NbExt(); i++) {
608         if (Extremas.SquareDistance(i) < Distance * Distance) {
609           Distance      = sqrt (Extremas.SquareDistance(i));
610         }
611       }
612     }
613     else {
614       if (TypeC1 == GeomAbs_Circle) {
615         Distance = C1.Circle().Radius();
616       }
617     }
618   }
619   return Standard_True;
620 }
621
622 //=============================================================================
623 //function : IsSameDistance
624 // purpose :
625 //=============================================================================
626 Standard_Boolean MAT2d_Tool2d::IsSameDistance (
627    const Handle(MAT_Bisector)& BisectorOne,
628    const Handle(MAT_Bisector)& BisectorTwo,
629    const gp_Pnt2d&             PCom,
630    Standard_Real&              Distance) const
631 {
632   TColStd_Array1OfReal Dist(1,4);
633   Standard_Integer     IEdge1,IEdge2,IEdge3,IEdge4;
634
635   IEdge1 = BisectorOne->FirstEdge() ->EdgeNumber();
636   IEdge2 = BisectorOne->SecondEdge()->EdgeNumber();
637   IEdge3 = BisectorTwo->FirstEdge() ->EdgeNumber();
638   IEdge4 = BisectorTwo->SecondEdge()->EdgeNumber();
639
640   Projection(IEdge1,PCom,Dist(1));
641   Projection(IEdge2,PCom,Dist(2));
642
643   if      (IEdge3 == IEdge1) Dist(3)  = Dist(1);
644   else if (IEdge3 == IEdge2) Dist(3)  = Dist(2);  
645   else                       Projection(IEdge3,PCom,Dist(3));
646
647   if      (IEdge4 == IEdge1) Dist(4)  = Dist(1);
648   else if (IEdge4 == IEdge2) Dist(4)  = Dist(2);  
649   else                       Projection(IEdge4,PCom,Dist(4));
650
651 #ifdef OCCT_DEBUG
652   Standard_Boolean Affich = Standard_False;
653   if (Affich)
654     for (Standard_Integer j = 1; j <= 4;j++){
655       cout <<"Distance number : "<<j<<" is :"<< Dist(j)<<endl;
656     }
657 #endif
658
659   Standard_Real EpsDist = MAT2d_TOLCONF*100. ;
660   Distance = Dist(1);
661   for (Standard_Integer i = 1; i <= 4; i++){
662     if (theJoinType == GeomAbs_Intersection &&
663         Precision::IsInfinite(Dist(i)))
664       continue;
665     if (Abs(Dist(i) - Distance) > EpsDist) {
666       Distance = Precision::Infinite();
667       return Standard_False;
668     }
669   }
670   return Standard_True;
671 }
672
673 //=============================================================================
674 //function : IntersectBisector
675 //purpose  :
676 //=============================================================================
677 Standard_Real MAT2d_Tool2d::IntersectBisector (
678    const Handle(MAT_Bisector)& BisectorOne,
679    const Handle(MAT_Bisector)& BisectorTwo,
680    Standard_Integer&           IntPnt)
681 {
682   Standard_Real    Tolerance     = MAT2d_TOLCONF;
683   Standard_Real    Param1,Param2;
684   Standard_Real    Parama,Paramb;
685   Standard_Real    Distance = 0.,DistanceMini;
686   Standard_Boolean SolutionValide;
687   gp_Pnt2d         PointSolution;
688
689   Handle(Geom2d_TrimmedCurve)
690     Bisector1 = Handle(Geom2d_TrimmedCurve)
691       ::DownCast(ChangeGeomBis(BisectorOne->BisectorNumber()).ChangeValue());
692
693   Handle(Geom2d_TrimmedCurve) 
694     Bisector2 = Handle(Geom2d_TrimmedCurve)
695       ::DownCast(ChangeGeomBis(BisectorTwo->BisectorNumber()).ChangeValue());
696
697   if(Bisector1.IsNull() || Bisector2.IsNull()) return Precision::Infinite();
698
699   //-------------------------------------------------------------------------
700   // Si les deux bissectrices separent des elements consecutifs et qu elles
701   // sont issues des connexions C1 et C2.
702   // Si C1 est la reverse de C2 ,alors les deux bissectrices sont issues
703   // du meme point. Dans ce cas l intersection n est pas validee.
704   //-------------------------------------------------------------------------
705   Standard_Integer IS1 = BisectorOne->SecondEdge()->EdgeNumber();
706   Standard_Integer IS2 = BisectorTwo->SecondEdge()->EdgeNumber();
707   Standard_Integer IF1 = BisectorOne->FirstEdge() ->EdgeNumber();
708   Standard_Integer IF2 = BisectorTwo->FirstEdge() ->EdgeNumber();
709   
710   if (AreNeighbours(IF1,IS1,NumberOfItems()) && 
711       AreNeighbours(IF2,IS2,NumberOfItems()) &&
712       theCircuit->ConnexionOn(IS2)           && 
713       theCircuit->ConnexionOn(IS1)             ) {
714     Handle(MAT2d_Connexion) C1,C2;
715     C1 = theCircuit->Connexion(IS1);
716     C2 = theCircuit->Connexion(IS2); 
717     if (C2->IndexFirstLine() == C1->IndexSecondLine() &&
718         C1->IndexFirstLine() == C2->IndexSecondLine()  )
719       return Precision::Infinite();
720   }
721
722   // -----------------------------------------
723   // Construction des domaines d intersection.
724   // -----------------------------------------
725   IntRes2d_Domain Domain1 = Domain(Bisector1,Tolerance);
726   IntRes2d_Domain Domain2 = Domain(Bisector2,Tolerance);
727
728   if (Domain1.LastParameter() - Domain1.FirstParameter()  < Tolerance) 
729      return Precision::Infinite();
730   if (Domain2.LastParameter() - Domain2.FirstParameter()  < Tolerance) 
731      return Precision::Infinite();
732
733 #ifdef OCCT_DEBUG
734   Standard_Boolean Affich = Standard_False;
735   if (Affich) {
736     cout<<endl;
737     cout<<"INTERSECTION de "<<BisectorOne->BisectorNumber()<<
738                    " et de "<<BisectorTwo->BisectorNumber()<<endl;
739     cout<<"  Bisector 1 : "<<endl;
740 //    (Bisector1->BasisCurve())->Dump(-1,1);
741     cout<<endl;
742     Debug(Domain1.FirstParameter());
743     Debug(Domain1.LastParameter());
744     cout<<"-----------------"<<endl;
745     cout<<"  Bisector 2 : "<<endl;
746 //    (Bisector2->BasisCurve())->Dump(-1,1);
747     cout<<endl;
748     Debug(Domain2.FirstParameter());
749     Debug(Domain2.LastParameter());
750     cout<<"-----------------"<<endl;
751   }
752 #endif
753
754 // -------------------------
755 // Calcul de l intersection.
756 // -------------------------
757
758   Bisector_Inter Intersect;
759   Intersect.Perform (GeomBis(BisectorOne->BisectorNumber()),Domain1,
760                      GeomBis(BisectorTwo->BisectorNumber()),Domain2,
761                      Tolerance,Tolerance,Standard_True);
762
763 //  Geom2dInt_GInter Intersect;
764 //  Intersect.Perform(Bisector1,Domain1,Bisector2,Domain2,Tolerance,Tolerance);
765
766 // -------------------------------------------------------------------------
767 // Exploitation du resultat de l intersection et selection du point solution
768 // equidistant des deux edges et le plus proche en parametre de l origine 
769 // des bissectrices.
770 // -------------------------------------------------------------------------
771
772   if(!Intersect.IsDone()) return Precision::Infinite();
773
774   if(Intersect.IsEmpty()) return Precision::Infinite();
775
776   DistanceMini   = Precision::Infinite();
777   Param1         = Precision::Infinite();
778   Param2         = Precision::Infinite();
779   SolutionValide = Standard_False;
780
781   if(Intersect.NbSegments() >= 1) {              
782     Standard_Real    MaxSegmentLength = 10.*Tolerance;
783     for (Standard_Integer i=1;i<=Intersect.NbSegments();i++) {
784       IntRes2d_IntersectionSegment Segment     = Intersect.Segment(i);
785       Standard_Boolean             PointRetenu = Standard_False;
786       gp_Pnt2d                     PointOnSegment;
787       // ----------------------------------------------------------------
788       // Si les segments sont petits, recherche des points sur le segment
789       // equidistants des edges.
790       // ----------------------------------------------------------------
791       if ((Segment.HasFirstPoint() && Segment.HasLastPoint())) { 
792         gp_Pnt2d      P1,P2;
793         Standard_Real SegmentLength;
794         P1 = Segment.FirstPoint().Value();
795         P2 = Segment.LastPoint().Value();
796         SegmentLength = P1.Distance(P2);
797         if (SegmentLength <= Tolerance) {
798           PointOnSegment = P1;
799           if(IsSameDistance(BisectorOne,BisectorTwo,
800                             PointOnSegment,Distance)) 
801             PointRetenu = Standard_True;
802         }
803         else if (SegmentLength <= MaxSegmentLength) {
804           gp_Dir2d  Dir(P2.X()-P1.X(),P2.Y()-P1.Y());
805           Standard_Real Dist = 0.;  
806           while (Dist <= SegmentLength + Tolerance){
807             PointOnSegment = P1.Translated(Dist*Dir);
808             if(IsSameDistance(BisectorOne,BisectorTwo,
809                               PointOnSegment,Distance)) {
810               PointRetenu = Standard_True;
811               break;
812             }
813             Dist = Dist + Tolerance;
814           }
815         }
816       }  
817
818       // ----------------------------------------------------------------
819       // Sauvegarde du point equidistant des edges de plus petit 
820       // parametre sur les bissectrices.
821       // ----------------------------------------------------------------
822       if(PointRetenu) {
823         Parama = Handle(Bisector_Curve)::DownCast(Bisector1->BasisCurve())
824           ->Parameter(PointOnSegment);
825         Paramb = Handle(Bisector_Curve)::DownCast(Bisector2->BasisCurve())
826           ->Parameter(PointOnSegment);
827         if(Parama < Param1 && Paramb < Param2) {
828           Param1         = Parama;
829           Param2         = Paramb;
830           DistanceMini   = Distance;
831           PointSolution  = PointOnSegment;
832           SolutionValide = Standard_True;
833         }
834       }
835     }
836   }
837
838   if(Intersect.NbPoints() != 1) {
839     for(Standard_Integer i=1; i<=Intersect.NbPoints(); i++) {
840       if(IsSameDistance(BisectorOne,BisectorTwo,
841                         Intersect.Point(i).Value(),Distance) &&
842          Distance > Tolerance                                   ) {
843         Parama = Intersect.Point(i).ParamOnFirst();
844         Paramb = Intersect.Point(i).ParamOnSecond();
845         if (Parama < Param1 && Paramb < Param2) {
846           Param1         = Parama;
847           Param2         = Paramb;
848           DistanceMini   = Distance;
849           PointSolution  = Intersect.Point(i).Value();
850           SolutionValide = Standard_True;
851         }
852       }
853     }
854   }
855   else {
856     PointSolution  = Intersect.Point(1).Value();
857     Param1         = Intersect.Point(1).ParamOnFirst();
858     Param2         = Intersect.Point(1).ParamOnSecond();
859     SolutionValide = IsSameDistance(BisectorOne,BisectorTwo,
860                                     PointSolution,DistanceMini);
861   }
862
863   if (!SolutionValide) return Precision::Infinite();
864   theNumberOfPnts++;
865   theGeomPnts.Bind(theNumberOfPnts,PointSolution);
866   IntPnt = theNumberOfPnts;
867
868   //-----------------------------------------------------------------------
869   // Si le point d intersection est quasi confondue avec une des extremites
870   // de l une ou l autre des bisectrices, l intersection n est pas validee.
871   //
872   // SAUF si une des bisectrices est issue d une connexion et que les 
873   // edges separes par les bissectrices sont des voisines sur le contour
874   // initiales.
875   // en effet le milieu de la connexion P qui est l origine d une des 
876   // bissectrices peut etre sur l autre bissectrice. 
877   // P est donc point d intersection
878   // et la bissectrice issue de la connexion est de longueur nulle.
879   // (ex : un rectangle dans un rectangle ou la connexion est entre un coin
880   // et un cote).
881   //-----------------------------------------------------------------------
882
883   Standard_Integer IndexEdge1,IndexEdge2,IndexEdge3,IndexEdge4;
884   Standard_Boolean ExtremiteControle = Standard_True;
885
886   IndexEdge1 = BisectorOne->FirstEdge() ->EdgeNumber();
887   IndexEdge2 = BisectorOne->SecondEdge()->EdgeNumber();
888   IndexEdge3 = BisectorTwo->FirstEdge() ->EdgeNumber();
889   IndexEdge4 = BisectorTwo->SecondEdge()->EdgeNumber();
890   
891   if (theCircuit->ConnexionOn(IndexEdge2)){
892     // --------------------------------------
893     // BisectorOne est issue d une connexion.  
894     // --------------------------------------
895    if (AreNeighbours(IndexEdge1,IndexEdge2,NumberOfItems()) && 
896        AreNeighbours(IndexEdge3,IndexEdge4,NumberOfItems()) && 
897        IndexEdge2 == IndexEdge3                               ){
898       ExtremiteControle = Standard_False;
899       Param1             = Param1 + Tolerance;
900     }
901   }
902   
903   if (theCircuit->ConnexionOn(IndexEdge4)){
904     // --------------------------------------
905     // BisectorTwo est issue d une connexion.   
906     // --------------------------------------
907     if (AreNeighbours(IndexEdge1,IndexEdge2,NumberOfItems()) && 
908         AreNeighbours(IndexEdge3,IndexEdge4,NumberOfItems()) &&
909         IndexEdge2 == IndexEdge3                               ){
910       ExtremiteControle = Standard_False;
911       Param2            = Param2 + Tolerance;
912     }
913   }
914  
915   if (ExtremiteControle) {
916     if(Bisector1->StartPoint().Distance(PointSolution) < Tolerance ||
917        Bisector2->StartPoint().Distance(PointSolution) < Tolerance  ) 
918       return Precision::Infinite();
919   }
920
921   if(BisectorOne->SecondParameter() < Precision::Infinite() &&
922      BisectorOne->SecondParameter() < Param1*(1. - Tolerance )) 
923     return Precision::Infinite();
924   
925   if(BisectorTwo->FirstParameter() < Precision::Infinite() &&
926      BisectorTwo->FirstParameter() < Param2*(1.- Tolerance)) 
927     return Precision::Infinite();
928
929   BisectorOne->SecondParameter(Param1);
930   BisectorTwo->FirstParameter (Param2);
931   
932 #ifdef OCCT_DEBUG
933   if (Affich) {
934     cout<<"   coordonnees    : "<<GeomPnt  (IntPnt).X()<<" "
935                                 <<GeomPnt  (IntPnt).Y()<<endl;
936     cout<<"   parametres     : "<<Param1<<" "<<Param2<<endl;
937     cout<<"   distancemini   : "<<DistanceMini<<endl;
938   }
939 #endif
940   
941   return DistanceMini;
942 }
943
944 //=============================================================================
945 //function : Distance
946 //purpose  :
947 //=============================================================================
948 Standard_Real MAT2d_Tool2d::Distance(const Handle(MAT_Bisector)& Bis,
949                                      const Standard_Real         Param1,
950                                      const Standard_Real         Param2) const
951 {
952   Standard_Real Dist = Precision::Infinite();
953
954   if (Param1 != Precision::Infinite() && Param2 != Precision::Infinite()) {
955     gp_Pnt2d P1 = GeomBis(Bis->BisectorNumber()).Value()->Value(Param1);
956     gp_Pnt2d P2 = GeomBis(Bis->BisectorNumber()).Value()->Value(Param2);
957     Dist        = P1.Distance(P2);
958   }
959   return Dist;
960 }
961
962 //=============================================================================
963 //function : Dump
964 //purpose  :
965 //=============================================================================
966 #ifndef OCCT_DEBUG
967 void MAT2d_Tool2d::Dump(const Standard_Integer ,
968                         const Standard_Integer ) const
969 {
970   Standard_NotImplemented::Raise();
971 #else
972 void MAT2d_Tool2d::Dump(const Standard_Integer bisector,
973                         const Standard_Integer) const
974 {
975   if(bisector == -1) return;
976   if(bisector > theNumberOfBisectors) return;
977
978   Handle(Geom2d_Curve) thebisector = GeomBis(bisector).Value(); 
979
980   MAT2d_DrawCurve(thebisector,3);
981
982 #endif
983 }
984
985
986 //=============================================================================
987 //function : GeomBis
988 //purpose  :
989 //=============================================================================
990 const Bisector_Bisec&  MAT2d_Tool2d::GeomBis (const Standard_Integer Index) 
991      const
992 {
993   return theGeomBisectors.Find(Index);
994 }
995
996 //=============================================================================
997 //function : ChangeGeomBis
998 //purpose  :
999 //=============================================================================
1000 Bisector_Bisec&  MAT2d_Tool2d::ChangeGeomBis(const Standard_Integer Index)
1001 {
1002   return theGeomBisectors.ChangeFind(Index);
1003 }
1004
1005
1006 //=============================================================================
1007 //function : GeomElt
1008 //purpose  :
1009 //=============================================================================
1010 Handle(Geom2d_Geometry)  MAT2d_Tool2d::GeomElt(const Standard_Integer Index)
1011                                                                         const 
1012 {
1013   return  theCircuit->Value(Index);
1014 }
1015
1016
1017 //=============================================================================
1018 //function : GeomPnt
1019 //purpose  :
1020 //=============================================================================
1021 const gp_Pnt2d&  MAT2d_Tool2d::GeomPnt(const Standard_Integer Index) const
1022 {
1023   return theGeomPnts.Find(Index);
1024 }
1025
1026 //=============================================================================
1027 //function : GeomVec
1028 //purpose  :
1029 //=============================================================================
1030 const gp_Vec2d&  MAT2d_Tool2d::GeomVec(const Standard_Integer Index)const 
1031 {
1032   return theGeomVecs.Find(Index);
1033 }
1034
1035 //=============================================================================
1036 //function : Circuit
1037 //purpose  :
1038 //=============================================================================
1039 Handle(MAT2d_Circuit) MAT2d_Tool2d::Circuit()const 
1040 {
1041   return theCircuit;
1042 }
1043
1044 //=============================================================================
1045 //function : BisecFusion
1046 //purpose  :
1047 //=============================================================================
1048 void MAT2d_Tool2d::BisecFusion(const Standard_Integer I1,
1049                                const Standard_Integer I2) 
1050 {
1051   Standard_Real               DU,UL1,UF1;
1052   Handle(Geom2d_TrimmedCurve) Bisector1;
1053   Handle(Geom2d_TrimmedCurve) Bisector2;
1054
1055   Bisector1 = Handle(Geom2d_TrimmedCurve)::DownCast(GeomBis(I1).Value());
1056   Bisector2 = Handle(Geom2d_TrimmedCurve)::DownCast(GeomBis(I2).Value());
1057   UF1       = Bisector1->FirstParameter();
1058   UL1       = Bisector1->LastParameter();
1059
1060   Handle(Standard_Type) Type1 = Bisector1->BasisCurve()->DynamicType();
1061   if (Type1 == STANDARD_TYPE(Bisector_BisecCC)) {
1062     //------------------------------------------------------------------------------------
1063     // les bissectrice courbe/courbe sont  construites avec un point de depart
1064     // elles ne peuvent pas etre trimes par un point se trouvant de l autre cote du
1065     // point de depart.
1066     // pour faire la fusion des deux bissectrices on reconstruit la bissectrice entre les
1067     // deux courbes avec comme point de depart le dernier point de la Bisector2.
1068     // on trime ensuite la courbe par le dernier point de Bisector1.
1069     //------------------------------------------------------------------------------------
1070     Standard_Real            Tolerance    = MAT2d_TOLCONF;
1071     Bisector_Bisec           Bis;
1072     gp_Vec2d                 VBid(1,0);
1073     gp_Pnt2d                 P2   = Bisector2->Value(Bisector2->LastParameter());     
1074     gp_Pnt2d                 P1   = Bisector1->Value(Bisector1->LastParameter());   
1075     Handle(Bisector_BisecCC) BCC1 = Handle(Bisector_BisecCC)::DownCast(Bisector1->BasisCurve());
1076
1077     Bis.Perform(BCC1->Curve(2), BCC1->Curve(1), P2, VBid, VBid, 
1078                 theDirection, Tolerance, Standard_False); 
1079
1080     Bisector1 = Handle(Geom2d_TrimmedCurve)::DownCast(Bis.Value());
1081     BCC1      = Handle(Bisector_BisecCC)   ::DownCast(Bisector1->BasisCurve()); 
1082     UF1       = BCC1->FirstParameter();
1083     UL1       = BCC1->Parameter(P1);
1084     Bisector1->SetTrim(UF1,UL1);
1085     theGeomBisectors.Bind(I1,Bis);
1086   }
1087   else {
1088     DU        = Bisector2->LastParameter() - Bisector2->FirstParameter();
1089     UF1       = UF1 - DU;
1090
1091     Handle(Bisector_BisecAna) BAna = Handle(Bisector_BisecAna)::DownCast(Bisector1->BasisCurve());
1092 //---------------------------- uncomment if new method Bisector_BisecAna::SetTrim(f,l) is not used
1093 //    Handle(Geom2d_Curve) C2d = BAna->Geom2dCurve();
1094 //    Handle(Geom2d_TrimmedCurve) trimC2d = new Geom2d_TrimmedCurve(C2d, UF1, UL1);
1095 //    BAna->Init(trimC2d);
1096 //--------------------------- end
1097     BAna->SetTrim(UF1,UL1); // put comment if SetTrim(f,l) is not used
1098
1099     Bisector1->SetTrim(UF1,UL1);
1100   }
1101 }
1102
1103 //=============================================================================
1104 //function : Type
1105 //purpose  :
1106 //=============================================================================
1107 static Handle(Standard_Type) Type(const Handle(Geom2d_Geometry)& aGeom) 
1108 {
1109   Handle(Standard_Type) type = aGeom->DynamicType();
1110   Handle(Geom2d_Curve)  curve;
1111
1112   if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
1113     curve = Handle(Geom2d_TrimmedCurve)::DownCast(aGeom)->BasisCurve();
1114     type  = curve->DynamicType();
1115   }
1116   return type;
1117 }
1118
1119 //==========================================================================
1120 //function : AreNeighbours
1121 //purpose  : Return TRUE si IEdge1 et IEdge2 correspondent a des elements 
1122 //           consecutifs sur un contour ferme de NbEdge elements.
1123 //==========================================================================
1124 Standard_Boolean AreNeighbours(const Standard_Integer IEdge1,
1125                                const Standard_Integer IEdge2,
1126                                const Standard_Integer NbEdge)
1127 {
1128   if      (Abs(IEdge1 - IEdge2) == 1)         return Standard_True;
1129   else if (Abs(IEdge1 - IEdge2) == NbEdge -1) return Standard_True;
1130   else                                        return Standard_False; 
1131 }
1132
1133 //==========================================================================
1134 //function : SetTrim
1135 //purpose  :
1136 //==========================================================================
1137 void SetTrim(Bisector_Bisec& Bis, Handle(Geom2d_Curve)& Line1)
1138 {  
1139   Geom2dInt_GInter Intersect; 
1140   Standard_Real    Distance;  
1141   Standard_Real    Tolerance = MAT2d_TOLCONF;  
1142   Handle(Geom2d_TrimmedCurve) Bisector = 
1143     Handle(Geom2d_TrimmedCurve)::DownCast(Bis.ChangeValue());
1144
1145   IntRes2d_Domain  Domain1   = Domain(Bisector,Tolerance);
1146   Standard_Real    UB1       = Bisector->FirstParameter();
1147   Standard_Real    UB2       = Bisector->LastParameter();
1148  
1149   gp_Pnt2d         FirstPointBisector = Bisector->Value(UB1);
1150   Standard_Real    UTrim              = Precision::Infinite();
1151
1152   Geom2dAdaptor_Curve AdapBisector(Bisector);
1153   Geom2dAdaptor_Curve AdapLine1   (Line1);
1154   Intersect.Perform(AdapBisector, Domain1, 
1155                     AdapLine1, Tolerance, Tolerance);
1156
1157   if (Intersect.IsDone() && !Intersect.IsEmpty()) {
1158     for (Standard_Integer i = 1; i <= Intersect.NbPoints(); i++) {
1159       gp_Pnt2d PInt = Intersect.Point(i).Value();
1160       Distance      = FirstPointBisector.Distance(PInt);
1161       if (Distance > 10.*Tolerance                     && 
1162           Intersect.Point(i).ParamOnFirst() < UTrim ) {
1163          UTrim = Intersect.Point(i).ParamOnFirst();
1164       }
1165     }
1166   } 
1167   // ------------------------------------------------------------------------
1168   // Restriction de la Bissectrice par le point d intersection de plus petit
1169   // parametre.
1170   // ------------------------------------------------------------------------
1171   if (UTrim < UB2 && UTrim > UB1) Bisector->SetTrim(UB1,UTrim);
1172 }
1173
1174 //==========================================================================
1175 //function : Domain
1176 //purpose  :
1177 //==========================================================================
1178 IntRes2d_Domain  Domain(const Handle(Geom2d_TrimmedCurve)& Bisector1,
1179                         const Standard_Real                Tolerance)
1180 {
1181   Standard_Real Param1 = Bisector1->FirstParameter();
1182   Standard_Real Param2 = Bisector1->LastParameter();
1183   if(Param2 > 10000.) {
1184     Param2 = 10000.;
1185     Handle(Standard_Type) Type1 = Type(Bisector1->BasisCurve());    
1186     Handle(Geom2d_Curve)  BasisCurve;
1187     if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) {
1188       BasisCurve = Handle(Bisector_BisecAna)
1189         ::DownCast(Bisector1->BasisCurve())->Geom2dCurve();
1190       Type1      = BasisCurve->DynamicType();
1191     }
1192     gp_Parab2d gpParabola;
1193     gp_Hypr2d  gpHyperbola;
1194     Standard_Real Focus;
1195     Standard_Real Limit = 50000.;
1196     if (Type1 == STANDARD_TYPE(Geom2d_Parabola)) {
1197       gpParabola = Handle(Geom2d_Parabola)::DownCast(BasisCurve)->Parab2d();
1198       Focus = gpParabola.Focal();
1199       Standard_Real Val1 = Sqrt(Limit*Focus);
1200       Standard_Real Val2 = Sqrt(Limit*Limit);
1201       Param2 = (Val1 <= Val2 ? Val1:Val2);
1202     }
1203     else if (Type1 == STANDARD_TYPE(Geom2d_Hyperbola)) {
1204       gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(BasisCurve)->Hypr2d();
1205       Standard_Real Majr  = gpHyperbola.MajorRadius();
1206       Standard_Real Minr  = gpHyperbola.MinorRadius();
1207       Standard_Real Valu1 = Limit/Majr;
1208       Standard_Real Valu2 = Limit/Minr;
1209       Standard_Real Val1  = Log(Valu1+Sqrt(Valu1*Valu1-1));
1210       Standard_Real Val2  = Log(Valu2+Sqrt(Valu2*Valu2+1));
1211       Param2 = (Val1 <= Val2 ? Val1:Val2);
1212     }
1213   }
1214  
1215   IntRes2d_Domain Domain1(Bisector1->Value(Param1),Param1,Tolerance,
1216                           Bisector1->Value(Param2),Param2,Tolerance);
1217   if(Bisector1->BasisCurve()->IsPeriodic()) {
1218     Domain1.SetEquivalentParameters(0.,2.*M_PI);
1219   }
1220   return Domain1;
1221 }
1222
1223 #ifdef OCCT_DEBUG
1224 //==========================================================================
1225 //function : MAT2d_DrawCurve
1226 //purpose  : Affichage d une courbe <aCurve> de Geom2d. dans une couleur
1227 //           definie par <Indice>.
1228 //            Indice = 1 jaune,
1229 //            Indice = 2 bleu,
1230 //            Indice = 3 rouge,
1231 //            Indice = 4 vert.
1232 //==========================================================================
1233 void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve,
1234                      const Standard_Integer      /*Indice*/)
1235 {  
1236   Handle(Standard_Type)      type = aCurve->DynamicType();
1237   Handle(Geom2d_Curve)       curve,CurveDraw;
1238 #ifdef DRAW
1239   Handle(DrawTrSurf_Curve2d) dr;
1240   Draw_Color                 Couleur;
1241 #endif
1242
1243   if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
1244     curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
1245     type = curve->DynamicType();    
1246     // PB de representation des courbes semi_infinies.
1247     gp_Parab2d gpParabola;
1248     gp_Hypr2d  gpHyperbola;
1249     Standard_Real Focus;
1250     Standard_Real Limit = 50000.;
1251     Standard_Real delta = 400;
1252
1253     // PB de representation des courbes semi_infinies.
1254     if (aCurve->LastParameter() == Precision::Infinite()) {
1255       
1256       if (type == STANDARD_TYPE(Geom2d_Parabola)) {
1257         gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d();
1258         Focus = gpParabola.Focal();
1259         Standard_Real Val1 = Sqrt(Limit*Focus);
1260         Standard_Real Val2 = Sqrt(Limit*Limit);
1261                       delta= (Val1 <= Val2 ? Val1:Val2);
1262       }
1263       else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) {
1264         gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d();
1265         Standard_Real Majr  = gpHyperbola.MajorRadius();
1266         Standard_Real Minr  = gpHyperbola.MinorRadius();
1267         Standard_Real Valu1 = Limit/Majr;
1268         Standard_Real Valu2 = Limit/Minr;
1269         Standard_Real Val1  = Log(Valu1+Sqrt(Valu1*Valu1-1));
1270         Standard_Real Val2  = Log(Valu2+Sqrt(Valu2*Valu2+1));
1271                       delta  = (Val1 <= Val2 ? Val1:Val2);
1272       }
1273       CurveDraw = new Geom2d_TrimmedCurve(aCurve,
1274                                           aCurve->FirstParameter(),
1275                                           aCurve->FirstParameter() + delta);
1276     }
1277     else {
1278       CurveDraw = aCurve;
1279     }
1280     // fin PB.
1281   }
1282   else {
1283     CurveDraw = aCurve;
1284   }
1285
1286 #ifdef DRAW
1287   if      (Indice == 1) Couleur = Draw_jaune;
1288   else if (Indice == 2) Couleur = Draw_bleu;
1289   else if (Indice == 3) Couleur = Draw_rouge;
1290   else if (Indice == 4) Couleur = Draw_vert;
1291
1292   if (type == STANDARD_TYPE(Geom2d_Circle))
1293     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30);
1294   else if (type  == STANDARD_TYPE(Geom2d_Line))
1295     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2);
1296   else
1297     dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500);
1298
1299   dout << dr;
1300   dout.Flush();
1301 #endif
1302 }
1303
1304 #endif
1305